Compare commits
3 Commits
2025.1.12.
...
2025.6.1.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ff0c4587eb | ||
|
|
fff63d0a9f | ||
|
|
2f838929cc |
88
Changelog.md
@@ -1,3 +1,91 @@
|
|||||||
|
# 2025.6.1.0
|
||||||
|
|
||||||
|
*2025-06-01*
|
||||||
|
|
||||||
|
- Added
|
||||||
|
- Sites:
|
||||||
|
- YouTube (standalone app):
|
||||||
|
- support for **youtu.be** domain
|
||||||
|
- **filters**
|
||||||
|
- hotkey `Ctrl+F5` for refresh
|
||||||
|
- **Bluesky, Instagram, OnlyFans, Reddit, Threads, Twitter: the ability to download text posts**
|
||||||
|
- OnlyFans:
|
||||||
|
- updated `DynamicRules`
|
||||||
|
- `backend` option *(`aio` & `httpx`)*
|
||||||
|
- Reddit: add `Best` and `Rising` view modes
|
||||||
|
- TikTok: downloading of avatar, site name and description
|
||||||
|
- Feed:
|
||||||
|
- **filters**
|
||||||
|
- add the ability to show test posts
|
||||||
|
- Minor improvements
|
||||||
|
- Updated
|
||||||
|
- yt-dlp up to version **2025.05.22**
|
||||||
|
- gallery-dl up to version **1.29.7**
|
||||||
|
- PluginProvider
|
||||||
|
- IUserMedia: properties `PostText`, `PostTextFile`, `PostTextFileSpecialFolder`
|
||||||
|
- Fixed
|
||||||
|
- Sites:
|
||||||
|
- OnlyFans:
|
||||||
|
- DRM videos are not downloading in some cases *(only if you can't download video try changing `backend` option to `httpx`)*
|
||||||
|
- incorrect open posts
|
||||||
|
- while limited downloading, the first time, the profile still loads completely
|
||||||
|
- Reddit:
|
||||||
|
- **data is not downloading**
|
||||||
|
- post date is incorrect
|
||||||
|
- Threads
|
||||||
|
- change domain from `net` to `com`
|
||||||
|
- data is not downloading
|
||||||
|
- Twitter
|
||||||
|
- fix JSON error
|
||||||
|
- data is not downloaded in some cases
|
||||||
|
- Minor bugs
|
||||||
|
|
||||||
|
# 2025.3.17.0
|
||||||
|
|
||||||
|
*2025-03-17*
|
||||||
|
|
||||||
|
- Added
|
||||||
|
- **TikTok: downloading photos**
|
||||||
|
- Updated
|
||||||
|
- gallery-dl up to version **1.29.2**
|
||||||
|
- Fixed
|
||||||
|
- Sites
|
||||||
|
- Facebook: reels aren't downloaded from noname profiles
|
||||||
|
- PornHub: newly added users aren't downloading
|
||||||
|
- Threads: users aren't updated if there is a pinned post
|
||||||
|
|
||||||
|
# 2025.2.25.0
|
||||||
|
|
||||||
|
*2025-02-25*
|
||||||
|
|
||||||
|
- Added
|
||||||
|
- Sites:
|
||||||
|
- **Bluesky**
|
||||||
|
- Facebook: **`Reels` downloads**
|
||||||
|
- OnlyFans: default value for `App-Token`
|
||||||
|
- Pinterest: **sub-boards downloading**
|
||||||
|
- Threads: ability to manually change `UserName`
|
||||||
|
- Twitter:
|
||||||
|
- new icon support
|
||||||
|
- **sleep timers to fully download large profiles**
|
||||||
|
- Feed:
|
||||||
|
- ability to invert selection
|
||||||
|
- open post URL when double-clicking on subscription image
|
||||||
|
- Minor improvements
|
||||||
|
- Updated
|
||||||
|
- yt-dlp up to version **2025.02.19**
|
||||||
|
- gallery-dl up to version **1.28.5**
|
||||||
|
- PluginProvider
|
||||||
|
- `IPluginContentProvider`: added property `NameTrue`
|
||||||
|
- Fixed
|
||||||
|
- Sites:
|
||||||
|
- Facebook: videos are not downloading
|
||||||
|
- LPSG: simplified 403 error
|
||||||
|
- PornHub: photos & videos are not downloading
|
||||||
|
- Reddit: **token does not update automatically**
|
||||||
|
- Threads: **data is not downloading**
|
||||||
|
- Minor bugs
|
||||||
|
|
||||||
# 2025.1.12.0
|
# 2025.1.12.0
|
||||||
|
|
||||||
*2025-01-12*
|
*2025-01-12*
|
||||||
|
|||||||
1
FAQ.md
@@ -63,6 +63,7 @@ I strongly recommend you to **regularly** create backup copies of the settings f
|
|||||||
|
|
||||||
- Reddit: don't use credentials at all or configure [OAuth](https://github.com/AAndyProgram/SCrawler/wiki/Settings#how-to-get-reddit-credentials). **Reddit profiles can be downloaded without any credentials at all. Subreddits require OAuth! If nothing downloads, use OAuth!** Don't use OAuth token to download saved posts (use cookies only).
|
- Reddit: don't use credentials at all or configure [OAuth](https://github.com/AAndyProgram/SCrawler/wiki/Settings#how-to-get-reddit-credentials). **Reddit profiles can be downloaded without any credentials at all. Subreddits require OAuth! If nothing downloads, use OAuth!** Don't use OAuth token to download saved posts (use cookies only).
|
||||||
- **META** (**Instagram**, Threads, Facebook): you need **cookies** and fill in **all fields**
|
- **META** (**Instagram**, Threads, Facebook): you need **cookies** and fill in **all fields**
|
||||||
|
- **Instagram [TIPS](https://github.com/AAndyProgram/SCrawler/wiki/Settings#instagram-tips)**
|
||||||
- **Instagram saved posts**: I don't consider questions like "I have 10k saved posts and only 1000 were downloaded". Download posts, remove them from saved posts, delete the `Saved posts` **settings folder**, repeat.
|
- **Instagram saved posts**: I don't consider questions like "I have 10k saved posts and only 1000 were downloaded". Download posts, remove them from saved posts, delete the `Saved posts` **settings folder**, repeat.
|
||||||
- TikTok: works via yt-dlp. If something doesn't download, we need to wait until yt-dlp fixes it. TikTok doesn't require cookies to download.
|
- TikTok: works via yt-dlp. If something doesn't download, we need to wait until yt-dlp fixes it. TikTok doesn't require cookies to download.
|
||||||
- Porn sites: **COOKIES**!
|
- Porn sites: **COOKIES**!
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
BIN
ProgramScreenshots/SettingsSiteBluesky.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 14 KiB |
17
README.md
@@ -38,13 +38,14 @@ A program to download photo and video from [any site](#supported-sites) (e.g. Yo
|
|||||||
- Reddit images, galleries of images, videos, saved posts;
|
- Reddit images, galleries of images, videos, saved posts;
|
||||||
- Redgifs images and videos (https://www.redgifs.com/);
|
- Redgifs images and videos (https://www.redgifs.com/);
|
||||||
- Twitter images and videos, saved (bookmarked) posts, likes, communities;
|
- Twitter images and videos, saved (bookmarked) posts, likes, communities;
|
||||||
|
- Bluesky images and videos;
|
||||||
- OnlyFans images and videos, saved (bookmarked) posts, stories;
|
- OnlyFans images and videos, saved (bookmarked) posts, stories;
|
||||||
- JustForFans images and videos, saved (bookmarked) posts;
|
- JustForFans images and videos, saved (bookmarked) posts;
|
||||||
- Mastodon images and videos, saved (bookmarked) posts;
|
- Mastodon images and videos, saved (bookmarked) posts;
|
||||||
- Instagram images and videos, tagged posts, stories, saved posts;
|
- Instagram images and videos, tagged posts, stories, saved posts;
|
||||||
- Threads images and videos, saved posts;
|
- Threads images and videos, saved posts;
|
||||||
- Facebook images and videos, stories, saved posts;
|
- Facebook images and videos, stories, saved posts;
|
||||||
- TikTok videos;
|
- TikTok images and videos;
|
||||||
- Pinterest boards, users, saved posts;
|
- Pinterest boards, users, saved posts;
|
||||||
- Imgur images, galleries and videos;
|
- Imgur images, galleries and videos;
|
||||||
- Gfycat videos;
|
- Gfycat videos;
|
||||||
@@ -78,6 +79,7 @@ A program to download photo and video from [any site](#supported-sites) (e.g. Yo
|
|||||||
- **YouTube Music**
|
- **YouTube Music**
|
||||||
- **Reddit**
|
- **Reddit**
|
||||||
- **Twitter**
|
- **Twitter**
|
||||||
|
- **Bluesky**
|
||||||
- **OnlyFans** *(partial support)*[^1]
|
- **OnlyFans** *(partial support)*[^1]
|
||||||
- **Instagram**
|
- **Instagram**
|
||||||
- **Threads**
|
- **Threads**
|
||||||
@@ -131,6 +133,7 @@ First, the program downloads the full profile. After the program downloads only
|
|||||||
- **[SITES REQUIREMENTS](https://github.com/AAndyProgram/SCrawler/wiki/Settings#sites-requirements)**
|
- **[SITES REQUIREMENTS](https://github.com/AAndyProgram/SCrawler/wiki/Settings#sites-requirements)**
|
||||||
- [Reddit](https://github.com/AAndyProgram/SCrawler/wiki/Settings#reddit)
|
- [Reddit](https://github.com/AAndyProgram/SCrawler/wiki/Settings#reddit)
|
||||||
- [Twitter](https://github.com/AAndyProgram/SCrawler/wiki/Settings#twitter)
|
- [Twitter](https://github.com/AAndyProgram/SCrawler/wiki/Settings#twitter)
|
||||||
|
- [Bluesky](https://github.com/AAndyProgram/SCrawler/wiki/Settings#bluesky)
|
||||||
- [OnlyFans](https://github.com/AAndyProgram/SCrawler/wiki/Settings#onlyfans)
|
- [OnlyFans](https://github.com/AAndyProgram/SCrawler/wiki/Settings#onlyfans)
|
||||||
- [Mastodon](https://github.com/AAndyProgram/SCrawler/wiki/Settings#mastodon)
|
- [Mastodon](https://github.com/AAndyProgram/SCrawler/wiki/Settings#mastodon)
|
||||||
- [Instagram](https://github.com/AAndyProgram/SCrawler/wiki/Settings#instagram)
|
- [Instagram](https://github.com/AAndyProgram/SCrawler/wiki/Settings#instagram)
|
||||||
@@ -215,16 +218,4 @@ F5-->[*]
|
|||||||
|
|
||||||
Discord server: https://discord.gg/uFNUXvFFmg
|
Discord server: https://discord.gg/uFNUXvFFmg
|
||||||
|
|
||||||
<!--
|
|
||||||
[e-mail](mailto:andyprogram@proton.me): andyprogram@proton.me
|
|
||||||
|
|
||||||
Matrix (Element): https://matrix.to/#/@andyprogram:matrix.org
|
|
||||||
|
|
||||||
Discord (contact the developer): andyprogram
|
|
||||||
|
|
||||||
Discord server: https://discord.gg/uFNUXvFFmg
|
|
||||||
|
|
||||||
[Wire](https://account.wire.com/user-profile/?id=93985052-cf2c-4b72-ac75-bbe3231cf544): @andyprogram
|
|
||||||
-->
|
|
||||||
|
|
||||||
[^1]: Partial support means that I don't have personal accounts on paid porn sites because I don't pay for porn. If this site has stopped downloading and you want me to fix it, please be ready to give me access to an account with at least one active subscription. Otherwise, the download from this site will not be fixed.
|
[^1]: Partial support means that I don't have personal accounts on paid porn sites because I don't pay for porn. If this site has stopped downloading and you want me to fix it, please be ready to give me access to an account with at least one active subscription. Otherwise, the download from this site will not be fixed.
|
||||||
@@ -17,6 +17,7 @@ Namespace Plugin
|
|||||||
Property Settings As ISiteSettings
|
Property Settings As ISiteSettings
|
||||||
Property AccountName As String
|
Property AccountName As String
|
||||||
Property Name As String
|
Property Name As String
|
||||||
|
Property NameTrue As String
|
||||||
Property ID As String
|
Property ID As String
|
||||||
Property Options As String
|
Property Options As String
|
||||||
Property ParseUserMediaOnly As Boolean
|
Property ParseUserMediaOnly As Boolean
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ Imports System.Runtime.InteropServices
|
|||||||
<Assembly: AssemblyDescription("Plugin provider for SCrawler")>
|
<Assembly: AssemblyDescription("Plugin provider for SCrawler")>
|
||||||
<Assembly: AssemblyCompany("AndyProgram")>
|
<Assembly: AssemblyCompany("AndyProgram")>
|
||||||
<Assembly: AssemblyProduct("SCrawler.PluginProvider")>
|
<Assembly: AssemblyProduct("SCrawler.PluginProvider")>
|
||||||
<Assembly: AssemblyCopyright("Copyright © 2024")>
|
<Assembly: AssemblyCopyright("Copyright © 2025")>
|
||||||
<Assembly: AssemblyTrademark("AndyProgram")>
|
<Assembly: AssemblyTrademark("AndyProgram")>
|
||||||
|
|
||||||
<Assembly: ComVisible(False)>
|
<Assembly: ComVisible(False)>
|
||||||
@@ -32,6 +32,6 @@ Imports System.Runtime.InteropServices
|
|||||||
' by using the '*' as shown below:
|
' by using the '*' as shown below:
|
||||||
' <Assembly: AssemblyVersion("1.0.*")>
|
' <Assembly: AssemblyVersion("1.0.*")>
|
||||||
|
|
||||||
<Assembly: AssemblyVersion("2024.5.18.0")>
|
<Assembly: AssemblyVersion("2025.6.1.0")>
|
||||||
<Assembly: AssemblyFileVersion("2024.5.18.0")>
|
<Assembly: AssemblyFileVersion("2025.6.1.0")>
|
||||||
<Assembly: NeutralResourcesLanguage("en")>
|
<Assembly: NeutralResourcesLanguage("en")>
|
||||||
|
|||||||
@@ -35,6 +35,9 @@ Namespace Plugin
|
|||||||
Public Property DownloadState As UserMediaStates Implements IUserMedia.DownloadState
|
Public Property DownloadState As UserMediaStates Implements IUserMedia.DownloadState
|
||||||
Public Property PostID As String Implements IUserMedia.PostID
|
Public Property PostID As String Implements IUserMedia.PostID
|
||||||
Public Property PostDate As Date? Implements IUserMedia.PostDate
|
Public Property PostDate As Date? Implements IUserMedia.PostDate
|
||||||
|
Public Property PostText As String Implements IUserMedia.PostText
|
||||||
|
Public Property PostTextFile As String Implements IUserMedia.PostTextFile
|
||||||
|
Public Property PostTextFileSpecialFolder As Boolean Implements IUserMedia.PostTextFileSpecialFolder
|
||||||
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
|
Public Property [Object] As Object Implements IUserMedia.Object
|
||||||
@@ -48,6 +51,9 @@ Namespace Plugin
|
|||||||
Property DownloadState As UserMediaStates
|
Property DownloadState As UserMediaStates
|
||||||
Property PostID As String
|
Property PostID As String
|
||||||
Property PostDate As Date?
|
Property PostDate As Date?
|
||||||
|
Property PostText As String
|
||||||
|
Property PostTextFile As String
|
||||||
|
Property PostTextFileSpecialFolder As Boolean
|
||||||
Property SpecialFolder As String
|
Property SpecialFolder As String
|
||||||
Property Attempts As Integer
|
Property Attempts As Integer
|
||||||
Property [Object] As Object
|
Property [Object] As Object
|
||||||
|
|||||||
BIN
SCrawler.Shared/Content/Icons/FilterIcon.ico
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
SCrawler.Shared/Content/Images/FilterPic.png
Normal file
|
After Width: | Height: | Size: 320 B |
@@ -32,6 +32,6 @@ Imports System.Runtime.InteropServices
|
|||||||
' by using the '*' as shown below:
|
' by using the '*' as shown below:
|
||||||
' <Assembly: AssemblyVersion("1.0.*")>
|
' <Assembly: AssemblyVersion("1.0.*")>
|
||||||
|
|
||||||
<Assembly: AssemblyVersion("2023.12.15.0")>
|
<Assembly: AssemblyVersion("2025.6.1.0")>
|
||||||
<Assembly: AssemblyFileVersion("2023.12.15.0")>
|
<Assembly: AssemblyFileVersion("2025.6.1.0")>
|
||||||
<Assembly: NeutralResourcesLanguage("en")>
|
<Assembly: NeutralResourcesLanguage("en")>
|
||||||
|
|||||||
26
SCrawler.Shared/My Project/Resources.Designer.vb
generated
@@ -26,7 +26,7 @@ Namespace My.Resources
|
|||||||
Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
|
Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
|
||||||
Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
|
Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
|
||||||
Global.Microsoft.VisualBasic.HideModuleNameAttribute()> _
|
Global.Microsoft.VisualBasic.HideModuleNameAttribute()> _
|
||||||
Friend Module Resources
|
Public Module Resources
|
||||||
|
|
||||||
Private resourceMan As Global.System.Resources.ResourceManager
|
Private resourceMan As Global.System.Resources.ResourceManager
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ Namespace My.Resources
|
|||||||
''' Returns the cached ResourceManager instance used by this class.
|
''' Returns the cached ResourceManager instance used by this class.
|
||||||
'''</summary>
|
'''</summary>
|
||||||
<Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
<Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
||||||
Friend ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager
|
Public ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager
|
||||||
Get
|
Get
|
||||||
If Object.ReferenceEquals(resourceMan, Nothing) Then
|
If Object.ReferenceEquals(resourceMan, Nothing) Then
|
||||||
Dim temp As Global.System.Resources.ResourceManager = New Global.System.Resources.ResourceManager("SCrawler.Resources", GetType(Resources).Assembly)
|
Dim temp As Global.System.Resources.ResourceManager = New Global.System.Resources.ResourceManager("SCrawler.Resources", GetType(Resources).Assembly)
|
||||||
@@ -51,7 +51,7 @@ Namespace My.Resources
|
|||||||
''' resource lookups using this strongly typed resource class.
|
''' resource lookups using this strongly typed resource class.
|
||||||
'''</summary>
|
'''</summary>
|
||||||
<Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
<Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
||||||
Friend Property Culture() As Global.System.Globalization.CultureInfo
|
Public Property Culture() As Global.System.Globalization.CultureInfo
|
||||||
Get
|
Get
|
||||||
Return resourceCulture
|
Return resourceCulture
|
||||||
End Get
|
End Get
|
||||||
@@ -59,5 +59,25 @@ Namespace My.Resources
|
|||||||
resourceCulture = value
|
resourceCulture = value
|
||||||
End Set
|
End Set
|
||||||
End Property
|
End Property
|
||||||
|
|
||||||
|
'''<summary>
|
||||||
|
''' Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
|
||||||
|
'''</summary>
|
||||||
|
Public ReadOnly Property FilterIcon() As System.Drawing.Icon
|
||||||
|
Get
|
||||||
|
Dim obj As Object = ResourceManager.GetObject("FilterIcon", resourceCulture)
|
||||||
|
Return CType(obj,System.Drawing.Icon)
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
|
|
||||||
|
'''<summary>
|
||||||
|
''' Looks up a localized resource of type System.Drawing.Bitmap.
|
||||||
|
'''</summary>
|
||||||
|
Public ReadOnly Property FilterPic() As System.Drawing.Bitmap
|
||||||
|
Get
|
||||||
|
Dim obj As Object = ResourceManager.GetObject("FilterPic", resourceCulture)
|
||||||
|
Return CType(obj,System.Drawing.Bitmap)
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
End Module
|
End Module
|
||||||
End Namespace
|
End Namespace
|
||||||
|
|||||||
@@ -46,7 +46,7 @@
|
|||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.binary.base64
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
value : The object must be serialized with
|
value : The object must be serialized with
|
||||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
: and then encoded with base64 encoding.
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.soap.base64
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
@@ -60,6 +60,7 @@
|
|||||||
: and then encoded with base64 encoding.
|
: 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: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:element name="root" msdata:IsDataSet="true">
|
||||||
<xsd:complexType>
|
<xsd:complexType>
|
||||||
<xsd:choice maxOccurs="unbounded">
|
<xsd:choice maxOccurs="unbounded">
|
||||||
@@ -68,9 +69,10 @@
|
|||||||
<xsd:sequence>
|
<xsd:sequence>
|
||||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
</xsd:sequence>
|
</xsd:sequence>
|
||||||
<xsd:attribute name="name" type="xsd:string" />
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
<xsd:attribute name="type" type="xsd:string" />
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
</xsd:complexType>
|
</xsd:complexType>
|
||||||
</xsd:element>
|
</xsd:element>
|
||||||
<xsd:element name="assembly">
|
<xsd:element name="assembly">
|
||||||
@@ -85,9 +87,10 @@
|
|||||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
<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:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
</xsd:sequence>
|
</xsd:sequence>
|
||||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
<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="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
</xsd:complexType>
|
</xsd:complexType>
|
||||||
</xsd:element>
|
</xsd:element>
|
||||||
<xsd:element name="resheader">
|
<xsd:element name="resheader">
|
||||||
@@ -109,9 +112,16 @@
|
|||||||
<value>2.0</value>
|
<value>2.0</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
<resheader name="reader">
|
<resheader name="reader">
|
||||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
<resheader name="writer">
|
<resheader name="writer">
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
|
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||||
|
<data name="FilterIcon" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
|
<value>..\Content\Icons\FilterIcon.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||||
|
</data>
|
||||||
|
<data name="FilterPic" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
|
<value>..\Content\Images\FilterPic.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
@@ -82,6 +82,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Data" />
|
<Reference Include="System.Data" />
|
||||||
|
<Reference Include="System.Drawing" />
|
||||||
<Reference Include="System.Windows.Forms" />
|
<Reference Include="System.Windows.Forms" />
|
||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
@@ -123,7 +124,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedResource Include="My Project\Resources.resx">
|
<EmbeddedResource Include="My Project\Resources.resx">
|
||||||
<Generator>VbMyResourcesResXFileCodeGenerator</Generator>
|
<Generator>PublicVbMyResourcesResXFileCodeGenerator</Generator>
|
||||||
<LastGenOutput>Resources.Designer.vb</LastGenOutput>
|
<LastGenOutput>Resources.Designer.vb</LastGenOutput>
|
||||||
<CustomToolNamespace>My.Resources</CustomToolNamespace>
|
<CustomToolNamespace>My.Resources</CustomToolNamespace>
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
@@ -147,5 +148,9 @@
|
|||||||
<Name>PersonalUtilities</Name>
|
<Name>PersonalUtilities</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="Content\Icons\FilterIcon.ico" />
|
||||||
|
<Content Include="Content\Images\FilterPic.png" />
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" />
|
||||||
</Project>
|
</Project>
|
||||||
@@ -18,6 +18,7 @@ Namespace API.YouTube.Base
|
|||||||
Public Const TrueUrlPattern As String = "https?://[^/]*?youtube.com/[^\?/&]+((\??[^\?/&]+|/[^\?/&]+))"
|
Public Const TrueUrlPattern As String = "https?://[^/]*?youtube.com/[^\?/&]+((\??[^\?/&]+|/[^\?/&]+))"
|
||||||
'2 - type; 5 - id
|
'2 - type; 5 - id
|
||||||
Public Const UrlTypePattern As String = "(?<=https?://[^/]*?youtube.com/)((@|[^\?/&]+))([/\?]{0,1}(list=|v=|)([^\?/&]*))(?=(\S+|\Z|))"
|
Public Const UrlTypePattern As String = "(?<=https?://[^/]*?youtube.com/)((@|[^\?/&]+))([/\?]{0,1}(list=|v=|)([^\?/&]*))(?=(\S+|\Z|))"
|
||||||
|
Public Const UrlTypePattern_BE As String = "(?<=https?://[^/]*?youtu.be/)([^\?/&]+)"
|
||||||
Private Sub New()
|
Private Sub New()
|
||||||
End Sub
|
End Sub
|
||||||
Public Shared Function StandardizeURL(ByVal URL As String) As String
|
Public Shared Function StandardizeURL(ByVal URL As String) As String
|
||||||
@@ -36,6 +37,7 @@ Namespace API.YouTube.Base
|
|||||||
Next
|
Next
|
||||||
data.Clear()
|
data.Clear()
|
||||||
End If
|
End If
|
||||||
|
If val.IsEmptyString Then val = RegexReplace(URL, RParams.DMS(UrlTypePattern_BE, 0, EDP.ReturnValue))
|
||||||
If Not val.IsEmptyString Then Return $"https://www.youtube.com/watch?v={val}"
|
If Not val.IsEmptyString Then Return $"https://www.youtube.com/watch?v={val}"
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
@@ -100,6 +102,9 @@ Namespace API.YouTube.Base
|
|||||||
Return YouTubeMediaType.Channel
|
Return YouTubeMediaType.Channel
|
||||||
End Select
|
End Select
|
||||||
End If
|
End If
|
||||||
|
Else
|
||||||
|
Dim v$ = RegexReplace(URL, RParams.DMS(UrlTypePattern_BE, 0, EDP.ReturnValue))
|
||||||
|
If Not v.IsEmptyString Then Return YouTubeMediaType.Single
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
Return YouTubeMediaType.Undefined
|
Return YouTubeMediaType.Undefined
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ Namespace API.YouTube.Base
|
|||||||
#Region "Declarations"
|
#Region "Declarations"
|
||||||
<Browsable(False)> Private ReadOnly Property XML As XmlFile Implements IXMLValuesContainer.XML
|
<Browsable(False)> Private ReadOnly Property XML As XmlFile Implements IXMLValuesContainer.XML
|
||||||
<Browsable(False)> Friend ReadOnly Property DesignXml As XmlFile
|
<Browsable(False)> Friend ReadOnly Property DesignXml As XmlFile
|
||||||
|
<Browsable(False)> Friend ReadOnly Property FILTER As Controls.YTDataFilter
|
||||||
<Browsable(False)> Private Property Mode As GridUpdateModes = GridUpdateModes.OnConfirm Implements IGridValuesContainer.Mode
|
<Browsable(False)> Private Property Mode As GridUpdateModes = GridUpdateModes.OnConfirm Implements IGridValuesContainer.Mode
|
||||||
<Browsable(False), XMLVV(-1)> Friend ReadOnly Property PlaylistFormSplitterDistance As XMLValue(Of Integer)
|
<Browsable(False), XMLVV(-1)> Friend ReadOnly Property PlaylistFormSplitterDistance As XMLValue(Of Integer)
|
||||||
<Browsable(False)> Friend ReadOnly Property DownloadLocations As DownloadLocationsCollection
|
<Browsable(False)> Friend ReadOnly Property DownloadLocations As DownloadLocationsCollection
|
||||||
@@ -168,9 +169,6 @@ Namespace API.YouTube.Base
|
|||||||
<Browsable(True), GridVisible, XMLVN({"Info"}), Category("Info"), DisplayName("Create description files"),
|
<Browsable(True), GridVisible, XMLVN({"Info"}), Category("Info"), DisplayName("Create description files"),
|
||||||
Description("Create video description files. Default: false.")>
|
Description("Create video description files. Default: false.")>
|
||||||
Public ReadOnly Property CreateDescriptionFiles As XMLValue(Of Boolean)
|
Public ReadOnly Property CreateDescriptionFiles As XMLValue(Of Boolean)
|
||||||
<Browsable(True), GridVisible, XMLVN({"Info"}, True), Category("Info"), DisplayName("Create description files: add upload date"),
|
|
||||||
Description("Add the upload date to the top of the description file. Default: true.")>
|
|
||||||
Public ReadOnly Property CreateDescriptionFiles_AddUploadDate As XMLValue(Of Boolean)
|
|
||||||
<Browsable(True), GridVisible, XMLVN({"Info"}, True), Category("Info"), DisplayName("Create description files: create without description"),
|
<Browsable(True), GridVisible, XMLVN({"Info"}, True), Category("Info"), DisplayName("Create description files: create without description"),
|
||||||
Description("Create a description file with the upload date, even if the description does not exist. Default: true.")>
|
Description("Create a description file with the upload date, even if the description does not exist. Default: true.")>
|
||||||
Public ReadOnly Property CreateDescriptionFiles_CreateWithNoDescription As XMLValue(Of Boolean)
|
Public ReadOnly Property CreateDescriptionFiles_CreateWithNoDescription As XMLValue(Of Boolean)
|
||||||
@@ -517,6 +515,7 @@ Namespace API.YouTube.Base
|
|||||||
XML.LoadData(EDP.None)
|
XML.LoadData(EDP.None)
|
||||||
DesignXml = New XmlFile("Settings\DesignDownloader.xml", Protector.Modes.All, False)
|
DesignXml = New XmlFile("Settings\DesignDownloader.xml", Protector.Modes.All, False)
|
||||||
DesignXml.LoadData(EDP.None)
|
DesignXml.LoadData(EDP.None)
|
||||||
|
FILTER = New Controls.YTDataFilter
|
||||||
InitializeXMLValueProperties(Me)
|
InitializeXMLValueProperties(Me)
|
||||||
AddHandler ShowNotificationsEveryDownload.TempValueChanged, AddressOf ShowNotificationsEveryDownload_TempValueChanged
|
AddHandler ShowNotificationsEveryDownload.TempValueChanged, AddressOf ShowNotificationsEveryDownload_TempValueChanged
|
||||||
Cookies = New CookieKeeper
|
Cookies = New CookieKeeper
|
||||||
|
|||||||
324
SCrawler.YouTube/Controls/FilterForm.Designer.vb
generated
Normal file
@@ -0,0 +1,324 @@
|
|||||||
|
' Copyright (C) Andy https://github.com/AAndyProgram
|
||||||
|
' This program is free software: you can redistribute it and/or modify
|
||||||
|
' it under the terms of the GNU General Public License as published by
|
||||||
|
' the Free Software Foundation, either version 3 of the License, or
|
||||||
|
' (at your option) any later version.
|
||||||
|
'
|
||||||
|
' This program is distributed in the hope that it will be useful,
|
||||||
|
' but WITHOUT ANY WARRANTY
|
||||||
|
Namespace API.YouTube.Controls
|
||||||
|
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
|
||||||
|
Partial Friend Class FilterForm : Inherits System.Windows.Forms.Form
|
||||||
|
<System.Diagnostics.DebuggerNonUserCode()>
|
||||||
|
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
|
||||||
|
Try
|
||||||
|
If disposing AndAlso components IsNot Nothing Then
|
||||||
|
components.Dispose()
|
||||||
|
End If
|
||||||
|
Finally
|
||||||
|
MyBase.Dispose(disposing)
|
||||||
|
End Try
|
||||||
|
End Sub
|
||||||
|
Private components As System.ComponentModel.IContainer
|
||||||
|
<System.Diagnostics.DebuggerStepThrough()>
|
||||||
|
Private Sub InitializeComponent()
|
||||||
|
Dim CONTAINER_MAIN As System.Windows.Forms.ToolStripContainer
|
||||||
|
Dim TP_MAIN As System.Windows.Forms.TableLayoutPanel
|
||||||
|
Dim TP_TYPES As System.Windows.Forms.TableLayoutPanel
|
||||||
|
Dim TP_USERS As System.Windows.Forms.TableLayoutPanel
|
||||||
|
Dim TP_USERS_2 As System.Windows.Forms.TableLayoutPanel
|
||||||
|
Me.CH_FILTER_ALL = New System.Windows.Forms.CheckBox()
|
||||||
|
Me.CH_FILTER_SINGLE = New System.Windows.Forms.CheckBox()
|
||||||
|
Me.CH_FILTER_CHANNEL = New System.Windows.Forms.CheckBox()
|
||||||
|
Me.CH_FILTER_PLS = New System.Windows.Forms.CheckBox()
|
||||||
|
Me.TP_MUSIC = New System.Windows.Forms.TableLayoutPanel()
|
||||||
|
Me.CH_M_ALL = New System.Windows.Forms.CheckBox()
|
||||||
|
Me.CH_M_VIDEO = New System.Windows.Forms.CheckBox()
|
||||||
|
Me.CH_M_MUSIC = New System.Windows.Forms.CheckBox()
|
||||||
|
Me.LIST_USERS = New System.Windows.Forms.CheckedListBox()
|
||||||
|
Me.CH_USERS_USE = New System.Windows.Forms.CheckBox()
|
||||||
|
Me.BTT_SELECT_ALL = New System.Windows.Forms.Button()
|
||||||
|
Me.BTT_SELECT_NONE = New System.Windows.Forms.Button()
|
||||||
|
CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer()
|
||||||
|
TP_MAIN = New System.Windows.Forms.TableLayoutPanel()
|
||||||
|
TP_TYPES = New System.Windows.Forms.TableLayoutPanel()
|
||||||
|
TP_USERS = New System.Windows.Forms.TableLayoutPanel()
|
||||||
|
TP_USERS_2 = New System.Windows.Forms.TableLayoutPanel()
|
||||||
|
CONTAINER_MAIN.ContentPanel.SuspendLayout()
|
||||||
|
CONTAINER_MAIN.SuspendLayout()
|
||||||
|
TP_MAIN.SuspendLayout()
|
||||||
|
TP_TYPES.SuspendLayout()
|
||||||
|
Me.TP_MUSIC.SuspendLayout()
|
||||||
|
TP_USERS.SuspendLayout()
|
||||||
|
TP_USERS_2.SuspendLayout()
|
||||||
|
Me.SuspendLayout()
|
||||||
|
'
|
||||||
|
'CONTAINER_MAIN
|
||||||
|
'
|
||||||
|
'
|
||||||
|
'CONTAINER_MAIN.ContentPanel
|
||||||
|
'
|
||||||
|
CONTAINER_MAIN.ContentPanel.Controls.Add(TP_MAIN)
|
||||||
|
CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(384, 361)
|
||||||
|
CONTAINER_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
CONTAINER_MAIN.LeftToolStripPanelVisible = False
|
||||||
|
CONTAINER_MAIN.Location = New System.Drawing.Point(0, 0)
|
||||||
|
CONTAINER_MAIN.Name = "CONTAINER_MAIN"
|
||||||
|
CONTAINER_MAIN.RightToolStripPanelVisible = False
|
||||||
|
CONTAINER_MAIN.Size = New System.Drawing.Size(384, 361)
|
||||||
|
CONTAINER_MAIN.TabIndex = 0
|
||||||
|
CONTAINER_MAIN.TopToolStripPanelVisible = False
|
||||||
|
'
|
||||||
|
'TP_MAIN
|
||||||
|
'
|
||||||
|
TP_MAIN.ColumnCount = 1
|
||||||
|
TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
|
TP_MAIN.Controls.Add(TP_TYPES, 0, 0)
|
||||||
|
TP_MAIN.Controls.Add(Me.TP_MUSIC, 0, 1)
|
||||||
|
TP_MAIN.Controls.Add(TP_USERS, 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 = 3
|
||||||
|
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.Absolute, 20.0!))
|
||||||
|
TP_MAIN.Size = New System.Drawing.Size(384, 361)
|
||||||
|
TP_MAIN.TabIndex = 0
|
||||||
|
'
|
||||||
|
'TP_TYPES
|
||||||
|
'
|
||||||
|
TP_TYPES.ColumnCount = 4
|
||||||
|
TP_TYPES.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25.0!))
|
||||||
|
TP_TYPES.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25.0!))
|
||||||
|
TP_TYPES.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25.0!))
|
||||||
|
TP_TYPES.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25.0!))
|
||||||
|
TP_TYPES.Controls.Add(Me.CH_FILTER_ALL, 0, 0)
|
||||||
|
TP_TYPES.Controls.Add(Me.CH_FILTER_SINGLE, 1, 0)
|
||||||
|
TP_TYPES.Controls.Add(Me.CH_FILTER_CHANNEL, 2, 0)
|
||||||
|
TP_TYPES.Controls.Add(Me.CH_FILTER_PLS, 3, 0)
|
||||||
|
TP_TYPES.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
TP_TYPES.Location = New System.Drawing.Point(0, 0)
|
||||||
|
TP_TYPES.Margin = New System.Windows.Forms.Padding(0)
|
||||||
|
TP_TYPES.Name = "TP_TYPES"
|
||||||
|
TP_TYPES.RowCount = 1
|
||||||
|
TP_TYPES.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
|
TP_TYPES.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
|
||||||
|
TP_TYPES.Size = New System.Drawing.Size(384, 25)
|
||||||
|
TP_TYPES.TabIndex = 0
|
||||||
|
'
|
||||||
|
'CH_FILTER_ALL
|
||||||
|
'
|
||||||
|
Me.CH_FILTER_ALL.AutoSize = True
|
||||||
|
Me.CH_FILTER_ALL.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.CH_FILTER_ALL.Location = New System.Drawing.Point(3, 3)
|
||||||
|
Me.CH_FILTER_ALL.Name = "CH_FILTER_ALL"
|
||||||
|
Me.CH_FILTER_ALL.Size = New System.Drawing.Size(90, 19)
|
||||||
|
Me.CH_FILTER_ALL.TabIndex = 0
|
||||||
|
Me.CH_FILTER_ALL.Text = "ALL"
|
||||||
|
Me.CH_FILTER_ALL.UseVisualStyleBackColor = True
|
||||||
|
'
|
||||||
|
'CH_FILTER_SINGLE
|
||||||
|
'
|
||||||
|
Me.CH_FILTER_SINGLE.AutoSize = True
|
||||||
|
Me.CH_FILTER_SINGLE.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.CH_FILTER_SINGLE.Location = New System.Drawing.Point(99, 3)
|
||||||
|
Me.CH_FILTER_SINGLE.Name = "CH_FILTER_SINGLE"
|
||||||
|
Me.CH_FILTER_SINGLE.Size = New System.Drawing.Size(90, 19)
|
||||||
|
Me.CH_FILTER_SINGLE.TabIndex = 1
|
||||||
|
Me.CH_FILTER_SINGLE.Text = "Single"
|
||||||
|
Me.CH_FILTER_SINGLE.UseVisualStyleBackColor = True
|
||||||
|
'
|
||||||
|
'CH_FILTER_CHANNEL
|
||||||
|
'
|
||||||
|
Me.CH_FILTER_CHANNEL.AutoSize = True
|
||||||
|
Me.CH_FILTER_CHANNEL.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.CH_FILTER_CHANNEL.Location = New System.Drawing.Point(195, 3)
|
||||||
|
Me.CH_FILTER_CHANNEL.Name = "CH_FILTER_CHANNEL"
|
||||||
|
Me.CH_FILTER_CHANNEL.Size = New System.Drawing.Size(90, 19)
|
||||||
|
Me.CH_FILTER_CHANNEL.TabIndex = 2
|
||||||
|
Me.CH_FILTER_CHANNEL.Text = "Channel"
|
||||||
|
Me.CH_FILTER_CHANNEL.UseVisualStyleBackColor = True
|
||||||
|
'
|
||||||
|
'CH_FILTER_PLS
|
||||||
|
'
|
||||||
|
Me.CH_FILTER_PLS.AutoSize = True
|
||||||
|
Me.CH_FILTER_PLS.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.CH_FILTER_PLS.Location = New System.Drawing.Point(291, 3)
|
||||||
|
Me.CH_FILTER_PLS.Name = "CH_FILTER_PLS"
|
||||||
|
Me.CH_FILTER_PLS.Size = New System.Drawing.Size(90, 19)
|
||||||
|
Me.CH_FILTER_PLS.TabIndex = 3
|
||||||
|
Me.CH_FILTER_PLS.Text = "Playlist"
|
||||||
|
Me.CH_FILTER_PLS.UseVisualStyleBackColor = True
|
||||||
|
'
|
||||||
|
'TP_MUSIC
|
||||||
|
'
|
||||||
|
Me.TP_MUSIC.ColumnCount = 3
|
||||||
|
Me.TP_MUSIC.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333!))
|
||||||
|
Me.TP_MUSIC.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333!))
|
||||||
|
Me.TP_MUSIC.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333!))
|
||||||
|
Me.TP_MUSIC.Controls.Add(Me.CH_M_ALL, 0, 0)
|
||||||
|
Me.TP_MUSIC.Controls.Add(Me.CH_M_VIDEO, 1, 0)
|
||||||
|
Me.TP_MUSIC.Controls.Add(Me.CH_M_MUSIC, 2, 0)
|
||||||
|
Me.TP_MUSIC.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.TP_MUSIC.Location = New System.Drawing.Point(0, 25)
|
||||||
|
Me.TP_MUSIC.Margin = New System.Windows.Forms.Padding(0)
|
||||||
|
Me.TP_MUSIC.Name = "TP_MUSIC"
|
||||||
|
Me.TP_MUSIC.RowCount = 1
|
||||||
|
Me.TP_MUSIC.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
|
Me.TP_MUSIC.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
|
||||||
|
Me.TP_MUSIC.Size = New System.Drawing.Size(384, 25)
|
||||||
|
Me.TP_MUSIC.TabIndex = 1
|
||||||
|
'
|
||||||
|
'CH_M_ALL
|
||||||
|
'
|
||||||
|
Me.CH_M_ALL.AutoSize = True
|
||||||
|
Me.CH_M_ALL.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.CH_M_ALL.Location = New System.Drawing.Point(3, 3)
|
||||||
|
Me.CH_M_ALL.Name = "CH_M_ALL"
|
||||||
|
Me.CH_M_ALL.Size = New System.Drawing.Size(122, 19)
|
||||||
|
Me.CH_M_ALL.TabIndex = 0
|
||||||
|
Me.CH_M_ALL.Text = "ALL"
|
||||||
|
Me.CH_M_ALL.UseVisualStyleBackColor = True
|
||||||
|
'
|
||||||
|
'CH_M_VIDEO
|
||||||
|
'
|
||||||
|
Me.CH_M_VIDEO.AutoSize = True
|
||||||
|
Me.CH_M_VIDEO.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.CH_M_VIDEO.Location = New System.Drawing.Point(131, 3)
|
||||||
|
Me.CH_M_VIDEO.Name = "CH_M_VIDEO"
|
||||||
|
Me.CH_M_VIDEO.Size = New System.Drawing.Size(122, 19)
|
||||||
|
Me.CH_M_VIDEO.TabIndex = 1
|
||||||
|
Me.CH_M_VIDEO.Text = "Video"
|
||||||
|
Me.CH_M_VIDEO.UseVisualStyleBackColor = True
|
||||||
|
'
|
||||||
|
'CH_M_MUSIC
|
||||||
|
'
|
||||||
|
Me.CH_M_MUSIC.AutoSize = True
|
||||||
|
Me.CH_M_MUSIC.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.CH_M_MUSIC.Location = New System.Drawing.Point(259, 3)
|
||||||
|
Me.CH_M_MUSIC.Name = "CH_M_MUSIC"
|
||||||
|
Me.CH_M_MUSIC.Size = New System.Drawing.Size(122, 19)
|
||||||
|
Me.CH_M_MUSIC.TabIndex = 2
|
||||||
|
Me.CH_M_MUSIC.Text = "Music"
|
||||||
|
Me.CH_M_MUSIC.UseVisualStyleBackColor = True
|
||||||
|
'
|
||||||
|
'TP_USERS
|
||||||
|
'
|
||||||
|
TP_USERS.ColumnCount = 1
|
||||||
|
TP_USERS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
|
TP_USERS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20.0!))
|
||||||
|
TP_USERS.Controls.Add(Me.LIST_USERS, 0, 1)
|
||||||
|
TP_USERS.Controls.Add(TP_USERS_2, 0, 0)
|
||||||
|
TP_USERS.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
TP_USERS.Location = New System.Drawing.Point(0, 50)
|
||||||
|
TP_USERS.Margin = New System.Windows.Forms.Padding(0)
|
||||||
|
TP_USERS.Name = "TP_USERS"
|
||||||
|
TP_USERS.RowCount = 2
|
||||||
|
TP_USERS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
|
||||||
|
TP_USERS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
|
TP_USERS.Size = New System.Drawing.Size(384, 311)
|
||||||
|
TP_USERS.TabIndex = 3
|
||||||
|
'
|
||||||
|
'LIST_USERS
|
||||||
|
'
|
||||||
|
Me.LIST_USERS.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.LIST_USERS.FormattingEnabled = True
|
||||||
|
Me.LIST_USERS.Location = New System.Drawing.Point(3, 28)
|
||||||
|
Me.LIST_USERS.Name = "LIST_USERS"
|
||||||
|
Me.LIST_USERS.Size = New System.Drawing.Size(378, 280)
|
||||||
|
Me.LIST_USERS.TabIndex = 1
|
||||||
|
'
|
||||||
|
'TP_USERS_2
|
||||||
|
'
|
||||||
|
TP_USERS_2.ColumnCount = 3
|
||||||
|
TP_USERS_2.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333!))
|
||||||
|
TP_USERS_2.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333!))
|
||||||
|
TP_USERS_2.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333!))
|
||||||
|
TP_USERS_2.Controls.Add(Me.CH_USERS_USE, 0, 0)
|
||||||
|
TP_USERS_2.Controls.Add(Me.BTT_SELECT_ALL, 1, 0)
|
||||||
|
TP_USERS_2.Controls.Add(Me.BTT_SELECT_NONE, 2, 0)
|
||||||
|
TP_USERS_2.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
TP_USERS_2.Location = New System.Drawing.Point(0, 0)
|
||||||
|
TP_USERS_2.Margin = New System.Windows.Forms.Padding(0)
|
||||||
|
TP_USERS_2.Name = "TP_USERS_2"
|
||||||
|
TP_USERS_2.RowCount = 1
|
||||||
|
TP_USERS_2.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
|
TP_USERS_2.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
|
||||||
|
TP_USERS_2.Size = New System.Drawing.Size(384, 25)
|
||||||
|
TP_USERS_2.TabIndex = 0
|
||||||
|
'
|
||||||
|
'CH_USERS_USE
|
||||||
|
'
|
||||||
|
Me.CH_USERS_USE.AutoSize = True
|
||||||
|
Me.CH_USERS_USE.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.CH_USERS_USE.Location = New System.Drawing.Point(3, 3)
|
||||||
|
Me.CH_USERS_USE.Name = "CH_USERS_USE"
|
||||||
|
Me.CH_USERS_USE.Size = New System.Drawing.Size(122, 19)
|
||||||
|
Me.CH_USERS_USE.TabIndex = 0
|
||||||
|
Me.CH_USERS_USE.Text = "Filter users"
|
||||||
|
Me.CH_USERS_USE.UseVisualStyleBackColor = True
|
||||||
|
'
|
||||||
|
'BTT_SELECT_ALL
|
||||||
|
'
|
||||||
|
Me.BTT_SELECT_ALL.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.BTT_SELECT_ALL.Location = New System.Drawing.Point(129, 1)
|
||||||
|
Me.BTT_SELECT_ALL.Margin = New System.Windows.Forms.Padding(1)
|
||||||
|
Me.BTT_SELECT_ALL.Name = "BTT_SELECT_ALL"
|
||||||
|
Me.BTT_SELECT_ALL.Size = New System.Drawing.Size(126, 23)
|
||||||
|
Me.BTT_SELECT_ALL.TabIndex = 1
|
||||||
|
Me.BTT_SELECT_ALL.Text = "All"
|
||||||
|
Me.BTT_SELECT_ALL.UseVisualStyleBackColor = True
|
||||||
|
'
|
||||||
|
'BTT_SELECT_NONE
|
||||||
|
'
|
||||||
|
Me.BTT_SELECT_NONE.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.BTT_SELECT_NONE.Location = New System.Drawing.Point(257, 1)
|
||||||
|
Me.BTT_SELECT_NONE.Margin = New System.Windows.Forms.Padding(1)
|
||||||
|
Me.BTT_SELECT_NONE.Name = "BTT_SELECT_NONE"
|
||||||
|
Me.BTT_SELECT_NONE.Size = New System.Drawing.Size(126, 23)
|
||||||
|
Me.BTT_SELECT_NONE.TabIndex = 2
|
||||||
|
Me.BTT_SELECT_NONE.Text = "None"
|
||||||
|
Me.BTT_SELECT_NONE.UseVisualStyleBackColor = True
|
||||||
|
'
|
||||||
|
'FilterForm
|
||||||
|
'
|
||||||
|
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
|
||||||
|
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
|
||||||
|
Me.ClientSize = New System.Drawing.Size(384, 361)
|
||||||
|
Me.Controls.Add(CONTAINER_MAIN)
|
||||||
|
Me.MinimizeBox = False
|
||||||
|
Me.MinimumSize = New System.Drawing.Size(400, 400)
|
||||||
|
Me.Name = "FilterForm"
|
||||||
|
Me.ShowInTaskbar = False
|
||||||
|
Me.Text = "Filter"
|
||||||
|
CONTAINER_MAIN.ContentPanel.ResumeLayout(False)
|
||||||
|
CONTAINER_MAIN.ResumeLayout(False)
|
||||||
|
CONTAINER_MAIN.PerformLayout()
|
||||||
|
TP_MAIN.ResumeLayout(False)
|
||||||
|
TP_TYPES.ResumeLayout(False)
|
||||||
|
TP_TYPES.PerformLayout()
|
||||||
|
Me.TP_MUSIC.ResumeLayout(False)
|
||||||
|
Me.TP_MUSIC.PerformLayout()
|
||||||
|
TP_USERS.ResumeLayout(False)
|
||||||
|
TP_USERS_2.ResumeLayout(False)
|
||||||
|
TP_USERS_2.PerformLayout()
|
||||||
|
Me.ResumeLayout(False)
|
||||||
|
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Private WithEvents CH_FILTER_ALL As CheckBox
|
||||||
|
Private WithEvents CH_FILTER_SINGLE As CheckBox
|
||||||
|
Private WithEvents CH_FILTER_CHANNEL As CheckBox
|
||||||
|
Private WithEvents CH_FILTER_PLS As CheckBox
|
||||||
|
Private WithEvents TP_MUSIC As TableLayoutPanel
|
||||||
|
Private WithEvents CH_M_ALL As CheckBox
|
||||||
|
Private WithEvents CH_M_VIDEO As CheckBox
|
||||||
|
Private WithEvents CH_M_MUSIC As CheckBox
|
||||||
|
Private WithEvents LIST_USERS As CheckedListBox
|
||||||
|
Private WithEvents CH_USERS_USE As CheckBox
|
||||||
|
Private WithEvents BTT_SELECT_ALL As Button
|
||||||
|
Private WithEvents BTT_SELECT_NONE As Button
|
||||||
|
End Class
|
||||||
|
End Namespace
|
||||||
135
SCrawler.YouTube/Controls/FilterForm.resx
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<metadata name="CONTAINER_MAIN.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</metadata>
|
||||||
|
<metadata name="TP_MAIN.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</metadata>
|
||||||
|
<metadata name="TP_TYPES.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</metadata>
|
||||||
|
<metadata name="TP_USERS.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</metadata>
|
||||||
|
<metadata name="TP_USERS_2.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</metadata>
|
||||||
|
</root>
|
||||||
181
SCrawler.YouTube/Controls/FilterForm.vb
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
' Copyright (C) Andy https://github.com/AAndyProgram
|
||||||
|
' This program is free software: you can redistribute it and/or modify
|
||||||
|
' it under the terms of the GNU General Public License as published by
|
||||||
|
' the Free Software Foundation, either version 3 of the License, or
|
||||||
|
' (at your option) any later version.
|
||||||
|
'
|
||||||
|
' This program is distributed in the hope that it will be useful,
|
||||||
|
' but WITHOUT ANY WARRANTY
|
||||||
|
Imports SCrawler.API.YouTube.Base
|
||||||
|
Imports SCrawler.API.YouTube.Objects
|
||||||
|
Imports PersonalUtilities.Forms
|
||||||
|
Imports SimpleUser = SCrawler.API.YouTube.Controls.YTDataFilter.SimpleUser
|
||||||
|
Namespace API.YouTube.Controls
|
||||||
|
Friend Class FilterForm
|
||||||
|
Private WithEvents MyDefs As DefaultFormOptions
|
||||||
|
Friend ReadOnly Property DATA As List(Of IYouTubeMediaContainer)
|
||||||
|
Private ReadOnly Property DataTMP As List(Of IYouTubeMediaContainer)
|
||||||
|
Private ReadOnly Property MyFilterTmp As YTDataFilter
|
||||||
|
Private ReadOnly Property MyTmpUsers As List(Of SimpleUser)
|
||||||
|
Friend Sub New(ByVal d As IEnumerable(Of IYouTubeMediaContainer))
|
||||||
|
InitializeComponent()
|
||||||
|
MyDefs = New DefaultFormOptions(Me, MyYouTubeSettings.DesignXml)
|
||||||
|
DATA = New List(Of IYouTubeMediaContainer)
|
||||||
|
DATA.ListAddList(d)
|
||||||
|
DataTMP = New List(Of IYouTubeMediaContainer)
|
||||||
|
DataTMP.ListAddList(d)
|
||||||
|
MyFilterTmp = New YTDataFilter(MyYouTubeSettings.FILTER)
|
||||||
|
MyTmpUsers = New List(Of SimpleUser)
|
||||||
|
Icon = My.Resources.FilterIcon
|
||||||
|
End Sub
|
||||||
|
Private Sub FilterForm_Load(sender As Object, e As EventArgs) Handles Me.Load
|
||||||
|
Try
|
||||||
|
With MyDefs
|
||||||
|
.MyViewInitialize()
|
||||||
|
.AddOkCancelToolbar(True)
|
||||||
|
|
||||||
|
With MyYouTubeSettings.FILTER
|
||||||
|
With .Types
|
||||||
|
If .Count = 0 Or (.Count = 1 AndAlso .Item(0) = YouTubeMediaType.Undefined) Then
|
||||||
|
CH_FILTER_ALL.Checked = True
|
||||||
|
Else
|
||||||
|
If .Contains(YouTubeMediaType.Single) Then CH_FILTER_SINGLE.Checked = True
|
||||||
|
If .Contains(YouTubeMediaType.Channel) Then CH_FILTER_CHANNEL.Checked = True
|
||||||
|
If .Contains(YouTubeMediaType.PlayList) Then CH_FILTER_PLS.Checked = True
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
If .IsMusic And .IsVideo Then
|
||||||
|
CH_M_ALL.Checked = True
|
||||||
|
Else
|
||||||
|
CH_M_MUSIC.Checked = .IsMusic
|
||||||
|
CH_M_VIDEO.Checked = .IsVideo
|
||||||
|
End If
|
||||||
|
|
||||||
|
CH_USERS_USE.Checked = .UserList.Count > 0
|
||||||
|
End With
|
||||||
|
|
||||||
|
.EndLoaderOperations()
|
||||||
|
_RefillEnabled = True
|
||||||
|
RefillList(True)
|
||||||
|
CH_USERS_USE_CheckedChanged()
|
||||||
|
End With
|
||||||
|
Catch ex As Exception
|
||||||
|
MyDefs.InvokeLoaderError(ex)
|
||||||
|
End Try
|
||||||
|
End Sub
|
||||||
|
Private Sub FilterForm_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed
|
||||||
|
DATA.ListClearDispose
|
||||||
|
DataTMP.ListClearDispose
|
||||||
|
MyTmpUsers.ListClearDispose
|
||||||
|
End Sub
|
||||||
|
Private _RefillEnabled As Boolean = False
|
||||||
|
Private Sub RefillList(Optional ByVal Init As Boolean = False)
|
||||||
|
If Not MyDefs.Initializing And _RefillEnabled Then
|
||||||
|
ApplyFilter(MyFilterTmp, Init)
|
||||||
|
MyFilterTmp.Populate(DATA, DataTMP, CH_USERS_USE.Checked)
|
||||||
|
With DataTMP
|
||||||
|
If .Count > 0 Then
|
||||||
|
Dim tmpUsers As New List(Of SimpleUser)
|
||||||
|
tmpUsers.ListAddList(DataTMP, LAP.NotContainsOnly, CType(Function(obj As YouTubeMediaContainerBase) CType(obj, SimpleUser), Func(Of Object, Object)))
|
||||||
|
If tmpUsers.Count > 0 Then
|
||||||
|
tmpUsers.Sort()
|
||||||
|
LIST_USERS.BeginUpdate()
|
||||||
|
LIST_USERS.Items.Clear()
|
||||||
|
tmpUsers.ForEach(Sub(u) LIST_USERS.Items.Add(u, True))
|
||||||
|
|
||||||
|
If CH_USERS_USE.Checked And MyFilterTmp.UserList.Count > 0 Then
|
||||||
|
For i% = 0 To LIST_USERS.Items.Count - 1
|
||||||
|
LIST_USERS.SetItemChecked(i, MyFilterTmp.UserList.Contains(LIST_USERS.Items(i)))
|
||||||
|
Next
|
||||||
|
End If
|
||||||
|
|
||||||
|
LIST_USERS.EndUpdate()
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
End If
|
||||||
|
End Sub
|
||||||
|
Private Sub ApplyFilter(ByRef Filter As YTDataFilter, ByVal Init As Boolean)
|
||||||
|
With Filter
|
||||||
|
.Reset(False, Not Init)
|
||||||
|
With .Types
|
||||||
|
If CH_FILTER_ALL.Checked Then
|
||||||
|
.Add(YouTubeMediaType.Undefined)
|
||||||
|
Else
|
||||||
|
If CH_FILTER_SINGLE.Checked Then .Add(YouTubeMediaType.Single)
|
||||||
|
If CH_FILTER_CHANNEL.Checked Then .Add(YouTubeMediaType.Channel)
|
||||||
|
If CH_FILTER_PLS.Checked Then .Add(YouTubeMediaType.PlayList)
|
||||||
|
End If
|
||||||
|
If .Count = 0 Then .Add(YouTubeMediaType.Undefined)
|
||||||
|
End With
|
||||||
|
If CH_M_ALL.Checked Then
|
||||||
|
.IsMusic = True
|
||||||
|
.IsVideo = True
|
||||||
|
Else
|
||||||
|
If CH_M_MUSIC.Checked Then .IsMusic = True
|
||||||
|
If CH_M_VIDEO.Checked Then .IsVideo = True
|
||||||
|
End If
|
||||||
|
If Not .IsVideo And Not .IsMusic Then .IsMusic = True : .IsVideo = True
|
||||||
|
|
||||||
|
If CH_USERS_USE.Checked And Not Init Then
|
||||||
|
.UserList.Clear()
|
||||||
|
If LIST_USERS.CheckedItems.Count > 0 Then
|
||||||
|
For Each item In LIST_USERS.CheckedItems : .UserList.Add(item) : Next
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
End Sub
|
||||||
|
Private Sub MyDefs_ButtonOkClick(ByVal Sender As Object, ByVal e As KeyHandleEventArgs) Handles MyDefs.ButtonOkClick
|
||||||
|
ApplyFilter(MyYouTubeSettings.FILTER, False)
|
||||||
|
MyYouTubeSettings.FILTER.RemoveAll(DATA)
|
||||||
|
MyYouTubeSettings.FILTER.Update()
|
||||||
|
MyDefs.CloseForm()
|
||||||
|
End Sub
|
||||||
|
Private Sub MyDefs_ButtonDeleteClickOC(ByVal Sender As Object, ByVal e As KeyHandleEventArgs) Handles MyDefs.ButtonDeleteClickOC
|
||||||
|
With MyYouTubeSettings.FILTER : .Reset() : .Update() : End With
|
||||||
|
MyDefs.CloseForm()
|
||||||
|
End Sub
|
||||||
|
Private Sub UpdateControlOptions(ByRef CNT As CheckBox, ByVal v As Boolean)
|
||||||
|
If v Then CNT.Checked = True
|
||||||
|
CNT.Enabled = Not v
|
||||||
|
End Sub
|
||||||
|
Private Sub CH_FILTER_ALL_CheckedChanged(sender As Object, e As EventArgs) Handles CH_FILTER_ALL.CheckedChanged
|
||||||
|
_RefillEnabled = False
|
||||||
|
Dim v As Boolean = CH_FILTER_ALL.Checked
|
||||||
|
UpdateControlOptions(CH_FILTER_SINGLE, v)
|
||||||
|
UpdateControlOptions(CH_FILTER_CHANNEL, v)
|
||||||
|
UpdateControlOptions(CH_FILTER_PLS, v)
|
||||||
|
_RefillEnabled = True
|
||||||
|
RefillList()
|
||||||
|
End Sub
|
||||||
|
Private Sub CH_FILTER_SINGLE_CHANNEL_PLS_CheckedChanged(sender As Object, e As EventArgs) Handles CH_FILTER_SINGLE.CheckedChanged,
|
||||||
|
CH_FILTER_CHANNEL.CheckedChanged,
|
||||||
|
CH_FILTER_PLS.CheckedChanged
|
||||||
|
RefillList()
|
||||||
|
End Sub
|
||||||
|
Private Sub CH_M_ALL_CheckedChanged(sender As Object, e As EventArgs) Handles CH_M_ALL.CheckedChanged
|
||||||
|
_RefillEnabled = False
|
||||||
|
Dim v As Boolean = CH_M_ALL.Checked
|
||||||
|
UpdateControlOptions(CH_M_VIDEO, v)
|
||||||
|
UpdateControlOptions(CH_M_MUSIC, v)
|
||||||
|
_RefillEnabled = True
|
||||||
|
RefillList()
|
||||||
|
End Sub
|
||||||
|
Private Sub CH_M_VIDEO_MUSIC_CheckedChanged(sender As Object, e As EventArgs) Handles CH_M_VIDEO.CheckedChanged, CH_M_MUSIC.CheckedChanged
|
||||||
|
RefillList()
|
||||||
|
End Sub
|
||||||
|
Private Sub CH_USERS_USE_CheckedChanged() Handles CH_USERS_USE.CheckedChanged
|
||||||
|
LIST_USERS.Enabled = CH_USERS_USE.Checked
|
||||||
|
BTT_SELECT_ALL.Enabled = CH_USERS_USE.Checked
|
||||||
|
BTT_SELECT_NONE.Enabled = CH_USERS_USE.Checked
|
||||||
|
End Sub
|
||||||
|
Private Sub BTT_SELECT_ALL_NONE_Click(sender As Object, e As EventArgs) Handles BTT_SELECT_ALL.Click, BTT_SELECT_NONE.Click
|
||||||
|
Dim checked As Boolean = sender Is BTT_SELECT_ALL
|
||||||
|
With LIST_USERS
|
||||||
|
If .Items.Count > 0 Then
|
||||||
|
For i% = 0 To .Items.Count - 1 : .SetItemChecked(i, checked) : Next
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
End Sub
|
||||||
|
End Class
|
||||||
|
End Namespace
|
||||||
@@ -155,7 +155,7 @@ Namespace API.YouTube.Controls
|
|||||||
With DirectCast(MyContainer, YouTubeMediaContainerBase)
|
With DirectCast(MyContainer, YouTubeMediaContainerBase)
|
||||||
Select Case Sender.DefaultButton
|
Select Case Sender.DefaultButton
|
||||||
Case ADB.Open
|
Case ADB.Open
|
||||||
Using f As New SimpleListForm(Of String)(IIf(isLyrics, AvailableSubtitlesFormats, AvailableAudioFormats)) With {
|
Using f As New SimpleListForm(Of String)(If(isLyrics, AvailableSubtitlesFormats, AvailableAudioFormats)) With {
|
||||||
.DesignXML = DesignXML,
|
.DesignXML = DesignXML,
|
||||||
.DesignXMLNodeName = SimpleArraysFormNode,
|
.DesignXMLNodeName = SimpleArraysFormNode,
|
||||||
.FormText = DirectCast(e.AssociatedControl, TextBoxExtended).CaptionText,
|
.FormText = DirectCast(e.AssociatedControl, TextBoxExtended).CaptionText,
|
||||||
|
|||||||
@@ -121,9 +121,10 @@ Namespace API.YouTube.Controls
|
|||||||
Me.TXT_LIMIT.Location = New System.Drawing.Point(3, 3)
|
Me.TXT_LIMIT.Location = New System.Drawing.Point(3, 3)
|
||||||
Me.TXT_LIMIT.Name = "TXT_LIMIT"
|
Me.TXT_LIMIT.Name = "TXT_LIMIT"
|
||||||
Me.TXT_LIMIT.PlaceholderEnabled = True
|
Me.TXT_LIMIT.PlaceholderEnabled = True
|
||||||
Me.TXT_LIMIT.PlaceholderText = "e.g. ABCDE"
|
Me.TXT_LIMIT.PlaceholderText = "e.g. RDAMP"
|
||||||
Me.TXT_LIMIT.Size = New System.Drawing.Size(378, 22)
|
Me.TXT_LIMIT.Size = New System.Drawing.Size(378, 22)
|
||||||
Me.TXT_LIMIT.TabIndex = 2
|
Me.TXT_LIMIT.TabIndex = 2
|
||||||
|
Me.TXT_LIMIT.Text = "RDAMP"
|
||||||
'
|
'
|
||||||
'CONTAINER_MAIN
|
'CONTAINER_MAIN
|
||||||
'
|
'
|
||||||
|
|||||||
122
SCrawler.YouTube/Controls/YTDataFilter.vb
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
' Copyright (C) Andy https://github.com/AAndyProgram
|
||||||
|
' This program is free software: you can redistribute it and/or modify
|
||||||
|
' it under the terms of the GNU General Public License as published by
|
||||||
|
' the Free Software Foundation, either version 3 of the License, or
|
||||||
|
' (at your option) any later version.
|
||||||
|
'
|
||||||
|
' This program is distributed in the hope that it will be useful,
|
||||||
|
' but WITHOUT ANY WARRANTY
|
||||||
|
Imports SCrawler.API.YouTube.Base
|
||||||
|
Imports SCrawler.API.YouTube.Objects
|
||||||
|
Imports PersonalUtilities.Functions.XML
|
||||||
|
Imports PersonalUtilities.Functions.XML.Base
|
||||||
|
Namespace API.YouTube.Controls
|
||||||
|
Friend Class YTDataFilter
|
||||||
|
Private Const Name_Types As String = "Types"
|
||||||
|
Private Const Name_IsMusic As String = "IsMusic"
|
||||||
|
Private Const Name_IsVideo As String = "IsVideo"
|
||||||
|
Private Const Name_UserList As String = "UserList"
|
||||||
|
Friend Structure SimpleUser : Implements IEContainerProvider, IComparable(Of SimpleUser)
|
||||||
|
Private Const Name_UID As String = "UID"
|
||||||
|
Friend Title As String
|
||||||
|
Friend ID As String
|
||||||
|
Friend Sub New(ByVal _Title As String, ByVal _ID As String)
|
||||||
|
Title = _Title
|
||||||
|
ID = _ID
|
||||||
|
End Sub
|
||||||
|
Private Sub New(ByVal u As YouTubeMediaContainerBase)
|
||||||
|
Title = u.Title
|
||||||
|
ID = u.ID
|
||||||
|
End Sub
|
||||||
|
Public Shared Widening Operator CType(ByVal u As YouTubeMediaContainerBase) As SimpleUser
|
||||||
|
Return New SimpleUser(u.UserTitle, u.UserID)
|
||||||
|
End Operator
|
||||||
|
Public Shared Widening Operator CType(ByVal e As EContainer) As SimpleUser
|
||||||
|
Return New SimpleUser(e.Value, e.Attribute(Name_UID).Value)
|
||||||
|
End Operator
|
||||||
|
Public Overrides Function ToString() As String
|
||||||
|
Return String.Format(CStr(Interaction.Switch(Title.IsEmptyString, "{1}", ID.IsEmptyString, "{0}", True, "{0} ({1})")), Title, ID)
|
||||||
|
End Function
|
||||||
|
Public Overrides Function Equals(ByVal Obj As Object) As Boolean
|
||||||
|
Return Not IsDBNull(Obj) AndAlso ToString() = DirectCast(Obj, SimpleUser).ToString
|
||||||
|
End Function
|
||||||
|
Private Function CompareTo(ByVal Other As SimpleUser) As Integer Implements IComparable(Of SimpleUser).CompareTo
|
||||||
|
Return ToString.CompareTo(Other.ToString)
|
||||||
|
End Function
|
||||||
|
Private Function ToEContainer(Optional ByVal e As ErrorsDescriber = Nothing) As EContainer Implements IEContainerProvider.ToEContainer
|
||||||
|
Return New EContainer("User", Title, {New EAttribute(Name_UID, ID)})
|
||||||
|
End Function
|
||||||
|
End Structure
|
||||||
|
Friend ReadOnly Property Types As List(Of YouTubeMediaType)
|
||||||
|
Friend Property IsMusic As Boolean = True
|
||||||
|
Friend Property IsVideo As Boolean = True
|
||||||
|
Friend ReadOnly Property UserList As List(Of SimpleUser)
|
||||||
|
Private ReadOnly File As New SFile("Settings\YouTubeFilter.xml")
|
||||||
|
Friend Sub New(Optional ByVal LoadFromFile As Boolean = True)
|
||||||
|
Types = New List(Of YouTubeMediaType) From {YouTubeMediaType.Undefined}
|
||||||
|
UserList = New List(Of SimpleUser)
|
||||||
|
If LoadFromFile AndAlso File.Exists Then
|
||||||
|
Using e As New XmlFile(File, Protector.Modes.All, False) With {.AllowSameNames = True}
|
||||||
|
e.LoadData()
|
||||||
|
If e.Count > 0 Then
|
||||||
|
Types.Clear()
|
||||||
|
Types.ListAddList(e.Value(Name_Types).StringToList(Of Integer)(","), LAP.NotContainsOnly)
|
||||||
|
IsMusic = e.Value(Name_IsMusic).FromXML(Of Boolean)(True)
|
||||||
|
IsVideo = e.Value(Name_IsVideo).FromXML(Of Boolean)(True)
|
||||||
|
UserList.ListAddList(e(Name_UserList), LAP.IgnoreICopier)
|
||||||
|
End If
|
||||||
|
End Using
|
||||||
|
End If
|
||||||
|
End Sub
|
||||||
|
Friend Sub New(ByVal f As YTDataFilter)
|
||||||
|
Me.New(False)
|
||||||
|
With f
|
||||||
|
Types.ListAddList(.Types, LAP.NotContainsOnly)
|
||||||
|
IsMusic = .IsMusic
|
||||||
|
IsVideo = .IsVideo
|
||||||
|
UserList.ListAddList(.UserList)
|
||||||
|
End With
|
||||||
|
End Sub
|
||||||
|
Friend Sub Reset(Optional ByVal AddDefType As Boolean = True, Optional ByVal ClearUserList As Boolean = True)
|
||||||
|
Types.Clear()
|
||||||
|
If AddDefType Then Types.Add(YouTubeMediaType.Undefined)
|
||||||
|
IsMusic = True
|
||||||
|
IsVideo = True
|
||||||
|
If ClearUserList Then UserList.Clear()
|
||||||
|
End Sub
|
||||||
|
Friend Sub Update()
|
||||||
|
Using x As New XmlFile With {.AllowSameNames = True}
|
||||||
|
With x
|
||||||
|
.Add(Name_Types, Types.ListToStringE(","))
|
||||||
|
.Add(Name_IsMusic, IsMusic.BoolToInteger)
|
||||||
|
.Add(Name_IsVideo, IsVideo.BoolToInteger)
|
||||||
|
.Add(Name_UserList, String.Empty)
|
||||||
|
.Self()(Name_UserList).AddRange(UserList)
|
||||||
|
.Name = "FILTER"
|
||||||
|
.Save(File)
|
||||||
|
End With
|
||||||
|
End Using
|
||||||
|
End Sub
|
||||||
|
Friend Function Ready(ByVal Item As YouTubeMediaContainerBase, Optional ByVal IgnoreUserList As Boolean = False) As Boolean
|
||||||
|
With Item
|
||||||
|
If Not IsMusic Or Not IsVideo Then
|
||||||
|
If .IsMusic And Not IsMusic Then Return False
|
||||||
|
If Not .IsMusic And Not IsVideo Then Return False
|
||||||
|
End If
|
||||||
|
If Not Types.Contains(YouTubeMediaType.Undefined) AndAlso Not Types.Contains(.ObjectType) Then Return False
|
||||||
|
If Not IgnoreUserList AndAlso UserList.Count > 0 AndAlso Not UserList.Contains(Item) Then Return False
|
||||||
|
End With
|
||||||
|
Return True
|
||||||
|
End Function
|
||||||
|
Friend Overloads Sub RemoveAll(ByRef Data As List(Of IYouTubeMediaContainer))
|
||||||
|
Data.RemoveAll(Function(item) Not Ready(item))
|
||||||
|
End Sub
|
||||||
|
Friend Overloads Sub RemoveAll(ByRef Data As List(Of YouTubeMediaContainerBase))
|
||||||
|
Data.RemoveAll(Function(item) Not Ready(item))
|
||||||
|
End Sub
|
||||||
|
Friend Sub Populate(ByVal InitList As List(Of IYouTubeMediaContainer), ByVal DestList As List(Of IYouTubeMediaContainer), ByVal IgnoreUserList As Boolean)
|
||||||
|
DestList.Clear()
|
||||||
|
If InitList.Count > 0 Then InitList.ForEach(Sub(item) If Ready(item, IgnoreUserList) Then DestList.ListAddValue(item))
|
||||||
|
End Sub
|
||||||
|
End Class
|
||||||
|
End Namespace
|
||||||
@@ -33,6 +33,7 @@ Namespace DownloadObjects.STDownloader
|
|||||||
Me.BTT_CLEAR_DONE = New System.Windows.Forms.ToolStripMenuItem()
|
Me.BTT_CLEAR_DONE = New System.Windows.Forms.ToolStripMenuItem()
|
||||||
Me.BTT_CLEAR_ALL = New System.Windows.Forms.ToolStripMenuItem()
|
Me.BTT_CLEAR_ALL = New System.Windows.Forms.ToolStripMenuItem()
|
||||||
Me.BTT_SELECT_ALL = New System.Windows.Forms.ToolStripMenuItem()
|
Me.BTT_SELECT_ALL = New System.Windows.Forms.ToolStripMenuItem()
|
||||||
|
Me.BTT_SELECT_NONE = New System.Windows.Forms.ToolStripMenuItem()
|
||||||
Me.TOOLBAR_BOTTOM = New System.Windows.Forms.StatusStrip()
|
Me.TOOLBAR_BOTTOM = New System.Windows.Forms.StatusStrip()
|
||||||
Me.PR_MAIN = New System.Windows.Forms.ToolStripProgressBar()
|
Me.PR_MAIN = New System.Windows.Forms.ToolStripProgressBar()
|
||||||
Me.LBL_INFO = New System.Windows.Forms.ToolStripStatusLabel()
|
Me.LBL_INFO = New System.Windows.Forms.ToolStripStatusLabel()
|
||||||
@@ -43,6 +44,7 @@ Namespace DownloadObjects.STDownloader
|
|||||||
Me.MENU_ADD = New System.Windows.Forms.ToolStripDropDownButton()
|
Me.MENU_ADD = New System.Windows.Forms.ToolStripDropDownButton()
|
||||||
Me.BTT_ADD = New PersonalUtilities.Forms.Controls.KeyClick.ToolStripMenuItemKeyClick()
|
Me.BTT_ADD = New PersonalUtilities.Forms.Controls.KeyClick.ToolStripMenuItemKeyClick()
|
||||||
Me.BTT_ADD_PLS_ARR = New PersonalUtilities.Forms.Controls.KeyClick.ToolStripMenuItemKeyClick()
|
Me.BTT_ADD_PLS_ARR = New PersonalUtilities.Forms.Controls.KeyClick.ToolStripMenuItemKeyClick()
|
||||||
|
Me.BTT_FILTER = New System.Windows.Forms.ToolStripButton()
|
||||||
Me.BTT_DOWN = New System.Windows.Forms.ToolStripButton()
|
Me.BTT_DOWN = New System.Windows.Forms.ToolStripButton()
|
||||||
Me.BTT_STOP = New System.Windows.Forms.ToolStripButton()
|
Me.BTT_STOP = New System.Windows.Forms.ToolStripButton()
|
||||||
Me.SEP_LOG = New System.Windows.Forms.ToolStripSeparator()
|
Me.SEP_LOG = New System.Windows.Forms.ToolStripSeparator()
|
||||||
@@ -50,7 +52,7 @@ Namespace DownloadObjects.STDownloader
|
|||||||
Me.BTT_INFO = New System.Windows.Forms.ToolStripButton()
|
Me.BTT_INFO = New System.Windows.Forms.ToolStripButton()
|
||||||
Me.BTT_DONATE = New System.Windows.Forms.ToolStripButton()
|
Me.BTT_DONATE = New System.Windows.Forms.ToolStripButton()
|
||||||
Me.BTT_BUG_REPORT = New System.Windows.Forms.ToolStripButton()
|
Me.BTT_BUG_REPORT = New System.Windows.Forms.ToolStripButton()
|
||||||
Me.BTT_SELECT_NONE = New System.Windows.Forms.ToolStripMenuItem()
|
Me.SEP_FILTER = New System.Windows.Forms.ToolStripSeparator()
|
||||||
SEP_2 = New System.Windows.Forms.ToolStripSeparator()
|
SEP_2 = New System.Windows.Forms.ToolStripSeparator()
|
||||||
SEP_3 = New System.Windows.Forms.ToolStripSeparator()
|
SEP_3 = New System.Windows.Forms.ToolStripSeparator()
|
||||||
MENU_DEL_CLEAR = New System.Windows.Forms.ToolStripDropDownButton()
|
MENU_DEL_CLEAR = New System.Windows.Forms.ToolStripDropDownButton()
|
||||||
@@ -134,6 +136,12 @@ Namespace DownloadObjects.STDownloader
|
|||||||
Me.BTT_SELECT_ALL.Size = New System.Drawing.Size(185, 22)
|
Me.BTT_SELECT_ALL.Size = New System.Drawing.Size(185, 22)
|
||||||
Me.BTT_SELECT_ALL.Text = "Select all"
|
Me.BTT_SELECT_ALL.Text = "Select all"
|
||||||
'
|
'
|
||||||
|
'BTT_SELECT_NONE
|
||||||
|
'
|
||||||
|
Me.BTT_SELECT_NONE.Name = "BTT_SELECT_NONE"
|
||||||
|
Me.BTT_SELECT_NONE.Size = New System.Drawing.Size(185, 22)
|
||||||
|
Me.BTT_SELECT_NONE.Text = "Select none"
|
||||||
|
'
|
||||||
'TOOLBAR_BOTTOM
|
'TOOLBAR_BOTTOM
|
||||||
'
|
'
|
||||||
Me.TOOLBAR_BOTTOM.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.PR_MAIN, Me.LBL_INFO})
|
Me.TOOLBAR_BOTTOM.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.PR_MAIN, Me.LBL_INFO})
|
||||||
@@ -169,7 +177,7 @@ Namespace DownloadObjects.STDownloader
|
|||||||
'TOOLBAR_TOP
|
'TOOLBAR_TOP
|
||||||
'
|
'
|
||||||
Me.TOOLBAR_TOP.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden
|
Me.TOOLBAR_TOP.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden
|
||||||
Me.TOOLBAR_TOP.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.BTT_SETTINGS, Me.SEP_1, Me.MENU_ADD, SEP_2, Me.BTT_DOWN, Me.BTT_STOP, SEP_3, MENU_DEL_CLEAR, Me.SEP_LOG, Me.BTT_LOG, Me.BTT_INFO, Me.BTT_DONATE, Me.BTT_BUG_REPORT})
|
Me.TOOLBAR_TOP.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.BTT_SETTINGS, Me.SEP_1, Me.MENU_ADD, Me.SEP_FILTER, Me.BTT_FILTER, SEP_2, Me.BTT_DOWN, Me.BTT_STOP, SEP_3, MENU_DEL_CLEAR, Me.SEP_LOG, Me.BTT_LOG, Me.BTT_INFO, Me.BTT_DONATE, Me.BTT_BUG_REPORT})
|
||||||
Me.TOOLBAR_TOP.Location = New System.Drawing.Point(0, 0)
|
Me.TOOLBAR_TOP.Location = New System.Drawing.Point(0, 0)
|
||||||
Me.TOOLBAR_TOP.Name = "TOOLBAR_TOP"
|
Me.TOOLBAR_TOP.Name = "TOOLBAR_TOP"
|
||||||
Me.TOOLBAR_TOP.Size = New System.Drawing.Size(584, 25)
|
Me.TOOLBAR_TOP.Size = New System.Drawing.Size(584, 25)
|
||||||
@@ -222,6 +230,15 @@ Namespace DownloadObjects.STDownloader
|
|||||||
Me.BTT_ADD_PLS_ARR.Text = "Add URL array"
|
Me.BTT_ADD_PLS_ARR.Text = "Add URL array"
|
||||||
Me.BTT_ADD_PLS_ARR.ToolTipText = "Click to add." & Global.Microsoft.VisualBasic.ChrW(13) & Global.Microsoft.VisualBasic.ChrW(10) & "Ctrl+click to use cookies for download (if supported)." & Global.Microsoft.VisualBasic.ChrW(13) & Global.Microsoft.VisualBasic.ChrW(10) & "Shift to a" &
|
Me.BTT_ADD_PLS_ARR.ToolTipText = "Click to add." & Global.Microsoft.VisualBasic.ChrW(13) & Global.Microsoft.VisualBasic.ChrW(10) & "Ctrl+click to use cookies for download (if supported)." & Global.Microsoft.VisualBasic.ChrW(13) & Global.Microsoft.VisualBasic.ChrW(10) & "Shift to a" &
|
||||||
"dd without downloading."
|
"dd without downloading."
|
||||||
|
'
|
||||||
|
'BTT_FILTER
|
||||||
|
'
|
||||||
|
Me.BTT_FILTER.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image
|
||||||
|
Me.BTT_FILTER.Image = CType(resources.GetObject("BTT_FILTER.Image"), System.Drawing.Image)
|
||||||
|
Me.BTT_FILTER.ImageTransparentColor = System.Drawing.Color.Magenta
|
||||||
|
Me.BTT_FILTER.Name = "BTT_FILTER"
|
||||||
|
Me.BTT_FILTER.Size = New System.Drawing.Size(23, 22)
|
||||||
|
Me.BTT_FILTER.Text = "Filter"
|
||||||
'
|
'
|
||||||
'BTT_DOWN
|
'BTT_DOWN
|
||||||
'
|
'
|
||||||
@@ -286,11 +303,10 @@ Namespace DownloadObjects.STDownloader
|
|||||||
Me.BTT_BUG_REPORT.Size = New System.Drawing.Size(23, 22)
|
Me.BTT_BUG_REPORT.Size = New System.Drawing.Size(23, 22)
|
||||||
Me.BTT_BUG_REPORT.Text = "Bug report"
|
Me.BTT_BUG_REPORT.Text = "Bug report"
|
||||||
'
|
'
|
||||||
'BTT_SELECT_NONE
|
'SEP_FILTER
|
||||||
'
|
'
|
||||||
Me.BTT_SELECT_NONE.Name = "BTT_SELECT_NONE"
|
Me.SEP_FILTER.Name = "SEP_FILTER"
|
||||||
Me.BTT_SELECT_NONE.Size = New System.Drawing.Size(185, 22)
|
Me.SEP_FILTER.Size = New System.Drawing.Size(6, 25)
|
||||||
Me.BTT_SELECT_NONE.Text = "Select none"
|
|
||||||
'
|
'
|
||||||
'VideoListForm
|
'VideoListForm
|
||||||
'
|
'
|
||||||
@@ -337,5 +353,7 @@ Namespace DownloadObjects.STDownloader
|
|||||||
Private WithEvents BTT_CLEAR_SELECTED As ToolStripMenuItem
|
Private WithEvents BTT_CLEAR_SELECTED As ToolStripMenuItem
|
||||||
Private WithEvents BTT_SELECT_ALL As ToolStripMenuItem
|
Private WithEvents BTT_SELECT_ALL As ToolStripMenuItem
|
||||||
Private WithEvents BTT_SELECT_NONE As ToolStripMenuItem
|
Private WithEvents BTT_SELECT_NONE As ToolStripMenuItem
|
||||||
|
Public WithEvents BTT_FILTER As ToolStripButton
|
||||||
|
Public WithEvents SEP_FILTER As ToolStripSeparator
|
||||||
End Class
|
End Class
|
||||||
End Namespace
|
End Namespace
|
||||||
@@ -130,30 +130,31 @@
|
|||||||
<data name="BTT_DELETE.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="BTT_DELETE.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
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
|
||||||
HR8AAAAASUVORK5CYII=
|
RxAASABgv+e63uX/HACQqUlmzgEAeHXVtQAAPE9icliTK/m/HpEQZP9/yTOIoS/Y32gy2FQGa9GfAAAA
|
||||||
|
AElFTkSuQmCC
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<metadata name="MENU_DEL_SEP_1.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
<metadata name="MENU_DEL_SEP_1.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
@@ -162,88 +163,91 @@
|
|||||||
<data name="BTT_CLEAR_SELECTED.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="BTT_CLEAR_SELECTED.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
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
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="BTT_CLEAR_DONE.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="BTT_CLEAR_DONE.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
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
|
||||||
HR8AAAAASUVORK5CYII=
|
RxAASABgv+e63uX/HACQqUlmzgEAeHXVtQAAPE9icliTK/m/HpEQZP9/yTOIoS/Y32gy2FQGa9GfAAAA
|
||||||
|
AElFTkSuQmCC
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="BTT_CLEAR_ALL.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="BTT_CLEAR_ALL.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
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
|
||||||
HR8AAAAASUVORK5CYII=
|
RxAASABgv+e63uX/HACQqUlmzgEAeHXVtQAAPE9icliTK/m/HpEQZP9/yTOIoS/Y32gy2FQGa9GfAAAA
|
||||||
|
AElFTkSuQmCC
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<metadata name="MENU_DEL_SEP_2.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
<metadata name="MENU_DEL_SEP_2.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
@@ -252,30 +256,31 @@
|
|||||||
<data name="MENU_DEL_CLEAR.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="MENU_DEL_CLEAR.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
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
|
||||||
dCWdzmEAAAAASUVORK5CYII=
|
W/rDDwBEAHDYdd/q8n8BAOjUpDPnCAC8vuFaAACOKzE9rOmd/t+KaAi6/7/iuqihJ9jfOenaM1O34/0A
|
||||||
|
AAAASUVORK5CYII=
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<metadata name="TOOLBAR_BOTTOM.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
<metadata name="TOOLBAR_BOTTOM.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
@@ -287,105 +292,123 @@
|
|||||||
<data name="BTT_ADD.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="BTT_ADD.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
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
|
||||||
hKygM1JCJAAAAABJRU5ErkJggg==
|
rwTiqI6ApvuidiViSNQekHhdhHhVL8AlQ/Cp10vnFTz/HxZurHotmkteAAAAAElFTkSuQmCC
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="BTT_ADD_PLS_ARR.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="BTT_ADD_PLS_ARR.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
|
iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
|
||||||
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAANqSURBVEhLrZVbSJNhGMe/mjhN1IWdpjPMssOitqklidPS
|
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAOKSURBVEhLrZVfTFNXHMePg/DHhlLTqSsU41A3vUZPVZSM
|
||||||
cksrmufyQAcPZWSKzqEZUla3UXQXXYyI6CaMrjpcmEV5KF31zXQt5k42Cxbdf/Hveb8meSEa+j3wh8H7
|
cMW1G9SyLV4BZfIn6qBoF5gECtG5NOK218Vlb8seGrMsvhjMnuaWTMiiFLVUPbdChym9t4V2Jiy+H/M1
|
||||||
8v897/P+32/cQhV+U2aV35JhLrG10LbFFzNS29RC7qgeBz7oYeRJdj1KXXkiJLRt8SUCPqqFFf0cYt5y
|
91Y2RhbUcL/J7+mcfD8nJ59zLyEvSN6lnGD+tzn4v9HWlu5/5WhFQkTgzgkR798T4WYi3LKIprhLhyzd
|
||||||
iBvmkPA+DHW+AgkBvFqIHeCwengZkkbl0PIxaA8USwfYTgDWebJNjtSxWOwdX4urP6qkA+gIkGyLwK4x
|
/8rRAfcFvnqUwHyLwHqboPRuLjqTHgMBTODFYwRrb6/Cxol8OJgZA+kGYwHaycsj+dgdLcaByfX48nGr
|
||||||
BQyOeJr/JtwM1ksHOEWAdLsCBY4EHJ/cgnq3Fnd/NUkHaOW1gvGLCtXubWj0pKLVm4n7v8z/B5gv5zMq
|
cQDKBF4eKcDeqAV1sRI0xTfj0rzXOMBJJvAK2QJPrBTHZt6GN+HAD096jAP0sZ3c/acdbYlt8Cm70adW
|
||||||
fZXzu8q9Fec96bBM6XE5kA/rzzasehA5r5SPoqxih3kzGad8F47rUeTIRY3LgPPeI+jwl+JaoIZ+p6PT
|
4ccn/pcDLOf5wjSM1DxtTWxFt1KBwVkRF9K1CP7dj9d/Klx2bFdNQf2ErgXHZRH1kyIOx5xoj9ehW/0I
|
||||||
n40rAQN6po2wBttwL2gWQXeCTbjxoxZXpivR7i+hERai0V0OZW8URAAzj3lDGR/koBoNh4ZiyJJi+pqM
|
Z1NN+Crdjm61AudS+zGUrsPFjBvB+X5cnvfroO/ne/DN4w4MZVowkGqEN1EPX+IobMMm6ACt3HyTwBoi
|
||||||
k+7tuODNwMWpfWRgxPXpAhFw+Vs+melR79Gi7GsK8ibWQWOPQeJIOBTkU243/QOwzpk5W9TYo2mzEsUh
|
sE/kgTKzbor0qBwnEtvxmVqJz2ffxVDGja8zHh1wYa4WAykRXsWBI4+2wDX1BqhsRlk4D5YQwVFZ+heg
|
||||||
82ZfBrr8uegJGAmQj0vfcmH2Z9FdpOHEpBpHnRuQM74GO/hoxI+GQTHEIZIeZfGHWYDCMT3Wk7mWOshz
|
nVwr1xapXATXlA0Nz8vPJCtxPuXExbQbQ5lafDHnhD9VDZ+yB8dnBByafhM1k+uwgxWhZCIXlnGCwlGC
|
||||||
KMUY1nk0aPHtRufUXnSRaYc/B2ZfFpq9u9BAa9VuNQ47k5BNJxXNR8LAHiMzX/aMg2loFuCYYz/2jMVR
|
hnuLAPVRERvCeXDIZrhiNl3DToWiN7kP52YP4PycE2dTNfAnq3FG3YsuhaItIeDD6Y3YP7k+Wx7OhfYY
|
||||||
DFWodG1FE11mGyXFQobMtNWXKaqFRtVAI2FpOuRcj6zPa7DtUxSU72SIphFH9HHgnpJ6CfB6FuAs5dzM
|
tfJV1wmk8UWAj2Pv4Z2oFZ6YHS3xrehRKtCvVmEwWa2X9iWr9OlVK9GlOHSbPpjegOqH67DtgQm2Ozko
|
||||||
pwrdfDXpNKmBVE86Qzon3P5+lsx3o86tQcXkZhQ4E2Hx1qCwL+d3LZ8mVPE6oYKUStJ9JL0nDeoEEcBi
|
uklQcIOA/EJAhgmkPxYBTjOB+5mDB1gbD7BPeIB18QDz8gA7xQPsU/7dX6fRq+5DZ4KieeYteKbLMKi2
|
||||||
OlfEZsQ2dfMWoc6zExWuFBykU2bQaRs9FeLavGIxXajYxm6+RSijezFMJCCNXvRGWyROuIpEk9C2xddf
|
4+DvNU872C7eyihvZpQ7GOX0PuX0LuU0RLkO0DRdqtd/VBs2IcAGeaeyE83xLTgYs6MyaoVPadbXlh1N
|
||||||
QKOQPxEvfujY1zSOknLcEZrxUusvoFbQ2WOhoqSspDiz/4aSmZwvtZhJE18pJI7IoaAYrnjJQfacUmKT
|
0xclC+jlR+KbUTdVij2yBZsihTgeP5y9gpUmC/Dx2qkS/UOnfU2t4wTHYs/veKXJAjr4LrkY9nAu1oQI
|
||||||
EHCKEsbMI6jz5SyGTwgwICGgkuIXSZ1z9IC4x6SHBOiXEFDyySSOxDRIogdk6iO9kApAWWZGc2rBnHPc
|
tH9D44LnK41W0sNaeFk4H5YxgtUjBDm/EkgRAwEnmYNr5QWjBK9pGv5MII0ZCGhhlBeOEJDrBOQaAblC
|
||||||
H0WkrMjY2947AAAAAElFTkSuQmCC
|
II0aCGh8IOlXIoUk/QFJNyRIvxkFuGoK/uP10nkJz58BqISsoFjBRioAAAAASUVORK5CYII=
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MENU_ADD.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="MENU_ADD.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
|
iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
|
||||||
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAN5SURBVEhLrZVJTFNRFIafljBIgBqcymAU54oWGSRCK1oU
|
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAOUSURBVEhLrZVfTFtVHMfPhPBnDaWmulkoy8RNt5rZCmx4
|
||||||
KqixAoIyiMqgGBAChYCaOsed0bgzLogxxo3RuHJYqDEqKFD1tUItKZ2gaIJxf8nvuc8SWRAw8E7yp03u
|
K3dgq1CLGu+ADcefzAnF1YAjUMjmTDOmezUzvi0+NMYYXxaMT04fNmImBVe67dza3rGU3ttC6xLM3s/y
|
||||||
zf+de95/3xNmquCbis6QWwpMJb4W2Db74kaJFjXT9+mw+7MOBpFk1aHImS1BAttmX9xE80XNFrwREPle
|
NecyFIlhW+g3+T2dk+/n5ORz7iXkISm6UBAq/rIA/zd8bf3+xw4vskVtzDUn4o0bIjxUhEcW0ZF065D1
|
||||||
QPRHAbE9Qaj25skHSBbVLOqDgMUf52FFXwiSxEi0+gvkA6QRgHeeYAlBsi0KO/qX4srPMvkAmWIiS7CE
|
+x87vGTfTRvbOkVg/I3APEtQeb0Q/Wlv/gAOamPl0wRPz27BzrliOKgRY9m2/AFqqY3xk1dHi1ETK0dT
|
||||||
Is2mRK49hua/GjfHauQDHBeTWapViTx7LI4MrUONKwl3fzfIB2gWM5jhexzKXRtQ505GsycD93+b/g8w
|
fDs+u9udP4BAbaw6WoL9MRNalAp0JHfhwrIvf4Dj1MHqZBO8SiWOLrwAX8qBr+8N5Q8wQl9hnttW9KT2
|
||||||
Xc4ndLQna7zMtR717lS0Detw0Z+Dzl8tWPQgbFqpHoV3Sh1mT2Sc8p3fr8NBux4VzlzUe/aj3VeEq/4K
|
wq/WYERz4tt7gUcDbOT56vTMNt7vTu3BoFqH8UURZ7PNCP01iqe+K91wLJcMIf2E7lXHZRGtcRGHFBd6
|
||||||
+p+KDt92XPLn4vKoAZ1jLbg3ZpJAd8YacONnFS6NlqLVV0gjzEedqxiqx+GQANw88h1lvEtAXF8wNBRD
|
ky0Y1N7BqUwHPs/2YlCrw+nMQUxkW3Au50FoeRTfLAd00MXlIXxxtw8TuS6MZdrhS7XCnzoCy6QBOoCX
|
||||||
nhTjYAKOuTbijCcdZ4d3koEB10bzJMDFkRwy06HGnYRDg2uQPbAMGmsk4nuDoSSfYqvxH4B3zs35osYa
|
G68RmMME1rki2KlRN0W6U433Uy/iY60enyy+homcB+dzXh1wdqkZYxkRPtWBw3d2w514BnbZiKpIEUxh
|
||||||
QZtVKAiYN3rTcc6nx2W/gQA5OD+ih8mnpWeRgsohNQ44ViKrfwk2iRGI6QuCsltAGF3Kgs+TAPk2HZaT
|
giOy9C+An5yX80W7XAZ3woK2B+Un0/U4k3HhXNaDiVwzPl1yIZBpgF+txbEFG96dfxaN8W3YR8tQMVcI
|
||||||
eRJ1kG1XSTGsdmvQ5N2KjuEdOEem7b4smLxaNHrSUEtr5S419jlWYDudVDLvDQK/jNx83nMBxu5JgMP2
|
0wxB6RRB2401gNaYiB2RIjhkI9yKRdewX7VjOH0ApxebcGbJhVOZRgTSDTip7ceAakdPyoa353fiYHz7
|
||||||
Xdhmi6YYxqHUuR4N9DBbKCltZMhNm70ZkppoVLU0Ep6mvY7l0H5bgg1fw6H6pEAEjTj0lQDhGekxAd5O
|
SnmkEPwx8vItlwmkmTWA95TXIcTM8CpWdCX3YEitw6jmxHi6QS8dSTv1GdbqMaA6dJvemt+Bhj+2Ye8t
|
||||||
ApwSU5nJqmVmezkzfz/BzI5aZh6sod+TzCyeZrd/nCLzrah2aVAytBZ5jni0eSpQ1K0frxJ1rEzMZCUk
|
Ayy/F6DsGkHJFQLyEwGZJJB+XQM4QWtYgDpZMN7DgokPWFAZYMHbPhZUPmRB+hH76s8TGNYOoD9lR+fC
|
||||||
LSnzC6mH1JXJJACP6VQRmxDfdN3axqrdm1HiXIM9dMp0Om2du0Ram1Y8pjMV33hBbGKH6LnkDsQihW70
|
8/DOV2Fc60XbdNP9Pvoq66YC66QCc1KBCTcFJlwXmBAWmA7gmq7X6z+qTRpwno6zfvUldCZ3403FivqY
|
||||||
KksYKp0HJZPAttkXNzGLdSxnIEZ60fG3aTQl5Yg9MOO51l9AFdtijUIcJWUhxZl/Gwoncj7X4iYNYimL
|
GX61U1/bcLimDwvfGKTD7HByF1oSlaiVTXguWopjyUMrV7DZrAD8rDlRoX/o+NfUPENwVHlwx5vNCqCP
|
||||||
7w2BkmK44LUAxQtKiUVGwHFRy7h5KHU+n8fwKQE+yAgopfiFUecCXSDhCekhAd7ICCj8apRGYuwi0QUy
|
vSyXwxopxJNhAv5vaF/1fLPhJUO0i1VFimGaJth6laDgZwIpmkfAcepkvLxkiuAJruGPBNJ0HgFdVGCl
|
||||||
viK9lAtAWeZGU2rGnAvCHy5drfKWDYjrAAAAAElFTkSuQmCC
|
VwnIZQLyAwH5nkCayiOg/ZakX4kUlvQHJF2RIP2SL8AlQ+gfr9fPI3j+N/WNrat6NXl+AAAAAElFTkSu
|
||||||
|
QmCC
|
||||||
|
</value>
|
||||||
|
</data>
|
||||||
|
<data name="BTT_FILTER.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>
|
||||||
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
|
||||||
|
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIFSURBVDhPpZLtS1NhGMbPPxJmmlYSgqHiKzGU1EDxg4iK
|
||||||
|
YKyG2WBogqMYJQOtCEVRFBGdTBCJfRnkS4VaaWNT5sqx1BUxRXxDHYxAJLvkusEeBaPAB+5z4Jzn+t3X
|
||||||
|
/aLhnEfjo8m+dCoa+7/C3O2Hqe0zDC+8KG+cRZHZhdzaaWTVTCLDMIY0vfM04Nfh77/G/sEhwpEDbO3t
|
||||||
|
I7TxE8urEVy99fT/AL5gWDLrTB/hnF4XsW0khCu5ln8DmJliT2AXrcNBsU1gj/MH4nMeKwBrPktM28xM
|
||||||
|
cX79DFKrHHD5d9D26hvicx4pABt2lpg10zYzU0zr7+e3xXGcrkEB2O2TNec9nJFwB3alZn5jZorfeDZh
|
||||||
|
6Q3g8s06BeCoKF4MRURoH1+BY2oNCbeb0TIclIYxOhzf8frTOuo7FxCbbVIAzpni0iceEc8vhzEwGkJD
|
||||||
|
lx83ymxifejdKjRNk/8PWnyIyTQqAJek0jqHwfEVscu31baIu8+90sTE4nY025dQ2/5FIPpnXlzKuK8A
|
||||||
|
HBUzHot52djqQ6HZhfR7IwK4mKpHtvEDMqvfCiQ6zaAAXM8x94aIWTNrLLG4kVUzgaTSPlzLtyJOZxbb
|
||||||
|
1wtfyg4Q+AfA3aZlButjSfxGcUJBk4g5tuP3haQKRKXcUQDOmbvNTpPOJeFFjordZmbWTNvMTHFUcpUC
|
||||||
|
nOccAdABIDXXE1nzAAAAAElFTkSuQmCC
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="BTT_STOP.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="BTT_STOP.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
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
|
||||||
bAAAAABJRU5ErkJggg==
|
CAIACQDs9lxXu/xfAAAyNcnM2QMAry+7FgCA9iQmhzW5kv+rEQlB9v9XPIMY+oL9DaXP2MIw0VMVAAAA
|
||||||
|
AElFTkSuQmCC
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="BTT_LOG.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="BTT_LOG.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
|
iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
|
||||||
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAFmSURBVFhH1dc/K4VhHMbxJ5EFEQbFiERKCotIrMJIiYEi
|
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGTSURBVFhH1ZfPK21RGIaf5GaCCAPF0JVISWEiElNhSIkB
|
||||||
pbwCZcOqJC9AikUWiqRkJYtSRDbESMT3V07dna7zHHru+9T51me+Ts//E+V7LRjFFAZRiZzUhDVc4/vX
|
RUr5C5QZpkryB0gxkQlFUjKlO1HKjcwQQyJatdXp7TtnH3t/Z+CpZ7be7z3tH2uvA7+cFmAUmAIGgSpd
|
||||||
B47Rh6D14Aqp4XQ36ECQ2nALNezaQjG8Vo5DqMF0bxiA1+bwCTWoLMFbNTiDGsrkABXw0jDsKldDmdyj
|
UCiagDXgCviMfAOOgT5d7E0P8C+jWL0GOjTkRRtwY5SqW0CJhtNSARwaZZYvwIAOSMsc8G6UZXNJB6Sh
|
||||||
HokrwCrUSBz7wXbRJs4eLkdQI9m0I3ENeIAaiGN3QjMSZ4fxv+ffnKIKibOnmhqI84V5eMleOHY41VAm
|
FjgzSnJ5AFTqoKQMR0+5luTyFmjQQUkoAlaNgjjDDw4PbWrC5nJkFORjuw5Lwl/gzhgeZ3gTmnVYEsJl
|
||||||
9k7wdgtW4wRqSHlCP7y2AjWmbMB7Y7DzqgZdz2iF9zrxCDXq2oU9uLz31+tgAcHahhp1DSFY9pGhRl29
|
/On9D54C1TosCWFX0+FxfgDzOigp4YMTLqeW5DJ8E9xewRrgxCjJ5gPQr0PSsmIUZXNDwx6MRfdVy9RH
|
||||||
CFYXxrMoQ7BmsZfFPkoRpHWow+56hX26BWkRatR1gRIEaQLvUMMpOyhCkBpxBzWcMoOgLUMNm0vUIWj2
|
oFXDHnQC90ahuhttXO7k+xwsaNCTbaNQHdKQJ+GQoYVqr4Y86QLGYyzXkCezwF6M+0CZBr1YNy65+hwd
|
||||||
ebaJF7jj5+hGTiqE/f+bxDRGUIt8LIp+AC/GHt3tQnwvAAAAAElFTkSuQmCC
|
3QrColGoXgClGvRiAng1SjPdAf5o0ItG4L9RmumMhrxZNkq/vQTqNeBNOJ5tAk9Sfg506+JCURz9/5sE
|
||||||
|
poERoE4X/Rq+AC/GHt09Rk0KAAAAAElFTkSuQmCC
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
</root>
|
</root>
|
||||||
@@ -39,6 +39,7 @@ Namespace DownloadObjects.STDownloader
|
|||||||
MyView = New FormView(Me)
|
MyView = New FormView(Me)
|
||||||
MyProgress = New MyProgress(TOOLBAR_BOTTOM, PR_MAIN, LBL_INFO)
|
MyProgress = New MyProgress(TOOLBAR_BOTTOM, PR_MAIN, LBL_INFO)
|
||||||
MyJob = New JobThread(Of MediaItem)
|
MyJob = New JobThread(Of MediaItem)
|
||||||
|
BTT_FILTER.Image = My.Resources.FilterPic
|
||||||
End Sub
|
End Sub
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Form handlers"
|
#Region "Form handlers"
|
||||||
@@ -95,15 +96,18 @@ Namespace DownloadObjects.STDownloader
|
|||||||
Dim b As Boolean = True
|
Dim b As Boolean = True
|
||||||
Select Case e.KeyCode
|
Select Case e.KeyCode
|
||||||
Case Keys.Insert : BTT_ADD.PerformClick()
|
Case Keys.Insert : BTT_ADD.PerformClick()
|
||||||
Case Keys.F5 : BTT_DOWN.PerformClick()
|
Case Keys.F5
|
||||||
|
If e.Control Then LoadData(True) Else BTT_DOWN.PerformClick()
|
||||||
Case Else : b = False
|
Case Else : b = False
|
||||||
End Select
|
End Select
|
||||||
If b Then e.Handled = True
|
If b Then e.Handled = True
|
||||||
End Sub
|
End Sub
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Refill, save list"
|
#Region "Refill, save list"
|
||||||
Protected Sub LoadData()
|
Protected Sub LoadData(Optional ByVal ClearTable As Boolean = False)
|
||||||
|
If ClearTable Then RemoveControls(,, False)
|
||||||
Dim c As List(Of IYouTubeMediaContainer) = LoadData_GetFiles()
|
Dim c As List(Of IYouTubeMediaContainer) = LoadData_GetFiles()
|
||||||
|
If c.ListExists Then MyYouTubeSettings.FILTER.RemoveAll(c)
|
||||||
If c.ListExists Then
|
If c.ListExists Then
|
||||||
c.Sort(New ContainerDateComparer)
|
c.Sort(New ContainerDateComparer)
|
||||||
SuspendLayout()
|
SuspendLayout()
|
||||||
@@ -415,6 +419,12 @@ Namespace DownloadObjects.STDownloader
|
|||||||
Return ErrorsDescriber.Execute(EDP.SendToLog + EDP.ReturnValue, ex, "[VideoListForm.ValidateContainerURL]", True)
|
Return ErrorsDescriber.Execute(EDP.SendToLog + EDP.ReturnValue, ex, "[VideoListForm.ValidateContainerURL]", True)
|
||||||
End Try
|
End Try
|
||||||
End Function
|
End Function
|
||||||
|
Private Sub BTT_FILTER_Click(sender As Object, e As EventArgs) Handles BTT_FILTER.Click
|
||||||
|
Using f As New FilterForm(LoadData_GetFiles)
|
||||||
|
f.ShowDialog()
|
||||||
|
If f.DialogResult = DialogResult.OK Or f.DialogResult = DialogResult.Abort Then LoadData(True)
|
||||||
|
End Using
|
||||||
|
End Sub
|
||||||
Private Sub BTT_DOWN_Click(sender As Object, e As EventArgs) Handles BTT_DOWN.Click
|
Private Sub BTT_DOWN_Click(sender As Object, e As EventArgs) Handles BTT_DOWN.Click
|
||||||
With TP_CONTROLS
|
With TP_CONTROLS
|
||||||
If .Controls.Count > 0 Then
|
If .Controls.Count > 0 Then
|
||||||
@@ -494,7 +504,8 @@ Namespace DownloadObjects.STDownloader
|
|||||||
Protected Sub CheckVersionImpl(ByVal Force As Boolean)
|
Protected Sub CheckVersionImpl(ByVal Force As Boolean)
|
||||||
CheckVersion(Force)
|
CheckVersion(Force)
|
||||||
End Sub
|
End Sub
|
||||||
Protected Overloads Sub RemoveControls(Optional ByVal Predicate As Predicate(Of MediaItem) = Nothing, Optional ByVal RemoveFiles As Boolean = False)
|
Protected Overloads Sub RemoveControls(Optional ByVal Predicate As Predicate(Of MediaItem) = Nothing, Optional ByVal RemoveFiles As Boolean = False,
|
||||||
|
Optional ByVal ProcessDelete As Boolean = True)
|
||||||
ControlInvokeFast(TP_CONTROLS, Sub()
|
ControlInvokeFast(TP_CONTROLS, Sub()
|
||||||
With TP_CONTROLS
|
With TP_CONTROLS
|
||||||
If .Controls.Count > 0 Then
|
If .Controls.Count > 0 Then
|
||||||
@@ -509,7 +520,10 @@ Namespace DownloadObjects.STDownloader
|
|||||||
For i = rCnt.Count - 1 To 0 Step -1
|
For i = rCnt.Count - 1 To 0 Step -1
|
||||||
cnt = .Controls(rCnt(i))
|
cnt = .Controls(rCnt(i))
|
||||||
.Controls.RemoveAt(rCnt(i))
|
.Controls.RemoveAt(rCnt(i))
|
||||||
If Not cnt.MyContainer Is Nothing Then cnt.MyContainer.Delete(RemoveFiles) : cnt.MyContainer.Dispose()
|
If Not cnt.MyContainer Is Nothing Then
|
||||||
|
If ProcessDelete Then cnt.MyContainer.Delete(RemoveFiles)
|
||||||
|
cnt.MyContainer.Dispose()
|
||||||
|
End If
|
||||||
cnt.Dispose()
|
cnt.Dispose()
|
||||||
Next
|
Next
|
||||||
End If
|
End If
|
||||||
|
|||||||
261
SCrawler.YouTube/Editors/BugReporterForm.Designer.vb
generated
@@ -24,7 +24,6 @@ Namespace Editors
|
|||||||
Private Sub InitializeComponent()
|
Private Sub InitializeComponent()
|
||||||
Me.components = New System.ComponentModel.Container()
|
Me.components = New System.ComponentModel.Container()
|
||||||
Dim TP_MAIN As System.Windows.Forms.TableLayoutPanel
|
Dim TP_MAIN As System.Windows.Forms.TableLayoutPanel
|
||||||
Dim TP_BUTTONS As System.Windows.Forms.TableLayoutPanel
|
|
||||||
Dim ActionButton1 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
Dim ActionButton1 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||||
Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(BugReporterForm))
|
Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(BugReporterForm))
|
||||||
Dim ActionButton2 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
Dim ActionButton2 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||||
@@ -33,31 +32,32 @@ Namespace Editors
|
|||||||
Dim ActionButton5 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
Dim ActionButton5 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||||
Dim ActionButton6 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
Dim ActionButton6 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||||
Dim ActionButton7 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
Dim ActionButton7 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||||
|
Dim TP_BUTTONS As System.Windows.Forms.TableLayoutPanel
|
||||||
Dim ActionButton8 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
Dim ActionButton8 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||||
Dim ActionButton9 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
Dim ActionButton9 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||||
Me.BTT_EMAIL = New System.Windows.Forms.Button()
|
|
||||||
Me.BTT_GITHUB = New System.Windows.Forms.Button()
|
|
||||||
Me.BTT_COPY = New System.Windows.Forms.Button()
|
|
||||||
Me.BTT_CANCEL = New System.Windows.Forms.Button()
|
|
||||||
Me.BTT_ANON = New System.Windows.Forms.Button()
|
|
||||||
Me.TT_MAIN = New System.Windows.Forms.ToolTip(Me.components)
|
|
||||||
Me.TXT_DESCR = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
Me.TXT_DESCR = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
||||||
Me.TXT_URL_PROFILE = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
Me.TXT_URL_PROFILE = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
||||||
Me.TXT_URL_POST = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
Me.TXT_URL_POST = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
||||||
Me.TXT_REPRODUCE = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
Me.TXT_REPRODUCE = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
||||||
Me.TXT_EXPECT = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
Me.TXT_EXPECT = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
||||||
Me.TXT_LOG = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
Me.TXT_LOG = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
||||||
|
Me.BTT_EMAIL = New System.Windows.Forms.Button()
|
||||||
|
Me.BTT_GITHUB = New System.Windows.Forms.Button()
|
||||||
|
Me.BTT_COPY = New System.Windows.Forms.Button()
|
||||||
|
Me.BTT_CANCEL = New System.Windows.Forms.Button()
|
||||||
|
Me.BTT_ANON = New System.Windows.Forms.Button()
|
||||||
Me.TXT_FILES = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
Me.TXT_FILES = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
||||||
|
Me.TT_MAIN = New System.Windows.Forms.ToolTip(Me.components)
|
||||||
TP_MAIN = New System.Windows.Forms.TableLayoutPanel()
|
TP_MAIN = New System.Windows.Forms.TableLayoutPanel()
|
||||||
TP_BUTTONS = New System.Windows.Forms.TableLayoutPanel()
|
TP_BUTTONS = New System.Windows.Forms.TableLayoutPanel()
|
||||||
TP_MAIN.SuspendLayout()
|
TP_MAIN.SuspendLayout()
|
||||||
TP_BUTTONS.SuspendLayout()
|
|
||||||
CType(Me.TXT_DESCR, System.ComponentModel.ISupportInitialize).BeginInit()
|
CType(Me.TXT_DESCR, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||||
CType(Me.TXT_URL_PROFILE, System.ComponentModel.ISupportInitialize).BeginInit()
|
CType(Me.TXT_URL_PROFILE, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||||
CType(Me.TXT_URL_POST, System.ComponentModel.ISupportInitialize).BeginInit()
|
CType(Me.TXT_URL_POST, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||||
CType(Me.TXT_REPRODUCE, System.ComponentModel.ISupportInitialize).BeginInit()
|
CType(Me.TXT_REPRODUCE, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||||
CType(Me.TXT_EXPECT, System.ComponentModel.ISupportInitialize).BeginInit()
|
CType(Me.TXT_EXPECT, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||||
CType(Me.TXT_LOG, System.ComponentModel.ISupportInitialize).BeginInit()
|
CType(Me.TXT_LOG, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||||
|
TP_BUTTONS.SuspendLayout()
|
||||||
CType(Me.TXT_FILES, System.ComponentModel.ISupportInitialize).BeginInit()
|
CType(Me.TXT_FILES, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||||
Me.SuspendLayout()
|
Me.SuspendLayout()
|
||||||
'
|
'
|
||||||
@@ -88,6 +88,123 @@ Namespace Editors
|
|||||||
TP_MAIN.Size = New System.Drawing.Size(584, 461)
|
TP_MAIN.Size = New System.Drawing.Size(584, 461)
|
||||||
TP_MAIN.TabIndex = 0
|
TP_MAIN.TabIndex = 0
|
||||||
'
|
'
|
||||||
|
'TXT_DESCR
|
||||||
|
'
|
||||||
|
ActionButton1.BackgroundImage = CType(resources.GetObject("ActionButton1.BackgroundImage"), System.Drawing.Image)
|
||||||
|
ActionButton1.Dock = System.Windows.Forms.DockStyle.Top
|
||||||
|
ActionButton1.Name = "Clear"
|
||||||
|
ActionButton1.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
|
||||||
|
Me.TXT_DESCR.Buttons.Add(ActionButton1)
|
||||||
|
Me.TXT_DESCR.CaptionDock = System.Windows.Forms.DockStyle.Top
|
||||||
|
Me.TXT_DESCR.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.None
|
||||||
|
Me.TXT_DESCR.CaptionVisible = False
|
||||||
|
Me.TXT_DESCR.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.TXT_DESCR.GroupBoxed = True
|
||||||
|
Me.TXT_DESCR.GroupBoxText = "Describe the bug or write your message"
|
||||||
|
Me.TXT_DESCR.Location = New System.Drawing.Point(3, 3)
|
||||||
|
Me.TXT_DESCR.Multiline = True
|
||||||
|
Me.TXT_DESCR.Name = "TXT_DESCR"
|
||||||
|
Me.TXT_DESCR.Size = New System.Drawing.Size(578, 69)
|
||||||
|
Me.TXT_DESCR.TabIndex = 0
|
||||||
|
Me.TXT_DESCR.TextToolTip = "A clear and concise description of what the bug is"
|
||||||
|
Me.TXT_DESCR.TextToolTipEnabled = True
|
||||||
|
'
|
||||||
|
'TXT_URL_PROFILE
|
||||||
|
'
|
||||||
|
ActionButton2.BackgroundImage = CType(resources.GetObject("ActionButton2.BackgroundImage"), System.Drawing.Image)
|
||||||
|
ActionButton2.Name = "Clear"
|
||||||
|
ActionButton2.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
|
||||||
|
Me.TXT_URL_PROFILE.Buttons.Add(ActionButton2)
|
||||||
|
Me.TXT_URL_PROFILE.CaptionText = "Profile URL"
|
||||||
|
Me.TXT_URL_PROFILE.CaptionWidth = 75.0R
|
||||||
|
Me.TXT_URL_PROFILE.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.TXT_URL_PROFILE.Location = New System.Drawing.Point(3, 78)
|
||||||
|
Me.TXT_URL_PROFILE.Name = "TXT_URL_PROFILE"
|
||||||
|
Me.TXT_URL_PROFILE.Size = New System.Drawing.Size(578, 22)
|
||||||
|
Me.TXT_URL_PROFILE.TabIndex = 1
|
||||||
|
'
|
||||||
|
'TXT_URL_POST
|
||||||
|
'
|
||||||
|
ActionButton3.BackgroundImage = CType(resources.GetObject("ActionButton3.BackgroundImage"), System.Drawing.Image)
|
||||||
|
ActionButton3.Name = "Clear"
|
||||||
|
ActionButton3.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
|
||||||
|
Me.TXT_URL_POST.Buttons.Add(ActionButton3)
|
||||||
|
Me.TXT_URL_POST.CaptionText = "Post URL"
|
||||||
|
Me.TXT_URL_POST.CaptionWidth = 75.0R
|
||||||
|
Me.TXT_URL_POST.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.TXT_URL_POST.Location = New System.Drawing.Point(3, 106)
|
||||||
|
Me.TXT_URL_POST.Name = "TXT_URL_POST"
|
||||||
|
Me.TXT_URL_POST.Size = New System.Drawing.Size(578, 22)
|
||||||
|
Me.TXT_URL_POST.TabIndex = 2
|
||||||
|
'
|
||||||
|
'TXT_REPRODUCE
|
||||||
|
'
|
||||||
|
ActionButton4.BackgroundImage = CType(resources.GetObject("ActionButton4.BackgroundImage"), System.Drawing.Image)
|
||||||
|
ActionButton4.Dock = System.Windows.Forms.DockStyle.Top
|
||||||
|
ActionButton4.Name = "Clear"
|
||||||
|
ActionButton4.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
|
||||||
|
Me.TXT_REPRODUCE.Buttons.Add(ActionButton4)
|
||||||
|
Me.TXT_REPRODUCE.CaptionDock = System.Windows.Forms.DockStyle.Top
|
||||||
|
Me.TXT_REPRODUCE.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.None
|
||||||
|
Me.TXT_REPRODUCE.CaptionVisible = False
|
||||||
|
Me.TXT_REPRODUCE.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.TXT_REPRODUCE.GroupBoxed = True
|
||||||
|
Me.TXT_REPRODUCE.GroupBoxText = "Steps to reproduce"
|
||||||
|
Me.TXT_REPRODUCE.Location = New System.Drawing.Point(3, 134)
|
||||||
|
Me.TXT_REPRODUCE.Multiline = True
|
||||||
|
Me.TXT_REPRODUCE.Name = "TXT_REPRODUCE"
|
||||||
|
Me.TXT_REPRODUCE.Size = New System.Drawing.Size(578, 69)
|
||||||
|
Me.TXT_REPRODUCE.TabIndex = 3
|
||||||
|
Me.TXT_REPRODUCE.TextToolTip = "Steps to reproduce the behavior:" & Global.Microsoft.VisualBasic.ChrW(13) & Global.Microsoft.VisualBasic.ChrW(10) & "1. Do something" & Global.Microsoft.VisualBasic.ChrW(13) & Global.Microsoft.VisualBasic.ChrW(10) & "2. See error"
|
||||||
|
Me.TXT_REPRODUCE.TextToolTipEnabled = True
|
||||||
|
'
|
||||||
|
'TXT_EXPECT
|
||||||
|
'
|
||||||
|
ActionButton5.BackgroundImage = CType(resources.GetObject("ActionButton5.BackgroundImage"), System.Drawing.Image)
|
||||||
|
ActionButton5.Dock = System.Windows.Forms.DockStyle.Top
|
||||||
|
ActionButton5.Name = "Clear"
|
||||||
|
ActionButton5.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
|
||||||
|
Me.TXT_EXPECT.Buttons.Add(ActionButton5)
|
||||||
|
Me.TXT_EXPECT.CaptionDock = System.Windows.Forms.DockStyle.Top
|
||||||
|
Me.TXT_EXPECT.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.None
|
||||||
|
Me.TXT_EXPECT.CaptionVisible = False
|
||||||
|
Me.TXT_EXPECT.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.TXT_EXPECT.GroupBoxed = True
|
||||||
|
Me.TXT_EXPECT.GroupBoxText = "Expected behavior"
|
||||||
|
Me.TXT_EXPECT.Location = New System.Drawing.Point(3, 209)
|
||||||
|
Me.TXT_EXPECT.Multiline = True
|
||||||
|
Me.TXT_EXPECT.Name = "TXT_EXPECT"
|
||||||
|
Me.TXT_EXPECT.Size = New System.Drawing.Size(578, 69)
|
||||||
|
Me.TXT_EXPECT.TabIndex = 4
|
||||||
|
Me.TXT_EXPECT.TextToolTip = "A clear and concise description of what you expected to happen."
|
||||||
|
Me.TXT_EXPECT.TextToolTipEnabled = True
|
||||||
|
'
|
||||||
|
'TXT_LOG
|
||||||
|
'
|
||||||
|
ActionButton6.BackgroundImage = CType(resources.GetObject("ActionButton6.BackgroundImage"), System.Drawing.Image)
|
||||||
|
ActionButton6.Dock = System.Windows.Forms.DockStyle.Top
|
||||||
|
ActionButton6.Name = "Open"
|
||||||
|
ActionButton6.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Open
|
||||||
|
ActionButton6.ToolTipText = "Select log files to add their text to the message"
|
||||||
|
ActionButton7.BackgroundImage = CType(resources.GetObject("ActionButton7.BackgroundImage"), System.Drawing.Image)
|
||||||
|
ActionButton7.Dock = System.Windows.Forms.DockStyle.Top
|
||||||
|
ActionButton7.Name = "Clear"
|
||||||
|
ActionButton7.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
|
||||||
|
ActionButton7.ToolTipText = "Empty"
|
||||||
|
Me.TXT_LOG.Buttons.Add(ActionButton6)
|
||||||
|
Me.TXT_LOG.Buttons.Add(ActionButton7)
|
||||||
|
Me.TXT_LOG.CaptionDock = System.Windows.Forms.DockStyle.Top
|
||||||
|
Me.TXT_LOG.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.None
|
||||||
|
Me.TXT_LOG.CaptionVisible = False
|
||||||
|
Me.TXT_LOG.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.TXT_LOG.GroupBoxed = True
|
||||||
|
Me.TXT_LOG.GroupBoxText = "Log data"
|
||||||
|
Me.TXT_LOG.Location = New System.Drawing.Point(3, 284)
|
||||||
|
Me.TXT_LOG.Multiline = True
|
||||||
|
Me.TXT_LOG.Name = "TXT_LOG"
|
||||||
|
Me.TXT_LOG.Size = New System.Drawing.Size(578, 69)
|
||||||
|
Me.TXT_LOG.TabIndex = 5
|
||||||
|
'
|
||||||
'TP_BUTTONS
|
'TP_BUTTONS
|
||||||
'
|
'
|
||||||
TP_BUTTONS.ColumnCount = 6
|
TP_BUTTONS.ColumnCount = 6
|
||||||
@@ -119,7 +236,7 @@ Namespace Editors
|
|||||||
Me.BTT_EMAIL.Name = "BTT_EMAIL"
|
Me.BTT_EMAIL.Name = "BTT_EMAIL"
|
||||||
Me.BTT_EMAIL.Size = New System.Drawing.Size(94, 24)
|
Me.BTT_EMAIL.Size = New System.Drawing.Size(94, 24)
|
||||||
Me.BTT_EMAIL.TabIndex = 1
|
Me.BTT_EMAIL.TabIndex = 1
|
||||||
Me.BTT_EMAIL.Text = "email"
|
Me.BTT_EMAIL.Text = "Email"
|
||||||
Me.TT_MAIN.SetToolTip(Me.BTT_EMAIL, "Create a message to send via email.")
|
Me.TT_MAIN.SetToolTip(Me.BTT_EMAIL, "Create a message to send via email.")
|
||||||
Me.BTT_EMAIL.UseVisualStyleBackColor = True
|
Me.BTT_EMAIL.UseVisualStyleBackColor = True
|
||||||
'
|
'
|
||||||
@@ -167,129 +284,6 @@ Namespace Editors
|
|||||||
Me.TT_MAIN.SetToolTip(Me.BTT_ANON, resources.GetString("BTT_ANON.ToolTip"))
|
Me.TT_MAIN.SetToolTip(Me.BTT_ANON, resources.GetString("BTT_ANON.ToolTip"))
|
||||||
Me.BTT_ANON.UseVisualStyleBackColor = True
|
Me.BTT_ANON.UseVisualStyleBackColor = True
|
||||||
'
|
'
|
||||||
'TXT_DESCR
|
|
||||||
'
|
|
||||||
ActionButton1.BackgroundImage = CType(resources.GetObject("ActionButton1.BackgroundImage"), System.Drawing.Image)
|
|
||||||
ActionButton1.Dock = System.Windows.Forms.DockStyle.Top
|
|
||||||
ActionButton1.Name = "Clear"
|
|
||||||
ActionButton1.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
|
|
||||||
Me.TXT_DESCR.Buttons.Add(ActionButton1)
|
|
||||||
Me.TXT_DESCR.CaptionDock = System.Windows.Forms.DockStyle.Top
|
|
||||||
Me.TXT_DESCR.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.None
|
|
||||||
Me.TXT_DESCR.CaptionVisible = False
|
|
||||||
Me.TXT_DESCR.Dock = System.Windows.Forms.DockStyle.Fill
|
|
||||||
Me.TXT_DESCR.GroupBoxed = True
|
|
||||||
Me.TXT_DESCR.GroupBoxText = "Describe the bug or write your message"
|
|
||||||
Me.TXT_DESCR.Lines = New String(-1) {}
|
|
||||||
Me.TXT_DESCR.Location = New System.Drawing.Point(3, 3)
|
|
||||||
Me.TXT_DESCR.Multiline = True
|
|
||||||
Me.TXT_DESCR.Name = "TXT_DESCR"
|
|
||||||
Me.TXT_DESCR.Size = New System.Drawing.Size(578, 69)
|
|
||||||
Me.TXT_DESCR.TabIndex = 0
|
|
||||||
Me.TXT_DESCR.TextToolTip = "A clear and concise description of what the bug is"
|
|
||||||
Me.TXT_DESCR.TextToolTipEnabled = True
|
|
||||||
'
|
|
||||||
'TXT_URL_PROFILE
|
|
||||||
'
|
|
||||||
ActionButton2.BackgroundImage = CType(resources.GetObject("ActionButton2.BackgroundImage"), System.Drawing.Image)
|
|
||||||
ActionButton2.Name = "Clear"
|
|
||||||
ActionButton2.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
|
|
||||||
Me.TXT_URL_PROFILE.Buttons.Add(ActionButton2)
|
|
||||||
Me.TXT_URL_PROFILE.CaptionText = "Profile URL"
|
|
||||||
Me.TXT_URL_PROFILE.CaptionWidth = 75.0R
|
|
||||||
Me.TXT_URL_PROFILE.Dock = System.Windows.Forms.DockStyle.Fill
|
|
||||||
Me.TXT_URL_PROFILE.Lines = New String(-1) {}
|
|
||||||
Me.TXT_URL_PROFILE.Location = New System.Drawing.Point(3, 78)
|
|
||||||
Me.TXT_URL_PROFILE.Name = "TXT_URL_PROFILE"
|
|
||||||
Me.TXT_URL_PROFILE.Size = New System.Drawing.Size(578, 22)
|
|
||||||
Me.TXT_URL_PROFILE.TabIndex = 1
|
|
||||||
'
|
|
||||||
'TXT_URL_POST
|
|
||||||
'
|
|
||||||
ActionButton3.BackgroundImage = CType(resources.GetObject("ActionButton3.BackgroundImage"), System.Drawing.Image)
|
|
||||||
ActionButton3.Name = "Clear"
|
|
||||||
ActionButton3.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
|
|
||||||
Me.TXT_URL_POST.Buttons.Add(ActionButton3)
|
|
||||||
Me.TXT_URL_POST.CaptionText = "Post URL"
|
|
||||||
Me.TXT_URL_POST.CaptionWidth = 75.0R
|
|
||||||
Me.TXT_URL_POST.Dock = System.Windows.Forms.DockStyle.Fill
|
|
||||||
Me.TXT_URL_POST.Lines = New String(-1) {}
|
|
||||||
Me.TXT_URL_POST.Location = New System.Drawing.Point(3, 106)
|
|
||||||
Me.TXT_URL_POST.Name = "TXT_URL_POST"
|
|
||||||
Me.TXT_URL_POST.Size = New System.Drawing.Size(578, 22)
|
|
||||||
Me.TXT_URL_POST.TabIndex = 2
|
|
||||||
'
|
|
||||||
'TXT_REPRODUCE
|
|
||||||
'
|
|
||||||
ActionButton4.BackgroundImage = CType(resources.GetObject("ActionButton4.BackgroundImage"), System.Drawing.Image)
|
|
||||||
ActionButton4.Dock = System.Windows.Forms.DockStyle.Top
|
|
||||||
ActionButton4.Name = "Clear"
|
|
||||||
ActionButton4.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
|
|
||||||
Me.TXT_REPRODUCE.Buttons.Add(ActionButton4)
|
|
||||||
Me.TXT_REPRODUCE.CaptionDock = System.Windows.Forms.DockStyle.Top
|
|
||||||
Me.TXT_REPRODUCE.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.None
|
|
||||||
Me.TXT_REPRODUCE.CaptionVisible = False
|
|
||||||
Me.TXT_REPRODUCE.Dock = System.Windows.Forms.DockStyle.Fill
|
|
||||||
Me.TXT_REPRODUCE.GroupBoxed = True
|
|
||||||
Me.TXT_REPRODUCE.GroupBoxText = "To Reproduce"
|
|
||||||
Me.TXT_REPRODUCE.Lines = New String(-1) {}
|
|
||||||
Me.TXT_REPRODUCE.Location = New System.Drawing.Point(3, 134)
|
|
||||||
Me.TXT_REPRODUCE.Multiline = True
|
|
||||||
Me.TXT_REPRODUCE.Name = "TXT_REPRODUCE"
|
|
||||||
Me.TXT_REPRODUCE.Size = New System.Drawing.Size(578, 69)
|
|
||||||
Me.TXT_REPRODUCE.TabIndex = 3
|
|
||||||
Me.TXT_REPRODUCE.TextToolTip = "Steps to reproduce the behavior:" & Global.Microsoft.VisualBasic.ChrW(13) & Global.Microsoft.VisualBasic.ChrW(10) & "1. Do something" & Global.Microsoft.VisualBasic.ChrW(13) & Global.Microsoft.VisualBasic.ChrW(10) & "2. See error"
|
|
||||||
Me.TXT_REPRODUCE.TextToolTipEnabled = True
|
|
||||||
'
|
|
||||||
'TXT_EXPECT
|
|
||||||
'
|
|
||||||
ActionButton5.BackgroundImage = CType(resources.GetObject("ActionButton5.BackgroundImage"), System.Drawing.Image)
|
|
||||||
ActionButton5.Dock = System.Windows.Forms.DockStyle.Top
|
|
||||||
ActionButton5.Name = "Clear"
|
|
||||||
ActionButton5.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
|
|
||||||
Me.TXT_EXPECT.Buttons.Add(ActionButton5)
|
|
||||||
Me.TXT_EXPECT.CaptionDock = System.Windows.Forms.DockStyle.Top
|
|
||||||
Me.TXT_EXPECT.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.None
|
|
||||||
Me.TXT_EXPECT.CaptionVisible = False
|
|
||||||
Me.TXT_EXPECT.Dock = System.Windows.Forms.DockStyle.Fill
|
|
||||||
Me.TXT_EXPECT.GroupBoxed = True
|
|
||||||
Me.TXT_EXPECT.GroupBoxText = "Expected behavior"
|
|
||||||
Me.TXT_EXPECT.Lines = New String(-1) {}
|
|
||||||
Me.TXT_EXPECT.Location = New System.Drawing.Point(3, 209)
|
|
||||||
Me.TXT_EXPECT.Multiline = True
|
|
||||||
Me.TXT_EXPECT.Name = "TXT_EXPECT"
|
|
||||||
Me.TXT_EXPECT.Size = New System.Drawing.Size(578, 69)
|
|
||||||
Me.TXT_EXPECT.TabIndex = 4
|
|
||||||
Me.TXT_EXPECT.TextToolTip = "A clear and concise description of what you expected to happen."
|
|
||||||
Me.TXT_EXPECT.TextToolTipEnabled = True
|
|
||||||
'
|
|
||||||
'TXT_LOG
|
|
||||||
'
|
|
||||||
ActionButton6.BackgroundImage = CType(resources.GetObject("ActionButton6.BackgroundImage"), System.Drawing.Image)
|
|
||||||
ActionButton6.Dock = System.Windows.Forms.DockStyle.Top
|
|
||||||
ActionButton6.Name = "Open"
|
|
||||||
ActionButton6.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Open
|
|
||||||
ActionButton6.ToolTipText = "Select log files to add their text to the message"
|
|
||||||
ActionButton7.BackgroundImage = CType(resources.GetObject("ActionButton7.BackgroundImage"), System.Drawing.Image)
|
|
||||||
ActionButton7.Dock = System.Windows.Forms.DockStyle.Top
|
|
||||||
ActionButton7.Name = "Clear"
|
|
||||||
ActionButton7.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
|
|
||||||
ActionButton7.ToolTipText = "Empty"
|
|
||||||
Me.TXT_LOG.Buttons.Add(ActionButton6)
|
|
||||||
Me.TXT_LOG.Buttons.Add(ActionButton7)
|
|
||||||
Me.TXT_LOG.CaptionDock = System.Windows.Forms.DockStyle.Top
|
|
||||||
Me.TXT_LOG.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.None
|
|
||||||
Me.TXT_LOG.CaptionVisible = False
|
|
||||||
Me.TXT_LOG.Dock = System.Windows.Forms.DockStyle.Fill
|
|
||||||
Me.TXT_LOG.GroupBoxed = True
|
|
||||||
Me.TXT_LOG.GroupBoxText = "Log data"
|
|
||||||
Me.TXT_LOG.Lines = New String(-1) {}
|
|
||||||
Me.TXT_LOG.Location = New System.Drawing.Point(3, 284)
|
|
||||||
Me.TXT_LOG.Multiline = True
|
|
||||||
Me.TXT_LOG.Name = "TXT_LOG"
|
|
||||||
Me.TXT_LOG.Size = New System.Drawing.Size(578, 69)
|
|
||||||
Me.TXT_LOG.TabIndex = 5
|
|
||||||
'
|
|
||||||
'TXT_FILES
|
'TXT_FILES
|
||||||
'
|
'
|
||||||
ActionButton8.BackgroundImage = CType(resources.GetObject("ActionButton8.BackgroundImage"), System.Drawing.Image)
|
ActionButton8.BackgroundImage = CType(resources.GetObject("ActionButton8.BackgroundImage"), System.Drawing.Image)
|
||||||
@@ -310,7 +304,6 @@ Namespace Editors
|
|||||||
Me.TXT_FILES.Dock = System.Windows.Forms.DockStyle.Fill
|
Me.TXT_FILES.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
Me.TXT_FILES.GroupBoxed = True
|
Me.TXT_FILES.GroupBoxed = True
|
||||||
Me.TXT_FILES.GroupBoxText = "Files"
|
Me.TXT_FILES.GroupBoxText = "Files"
|
||||||
Me.TXT_FILES.Lines = New String(-1) {}
|
|
||||||
Me.TXT_FILES.Location = New System.Drawing.Point(3, 359)
|
Me.TXT_FILES.Location = New System.Drawing.Point(3, 359)
|
||||||
Me.TXT_FILES.Multiline = True
|
Me.TXT_FILES.Multiline = True
|
||||||
Me.TXT_FILES.Name = "TXT_FILES"
|
Me.TXT_FILES.Name = "TXT_FILES"
|
||||||
@@ -332,13 +325,13 @@ Namespace Editors
|
|||||||
Me.Name = "BugReporterForm"
|
Me.Name = "BugReporterForm"
|
||||||
Me.Text = "New message"
|
Me.Text = "New message"
|
||||||
TP_MAIN.ResumeLayout(False)
|
TP_MAIN.ResumeLayout(False)
|
||||||
TP_BUTTONS.ResumeLayout(False)
|
|
||||||
CType(Me.TXT_DESCR, System.ComponentModel.ISupportInitialize).EndInit()
|
CType(Me.TXT_DESCR, System.ComponentModel.ISupportInitialize).EndInit()
|
||||||
CType(Me.TXT_URL_PROFILE, System.ComponentModel.ISupportInitialize).EndInit()
|
CType(Me.TXT_URL_PROFILE, System.ComponentModel.ISupportInitialize).EndInit()
|
||||||
CType(Me.TXT_URL_POST, System.ComponentModel.ISupportInitialize).EndInit()
|
CType(Me.TXT_URL_POST, System.ComponentModel.ISupportInitialize).EndInit()
|
||||||
CType(Me.TXT_REPRODUCE, System.ComponentModel.ISupportInitialize).EndInit()
|
CType(Me.TXT_REPRODUCE, System.ComponentModel.ISupportInitialize).EndInit()
|
||||||
CType(Me.TXT_EXPECT, System.ComponentModel.ISupportInitialize).EndInit()
|
CType(Me.TXT_EXPECT, System.ComponentModel.ISupportInitialize).EndInit()
|
||||||
CType(Me.TXT_LOG, System.ComponentModel.ISupportInitialize).EndInit()
|
CType(Me.TXT_LOG, System.ComponentModel.ISupportInitialize).EndInit()
|
||||||
|
TP_BUTTONS.ResumeLayout(False)
|
||||||
CType(Me.TXT_FILES, System.ComponentModel.ISupportInitialize).EndInit()
|
CType(Me.TXT_FILES, System.ComponentModel.ISupportInitialize).EndInit()
|
||||||
Me.ResumeLayout(False)
|
Me.ResumeLayout(False)
|
||||||
|
|
||||||
|
|||||||
@@ -124,60 +124,60 @@
|
|||||||
<data name="ActionButton1.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ActionButton1.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
|
xAAADsQBlSsOGwAAAHpJREFUOE+1kVEKgDAMQ3e2/e+MXqpn6W/HxM7SpkIVB4HxSMKiTUTaFwVQ1X25
|
||||||
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
|
DjMfSxskHBYsAxHJkjUjHgrUNMY4peaMPxb03rcZMVhgn2oDKAwn+L0aROH/Cny4NAGFSx8x+10ZDwV2
|
||||||
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
|
gt+LOCxQsw1nPBS8VQBVTTzyhrdZSUm7AAAAAElFTkSuQmCC
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ActionButton2.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ActionButton2.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
|
xAAADsQBlSsOGwAAAHpJREFUOE+1kVEKgDAMQ3e2/e+MXqpn6W/HxM7SpkIVB4HxSMKiTUTaFwVQ1X25
|
||||||
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
|
DjMfSxskHBYsAxHJkjUjHgrUNMY4peaMPxb03rcZMVhgn2oDKAwn+L0aROH/Cny4NAGFSx8x+10ZDwV2
|
||||||
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
|
gt+LOCxQsw1nPBS8VQBVTTzyhrdZSUm7AAAAAElFTkSuQmCC
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ActionButton3.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ActionButton3.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
|
xAAADsQBlSsOGwAAAHpJREFUOE+1kVEKgDAMQ3e2/e+MXqpn6W/HxM7SpkIVB4HxSMKiTUTaFwVQ1X25
|
||||||
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
|
DjMfSxskHBYsAxHJkjUjHgrUNMY4peaMPxb03rcZMVhgn2oDKAwn+L0aROH/Cny4NAGFSx8x+10ZDwV2
|
||||||
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
|
gt+LOCxQsw1nPBS8VQBVTTzyhrdZSUm7AAAAAElFTkSuQmCC
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ActionButton4.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ActionButton4.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
|
xAAADsQBlSsOGwAAAHpJREFUOE+1kVEKgDAMQ3e2/e+MXqpn6W/HxM7SpkIVB4HxSMKiTUTaFwVQ1X25
|
||||||
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
|
DjMfSxskHBYsAxHJkjUjHgrUNMY4peaMPxb03rcZMVhgn2oDKAwn+L0aROH/Cny4NAGFSx8x+10ZDwV2
|
||||||
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
|
gt+LOCxQsw1nPBS8VQBVTTzyhrdZSUm7AAAAAElFTkSuQmCC
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ActionButton5.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ActionButton5.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
|
xAAADsQBlSsOGwAAAHpJREFUOE+1kVEKgDAMQ3e2/e+MXqpn6W/HxM7SpkIVB4HxSMKiTUTaFwVQ1X25
|
||||||
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
|
DjMfSxskHBYsAxHJkjUjHgrUNMY4peaMPxb03rcZMVhgn2oDKAwn+L0aROH/Cny4NAGFSx8x+10ZDwV2
|
||||||
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
|
gt+LOCxQsw1nPBS8VQBVTTzyhrdZSUm7AAAAAElFTkSuQmCC
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ActionButton6.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ActionButton6.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP
|
wwAADsMBx2+oZAAAARlJREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbWujg3dATZPKYZC6BQhvw1AMkg3dP
|
||||||
WQwhyWIyJIUW5NqyPb7oCVtIlhVTwYf8nv7/t2zJagel9KmqKsIACYL9RjI8UHz5zshougZr/AEvbxEP
|
XQyl7WIyJIEW5CbS0/jKE5GwpCghgg9s6/8/y5Kj6DA45zcAwAAAezB6rjNnB4XX244NHt8wGs7wblop
|
||||||
aZCDBY3VslixaJvX3wzkkDiOwbZtDRGA5vdNAg+TL27qgmt5XkBG/gTdAG7Gt+3PP9oOaEGFCVEC6rp+
|
yRGxwZQBYKIfbn477EvqusY4jj2MgMpPiwav7l9UyYXmdrs9duzP4ApUmd72sfrxVsD33JQISyClvFUX
|
||||||
5g9MfM/c5e4OsEZMZkQEtGL5H2DdZ5JRArDwPA+iKII0TfkC9vroC9j5vq8JTWw3WzWgLMtZGIaa0MR8
|
w9nJssvJFei9CJUtgQ7394Du3YKLJaCbLMuwqips21ZNuDve/35X8J7nuRcMsVwsbYEQYlSWpRcMMR5P
|
||||||
vlAD8PYlSaIJTTiOowY0p0Bc19XEJo6HE59FAPuMzyAINKGJ1XLFZxHALtMrnkBXOIQIIIQ8YvF/KrgB
|
bAH9fU3TeMEQSZLYgsMpsDRNvXCIr89vWyCEeC6KwguGmL/ObYGU8oFOwA2ewwgYY9f6f7iUf3DGkTcu
|
||||||
cMaRN0UdBBkAAAAASUVORK5CYII=
|
khP7AAAAAElFTkSuQmCC
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ActionButton7.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ActionButton7.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
|
xAAADsQBlSsOGwAAAHpJREFUOE+1kVEKgDAMQ3e2/e+MXqpn6W/HxM7SpkIVB4HxSMKiTUTaFwVQ1X25
|
||||||
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
|
DjMfSxskHBYsAxHJkjUjHgrUNMY4peaMPxb03rcZMVhgn2oDKAwn+L0aROH/Cny4NAGFSx8x+10ZDwV2
|
||||||
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
|
gt+LOCxQsw1nPBS8VQBVTTzyhrdZSUm7AAAAAElFTkSuQmCC
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<metadata name="TP_BUTTONS.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
<metadata name="TP_BUTTONS.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
@@ -195,31 +195,31 @@ If you would like a response from the developer, response, please add your conta
|
|||||||
<data name="ActionButton8.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ActionButton8.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
|
iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
|
||||||
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAADmUlE
|
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAADrElE
|
||||||
QVRIS62WWWxMURjHL220JW1HausmlFrDFKUhnUGH6bRFzJ2idImlC0Vp2mlji1A8iNhCPIjIRES8EU+W
|
QVRIS62WX2xTZRjGP9yybpB1NVVwW0dwggJGW2GwuOwUbLXrOjSe0w0G+xPErZPqJsvWLSDGsKkXxqAQ
|
||||||
h2oEtbSDTk3HNNM7S01VKsXjkb/vXBo3k1Ee7sMvmZzzzf//ne/+z50RAAxL1MUIG4G/YAv3HSVhF5Vw
|
jReEmMYY4x3GK9ELWAyuQ7oCO6UrXbrzp1vryMzEy4885pxBXL5G5sW5+N28583zO/nyfKclAMjDMJ0t
|
||||||
IYNdz3LadVj9RgdTB+HQYYPHIJuE1ocSdlEJFzG+1bPRLQLinglIeCkg+XUkKvz56hnkOfQs/rmA8S9H
|
CJvOFuA/CLP7LHkDFi3IHXNS1ySHV65z8E5x8IocWtJuXcLus+QNWLQQzw0nXTtGYP6NwHqVoPJaIbpV
|
||||||
YEp7FDI64tAQtKhnsMapZ7zzNHsUFnbGY4VzIk70l6hnIH4wsDR7NBZ3apDrSqL5T8eFgUr1DLZ78lim
|
n3GCRtFJy8YJHr+6BpsmTXBMmTGU9Rsn2JdwUu3Nq2Mm7IiXYW9iAz5caDdOINx20+pYMXbFLWhIVqAl
|
||||||
Q4N8VzK29MxEpZSBa4M16hnU+c3M9CEFpdJsVHsXos63DDcHrf9nQEXD5VymwW/5USLNwl5vJhp7dTgW
|
vRlnFgPGCY6kG2mNaIEvWYlDs88gIDlwfqnPOMGAylPvbRs6pG0IyjswoNTh26XQ/xOs0nOdIdV/r13a
|
||||||
NML2pR7jbsUMS+KdMTa5Q8NQxinfBU4dRFcOyjy52OtbhwOBDTgZLKPPmTgY0ON4MBdNfSbYBupxY8Aq
|
il65BsNzHE5lPQj/OYjHvit5KOUX1oWXe/6g4yKHpgQHIelCZ7oBvcprOJ5pwUfZTvQqNTiRcWIk24DR
|
||||||
G10dqMG5/nIc7ytGQ6CQRliAamkTN/g1Ai4e95Qy3iogpX0UtBRDnhRzdxq2SXOxz5eFQ70rScCEU335
|
nBfhxUF8sxjSRecW+/DZQhdGcm0YyjQjIDUhKB3QBMtHoIWbrxBYIwS2ySLYp8x6U/iZarwhPYt3lVq8
|
||||||
ssGxj0YS06HSm4GN3ekwdE2C1hGH1LZR0JDOJof5jwHvnIvzTa0jlooTYfktvt+fhcOBHDQFTWRgxJGP
|
N/cSRnJefJzz6YJT8x4MZTgEZAf2z2yBe/oJ2EUzqqJFsEQIDoj8vwLtzbVw7aFdLIV7uhz+++HH1Fqc
|
||||||
ObAGsulZLMLWnjlY756K5c4JmNcRi6T2SGheCIihS2l5ozAo6NRhMolnUAcGV6IcwwqvFrX+JTjYuwKH
|
zLgwmvViJOfB+/MuhDL1CMo7cXh2O15PPYk9ifV4bqoUFZOFsEwQlIwR+K+vEDTFOWyMFsEhmuFOlus1
|
||||||
SfRAYDms/mzs9y1GFe2VSnOw1j0FejqpLN4WCX4ZufiIBwLMLxQGm12rsLQzgWKYgmLPLNTQw6ynpDSS
|
7Jbt6Fd348TcXpycd+F4Zg9Caj2OKbvQI9vRIW3Hq6lNcCY2LIdHC6FdRi18zUUCfmKF4GDyZbwYt8KX
|
||||||
IBet8y+TqaVRVdFIeJrWuCcj+/0EzH43BomvIhBLI45uFiDcJ+6QwROFwa6+Amb9bGFNg6Xs9Ncd7Oy3
|
tKEtvRV9cg0GlToMq/V66IBap9Ov1KJHduht2pfaiPpb67Ht5jqU/16A0isExZcIyE8E5AIB/+sKwdFc
|
||||||
Knb2eyU7/20nu9y/m136tIvEl6BC0qKoZwby3alo9JVhj7T5R7m/kJVIIityi8zyXmTiW+I10SqyIQNb
|
Ew3d8dPRpQ76yV9v0tN3e+jpvwP087tv0S8X3qZf/HEU/cpudEt2tM4+DV+qCsNKJ96RDt7rUptpuyTQ
|
||||||
uIgNwYuuf25kFd75KPKkI49OmUWnrfYWyXv/wBb2cijhhVf6a9lGei65XclYRDd6mj0GWz2iLBJaH0rY
|
1pRA/bcEKtwQqHBNoEJEoA8EYbZeTNXw9Z1h2i0/j9b0FjQmbaiNWxGUW/VnqxDOuxgs2uJXC/10f3oz
|
||||||
RSVc5Eywmhm7kuQXHX+bJlBStrh+zTi0PpSwi0q4yNFAOVvgiEcKJWUsxZn/NhT+znlofShhF5VwkRpv
|
GqYrsVO04KlYCQ6nBT2E3WfJG7BoIZ9mg9QzXaF/6LSvqXWC4FBy+YzZfZa8AYsW8kGmi74glsEWLcSj
|
||||||
MUtti4KGYjj6sYCIh5QSu4oG27stjItHU+cjeQzvkcFzFQ2KnSKLoc4FukDCXeI2GbSoaFD4ziyPxNxK
|
EQLtt6H5fs/ZfZa8AYsW0ie30aqoCZZxgrWXCQp+JuBjBgqOzPipFl48RvCIVsMfCfhxAwVtCYGWXCYg
|
||||||
0AUyNxOP1DOwcaG/8I+/LRB+At7psBnyDBG0AAAAAElFTkSuQmCC
|
FwnIDwTkewJ+zEBB801ePxI+wusXiL/Eg//FOEF4Ra9ZVv3b8g/e6bAZV4ggywAAAABJRU5ErkJggg==
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ActionButton9.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ActionButton9.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
|
xAAADsQBlSsOGwAAAHpJREFUOE+1kVEKgDAMQ3e2/e+MXqpn6W/HxM7SpkIVB4HxSMKiTUTaFwVQ1X25
|
||||||
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
|
DjMfSxskHBYsAxHJkjUjHgrUNMY4peaMPxb03rcZMVhgn2oDKAwn+L0aROH/Cny4NAGFSx8x+10ZDwV2
|
||||||
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
|
gt+LOCxQsw1nPBS8VQBVTTzyhrdZSUm7AAAAAElFTkSuQmCC
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
</root>
|
</root>
|
||||||
@@ -32,6 +32,6 @@ Imports System.Runtime.InteropServices
|
|||||||
' by using the '*' as shown below:
|
' by using the '*' as shown below:
|
||||||
' <Assembly: AssemblyVersion("1.0.*")>
|
' <Assembly: AssemblyVersion("1.0.*")>
|
||||||
|
|
||||||
<Assembly: AssemblyVersion("2025.1.12.0")>
|
<Assembly: AssemblyVersion("2025.6.1.0")>
|
||||||
<Assembly: AssemblyFileVersion("2025.1.12.0")>
|
<Assembly: AssemblyFileVersion("2025.6.1.0")>
|
||||||
<Assembly: NeutralResourcesLanguage("en")>
|
<Assembly: NeutralResourcesLanguage("en")>
|
||||||
|
|||||||
@@ -116,7 +116,9 @@ Namespace API.YouTube.Objects
|
|||||||
<XMLEC> Public Property IsShorts As Boolean = False Implements IYouTubeMediaContainer.IsShorts
|
<XMLEC> Public Property IsShorts As Boolean = False Implements IYouTubeMediaContainer.IsShorts
|
||||||
<XMLEC> Public Property ID As String Implements IYouTubeMediaContainer.ID, IUserMedia.PostID
|
<XMLEC> Public Property ID As String Implements IYouTubeMediaContainer.ID, IUserMedia.PostID
|
||||||
<XMLEC> Public Property Title As String Implements IDownloadableMedia.Title
|
<XMLEC> Public Property Title As String Implements IDownloadableMedia.Title
|
||||||
<XMLEC> Public Property Description As String Implements IYouTubeMediaContainer.Description
|
<XMLEC> Public Property Description As String Implements IYouTubeMediaContainer.Description, IUserMedia.PostText
|
||||||
|
Private Property IUserMedia_PostTextFile As String Implements IUserMedia.PostTextFile
|
||||||
|
Private Property IUserMedia_PostTextFileSpecialFolder As Boolean Implements IUserMedia.PostTextFileSpecialFolder
|
||||||
<XMLEC> Public Property PlaylistID As String Implements IYouTubeMediaContainer.PlaylistID
|
<XMLEC> Public Property PlaylistID As String Implements IYouTubeMediaContainer.PlaylistID
|
||||||
<XMLEC> Public Property PlaylistTitle As String Implements IYouTubeMediaContainer.PlaylistTitle
|
<XMLEC> Public Property PlaylistTitle As String Implements IYouTubeMediaContainer.PlaylistTitle
|
||||||
<XMLEC> Public Property UserID As String Implements IYouTubeMediaContainer.UserID
|
<XMLEC> Public Property UserID As String Implements IYouTubeMediaContainer.UserID
|
||||||
@@ -1215,12 +1217,12 @@ Namespace API.YouTube.Objects
|
|||||||
End If
|
End If
|
||||||
|
|
||||||
With MyYouTubeSettings
|
With MyYouTubeSettings
|
||||||
If .CreateDescriptionFiles And (Not Description.IsEmptyString Or
|
If .CreateDescriptionFiles And (Not Description.IsEmptyString Or .CreateDescriptionFiles_CreateWithNoDescription) Then
|
||||||
(.CreateDescriptionFiles_CreateWithNoDescription And .CreateDescriptionFiles_AddUploadDate)) Then
|
|
||||||
Dim fileDesr As SFile = File
|
Dim fileDesr As SFile = File
|
||||||
fileDesr.Extension = "txt"
|
fileDesr.Extension = "txt"
|
||||||
Using fileDesrText As New TextSaver(fileDesr)
|
Using fileDesrText As New TextSaver(fileDesr)
|
||||||
If .CreateDescriptionFiles_AddUploadDate Then fileDesrText.Append($"Uploaded: {DateAdded:yyyy-MM-dd HH:mm:ss}")
|
fileDesrText.Append($"Uploaded: {DateAdded:yyyy-MM-dd HH:mm:ss}")
|
||||||
|
fileDesrText.AppendLine()
|
||||||
fileDesrText.AppendLine($"URL: {URL}")
|
fileDesrText.AppendLine($"URL: {URL}")
|
||||||
fileDesrText.AppendLine($"Channel name: {AccountName}")
|
fileDesrText.AppendLine($"Channel name: {AccountName}")
|
||||||
fileDesrText.AppendLine($"Channel ID: {UserID}")
|
fileDesrText.AppendLine($"Channel ID: {UserID}")
|
||||||
|
|||||||
@@ -124,12 +124,19 @@
|
|||||||
<Compile Include="Controls\ChannelTabsChooserForm.vb">
|
<Compile Include="Controls\ChannelTabsChooserForm.vb">
|
||||||
<SubType>Form</SubType>
|
<SubType>Form</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="Controls\FilterForm.Designer.vb">
|
||||||
|
<DependentUpon>FilterForm.vb</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Controls\FilterForm.vb">
|
||||||
|
<SubType>Form</SubType>
|
||||||
|
</Compile>
|
||||||
<Compile Include="Controls\PlayListParserForm.Designer.vb">
|
<Compile Include="Controls\PlayListParserForm.Designer.vb">
|
||||||
<DependentUpon>PlayListParserForm.vb</DependentUpon>
|
<DependentUpon>PlayListParserForm.vb</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Controls\PlayListParserForm.vb">
|
<Compile Include="Controls\PlayListParserForm.vb">
|
||||||
<SubType>Form</SubType>
|
<SubType>Form</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="Controls\YTDataFilter.vb" />
|
||||||
<Compile Include="Downloader\DownloadLocationsCollection.vb" />
|
<Compile Include="Downloader\DownloadLocationsCollection.vb" />
|
||||||
<Compile Include="Downloader\IDownloaderSettings.vb" />
|
<Compile Include="Downloader\IDownloaderSettings.vb" />
|
||||||
<Compile Include="Downloader\Notificator.vb" />
|
<Compile Include="Downloader\Notificator.vb" />
|
||||||
@@ -220,6 +227,9 @@
|
|||||||
<EmbeddedResource Include="Controls\ChannelTabsChooserForm.resx">
|
<EmbeddedResource Include="Controls\ChannelTabsChooserForm.resx">
|
||||||
<DependentUpon>ChannelTabsChooserForm.vb</DependentUpon>
|
<DependentUpon>ChannelTabsChooserForm.vb</DependentUpon>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
|
<EmbeddedResource Include="Controls\FilterForm.resx">
|
||||||
|
<DependentUpon>FilterForm.vb</DependentUpon>
|
||||||
|
</EmbeddedResource>
|
||||||
<EmbeddedResource Include="Controls\PlayListParserForm.resx">
|
<EmbeddedResource Include="Controls\PlayListParserForm.resx">
|
||||||
<DependentUpon>PlayListParserForm.vb</DependentUpon>
|
<DependentUpon>PlayListParserForm.vb</DependentUpon>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
|
|||||||
@@ -32,6 +32,6 @@ Imports System.Runtime.InteropServices
|
|||||||
' by using the '*' as shown below:
|
' by using the '*' as shown below:
|
||||||
' <Assembly: AssemblyVersion("1.0.*")>
|
' <Assembly: AssemblyVersion("1.0.*")>
|
||||||
|
|
||||||
<Assembly: AssemblyVersion("2025.1.12.0")>
|
<Assembly: AssemblyVersion("2025.6.1.0")>
|
||||||
<Assembly: AssemblyFileVersion("2025.1.12.0")>
|
<Assembly: AssemblyFileVersion("2025.6.1.0")>
|
||||||
<Assembly: NeutralResourcesLanguage("en")>
|
<Assembly: NeutralResourcesLanguage("en")>
|
||||||
|
|||||||
@@ -30,6 +30,13 @@ Namespace API.Base
|
|||||||
Friend Const UseMD5ComparisonToolTip As String = "Each image will be checked for existence using MD5"
|
Friend Const UseMD5ComparisonToolTip As String = "Each image will be checked for existence using MD5"
|
||||||
Friend Const UserNameChangeCaption As String = "UserName"
|
Friend Const UserNameChangeCaption As String = "UserName"
|
||||||
Friend Const UserNameChangeToolTip As String = "If the user has changed their UserName, you can set a new name here. Not required for new users."
|
Friend Const UserNameChangeToolTip As String = "If the user has changed their UserName, you can set a new name here. Not required for new users."
|
||||||
|
|
||||||
|
Friend Const DownloadTextCaption As String = "Download text"
|
||||||
|
Friend Const DownloadTextTip As String = "Download text (if available) for posts with image and video" & vbCr & "If this checkbox is checked, the post text will be downloaded along with the file and saved under the same name but with the 'txt' extension."
|
||||||
|
Friend Const DownloadTextPostsCaption As String = "Download text posts"
|
||||||
|
Friend Const DownloadTextPostsTip As String = "Download text (if available) for text posts (no image and video)"
|
||||||
|
Friend Const DownloadTextSpecialFolderCaption As String = "Text special folder"
|
||||||
|
Friend Const DownloadTextSpecialFolderTip As String = "If checked, text files will be saved to a separate folder"
|
||||||
Private Sub New()
|
Private Sub New()
|
||||||
End Sub
|
End Sub
|
||||||
End Class
|
End Class
|
||||||
|
|||||||
46
SCrawler/API/Base/EditorExchangeOptionsBase.vb
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
' Copyright (C) Andy https://github.com/AAndyProgram
|
||||||
|
' This program is free software: you can redistribute it and/or modify
|
||||||
|
' it under the terms of the GNU General Public License as published by
|
||||||
|
' the Free Software Foundation, either version 3 of the License, or
|
||||||
|
' (at your option) any later version.
|
||||||
|
'
|
||||||
|
' This program is distributed in the hope that it will be useful,
|
||||||
|
' but WITHOUT ANY WARRANTY
|
||||||
|
Imports SCrawler.Plugin.Attributes
|
||||||
|
Imports DN = SCrawler.API.Base.DeclaredNames
|
||||||
|
Namespace API.Base
|
||||||
|
Friend Class EditorExchangeOptionsBase
|
||||||
|
Friend Overridable Property SiteKey As String
|
||||||
|
<PSetting(Address:=SettingAddress.User, Caption:=DN.UserNameChangeCaption, ToolTip:=DN.UserNameChangeToolTip)>
|
||||||
|
Friend Overridable Property UserName As String = String.Empty
|
||||||
|
<PSetting(Address:=SettingAddress.User, Caption:=DN.DownloadTextCaption, ToolTip:=DN.DownloadTextTip)>
|
||||||
|
Friend Overridable Property DownloadText As Boolean = False
|
||||||
|
<PSetting(Address:=SettingAddress.User, Caption:=DN.DownloadTextPostsCaption, ToolTip:=DN.DownloadTextPostsTip)>
|
||||||
|
Friend Overridable Property DownloadTextPosts As Boolean = False
|
||||||
|
<PSetting(Address:=SettingAddress.User, Caption:=DN.DownloadTextSpecialFolderCaption, ToolTip:=DN.DownloadTextSpecialFolderTip)>
|
||||||
|
Friend Overridable Property DownloadTextSpecialFolder As Boolean = False
|
||||||
|
Friend Sub New(ByVal u As UserDataBase)
|
||||||
|
UserName = u.NameTrue(True)
|
||||||
|
DownloadText = u.DownloadText
|
||||||
|
DownloadTextPosts = u.DownloadTextPosts
|
||||||
|
DownloadTextSpecialFolder = u.DownloadTextSpecialFolder
|
||||||
|
End Sub
|
||||||
|
Friend Sub New(ByVal s As SiteSettingsBase)
|
||||||
|
DownloadText = s.DownloadText.Value
|
||||||
|
DownloadTextPosts = s.DownloadTextPosts.Value
|
||||||
|
DownloadTextSpecialFolder = s.DownloadTextSpecialFolder.Value
|
||||||
|
End Sub
|
||||||
|
Friend Sub New()
|
||||||
|
End Sub
|
||||||
|
Protected _ApplyBase_Name As Boolean = True
|
||||||
|
Protected _ApplyBase_Text As Boolean = True
|
||||||
|
Friend Sub ApplyBase(ByRef u As UserDataBase)
|
||||||
|
If _ApplyBase_Name Then u.NameTrue = UserName
|
||||||
|
If _ApplyBase_Text Then
|
||||||
|
u.DownloadText = DownloadText
|
||||||
|
u.DownloadTextPosts = DownloadTextPosts
|
||||||
|
u.DownloadTextSpecialFolder = DownloadTextSpecialFolder
|
||||||
|
End If
|
||||||
|
End Sub
|
||||||
|
End Class
|
||||||
|
End Namespace
|
||||||
@@ -6,66 +6,7 @@
|
|||||||
'
|
'
|
||||||
' This program is distributed in the hope that it will be useful,
|
' This program is distributed in the hope that it will be useful,
|
||||||
' but WITHOUT ANY WARRANTY
|
' but WITHOUT ANY WARRANTY
|
||||||
Imports PersonalUtilities.Tools
|
|
||||||
Imports PersonalUtilities.Functions.RegularExpressions
|
|
||||||
Namespace API.Base.GDL
|
Namespace API.Base.GDL
|
||||||
Friend Module Declarations
|
|
||||||
Private Structure GDLURL : Implements IRegExCreator
|
|
||||||
Private _URL As String
|
|
||||||
Friend ReadOnly Property URL As String
|
|
||||||
Get
|
|
||||||
Return _URL
|
|
||||||
End Get
|
|
||||||
End Property
|
|
||||||
Public Shared Widening Operator CType(ByVal u As String) As GDLURL
|
|
||||||
Return New GDLURL With {._URL = u}
|
|
||||||
End Operator
|
|
||||||
Public Shared Widening Operator CType(ByVal u As GDLURL) As String
|
|
||||||
Return u.URL
|
|
||||||
End Operator
|
|
||||||
Private Function CreateFromArray(ByVal ParamsArray() As String) As Object Implements IRegExCreator.CreateFromArray
|
|
||||||
If ParamsArray.ListExists(2) Then
|
|
||||||
Dim u$ = ParamsArray(0).StringTrim.StringTrimEnd("/"), u2$
|
|
||||||
If Not u.IsEmptyString Then
|
|
||||||
u2 = ParamsArray(1).StringTrim
|
|
||||||
If Not u2.IsEmptyString AndAlso u2.StartsWith("GET", StringComparison.OrdinalIgnoreCase) Then
|
|
||||||
u2 = u2.Remove(0, 3).StringTrim.StringTrimStart("/")
|
|
||||||
If Not u2.IsEmptyString Then _URL = $"{u}/{u2}"
|
|
||||||
End If
|
|
||||||
End If
|
|
||||||
End If
|
|
||||||
Return Me
|
|
||||||
End Function
|
|
||||||
Public Shared Operator =(ByVal x As GDLURL, ByVal y As GDLURL) As Boolean
|
|
||||||
Return x.URL = y.URL
|
|
||||||
End Operator
|
|
||||||
Public Shared Operator <>(ByVal x As GDLURL, ByVal y As GDLURL) As Boolean
|
|
||||||
Return Not x.URL = y.URL
|
|
||||||
End Operator
|
|
||||||
Public Overrides Function ToString() As String
|
|
||||||
Return URL
|
|
||||||
End Function
|
|
||||||
Public Overrides Function Equals(ByVal Obj As Object) As Boolean
|
|
||||||
Return URL = CType(Obj, String)
|
|
||||||
End Function
|
|
||||||
End Structure
|
|
||||||
Private ReadOnly Property GdlUrlPattern As RParams = RParams.DM(GDLBatch.UrlLibStart.Replace("[", "\[").Replace("]", "\]") &
|
|
||||||
"([^""]+?)""(GET [^""]+)""", 0, EDP.ReturnValue)
|
|
||||||
Friend Function GetUrlsFromGalleryDl(ByVal Batch As BatchExecutor, ByVal Command As String) As List(Of String)
|
|
||||||
Dim urls As New List(Of String)
|
|
||||||
Dim u As GDLURL
|
|
||||||
With Batch
|
|
||||||
.Execute(Command)
|
|
||||||
If .ErrorOutputData.Count > 0 Then
|
|
||||||
For Each eValue$ In .ErrorOutputData
|
|
||||||
u = RegexFields(Of GDLURL)(eValue, {GdlUrlPattern}, {1, 2}, EDP.ReturnValue).ListIfNothing.FirstOrDefault
|
|
||||||
If Not u.URL.IsEmptyString Then urls.ListAddValue(u, LNC)
|
|
||||||
Next
|
|
||||||
End If
|
|
||||||
End With
|
|
||||||
Return urls
|
|
||||||
End Function
|
|
||||||
End Module
|
|
||||||
Friend Class GDLBatch : Inherits TokenBatch
|
Friend Class GDLBatch : Inherits TokenBatch
|
||||||
Friend Const UrlLibStart As String = "[urllib3.connectionpool][debug]"
|
Friend Const UrlLibStart As String = "[urllib3.connectionpool][debug]"
|
||||||
Friend Const UrlTextStart As String = UrlLibStart & " https"
|
Friend Const UrlTextStart As String = UrlLibStart & " https"
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ Namespace API.Base
|
|||||||
End Enum
|
End Enum
|
||||||
ReadOnly Property Site As String
|
ReadOnly Property Site As String
|
||||||
ReadOnly Property Name As String
|
ReadOnly Property Name As String
|
||||||
|
Property NameTrue As String
|
||||||
Property ID As String
|
Property ID As String
|
||||||
Property Options As String
|
Property Options As String
|
||||||
Property FriendlyName As String
|
Property FriendlyName As String
|
||||||
@@ -56,6 +57,7 @@ Namespace API.Base
|
|||||||
Property FileExists As Boolean
|
Property FileExists As Boolean
|
||||||
Property DownloadedPictures(ByVal Total As Boolean) As Integer
|
Property DownloadedPictures(ByVal Total As Boolean) As Integer
|
||||||
Property DownloadedVideos(ByVal Total As Boolean) As Integer
|
Property DownloadedVideos(ByVal Total As Boolean) As Integer
|
||||||
|
Property DownloadedTexts(ByVal Total As Boolean) As Integer
|
||||||
ReadOnly Property DownloadedTotal(Optional ByVal Total As Boolean = True) As Integer
|
ReadOnly Property DownloadedTotal(Optional ByVal Total As Boolean = True) As Integer
|
||||||
ReadOnly Property DownloadedInformation As String
|
ReadOnly Property DownloadedInformation As String
|
||||||
Property HasError As Boolean
|
Property HasError As Boolean
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ Imports PersonalUtilities.Tools.Web.Cookies
|
|||||||
Imports PersonalUtilities.Tools.Web.Clients
|
Imports PersonalUtilities.Tools.Web.Clients
|
||||||
Imports PersonalUtilities.Functions.RegularExpressions
|
Imports PersonalUtilities.Functions.RegularExpressions
|
||||||
Imports Download = SCrawler.Plugin.ISiteSettings.Download
|
Imports Download = SCrawler.Plugin.ISiteSettings.Download
|
||||||
|
Imports DN = SCrawler.API.Base.DeclaredNames
|
||||||
Namespace API.Base
|
Namespace API.Base
|
||||||
Friend MustInherit Class SiteSettingsBase : Implements ISiteSettings, IResponserContainer
|
Friend MustInherit Class SiteSettingsBase : Implements ISiteSettings, IResponserContainer
|
||||||
#Region "Declarations"
|
#Region "Declarations"
|
||||||
@@ -33,7 +34,7 @@ Namespace API.Base
|
|||||||
End Property
|
End Property
|
||||||
Friend Property AccountName As String Implements ISiteSettings.AccountName
|
Friend Property AccountName As String Implements ISiteSettings.AccountName
|
||||||
Friend Property Temporary As Boolean = False Implements ISiteSettings.Temporary
|
Friend Property Temporary As Boolean = False Implements ISiteSettings.Temporary
|
||||||
Friend Property DefaultInstance As ISiteSettings = Nothing Implements ISiteSettings.DefaultInstance
|
Friend Overridable Property DefaultInstance As ISiteSettings = Nothing Implements ISiteSettings.DefaultInstance
|
||||||
Protected _UserAgentDefault As String = String.Empty
|
Protected _UserAgentDefault As String = String.Empty
|
||||||
Friend Overridable Property UserAgentDefault As String Implements ISiteSettings.UserAgentDefault
|
Friend Overridable Property UserAgentDefault As String Implements ISiteSettings.UserAgentDefault
|
||||||
Get
|
Get
|
||||||
@@ -55,6 +56,11 @@ Namespace API.Base
|
|||||||
Friend Overridable ReadOnly Property Responser As Responser
|
Friend Overridable ReadOnly Property Responser As Responser
|
||||||
Private _UserOptionsExists As Boolean = False
|
Private _UserOptionsExists As Boolean = False
|
||||||
Private _UserOptionsType As Type = Nothing
|
Private _UserOptionsType As Type = Nothing
|
||||||
|
Protected Overridable Function UserOptionsValid(ByVal Options As Object) As Boolean
|
||||||
|
Return True
|
||||||
|
End Function
|
||||||
|
Protected Overridable Sub UserOptionsSetParameters(ByRef Options As Object)
|
||||||
|
End Sub
|
||||||
Protected Property UserOptionsType As Type
|
Protected Property UserOptionsType As Type
|
||||||
Get
|
Get
|
||||||
Return _UserOptionsType
|
Return _UserOptionsType
|
||||||
@@ -64,6 +70,14 @@ Namespace API.Base
|
|||||||
_UserOptionsExists = Not t Is Nothing
|
_UserOptionsExists = Not t Is Nothing
|
||||||
End Set
|
End Set
|
||||||
End Property
|
End Property
|
||||||
|
#Region "New user defaults"
|
||||||
|
<PropertyOption(ControlText:=DN.DownloadTextCaption, ControlToolTip:=DN.DownloadTextTip, Category:=DN.CAT_UserDefs), PXML, PClonable>
|
||||||
|
Friend Overridable Property DownloadText As PropertyValue
|
||||||
|
<PropertyOption(ControlText:=DN.DownloadTextPostsCaption, ControlToolTip:=DN.DownloadTextPostsTip, Category:=DN.CAT_UserDefs), PXML, PClonable>
|
||||||
|
Friend Overridable Property DownloadTextPosts As PropertyValue
|
||||||
|
<PropertyOption(ControlText:=DN.DownloadTextSpecialFolderCaption, ControlToolTip:=DN.DownloadTextSpecialFolderTip, Category:=DN.CAT_UserDefs), PXML, PClonable>
|
||||||
|
Friend Overridable Property DownloadTextSpecialFolder As PropertyValue
|
||||||
|
#End Region
|
||||||
#End Region
|
#End Region
|
||||||
#Region "EnvironmentPrograms"
|
#Region "EnvironmentPrograms"
|
||||||
Private Property CMDEncoding As String Implements ISiteSettings.CMDEncoding
|
Private Property CMDEncoding As String Implements ISiteSettings.CMDEncoding
|
||||||
@@ -119,6 +133,9 @@ Namespace API.Base
|
|||||||
_Image = __Image
|
_Image = __Image
|
||||||
Responser = New Responser With {.DeclaredError = EDP.ThrowException}
|
Responser = New Responser With {.DeclaredError = EDP.ThrowException}
|
||||||
SettingsVersion = New PropertyValue(0)
|
SettingsVersion = New PropertyValue(0)
|
||||||
|
DownloadText = New PropertyValue(False)
|
||||||
|
DownloadTextPosts = New PropertyValue(False)
|
||||||
|
DownloadTextSpecialFolder = New PropertyValue(True)
|
||||||
UpdateResponserFile()
|
UpdateResponserFile()
|
||||||
End Sub
|
End Sub
|
||||||
Friend Sub New(ByVal SiteName As String, ByVal CookiesDomain As String, ByVal AccName As String, ByVal Temp As Boolean,
|
Friend Sub New(ByVal SiteName As String, ByVal CookiesDomain As String, ByVal AccName As String, ByVal Temp As Boolean,
|
||||||
@@ -243,7 +260,7 @@ Namespace API.Base
|
|||||||
#Region "User info"
|
#Region "User info"
|
||||||
Protected UrlPatternUser As String = String.Empty
|
Protected UrlPatternUser As String = String.Empty
|
||||||
Friend Overridable Function GetUserUrl(ByVal User As IPluginContentProvider) As String Implements ISiteSettings.GetUserUrl
|
Friend Overridable Function GetUserUrl(ByVal User As IPluginContentProvider) As String Implements ISiteSettings.GetUserUrl
|
||||||
If Not UrlPatternUser.IsEmptyString Then Return String.Format(UrlPatternUser, User.Name)
|
If Not UrlPatternUser.IsEmptyString Then Return String.Format(UrlPatternUser, User.NameTrue.IfNullOrEmpty(User.Name))
|
||||||
Return String.Empty
|
Return String.Empty
|
||||||
End Function
|
End Function
|
||||||
Private Function ISiteSettings_GetUserPostUrl(ByVal User As IPluginContentProvider, ByVal Media As IUserMedia) As String Implements ISiteSettings.GetUserPostUrl
|
Private Function ISiteSettings_GetUserPostUrl(ByVal User As IPluginContentProvider, ByVal Media As IUserMedia) As String Implements ISiteSettings.GetUserPostUrl
|
||||||
@@ -380,11 +397,41 @@ Namespace API.Base
|
|||||||
End Sub
|
End Sub
|
||||||
Friend Overridable Sub UserOptions(ByRef Options As Object, ByVal OpenForm As Boolean) Implements ISiteSettings.UserOptions
|
Friend Overridable Sub UserOptions(ByRef Options As Object, ByVal OpenForm As Boolean) Implements ISiteSettings.UserOptions
|
||||||
If _UserOptionsExists Then
|
If _UserOptionsExists Then
|
||||||
If Options Is Nothing OrElse Not Options.GetType Is _UserOptionsType Then
|
If Options Is Nothing OrElse (Not Options.GetType Is _UserOptionsType OrElse Not UserOptionsValid(Options)) Then
|
||||||
Options = AConvert(Me, AModes.Var, _UserOptionsType,, True, Nothing)
|
Dim args% = 0
|
||||||
|
Dim constructor As ConstructorInfo = Nothing
|
||||||
|
With _UserOptionsType.GetTypeInfo.DeclaredConstructors
|
||||||
|
If .ListExists Then
|
||||||
|
With .Where(Function(ByVal c As ConstructorInfo) As Boolean
|
||||||
|
With c.GetParameters
|
||||||
|
If .ListExists Then
|
||||||
|
If .Count = 1 Then
|
||||||
|
Return .Self()(0).ParameterType Is Me.GetType
|
||||||
|
Else
|
||||||
|
Return False
|
||||||
|
End If
|
||||||
|
Else
|
||||||
|
Return True
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
Return If(c.GetParameters?.Count, 0).ValueBetween(0, 1)
|
||||||
|
End Function)
|
||||||
|
If .ListExists Then
|
||||||
|
args = .Max(Of Integer)(Function(c) If(c.GetParameters?.Count, 0))
|
||||||
|
constructor = .First(Function(c) If(c.GetParameters?.Count, 0) = args)
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
If Not constructor Is Nothing Then
|
||||||
|
If args > 0 AndAlso constructor.GetParameters()(0).ParameterType.GetInterface(GetType(ISiteSettings).Name) Is Nothing Then _
|
||||||
|
Throw New Exception("Class Interface type is incompatible")
|
||||||
|
If args = 0 Then Options = constructor.Invoke(Nothing) Else Options = constructor.Invoke({Me})
|
||||||
|
End If
|
||||||
If Options Is Nothing Then Options = Activator.CreateInstance(_UserOptionsType)
|
If Options Is Nothing Then Options = Activator.CreateInstance(_UserOptionsType)
|
||||||
|
If Not Options Is Nothing Then UserOptionsSetParameters(Options)
|
||||||
End If
|
End If
|
||||||
If OpenForm Then
|
If Not Options Is Nothing And OpenForm Then
|
||||||
Using f As New InternalSettingsForm(Options, Me, False) : f.ShowDialog() : End Using
|
Using f As New InternalSettingsForm(Options, Me, False) : f.ShowDialog() : End Using
|
||||||
End If
|
End If
|
||||||
Else
|
Else
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ Namespace API.Base
|
|||||||
Private Const Name_MediaPostID As String = "ID"
|
Private Const Name_MediaPostID As String = "ID"
|
||||||
Private Const Name_MediaPostDate As String = "Date"
|
Private Const Name_MediaPostDate As String = "Date"
|
||||||
Private Const Name_SpecialFolder As String = "SpecialFolder"
|
Private Const Name_SpecialFolder As String = "SpecialFolder"
|
||||||
|
Private Const Name_PostTextFile As String = "PostTextFile"
|
||||||
|
Private Const Name_PostTextFileSpecialFolder As String = "PostTextFileSpecialFolder"
|
||||||
#End Region
|
#End Region
|
||||||
Friend Enum Types As Integer
|
Friend Enum Types As Integer
|
||||||
Undefined = 0
|
Undefined = 0
|
||||||
@@ -46,12 +48,25 @@ Namespace API.Base
|
|||||||
End Enum
|
End Enum
|
||||||
Friend Enum States As Integer : Unknown = 0 : Tried = 1 : Downloaded = 2 : Skipped = 3 : Missing = 4 : End Enum
|
Friend Enum States As Integer : Unknown = 0 : Tried = 1 : Downloaded = 2 : Skipped = 3 : Missing = 4 : End Enum
|
||||||
Friend [Type] As Types
|
Friend [Type] As Types
|
||||||
|
Friend ReadOnly Property IsVideoType As Boolean
|
||||||
|
Get
|
||||||
|
Return Type = Types.m3u8 Or Type = Types.Video Or Type = Types.VideoPre
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
|
Friend ReadOnly Property IsAudioType As Boolean
|
||||||
|
Get
|
||||||
|
Return Type = Types.Audio Or Type = Types.AudioPre
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
Friend URL_BASE As String
|
Friend URL_BASE As String
|
||||||
Friend URL As String
|
Friend URL As String
|
||||||
Friend MD5 As String
|
Friend MD5 As String
|
||||||
Friend [File] As SFile
|
Friend [File] As SFile
|
||||||
Friend Post As UserPost
|
Friend Post As UserPost
|
||||||
Friend PictureOption As String
|
Friend PictureOption As String
|
||||||
|
Friend PostText As String
|
||||||
|
Friend PostTextFile As SFile
|
||||||
|
Friend PostTextFileSpecialFolder As Boolean
|
||||||
Friend State As States
|
Friend State As States
|
||||||
Friend Attempts As Integer
|
Friend Attempts As Integer
|
||||||
''' <summary>
|
''' <summary>
|
||||||
@@ -125,6 +140,30 @@ Namespace API.Base
|
|||||||
Post = New UserPost(Post.ID, PostDate)
|
Post = New UserPost(Post.ID, PostDate)
|
||||||
End Set
|
End Set
|
||||||
End Property
|
End Property
|
||||||
|
Private Property IUserMedia_PostText As String Implements IUserMedia.PostText
|
||||||
|
Get
|
||||||
|
Return PostText
|
||||||
|
End Get
|
||||||
|
Set(ByVal NewText As String)
|
||||||
|
PostText = NewText
|
||||||
|
End Set
|
||||||
|
End Property
|
||||||
|
Private Property IUserMedia_PostTextFile As String Implements IUserMedia.PostTextFile
|
||||||
|
Get
|
||||||
|
Return PostTextFile.ToString
|
||||||
|
End Get
|
||||||
|
Set(ByVal NewPostFile As String)
|
||||||
|
If Not NewPostFile.IsEmptyString Then PostTextFile = New SFile(NewPostFile) Else PostTextFile = Nothing
|
||||||
|
End Set
|
||||||
|
End Property
|
||||||
|
Private Property IUserMedia_PostTextFileSpecialFolder As Boolean Implements IUserMedia.PostTextFileSpecialFolder
|
||||||
|
Get
|
||||||
|
Return PostTextFileSpecialFolder
|
||||||
|
End Get
|
||||||
|
Set(ByVal IsSpecialFolder As Boolean)
|
||||||
|
PostTextFileSpecialFolder = IsSpecialFolder
|
||||||
|
End Set
|
||||||
|
End Property
|
||||||
Private Property IUserMedia_SpecialFolder As String Implements IUserMedia.SpecialFolder
|
Private Property IUserMedia_SpecialFolder As String Implements IUserMedia.SpecialFolder
|
||||||
Get
|
Get
|
||||||
Return SpecialFolder
|
Return SpecialFolder
|
||||||
@@ -171,6 +210,9 @@ Namespace API.Base
|
|||||||
SpecialFolder = m.SpecialFolder
|
SpecialFolder = m.SpecialFolder
|
||||||
Attempts = m.Attempts
|
Attempts = m.Attempts
|
||||||
Me.Object = m.Object
|
Me.Object = m.Object
|
||||||
|
PostText = m.PostText
|
||||||
|
PostTextFile = m.PostTextFile
|
||||||
|
PostTextFileSpecialFolder = m.PostTextFileSpecialFolder
|
||||||
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))
|
||||||
@@ -180,6 +222,8 @@ Namespace API.Base
|
|||||||
URL_BASE = e.Value
|
URL_BASE = e.Value
|
||||||
MD5 = e.Attribute(Name_MediaHash).Value
|
MD5 = e.Attribute(Name_MediaHash).Value
|
||||||
File = e.Attribute(Name_MediaFile).Value
|
File = e.Attribute(Name_MediaFile).Value
|
||||||
|
PostTextFile = e.Attribute(Name_PostTextFile).Value
|
||||||
|
PostTextFileSpecialFolder = e.Attribute(Name_PostTextFileSpecialFolder).Value.FromXML(Of Boolean)(False)
|
||||||
|
|
||||||
Dim vp As Boolean? = Nothing
|
Dim vp As Boolean? = Nothing
|
||||||
Dim upath$ = String.Empty
|
Dim upath$ = String.Empty
|
||||||
@@ -194,7 +238,13 @@ Namespace API.Base
|
|||||||
SpecialFolder = e.Attribute(Name_SpecialFolder).Value
|
SpecialFolder = e.Attribute(Name_SpecialFolder).Value
|
||||||
If Not SpecialFolder.IsEmptyString Then upath &= $"{SpecialFolder}\"
|
If Not SpecialFolder.IsEmptyString Then upath &= $"{SpecialFolder}\"
|
||||||
If vp.HasValue AndAlso vp.Value Then upath &= $"Video\"
|
If vp.HasValue AndAlso vp.Value Then upath &= $"Video\"
|
||||||
If Not upath.IsEmptyString Then File = $"{upath.CSFilePS}{File.File}"
|
If Not upath.IsEmptyString Then
|
||||||
|
File = $"{upath.CSFilePS}{File.File}"
|
||||||
|
If Not PostTextFile.IsEmptyString Then
|
||||||
|
PostTextFile = $"{upath.CSFilePS}{IIf(PostTextFileSpecialFolder, $"{UserDataBase.PostTextSpecialFolderDefault}\", String.Empty)}{PostTextFile.File}"
|
||||||
|
If Type = Types.Text Then File = PostTextFile
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
|
||||||
Post = New UserPost With {
|
Post = New UserPost With {
|
||||||
.ID = e.Attribute(Name_MediaPostID).Value,
|
.ID = e.Attribute(Name_MediaPostID).Value,
|
||||||
@@ -234,7 +284,9 @@ Namespace API.Base
|
|||||||
New EAttribute(Name_MediaURL, URL),
|
New EAttribute(Name_MediaURL, URL),
|
||||||
New EAttribute(Name_MediaHash, MD5),
|
New EAttribute(Name_MediaHash, MD5),
|
||||||
New EAttribute(Name_MediaFile, File.File),
|
New EAttribute(Name_MediaFile, File.File),
|
||||||
|
New EAttribute(Name_PostTextFile, PostTextFile.File),
|
||||||
New EAttribute(Name_SpecialFolder, SpecialFolder),
|
New EAttribute(Name_SpecialFolder, SpecialFolder),
|
||||||
|
New EAttribute(Name_PostTextFileSpecialFolder, PostTextFileSpecialFolder.BoolToInteger),
|
||||||
New EAttribute(Name_MediaPostID, Post.ID),
|
New EAttribute(Name_MediaPostID, Post.ID),
|
||||||
New EAttribute(Name_MediaPostDate, AConvert(Of String)(Post.Date, DateTimeDefaultProvider, String.Empty))
|
New EAttribute(Name_MediaPostDate, AConvert(Of String)(Post.Date, DateTimeDefaultProvider, String.Empty))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ Imports CookieUpdateModes = PersonalUtilities.Tools.Web.Cookies.CookieKeeper.Upd
|
|||||||
Namespace API.Base
|
Namespace API.Base
|
||||||
Friend MustInherit Class UserDataBase : Implements IUserData, IPluginContentProvider, IThrower
|
Friend MustInherit Class UserDataBase : Implements IUserData, IPluginContentProvider, IThrower
|
||||||
Friend Const UserFileAppender As String = "User"
|
Friend Const UserFileAppender As String = "User"
|
||||||
|
Friend Const PostTextSpecialFolderDefault As String = "txt"
|
||||||
#Region "Events"
|
#Region "Events"
|
||||||
Private ReadOnly UserUpdatedEventHandlers As List(Of IUserData.UserUpdatedEventHandler)
|
Private ReadOnly UserUpdatedEventHandlers As List(Of IUserData.UserUpdatedEventHandler)
|
||||||
Friend Custom Event UserUpdated As IUserData.UserUpdatedEventHandler Implements IUserData.UserUpdated
|
Friend Custom Event UserUpdated As IUserData.UserUpdatedEventHandler Implements IUserData.UserUpdated
|
||||||
@@ -152,6 +153,9 @@ Namespace API.Base
|
|||||||
Private Const Name_IsSubscription As String = UserInfo.Name_IsSubscription
|
Private Const Name_IsSubscription As String = UserInfo.Name_IsSubscription
|
||||||
Private Const Name_Temporary As String = "Temporary"
|
Private Const Name_Temporary As String = "Temporary"
|
||||||
Private Const Name_Favorite As String = "Favorite"
|
Private Const Name_Favorite As String = "Favorite"
|
||||||
|
Private Const Name_DownloadText As String = "DownloadText"
|
||||||
|
Private Const Name_DownloadTextPosts As String = "DownloadTextPosts"
|
||||||
|
Private Const Name_DownloadTextSpecialFolder As String = "DownloadTextSpecialFolder"
|
||||||
Private Const Name_BackColor As String = "BackColor"
|
Private Const Name_BackColor As String = "BackColor"
|
||||||
Private Const Name_ForeColor As String = "ForeColor"
|
Private Const Name_ForeColor As String = "ForeColor"
|
||||||
Private Const Name_CreatedByChannel As String = "CreatedByChannel"
|
Private Const Name_CreatedByChannel As String = "CreatedByChannel"
|
||||||
@@ -167,6 +171,7 @@ Namespace API.Base
|
|||||||
|
|
||||||
Private Const Name_VideoCount As String = "VideoCount"
|
Private Const Name_VideoCount As String = "VideoCount"
|
||||||
Private Const Name_PicturesCount As String = "PicturesCount"
|
Private Const Name_PicturesCount As String = "PicturesCount"
|
||||||
|
Private Const Name_TextCount As String = "TextCount"
|
||||||
Private Const Name_LastUpdated As String = "LastUpdated"
|
Private Const Name_LastUpdated As String = "LastUpdated"
|
||||||
|
|
||||||
Private Const Name_ScriptUse As String = "ScriptUse"
|
Private Const Name_ScriptUse As String = "ScriptUse"
|
||||||
@@ -178,6 +183,8 @@ Namespace API.Base
|
|||||||
#Region "Additional names"
|
#Region "Additional names"
|
||||||
Protected Const Name_SiteMode As String = "SiteMode"
|
Protected Const Name_SiteMode As String = "SiteMode"
|
||||||
Protected Const Name_TrueName As String = "TrueName"
|
Protected Const Name_TrueName As String = "TrueName"
|
||||||
|
'TODELETE Name_TrueName2
|
||||||
|
<Obsolete> Protected Const Name_TrueName2 As String = "NameTrue"
|
||||||
Protected Const Name_Arguments As String = "Arguments"
|
Protected Const Name_Arguments As String = "Arguments"
|
||||||
#End Region
|
#End Region
|
||||||
#End Region
|
#End Region
|
||||||
@@ -278,6 +285,21 @@ Namespace API.Base
|
|||||||
Return User.Name
|
Return User.Name
|
||||||
End Get
|
End Get
|
||||||
End Property
|
End Property
|
||||||
|
Private _NameTrue As String = String.Empty
|
||||||
|
Friend Overridable Overloads Property NameTrue As String Implements IUserData.NameTrue, IPluginContentProvider.NameTrue
|
||||||
|
Get
|
||||||
|
Return NameTrue(False)
|
||||||
|
End Get
|
||||||
|
Set(ByVal NewName As String)
|
||||||
|
If Not _NameTrue = NewName Then EnvirChanged(NewName)
|
||||||
|
_NameTrue = NewName
|
||||||
|
End Set
|
||||||
|
End Property
|
||||||
|
Friend Overloads ReadOnly Property NameTrue(ByVal Exact As Boolean) As String
|
||||||
|
Get
|
||||||
|
Return If(Exact, _NameTrue, _NameTrue.IfNullOrEmpty(Name))
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
Friend Overridable Property ID As String = String.Empty Implements IUserData.ID, IPluginContentProvider.ID
|
Friend Overridable Property ID As String = String.Empty Implements IUserData.ID, IPluginContentProvider.ID
|
||||||
Protected _FriendlyName As String = String.Empty
|
Protected _FriendlyName As String = String.Empty
|
||||||
Friend Overridable Property FriendlyName As String Implements IUserData.FriendlyName
|
Friend Overridable Property FriendlyName As String Implements IUserData.FriendlyName
|
||||||
@@ -348,12 +370,20 @@ Namespace API.Base
|
|||||||
Protected Function UserDescriptionNeedToUpdate() As Boolean
|
Protected Function UserDescriptionNeedToUpdate() As Boolean
|
||||||
Return (UserDescription.IsEmptyString Or _DescriptionEveryTime) And Not _DescriptionChecked
|
Return (UserDescription.IsEmptyString Or _DescriptionEveryTime) And Not _DescriptionChecked
|
||||||
End Function
|
End Function
|
||||||
Protected Sub UserDescriptionUpdate(ByVal Descr As String)
|
Protected Sub UserDescriptionUpdate(ByVal Descr As String, Optional ByVal Force As Boolean = False,
|
||||||
If UserDescriptionNeedToUpdate() Then
|
Optional ByVal InsertFirst As Boolean = False, Optional ByVal AppendDate As Boolean = False)
|
||||||
|
If UserDescriptionNeedToUpdate() Or Force Then
|
||||||
|
If AppendDate Then Descr = $"{Now.ToStringDateDef}: {Descr}"
|
||||||
If UserDescription.IsEmptyString Then
|
If UserDescription.IsEmptyString Then
|
||||||
UserDescription = Descr
|
UserDescription = Descr
|
||||||
|
_ForceSaveUserInfo = True
|
||||||
ElseIf Not UserDescription.Contains(Descr) Then
|
ElseIf Not UserDescription.Contains(Descr) Then
|
||||||
UserDescription &= $"{vbNewLine}----{vbNewLine}{Descr}"
|
If InsertFirst Then
|
||||||
|
UserDescription = $"{Descr}{vbNewLine}{UserDescription}"
|
||||||
|
Else
|
||||||
|
UserDescription &= $"{vbNewLine}----{vbNewLine}{Descr}"
|
||||||
|
End If
|
||||||
|
_ForceSaveUserInfo = True
|
||||||
End If
|
End If
|
||||||
_DescriptionChecked = True
|
_DescriptionChecked = True
|
||||||
End If
|
End If
|
||||||
@@ -614,6 +644,9 @@ BlockNullPicture:
|
|||||||
Friend Overridable Property ReadyForDownload As Boolean = True Implements IUserData.ReadyForDownload
|
Friend Overridable Property ReadyForDownload As Boolean = True Implements IUserData.ReadyForDownload
|
||||||
Friend Property DownloadImages As Boolean = True Implements IUserData.DownloadImages
|
Friend Property DownloadImages As Boolean = True Implements IUserData.DownloadImages
|
||||||
Friend Property DownloadVideos As Boolean = True Implements IUserData.DownloadVideos
|
Friend Property DownloadVideos As Boolean = True Implements IUserData.DownloadVideos
|
||||||
|
Friend Overridable Property DownloadText As Boolean = False
|
||||||
|
Friend Overridable Property DownloadTextPosts As Boolean = False
|
||||||
|
Friend Overridable Property DownloadTextSpecialFolder As Boolean = True
|
||||||
Friend Property DownloadMissingOnly As Boolean = False Implements IUserData.DownloadMissingOnly
|
Friend Property DownloadMissingOnly As Boolean = False Implements IUserData.DownloadMissingOnly
|
||||||
Private _IconBannerDownloaded As Boolean = False
|
Private _IconBannerDownloaded As Boolean = False
|
||||||
Friend WriteOnly Property IconBannerDownloaded As Boolean
|
Friend WriteOnly Property IconBannerDownloaded As Boolean
|
||||||
@@ -725,9 +758,23 @@ BlockNullPicture:
|
|||||||
End If
|
End If
|
||||||
End Set
|
End Set
|
||||||
End Property
|
End Property
|
||||||
|
Private _DownloadedTextsTotal As Integer = 0
|
||||||
|
Private _DownloadedTextsSession As Integer = 0
|
||||||
|
Friend Property DownloadedTexts(ByVal Total As Boolean) As Integer Implements IUserData.DownloadedTexts
|
||||||
|
Get
|
||||||
|
Return IIf(Total, _DownloadedTextsTotal, _DownloadedTextsSession)
|
||||||
|
End Get
|
||||||
|
Set(ByVal NewValue As Integer)
|
||||||
|
If Total Then
|
||||||
|
_DownloadedTextsTotal = NewValue
|
||||||
|
Else
|
||||||
|
_DownloadedTextsSession = NewValue
|
||||||
|
End If
|
||||||
|
End Set
|
||||||
|
End Property
|
||||||
Friend Overridable ReadOnly Property DownloadedTotal(Optional ByVal Total As Boolean = True) As Integer Implements IUserData.DownloadedTotal
|
Friend Overridable ReadOnly Property DownloadedTotal(Optional ByVal Total As Boolean = True) As Integer Implements IUserData.DownloadedTotal
|
||||||
Get
|
Get
|
||||||
Return DownloadedPictures(Total) + DownloadedVideos(Total)
|
Return DownloadedPictures(Total) + DownloadedVideos(Total) + DownloadedTexts(Total)
|
||||||
End Get
|
End Get
|
||||||
End Property
|
End Property
|
||||||
Friend ReadOnly Property DownloadedInformation As String Implements IUserData.DownloadedInformation
|
Friend ReadOnly Property DownloadedInformation As String Implements IUserData.DownloadedInformation
|
||||||
@@ -907,6 +954,10 @@ BlockNullPicture:
|
|||||||
FileExists = True
|
FileExists = True
|
||||||
Using x As New XmlFile(MyFileSettings) With {.XmlReadOnly = True}
|
Using x As New XmlFile(MyFileSettings) With {.XmlReadOnly = True}
|
||||||
If User.Name.IsEmptyString Then User.Name = x.Value(Name_UserName)
|
If User.Name.IsEmptyString Then User.Name = x.Value(Name_UserName)
|
||||||
|
_NameTrue = x.Value(Name_TrueName)
|
||||||
|
#Disable Warning BC40008
|
||||||
|
If _NameTrue.IsEmptyString AndAlso x.Contains(Name_TrueName2) Then _NameTrue = x.Value(Name_TrueName2)
|
||||||
|
#Enable Warning
|
||||||
UserExists = x.Value(Name_UserExists).FromXML(Of Boolean)(True)
|
UserExists = x.Value(Name_UserExists).FromXML(Of Boolean)(True)
|
||||||
UserSuspended = x.Value(Name_UserSuspended).FromXML(Of Boolean)(False)
|
UserSuspended = x.Value(Name_UserSuspended).FromXML(Of Boolean)(False)
|
||||||
ID = x.Value(Name_UserID)
|
ID = x.Value(Name_UserID)
|
||||||
@@ -934,9 +985,13 @@ BlockNullPicture:
|
|||||||
ReadyForDownload = x.Value(Name_ReadyForDownload).FromXML(Of Boolean)(True)
|
ReadyForDownload = x.Value(Name_ReadyForDownload).FromXML(Of Boolean)(True)
|
||||||
DownloadImages = x.Value(Name_DownloadImages).FromXML(Of Boolean)(True)
|
DownloadImages = x.Value(Name_DownloadImages).FromXML(Of Boolean)(True)
|
||||||
DownloadVideos = x.Value(Name_DownloadVideos).FromXML(Of Boolean)(True)
|
DownloadVideos = x.Value(Name_DownloadVideos).FromXML(Of Boolean)(True)
|
||||||
|
DownloadText = x.Value(Name_DownloadText).FromXML(Of Boolean)(False)
|
||||||
|
DownloadTextPosts = x.Value(Name_DownloadTextPosts).FromXML(Of Boolean)(False)
|
||||||
|
DownloadTextSpecialFolder = x.Value(Name_DownloadTextSpecialFolder).FromXML(Of Boolean)(True)
|
||||||
_IconBannerDownloaded = x.Value(Name_IconBannerDownloaded).FromXML(Of Boolean)(False)
|
_IconBannerDownloaded = x.Value(Name_IconBannerDownloaded).FromXML(Of Boolean)(False)
|
||||||
DownloadedVideos(True) = x.Value(Name_VideoCount).FromXML(Of Integer)(0)
|
DownloadedVideos(True) = x.Value(Name_VideoCount).FromXML(Of Integer)(0)
|
||||||
DownloadedPictures(True) = x.Value(Name_PicturesCount).FromXML(Of Integer)(0)
|
DownloadedPictures(True) = x.Value(Name_PicturesCount).FromXML(Of Integer)(0)
|
||||||
|
DownloadedTexts(True) = x.Value(Name_TextCount).FromXML(Of Integer)(0)
|
||||||
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)
|
||||||
@@ -967,6 +1022,7 @@ BlockNullPicture:
|
|||||||
x.Add(Name_Plugin, HOST.Key)
|
x.Add(Name_Plugin, HOST.Key)
|
||||||
x.Add(Name_AccountName, AccountName)
|
x.Add(Name_AccountName, AccountName)
|
||||||
x.Add(Name_UserName, User.Name)
|
x.Add(Name_UserName, User.Name)
|
||||||
|
x.Add(Name_TrueName, _NameTrue)
|
||||||
x.Add(Name_Model_User, CInt(UserModel))
|
x.Add(Name_Model_User, CInt(UserModel))
|
||||||
x.Add(Name_Model_Collection, CInt(CollectionModel))
|
x.Add(Name_Model_Collection, CInt(CollectionModel))
|
||||||
x.Add(Name_SpecialPath, User.SpecialPath)
|
x.Add(Name_SpecialPath, User.SpecialPath)
|
||||||
@@ -995,9 +1051,13 @@ BlockNullPicture:
|
|||||||
x.Add(Name_ReadyForDownload, ReadyForDownload.BoolToInteger)
|
x.Add(Name_ReadyForDownload, ReadyForDownload.BoolToInteger)
|
||||||
x.Add(Name_DownloadImages, DownloadImages.BoolToInteger)
|
x.Add(Name_DownloadImages, DownloadImages.BoolToInteger)
|
||||||
x.Add(Name_DownloadVideos, DownloadVideos.BoolToInteger)
|
x.Add(Name_DownloadVideos, DownloadVideos.BoolToInteger)
|
||||||
|
x.Add(Name_DownloadText, DownloadText.BoolToInteger)
|
||||||
|
x.Add(Name_DownloadTextPosts, DownloadTextPosts.BoolToInteger)
|
||||||
|
x.Add(Name_DownloadTextSpecialFolder, DownloadTextSpecialFolder.BoolToInteger)
|
||||||
x.Add(Name_IconBannerDownloaded, _IconBannerDownloaded.BoolToInteger)
|
x.Add(Name_IconBannerDownloaded, _IconBannerDownloaded.BoolToInteger)
|
||||||
x.Add(Name_VideoCount, DownloadedVideos(True))
|
x.Add(Name_VideoCount, DownloadedVideos(True))
|
||||||
x.Add(Name_PicturesCount, DownloadedPictures(True))
|
x.Add(Name_PicturesCount, DownloadedPictures(True))
|
||||||
|
x.Add(Name_TextCount, DownloadedTexts(True))
|
||||||
x.Add(Name_LastUpdated, AConvert(Of String)(LastUpdated, ADateTime.Formats.BaseDateTime, String.Empty))
|
x.Add(Name_LastUpdated, AConvert(Of String)(LastUpdated, ADateTime.Formats.BaseDateTime, String.Empty))
|
||||||
x.Add(Name_ScriptUse, ScriptUse.BoolToInteger)
|
x.Add(Name_ScriptUse, ScriptUse.BoolToInteger)
|
||||||
x.Add(Name_ScriptData, ScriptData)
|
x.Add(Name_ScriptData, ScriptData)
|
||||||
@@ -1162,6 +1222,7 @@ BlockNullPicture:
|
|||||||
Select Case Caller
|
Select Case Caller
|
||||||
Case NameOf(UserExists) : If Not _EnvirUserExists = CBool(NewValue) Then _EnvirChanged = True : _EnvirInvokeUserUpdated = True
|
Case NameOf(UserExists) : If Not _EnvirUserExists = CBool(NewValue) Then _EnvirChanged = True : _EnvirInvokeUserUpdated = True
|
||||||
Case NameOf(UserSuspended) : If Not _EnvirUserSuspended = CBool(NewValue) Then _EnvirChanged = True : _EnvirInvokeUserUpdated = True
|
Case NameOf(UserSuspended) : If Not _EnvirUserSuspended = CBool(NewValue) Then _EnvirChanged = True : _EnvirInvokeUserUpdated = True
|
||||||
|
Case NameOf(NameTrue) : _EnvirChanged = True : _EnvirInvokeUserUpdated = True : _ForceSaveUserInfo = True : _ForceSaveUserInfoOnException = True
|
||||||
Case Else : _EnvirChanged = True
|
Case Else : _EnvirChanged = True
|
||||||
End Select
|
End Select
|
||||||
End If
|
End If
|
||||||
@@ -1215,6 +1276,7 @@ BlockNullPicture:
|
|||||||
If Not DownloadImages Then _TempMediaList.RemoveAll(Function(m) m.Type = UTypes.GIF Or m.Type = UTypes.Picture)
|
If Not DownloadImages Then _TempMediaList.RemoveAll(Function(m) m.Type = UTypes.GIF Or m.Type = UTypes.Picture)
|
||||||
If Not DownloadVideos Then _TempMediaList.RemoveAll(Function(m) m.Type = UTypes.Video Or
|
If Not DownloadVideos Then _TempMediaList.RemoveAll(Function(m) m.Type = UTypes.Video Or
|
||||||
m.Type = UTypes.VideoPre Or m.Type = UTypes.m3u8)
|
m.Type = UTypes.VideoPre Or m.Type = UTypes.m3u8)
|
||||||
|
If Not DownloadTextPosts Then _TempMediaList.RemoveAll(Function(m) m.Type = UTypes.Text)
|
||||||
If DownloadMissingOnly Then _TempMediaList.RemoveAll(Function(m) Not m.State = UStates.Missing)
|
If DownloadMissingOnly Then _TempMediaList.RemoveAll(Function(m) Not m.State = UStates.Missing)
|
||||||
End If
|
End If
|
||||||
|
|
||||||
@@ -1282,9 +1344,9 @@ BlockNullPicture:
|
|||||||
UpdateUserInformation_Ex()
|
UpdateUserInformation_Ex()
|
||||||
If Not exit_ex.Silent Then
|
If Not exit_ex.Silent Then
|
||||||
If exit_ex.SimpleLogLine Then
|
If exit_ex.SimpleLogLine Then
|
||||||
MyMainLOG = $"{ToStringForLog()}: downloading interrupted (exit) ({exit_ex.Message})"
|
LogError(Nothing, $"downloading interrupted (exit) ({exit_ex.Message})")
|
||||||
Else
|
Else
|
||||||
ErrorsDescriber.Execute(EDP.SendToLog, exit_ex, $"{ToStringForLog()}: downloading interrupted (exit)")
|
LogError(exit_ex, "downloading interrupted (exit)")
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
If _EnvirInvokeUserUpdated Then OnUserUpdated()
|
If _EnvirInvokeUserUpdated Then OnUserUpdated()
|
||||||
@@ -1430,6 +1492,7 @@ BlockNullPicture:
|
|||||||
Data.DownloadState = UserMediaStates.Missing
|
Data.DownloadState = UserMediaStates.Missing
|
||||||
End If
|
End If
|
||||||
YouTube.Objects.YouTubeMediaContainerBase.Update(_ContentNew(0), Data)
|
YouTube.Objects.YouTubeMediaContainerBase.Update(_ContentNew(0), Data)
|
||||||
|
If _ContentNew.Count > 1 Then Data.Files.ListAddList(_ContentNew.Select(Function(cc) cc.File), LNC)
|
||||||
If ResetTitle And Not _ContentNew(0).File.Name.IsEmptyString Then Data.Title = _ContentNew(0).File.Name
|
If ResetTitle And Not _ContentNew(0).File.Name.IsEmptyString Then Data.Title = _ContentNew(0).File.Name
|
||||||
Else
|
Else
|
||||||
Data.DownloadState = UserMediaStates.Missing
|
Data.DownloadState = UserMediaStates.Missing
|
||||||
@@ -1627,7 +1690,8 @@ BlockNullPicture:
|
|||||||
Dim dCount% = 0, dTotal% = 0
|
Dim dCount% = 0, dTotal% = 0
|
||||||
ThrowAny(Token)
|
ThrowAny(Token)
|
||||||
If _ContentNew.Count > 0 Then
|
If _ContentNew.Count > 0 Then
|
||||||
_ContentNew.RemoveAll(Function(c) c.URL.IsEmptyString)
|
_ContentNew.RemoveAll(Function(c) Not c.Type = UTypes.Text And c.URL.IsEmptyString)
|
||||||
|
If Not DownloadText Or Not DownloadTextPosts Then _ContentNew.RemoveAll(Function(c) c.Type = UTypes.Text)
|
||||||
If _ContentNew.Count > 0 Then
|
If _ContentNew.Count > 0 Then
|
||||||
If UseMD5Comparison Then LoadMD5()
|
If UseMD5Comparison Then LoadMD5()
|
||||||
MyFile.Exists(SFO.Path)
|
MyFile.Exists(SFO.Path)
|
||||||
@@ -1636,7 +1700,7 @@ BlockNullPicture:
|
|||||||
Dim vsf As Boolean = SeparateVideoFolderF
|
Dim vsf As Boolean = SeparateVideoFolderF
|
||||||
Dim __isVideo As Boolean
|
Dim __isVideo As Boolean
|
||||||
Dim __interrupt As Boolean
|
Dim __interrupt As Boolean
|
||||||
Dim f As SFile
|
Dim f As SFile, fTxt As SFile
|
||||||
Dim v As UserMedia
|
Dim v As UserMedia
|
||||||
Dim __fileDeleted As Boolean
|
Dim __fileDeleted As Boolean
|
||||||
Dim fileNumProvider As SFileNumbers = SFileNumbers.Default
|
Dim fileNumProvider As SFileNumbers = SFileNumbers.Default
|
||||||
@@ -1650,18 +1714,20 @@ BlockNullPicture:
|
|||||||
ErrorsDescriber.Execute(EDP.SendToLog, file_del_ex)
|
ErrorsDescriber.Execute(EDP.SendToLog, file_del_ex)
|
||||||
End Try
|
End Try
|
||||||
End Sub
|
End Sub
|
||||||
Dim updateDownCount As Action = Sub()
|
Dim updateDownCount As Action(Of Boolean) = Sub(ByVal forceText As Boolean)
|
||||||
Dim __n% = IIf(__fileDeleted, -1, 1)
|
Dim __n% = IIf(__fileDeleted And Not forceText, -1, 1)
|
||||||
If __isVideo Then
|
If v.Type = UTypes.Text Or forceText Then
|
||||||
v.Type = UTypes.Video
|
DownloadedTexts(False) += __n
|
||||||
DownloadedVideos(False) += __n
|
ElseIf __isVideo Then
|
||||||
ElseIf v.Type = UTypes.GIF Then
|
v.Type = UTypes.Video
|
||||||
DownloadedPictures(False) += __n
|
DownloadedVideos(False) += __n
|
||||||
Else
|
ElseIf v.Type = UTypes.GIF Then
|
||||||
v.Type = UTypes.Picture
|
DownloadedPictures(False) += __n
|
||||||
DownloadedPictures(False) += __n
|
Else
|
||||||
End If
|
v.Type = UTypes.Picture
|
||||||
End Sub
|
DownloadedPictures(False) += __n
|
||||||
|
End If
|
||||||
|
End Sub
|
||||||
|
|
||||||
Using w As New OptionalWebClient(Me)
|
Using w As New OptionalWebClient(Me)
|
||||||
If vsf Then CSFileP($"{MyDir}\{VideoFolderName}\").Exists(SFO.Path)
|
If vsf Then CSFileP($"{MyDir}\{VideoFolderName}\").Exists(SFO.Path)
|
||||||
@@ -1694,8 +1760,9 @@ BlockNullPicture:
|
|||||||
|
|
||||||
__fileDeleted = False
|
__fileDeleted = False
|
||||||
|
|
||||||
If Not f.IsEmptyString And Not v.URL.IsEmptyString Then
|
If (v.Type = UTypes.Text And DownloadText) Or (Not f.IsEmptyString And Not v.URL.IsEmptyString) Then
|
||||||
Try
|
Try
|
||||||
|
If v.Type = UTypes.Text Then GoTo stxt
|
||||||
__isVideo = v.Type = UTypes.Video Or f.Extension = "mp4" Or v.Type = UTypes.m3u8
|
__isVideo = v.Type = UTypes.Video Or f.Extension = "mp4" Or v.Type = UTypes.m3u8
|
||||||
|
|
||||||
If f.Extension.IsEmptyString Then
|
If f.Extension.IsEmptyString Then
|
||||||
@@ -1738,7 +1805,7 @@ BlockNullPicture:
|
|||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
|
|
||||||
updateDownCount()
|
updateDownCount(False)
|
||||||
|
|
||||||
v.File = ChangeFileNameByProvider(f, v)
|
v.File = ChangeFileNameByProvider(f, v)
|
||||||
v.State = UStates.Downloaded
|
v.State = UStates.Downloaded
|
||||||
@@ -1749,7 +1816,7 @@ BlockNullPicture:
|
|||||||
If Not v.MD5.IsEmptyString Then
|
If Not v.MD5.IsEmptyString Then
|
||||||
If _MD5List.Contains(v.MD5) Then
|
If _MD5List.Contains(v.MD5) Then
|
||||||
__fileDeleted = v.File.Delete(SFO.File, SFODelete.DeletePermanently, EDP.ReturnValue)
|
__fileDeleted = v.File.Delete(SFO.File, SFODelete.DeletePermanently, EDP.ReturnValue)
|
||||||
If __fileDeleted Then dCount -= 1 : updateDownCount()
|
If __fileDeleted Then dCount -= 1 : updateDownCount(False)
|
||||||
Else
|
Else
|
||||||
_MD5List.Add(v.MD5)
|
_MD5List.Add(v.MD5)
|
||||||
End If
|
End If
|
||||||
@@ -1758,7 +1825,33 @@ BlockNullPicture:
|
|||||||
dCount -= 1
|
dCount -= 1
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
|
stxt:
|
||||||
|
If DownloadText And Not v.PostText.IsEmptyString And (v.Type = UTypes.Text Or v.File.Exists) Then
|
||||||
|
fTxt = v.File
|
||||||
|
If fTxt.IsEmptyString Then
|
||||||
|
If DownloadTextPosts And Not f.IsEmptyString Then
|
||||||
|
fTxt = f
|
||||||
|
If v.Type = UTypes.Text Then fTxt.Name &= IIf(fTxt.Name.IsEmptyString, String.Empty, "_") &
|
||||||
|
v.Post.ID.StringRemoveWinForbiddenSymbols
|
||||||
|
If fTxt.IsEmptyString Then Throw New ArgumentNullException("Text", "Error downloading text") With {.HelpLink = 10}
|
||||||
|
Else
|
||||||
|
Continue For
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
v.PostTextFileSpecialFolder = DownloadTextSpecialFolder
|
||||||
|
If DownloadTextSpecialFolder Then fTxt.Path = $"{fTxt.Path.StringTrimEnd("\")}\{PostTextSpecialFolderDefault}"
|
||||||
|
fTxt.Extension = "txt"
|
||||||
|
v.PostTextFile = TextSaver.SaveTextToFile(v.PostText, fTxt,,, Settings.FeedShowTextPosts_LogErrors_E)
|
||||||
|
If Not v.PostTextFile.Exists Then Throw New ArgumentNullException("Text", "Error downloading text") With {.HelpLink = 10}
|
||||||
|
If v.Type = UTypes.Text Then v.File = v.PostTextFile
|
||||||
|
v.State = UStates.Downloaded
|
||||||
|
updateDownCount(Not v.Type = UTypes.Text)
|
||||||
|
If v.URL.IsEmptyString Then v.URL = v.PostTextFile.File
|
||||||
|
If v.URL_BASE.IsEmptyString Then v.URL_BASE = v.URL
|
||||||
|
End If
|
||||||
dCount += 1
|
dCount += 1
|
||||||
|
Catch anex As ArgumentNullException When anex.HelpLink = 10
|
||||||
|
LogError(anex, anex.Message, Settings.FeedShowTextPosts_LogErrors_E)
|
||||||
Catch woex As OperationCanceledException When Token.IsCancellationRequested
|
Catch woex As OperationCanceledException When Token.IsCancellationRequested
|
||||||
__deleteFile.Invoke(f, v.URL_BASE)
|
__deleteFile.Invoke(f, v.URL_BASE)
|
||||||
v.State = UStates.Missing
|
v.State = UStates.Missing
|
||||||
@@ -1766,7 +1859,7 @@ BlockNullPicture:
|
|||||||
_ContentNew(i) = v
|
_ContentNew(i) = v
|
||||||
Throw woex
|
Throw woex
|
||||||
Catch wex As Exception
|
Catch wex As Exception
|
||||||
If DownloadContentDefault_ProcessDownloadException() Then
|
If Not v.Type = UTypes.Text AndAlso DownloadContentDefault_ProcessDownloadException() Then
|
||||||
v.Attempts += 1
|
v.Attempts += 1
|
||||||
v.State = UStates.Missing
|
v.State = UStates.Missing
|
||||||
If MissingErrorsAdd Then ErrorDownloading(f, v.URL)
|
If MissingErrorsAdd Then ErrorDownloading(f, v.URL)
|
||||||
@@ -1846,6 +1939,31 @@ BlockNullPicture:
|
|||||||
Protected Overridable Function CreateFileFromUrl(ByVal URL As String) As SFile
|
Protected Overridable Function CreateFileFromUrl(ByVal URL As String) As SFile
|
||||||
Return New SFile(URL)
|
Return New SFile(URL)
|
||||||
End Function
|
End Function
|
||||||
|
Protected Overridable Function SimpleDownloadAvatar(ByVal ImageAddress As String, Optional ByVal FileCreateFunc As Func(Of String, SFile) = Nothing,
|
||||||
|
Optional ByVal e As ErrorsDescriber = Nothing) As SFile
|
||||||
|
Try
|
||||||
|
If Not ImageAddress.IsEmptyString Then
|
||||||
|
Dim f As SFile
|
||||||
|
If FileCreateFunc Is Nothing Then
|
||||||
|
f = CreateFileFromUrl(ImageAddress)
|
||||||
|
Else
|
||||||
|
f = FileCreateFunc.Invoke(ImageAddress)
|
||||||
|
End If
|
||||||
|
If Not f.Name.IsEmptyString Then f.Name = f.Name.StringRemoveWinForbiddenSymbols.StringTrim
|
||||||
|
If Not f.Name.IsEmptyString Then
|
||||||
|
f.Path = DownloadContentDefault_GetRootDir()
|
||||||
|
f.Separator = "\"
|
||||||
|
If f.Extension.IsEmptyString Then f.Extension = "jpg"
|
||||||
|
If Not f.Exists Then GetWebFile(ImageAddress, f, EDP.ReturnValue)
|
||||||
|
If f.Exists Then IconBannerDownloaded = True : Return f
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
Return Nothing
|
||||||
|
Catch ex As Exception
|
||||||
|
If Not e.Exists Then e = New ErrorsDescriber(EDP.ReturnValue)
|
||||||
|
Return ErrorsDescriber.Execute(e, ex, $"SimpleDownloadAvatar({ImageAddress})", New SFile)
|
||||||
|
End Try
|
||||||
|
End Function
|
||||||
Protected Overridable Function ChangeFileNameByProvider(ByVal f As SFile, ByVal m As UserMedia) As SFile
|
Protected Overridable Function ChangeFileNameByProvider(ByVal f As SFile, ByVal m As UserMedia) As SFile
|
||||||
Dim ff As SFile = Nothing
|
Dim ff As SFile = Nothing
|
||||||
Try
|
Try
|
||||||
@@ -1934,7 +2052,7 @@ BlockNullPicture:
|
|||||||
End If
|
End If
|
||||||
If m.Contains(IUserData.EraseMode.Data) Then
|
If m.Contains(IUserData.EraseMode.Data) Then
|
||||||
Dim files As List(Of SFile) = SFile.GetFiles(DownloadContentDefault_GetRootDir.CSFileP,, SearchOption.AllDirectories, e)
|
Dim files As List(Of SFile) = SFile.GetFiles(DownloadContentDefault_GetRootDir.CSFileP,, SearchOption.AllDirectories, e)
|
||||||
If files.ListExists Then files.RemoveAll(Function(f) Not f.Extension.IsEmptyString AndAlso (f.Extension = "txt" Or f.Extension = "xml"))
|
If files.ListExists Then files.RemoveAll(Function(f) Not f.Extension.IsEmptyString AndAlso ((f.Path.EndsWith(SettingsFolderName) And f.Extension = "txt") Or f.Extension = "xml"))
|
||||||
If files.ListExists Then files.ForEach(Sub(f) f.Delete(SFO.File, Settings.DeleteMode, e))
|
If files.ListExists Then files.ForEach(Sub(f) f.Delete(SFO.File, Settings.DeleteMode, e))
|
||||||
LatestData.Clear()
|
LatestData.Clear()
|
||||||
result = True
|
result = True
|
||||||
@@ -2177,6 +2295,17 @@ BlockNullPicture:
|
|||||||
Friend Function ToStringForLog() As String
|
Friend Function ToStringForLog() As String
|
||||||
Return $"{IIf(IncludedInCollection, $"[{CollectionName}] - ", String.Empty)}[{Site}] - {Name}"
|
Return $"{IIf(IncludedInCollection, $"[{CollectionName}] - ", String.Empty)}[{Site}] - {Name}"
|
||||||
End Function
|
End Function
|
||||||
|
Friend Overloads Function ToStringExt(ByVal UseFriendlyName As Boolean) As String
|
||||||
|
Return $"{IIf(IncludedInCollection, $"[{CollectionName}] - ", String.Empty)}[{Site}] - {String.Format(CStr(IIf(Not FriendlyName.IsEmptyString And
|
||||||
|
UseFriendlyName, "{1} ({0})", "{0}")), Name, FriendlyName)}"
|
||||||
|
End Function
|
||||||
|
Friend Overloads Shared Function ToStringExt(ByVal User As UserInfo) As String
|
||||||
|
If Not IsDBNull(User) Then
|
||||||
|
With User : Return $"{IIf(.IncludedInCollection, $"[{ .CollectionName}] - ", String.Empty)}[{ .Site}] - { .Name}" : End With
|
||||||
|
Else
|
||||||
|
Return String.Empty
|
||||||
|
End If
|
||||||
|
End Function
|
||||||
Public Overrides Function ToString() As String
|
Public Overrides Function ToString() As String
|
||||||
If IsCollection Then
|
If IsCollection Then
|
||||||
Return CollectionName
|
Return CollectionName
|
||||||
|
|||||||
@@ -134,6 +134,7 @@ Namespace API.Base
|
|||||||
m.GetMemberCustomAttributes(Of Provider).ListExists
|
m.GetMemberCustomAttributes(Of Provider).ListExists
|
||||||
Dim m1 As MemberInfo, m2 As MemberInfo
|
Dim m1 As MemberInfo, m2 As MemberInfo
|
||||||
Dim tmpObj As Object
|
Dim tmpObj As Object
|
||||||
|
Dim maxOffset%
|
||||||
|
|
||||||
members = GetObjectMembers(MyObject, Function(m) (m.MemberType = MemberTypes.Field Or m.MemberType = MemberTypes.Property) AndAlso
|
members = GetObjectMembers(MyObject, Function(m) (m.MemberType = MemberTypes.Field Or m.MemberType = MemberTypes.Property) AndAlso
|
||||||
Not m.GetCustomAttribute(Of PSettingAttribute) Is Nothing,, True,
|
Not m.GetCustomAttribute(Of PSettingAttribute) Is Nothing,, True,
|
||||||
@@ -175,6 +176,9 @@ Namespace API.Base
|
|||||||
|
|
||||||
If MyMembers.Count > 0 Then
|
If MyMembers.Count > 0 Then
|
||||||
|
|
||||||
|
maxOffset = MyMembers.Max(Function(mm) mm.LeftOffset)
|
||||||
|
If maxOffset > 0 Then MyMembers.ForEach(Sub(mm) mm.LeftOffset = maxOffset)
|
||||||
|
|
||||||
Dim prov As IEnumerable(Of Provider)
|
Dim prov As IEnumerable(Of Provider)
|
||||||
Dim _prov As Provider
|
Dim _prov As Provider
|
||||||
Dim si% = -1
|
Dim si% = -1
|
||||||
|
|||||||
18
SCrawler/API/Bluesky/Declarations.vb
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
' Copyright (C) Andy https://github.com/AAndyProgram
|
||||||
|
' This program is free software: you can redistribute it and/or modify
|
||||||
|
' it under the terms of the GNU General Public License as published by
|
||||||
|
' the Free Software Foundation, either version 3 of the License, or
|
||||||
|
' (at your option) any later version.
|
||||||
|
'
|
||||||
|
' This program is distributed in the hope that it will be useful,
|
||||||
|
' but WITHOUT ANY WARRANTY
|
||||||
|
Imports PersonalUtilities.Functions.RegularExpressions
|
||||||
|
Namespace API.Bluesky
|
||||||
|
Friend Module Declarations
|
||||||
|
Friend Const BlueskySiteKey As String = "AndyProgram_Bluesky"
|
||||||
|
Friend ReadOnly DateProvider As New ADateTime("yyyy-MM-ddTHH:mm:ss.FFF%K")
|
||||||
|
Friend ReadOnly RegEx_PlayLists As RParams = RParams.DM("RESOLUTION=\d+x(\d+)\s*(\S+)", 0, RegexReturn.List, EDP.ReturnValue)
|
||||||
|
Friend ReadOnly RegEx_FilePattern As RParams = RParams.DM("(.+?)(\.|@)(gif|m3u8|[^/\?\&]+)", 0, RegexReturn.ListByMatch, EDP.ReturnValue)
|
||||||
|
Friend ReadOnly RegEx_SinglePostPattern As RParams = RParams.DM("profile/([^/]+)/post/([^/\?\&]+)", 0, RegexReturn.ListByMatch, EDP.ReturnValue)
|
||||||
|
End Module
|
||||||
|
End Namespace
|
||||||
51
SCrawler/API/Bluesky/M3U8.vb
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
' Copyright (C) Andy https://github.com/AAndyProgram
|
||||||
|
' This program is free software: you can redistribute it and/or modify
|
||||||
|
' it under the terms of the GNU General Public License as published by
|
||||||
|
' the Free Software Foundation, either version 3 of the License, or
|
||||||
|
' (at your option) any later version.
|
||||||
|
'
|
||||||
|
' This program is distributed in the hope that it will be useful,
|
||||||
|
' but WITHOUT ANY WARRANTY
|
||||||
|
Imports System.Threading
|
||||||
|
Imports SCrawler.API.Base
|
||||||
|
Imports PersonalUtilities.Forms.Toolbars
|
||||||
|
Imports PersonalUtilities.Tools.Web.Clients
|
||||||
|
Imports PersonalUtilities.Functions.RegularExpressions
|
||||||
|
Namespace API.Bluesky
|
||||||
|
Friend NotInheritable Class M3U8
|
||||||
|
Private Sub New()
|
||||||
|
End Sub
|
||||||
|
Private Shared Function GetUrlsList(ByVal URL As String) As List(Of String)
|
||||||
|
Using resp As New Responser With {.AllowAutoRedirect = False}
|
||||||
|
Dim r$ = resp.GetResponse(URL)
|
||||||
|
If Not r.IsEmptyString Then
|
||||||
|
Dim file$ = String.Empty, appender$
|
||||||
|
Dim files As List(Of Sizes) = RegexFields(Of Sizes)(r, {RegEx_PlayLists}, {1, 2})
|
||||||
|
If files.ListExists Then files.RemoveAll(Function(ff) ff.Value = 0 Or ff.Data.IsEmptyString)
|
||||||
|
If files.ListExists Then
|
||||||
|
files.Sort()
|
||||||
|
file = files(0).Data
|
||||||
|
appender = URL.Replace(URL.Split("/").Last, String.Empty)
|
||||||
|
file = M3U8Base.CreateUrl(appender, file)
|
||||||
|
If Not file.IsEmptyString Then
|
||||||
|
r = resp.GetResponse(file)
|
||||||
|
If Not r.IsEmptyString Then
|
||||||
|
Dim l As List(Of String) = RegexReplace(r, M3U8Declarations.TsFilesRegEx)
|
||||||
|
If l.ListExists Then
|
||||||
|
appender = file.Replace(file.Split("/").Last, String.Empty)
|
||||||
|
For i% = 0 To l.Count - 1 : l(i) = M3U8Base.CreateUrl(appender, l(i)) : Next
|
||||||
|
Return l
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
End Using
|
||||||
|
Return Nothing
|
||||||
|
End Function
|
||||||
|
Friend Shared Function Download(ByVal URL As String, ByVal Destination As SFile, ByVal Token As CancellationToken,
|
||||||
|
ByVal Progress As MyProgress, ByVal UsePreProgress As Boolean) As SFile
|
||||||
|
Return M3U8Base.Download(GetUrlsList(URL), Destination,, Token, Progress, UsePreProgress)
|
||||||
|
End Function
|
||||||
|
End Class
|
||||||
|
End Namespace
|
||||||
100
SCrawler/API/Bluesky/SiteSettings.vb
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
' Copyright (C) Andy https://github.com/AAndyProgram
|
||||||
|
' This program is free software: you can redistribute it and/or modify
|
||||||
|
' it under the terms of the GNU General Public License as published by
|
||||||
|
' the Free Software Foundation, either version 3 of the License, or
|
||||||
|
' (at your option) any later version.
|
||||||
|
'
|
||||||
|
' This program is distributed in the hope that it will be useful,
|
||||||
|
' but WITHOUT ANY WARRANTY
|
||||||
|
Imports SCrawler.API.Base
|
||||||
|
Imports SCrawler.Plugin
|
||||||
|
Imports SCrawler.Plugin.Attributes
|
||||||
|
Imports PersonalUtilities.Functions.XML
|
||||||
|
Imports PersonalUtilities.Functions.RegularExpressions
|
||||||
|
Imports PersonalUtilities.Tools.Web.Clients
|
||||||
|
Imports PersonalUtilities.Tools.Web.Documents.JSON
|
||||||
|
Namespace API.Bluesky
|
||||||
|
<Manifest(BlueskySiteKey), SpecialForm(False)>
|
||||||
|
Friend Class SiteSettings : Inherits SiteSettingsBase
|
||||||
|
<PropertyOption(ControlText:="Cookies enabled", ControlToolTip:="If checked, cookies will be used in requests", IsAuth:=True), PXML, PClonable, HiddenControl>
|
||||||
|
Friend ReadOnly Property CookiesEnabled As PropertyValue
|
||||||
|
<PropertyOption(ControlText:="User name", IsAuth:=True, AllowNull:=False), PXML>
|
||||||
|
Friend ReadOnly Property UserHandle As PropertyValue
|
||||||
|
<PropertyOption(ControlText:="Password", IsAuth:=True, AllowNull:=False), PXML>
|
||||||
|
Friend ReadOnly Property UserPassword As PropertyValue
|
||||||
|
<PXML> Friend ReadOnly Property Token As PropertyValue
|
||||||
|
<PXML> Friend ReadOnly Property TokenUpdateTime As PropertyValue
|
||||||
|
<PropertyOption(ControlText:="Token update", ControlToolTip:="Token refresh interval (in minutes)." & vbCr & "Default: 120.", IsAuth:=True), PXML, PClonable, HiddenControl>
|
||||||
|
Friend ReadOnly Property TokenRefreshInterval As PropertyValue
|
||||||
|
Friend Sub New(ByVal AccName As String, ByVal Temp As Boolean)
|
||||||
|
MyBase.New("Bluesky", "bsky.app", AccName, Temp, My.Resources.SiteResources.BlueskyIcon_32, My.Resources.SiteResources.BlueskyPic_32)
|
||||||
|
|
||||||
|
Responser.ContentType = "application/json"
|
||||||
|
|
||||||
|
CookiesEnabled = New PropertyValue(False)
|
||||||
|
UserHandle = New PropertyValue(String.Empty, GetType(String))
|
||||||
|
UserPassword = New PropertyValue(String.Empty, GetType(String))
|
||||||
|
Token = New PropertyValue(String.Empty, GetType(String))
|
||||||
|
TokenUpdateTime = New PropertyValue(Now.AddYears(-1))
|
||||||
|
TokenRefreshInterval = New PropertyValue(120)
|
||||||
|
|
||||||
|
_AllowUserAgentUpdate = False
|
||||||
|
UrlPatternUser = "https://bsky.app/profile/{0}"
|
||||||
|
ImageVideoContains = "bsky.app"
|
||||||
|
UserRegex = RParams.DMS("bsky.app/profile/([^/\?]+)", 1, EDP.ReturnValue)
|
||||||
|
UserOptionsType = GetType(EditorExchangeOptionsBase)
|
||||||
|
End Sub
|
||||||
|
Protected Overrides Function UserOptionsValid(ByVal Options As Object) As Boolean
|
||||||
|
Return DirectCast(Options, EditorExchangeOptionsBase).SiteKey = BlueskySiteKey
|
||||||
|
End Function
|
||||||
|
Protected Overrides Sub UserOptionsSetParameters(ByRef Options As Object)
|
||||||
|
DirectCast(Options, EditorExchangeOptionsBase).SiteKey = BlueskySiteKey
|
||||||
|
End Sub
|
||||||
|
Friend Overrides Function GetInstance(ByVal What As ISiteSettings.Download) As IPluginContentProvider
|
||||||
|
Return New UserData
|
||||||
|
End Function
|
||||||
|
Friend Overrides Function BaseAuthExists() As Boolean
|
||||||
|
Return Not CStr(UserHandle.Value).IsEmptyString And Not CStr(UserPassword.Value).IsEmptyString
|
||||||
|
End Function
|
||||||
|
Friend Overrides Function Available(ByVal What As ISiteSettings.Download, ByVal Silent As Boolean) As Boolean
|
||||||
|
Return MyBase.Available(What, Silent) AndAlso UpdateToken()
|
||||||
|
End Function
|
||||||
|
Private _TokenUpdating As Boolean = False
|
||||||
|
Friend Function UpdateToken(Optional ByVal Force As Boolean = False) As Boolean
|
||||||
|
Try
|
||||||
|
While _TokenUpdating : Threading.Thread.Sleep(100) : End While
|
||||||
|
_TokenUpdating = True
|
||||||
|
If BaseAuthExists() Then
|
||||||
|
If CDate(TokenUpdateTime.Value).AddMinutes(TokenRefreshInterval.Value) < Now Or Force Then
|
||||||
|
Using resp As Responser = Responser.Copy
|
||||||
|
With resp
|
||||||
|
.Mode = Responser.Modes.Curl
|
||||||
|
.Method = "POST"
|
||||||
|
.CurlSslNoRevoke = True
|
||||||
|
.CurlInsecure = True
|
||||||
|
.CurlArgumentsLeft = "-d ""{\" & $"""identifier\"": \""{UserHandle.Value}\"", \""password\"": \""{UserPassword.Value}\""" & "}"""
|
||||||
|
|
||||||
|
Dim r$ = .GetResponse("https://bsky.social/xrpc/com.atproto.server.createSession")
|
||||||
|
If Not r.IsEmptyString Then
|
||||||
|
Using j As EContainer = JsonDocument.Parse(r, EDP.ReturnValue)
|
||||||
|
If j.ListExists Then
|
||||||
|
Dim t$ = j.Value("accessJwt")
|
||||||
|
If Not t.IsEmptyString Then Token.Value = $"Bearer {t}" : TokenUpdateTime.Value = Now : Return True
|
||||||
|
End If
|
||||||
|
End Using
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
End Using
|
||||||
|
Else
|
||||||
|
Return True
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
Return False
|
||||||
|
Catch ex As Exception
|
||||||
|
Return ErrorsDescriber.Execute(EDP.SendToLog + EDP.ReturnValue, ex, "Bluesky.SiteSettings.UpdateToken", False)
|
||||||
|
Finally
|
||||||
|
_TokenUpdating = False
|
||||||
|
End Try
|
||||||
|
End Function
|
||||||
|
End Class
|
||||||
|
End Namespace
|
||||||
343
SCrawler/API/Bluesky/UserData.vb
Normal file
@@ -0,0 +1,343 @@
|
|||||||
|
' Copyright (C) Andy https://github.com/AAndyProgram
|
||||||
|
' This program is free software: you can redistribute it and/or modify
|
||||||
|
' it under the terms of the GNU General Public License as published by
|
||||||
|
' the Free Software Foundation, either version 3 of the License, or
|
||||||
|
' (at your option) any later version.
|
||||||
|
'
|
||||||
|
' This program is distributed in the hope that it will be useful,
|
||||||
|
' but WITHOUT ANY WARRANTY
|
||||||
|
Imports System.Threading
|
||||||
|
Imports SCrawler.API.Base
|
||||||
|
Imports SCrawler.API.YouTube.Objects
|
||||||
|
Imports PersonalUtilities.Functions.XML
|
||||||
|
Imports PersonalUtilities.Functions.RegularExpressions
|
||||||
|
Imports PersonalUtilities.Tools.Web.Documents.JSON
|
||||||
|
Imports UTypes = SCrawler.API.Base.UserMedia.Types
|
||||||
|
Imports UStates = SCrawler.API.Base.UserMedia.States
|
||||||
|
Namespace API.Bluesky
|
||||||
|
Friend Class UserData : Inherits UserDataBase
|
||||||
|
#Region "Declarations"
|
||||||
|
Private ReadOnly Property MySettings As SiteSettings
|
||||||
|
Get
|
||||||
|
Return HOST.Source
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
|
Private ReadOnly Property ID_Encoded As String
|
||||||
|
Get
|
||||||
|
Return If(ID.IsEmptyString, String.Empty, SymbolsConverter.ASCII.EncodeSymbolsOnly(ID))
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
|
#End Region
|
||||||
|
#Region "Loader"
|
||||||
|
Protected Overrides Sub LoadUserInformation_OptionalFields(ByRef Container As XmlFile, ByVal Loading As Boolean)
|
||||||
|
End Sub
|
||||||
|
Friend Overrides Function ExchangeOptionsGet() As Object
|
||||||
|
Return New EditorExchangeOptionsBase(Me) With {.SiteKey = BlueskySiteKey}
|
||||||
|
End Function
|
||||||
|
Friend Overrides Sub ExchangeOptionsSet(ByVal Obj As Object)
|
||||||
|
If Not Obj Is Nothing AndAlso TypeOf Obj Is EditorExchangeOptionsBase AndAlso
|
||||||
|
DirectCast(Obj, EditorExchangeOptionsBase).SiteKey = BlueskySiteKey Then DirectCast(Obj, EditorExchangeOptionsBase).ApplyBase(Me)
|
||||||
|
End Sub
|
||||||
|
#End Region
|
||||||
|
#Region "Initializer"
|
||||||
|
Friend Sub New()
|
||||||
|
UseInternalM3U8Function = True
|
||||||
|
End Sub
|
||||||
|
#End Region
|
||||||
|
#Region "Token"
|
||||||
|
Private Function UpdateToken(Optional ByVal Force As Boolean = False, Optional ByVal OnlyAddHeader As Boolean = False) As Boolean
|
||||||
|
Dim process As Boolean = True
|
||||||
|
If CDate(MySettings.TokenUpdateTime.Value).AddHours(2) <= Now Or Force Then
|
||||||
|
process = MySettings.UpdateToken(Force)
|
||||||
|
If process Then _TokenUpdateCount += 1
|
||||||
|
End If
|
||||||
|
If process Or OnlyAddHeader Then Responser.Headers.Add("authorization", MySettings.Token.Value)
|
||||||
|
Return Not Responser.Headers.Value("authorization").IsEmptyString
|
||||||
|
End Function
|
||||||
|
Private _TokenUpdateCount As Integer = 0
|
||||||
|
Private Sub TokenUpdateCountReset()
|
||||||
|
_TokenUpdateCount = 0
|
||||||
|
End Sub
|
||||||
|
#End Region
|
||||||
|
#Region "Download"
|
||||||
|
Private _PostCount As Integer = 0
|
||||||
|
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
|
||||||
|
If Not CBool(MySettings.CookiesEnabled.Value) Then Responser.Cookies.Clear()
|
||||||
|
UpdateToken(, True)
|
||||||
|
_TokenUpdateCount = 0
|
||||||
|
_PostCount = 0
|
||||||
|
DownloadData(String.Empty, Token)
|
||||||
|
End Sub
|
||||||
|
Private Overloads Sub DownloadData(ByVal Cursor As String, ByVal Token As CancellationToken)
|
||||||
|
Dim URL$ = String.Empty
|
||||||
|
Try
|
||||||
|
If ID.IsEmptyString Then GetProfileInfo(Token)
|
||||||
|
If ID.IsEmptyString Then Throw New ArgumentNullException("ID", "ID is null")
|
||||||
|
If UpdateToken() Then
|
||||||
|
Dim nextCursor$ = String.Empty
|
||||||
|
Dim c%
|
||||||
|
URL = $"https://bsky.social/xrpc/app.bsky.feed.getAuthorFeed?actor={ID_Encoded}&filter=posts_and_author_threads&includePins=false&limit=99"
|
||||||
|
If Not Cursor.IsEmptyString Then URL &= $"&cursor={SymbolsConverter.ASCII.EncodeSymbolsOnly(Cursor)}"
|
||||||
|
Dim r$ = Responser.GetResponse(URL)
|
||||||
|
TokenUpdateCountReset()
|
||||||
|
If Not r.IsEmptyString Then
|
||||||
|
Using j As EContainer = JsonDocument.Parse(r)
|
||||||
|
If j.ListExists Then
|
||||||
|
With j("feed")
|
||||||
|
If .ListExists Then
|
||||||
|
For Each post As EContainer In .Self
|
||||||
|
With post({"post"})
|
||||||
|
c = DefaultParser(.Self,, nextCursor)
|
||||||
|
Select Case c
|
||||||
|
Case CInt(DateResult.Skip) * -1 : Continue For
|
||||||
|
Case CInt(DateResult.Exit) * -1 : Exit Sub
|
||||||
|
Case Is > 0 : _PostCount += c
|
||||||
|
End Select
|
||||||
|
If DownloadTopCount.HasValue AndAlso DownloadTopCount.Value <= _PostCount Then Exit Sub
|
||||||
|
End With
|
||||||
|
Next
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
End If
|
||||||
|
End Using
|
||||||
|
|
||||||
|
If Not nextCursor.IsEmptyString Then DownloadData(nextCursor, Token)
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
Catch ex As Exception
|
||||||
|
ProcessException(ex, Token, $"DownloadData({URL})")
|
||||||
|
End Try
|
||||||
|
End Sub
|
||||||
|
#End Region
|
||||||
|
#Region "DefaultParser"
|
||||||
|
Private Const Down_ImageAddress As String = "https://cdn.bsky.app/img/feed_fullsize/plain/{0}/{1}"
|
||||||
|
Private Function GetPostID(ByVal PostUri As String) As String
|
||||||
|
Return If(PostUri.IsEmptyString, String.Empty, PostUri.Split("/").LastOrDefault)
|
||||||
|
End Function
|
||||||
|
Private Function DefaultParser(ByVal e As EContainer, Optional ByVal CheckDateLimits As Boolean = True, Optional ByRef NextCursor As String = Nothing,
|
||||||
|
Optional ByVal CheckTempPosts As Boolean = True, Optional ByVal State As UStates = UStates.Unknown) As Integer
|
||||||
|
Const exitReturn% = CInt(DateResult.Exit) * -1
|
||||||
|
Dim postID$, postDate$, __url$, __urlBase$, __txt$
|
||||||
|
Dim updateUrl As Boolean
|
||||||
|
Dim c% = 0
|
||||||
|
Dim m As UserMedia
|
||||||
|
Dim d As EContainer
|
||||||
|
With e
|
||||||
|
If .ListExists Then
|
||||||
|
postID = GetPostID(.Value("uri"))
|
||||||
|
postDate = String.Empty
|
||||||
|
__urlBase = String.Empty
|
||||||
|
__txt = String.Empty
|
||||||
|
With .Item({"record"})
|
||||||
|
If .ListExists Then
|
||||||
|
'2025-01-28T02:42:12.415Z
|
||||||
|
postDate = .Value("createdAt")
|
||||||
|
NextCursor = postDate
|
||||||
|
If CheckDateLimits Then
|
||||||
|
Select Case CheckDatesLimit(postDate, DateProvider)
|
||||||
|
Case DateResult.Skip : Return CInt(DateResult.Skip) * -1 'Continue For
|
||||||
|
Case DateResult.Exit : Return exitReturn 'Exit Sub
|
||||||
|
End Select
|
||||||
|
End If
|
||||||
|
|
||||||
|
If CheckTempPosts Then
|
||||||
|
If _TempPostsList.Contains(postID) Then Return exitReturn Else _TempPostsList.Add(postID)
|
||||||
|
End If
|
||||||
|
__urlBase = $"https://bsky.app/profile/{NameTrue}/post/{postID}"
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
|
||||||
|
Dim createMedia As Func(Of String, UTypes, UserMedia) =
|
||||||
|
Function(ByVal url As String, ByVal type As UTypes) As UserMedia
|
||||||
|
m = New UserMedia(url, type) With {
|
||||||
|
.URL_BASE = __urlBase,
|
||||||
|
.File = CreateFileFromUrl(url, type),
|
||||||
|
.Post = New UserPost(postID, If(AConvert(Of Date)(postDate, DateProvider, Nothing, EDP.ReturnValue), Nothing)),
|
||||||
|
.State = State,
|
||||||
|
.PostText = __txt,
|
||||||
|
.PostTextFileSpecialFolder = DownloadTextSpecialFolder
|
||||||
|
}
|
||||||
|
If type = UTypes.Text Then m.PostTextFile = $"{postID}.txt"
|
||||||
|
_TempMediaList.ListAddValue(m, LNC)
|
||||||
|
c += 1
|
||||||
|
Return m
|
||||||
|
End Function
|
||||||
|
|
||||||
|
__txt = .Value({"record"}, "text").IfNullOrEmpty(__txt)
|
||||||
|
|
||||||
|
For Each SecondExtraction As Boolean In {False, True}
|
||||||
|
With If(SecondExtraction, .Item({"record", "embed"}), .Item("embed"))
|
||||||
|
If .ListExists Then
|
||||||
|
|
||||||
|
If If(.Item("images")?.Count, 0) > 0 Then
|
||||||
|
With .Item("images")
|
||||||
|
For Each d In .Self
|
||||||
|
updateUrl = False
|
||||||
|
__url = d.Value("fullsize")
|
||||||
|
If __url.IsEmptyString Then __url = d.Value({"image", "ref"}, "$link") : updateUrl = True
|
||||||
|
If __url.IsEmptyString And SecondExtraction Then updateUrl = False : __url = e.Value({"embed"}, "thumb")
|
||||||
|
If Not __url.IsEmptyString Then createMedia(__url, UTypes.Picture)
|
||||||
|
Next
|
||||||
|
End With
|
||||||
|
End If
|
||||||
|
|
||||||
|
If Not .Value("playlist").IsEmptyString Then createMedia(.Value("playlist"), UTypes.m3u8)
|
||||||
|
|
||||||
|
If If(.Item("external")?.Count, 0) > 0 Then
|
||||||
|
__txt = .Value({"external"}, "title").IfNullOrEmpty(__txt)
|
||||||
|
createMedia(.Value({"external"}, "uri"), UTypes.GIF)
|
||||||
|
End If
|
||||||
|
|
||||||
|
If If(.Item({"media"}, "external")?.Count, 0) > 0 Then
|
||||||
|
__txt = .Value({"media", "external"}, "title").IfNullOrEmpty(__txt)
|
||||||
|
createMedia(.Value({"media", "external"}, "uri"), UTypes.GIF)
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
|
||||||
|
If c > 0 Then Exit For
|
||||||
|
Next
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
Return c
|
||||||
|
End Function
|
||||||
|
#End Region
|
||||||
|
#Region "GetProfileInfo"
|
||||||
|
Private Sub GetProfileInfo(ByVal Token As CancellationToken)
|
||||||
|
Try
|
||||||
|
If UpdateToken() Then
|
||||||
|
Dim r$ = Responser.GetResponse($"https://bsky.social/xrpc/app.bsky.actor.getProfile?actor={ID.IfNullOrEmpty(NameTrue)}")
|
||||||
|
TokenUpdateCountReset()
|
||||||
|
If Not r.IsEmptyString Then
|
||||||
|
Using j As EContainer = JsonDocument.Parse(r)
|
||||||
|
If j.ListExists Then
|
||||||
|
ID = j.Value("did")
|
||||||
|
UserSiteNameUpdate(j.Value("displayName"))
|
||||||
|
UserDescriptionUpdate(j.Value("description"))
|
||||||
|
NameTrue = j.Value("handle")
|
||||||
|
SimpleDownloadAvatar(j.Value("avatar"))
|
||||||
|
SimpleDownloadAvatar(j.Value("banner"))
|
||||||
|
End If
|
||||||
|
End Using
|
||||||
|
End If
|
||||||
|
Else
|
||||||
|
Throw New ArgumentException("Token is null", "Token")
|
||||||
|
End If
|
||||||
|
Catch ex As Exception
|
||||||
|
ProcessException(ex, Token, "GetProfileInfo")
|
||||||
|
End Try
|
||||||
|
End Sub
|
||||||
|
#End Region
|
||||||
|
#Region "ReparseMissing"
|
||||||
|
Protected Overrides Sub ReparseMissing(ByVal Token As CancellationToken)
|
||||||
|
Const uriPattern$ = "at://{0}/app.bsky.feed.post/{1}"
|
||||||
|
Dim rList As New List(Of Integer)
|
||||||
|
Try
|
||||||
|
If ContentMissingExists AndAlso UpdateToken() Then
|
||||||
|
Dim r$, url$, uri$
|
||||||
|
Dim tu As Byte
|
||||||
|
Dim m As UserMedia
|
||||||
|
Dim j As EContainer
|
||||||
|
For i% = 0 To _ContentList.Count - 1
|
||||||
|
m = _ContentList(i)
|
||||||
|
If m.State = UStates.Missing Then
|
||||||
|
uri = SymbolsConverter.ASCII.EncodeSymbolsOnly(String.Format(uriPattern, NameTrue, m.Post.ID))
|
||||||
|
url = $"https://bsky.social/xrpc/app.bsky.feed.getPostThread?uri={uri}&depth=10"
|
||||||
|
For tu = 0 To 1
|
||||||
|
Try
|
||||||
|
Responser.ResetStatus()
|
||||||
|
r = Responser.GetResponse(url)
|
||||||
|
TokenUpdateCountReset()
|
||||||
|
If Not r.IsEmptyString Then
|
||||||
|
j = JsonDocument.Parse(r)
|
||||||
|
If j.ListExists Then
|
||||||
|
If DefaultParser(j({"thread", "post"}), False,, False, UStates.Missing) > 0 Then rList.Add(i)
|
||||||
|
j.Dispose()
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
Exit For
|
||||||
|
Catch eex As Exception
|
||||||
|
If ProcessException(eex, Token, $"ReparseMissing({url})",,, False) <> 1 Then Throw eex
|
||||||
|
End Try
|
||||||
|
Next
|
||||||
|
End If
|
||||||
|
Next
|
||||||
|
Else
|
||||||
|
Throw New ArgumentException("Token is null", "Token")
|
||||||
|
End If
|
||||||
|
Catch ex As Exception
|
||||||
|
ProcessException(ex, Token, "ReparseMissing error")
|
||||||
|
Finally
|
||||||
|
If rList.Count > 0 Then
|
||||||
|
For i% = rList.Count - 1 To 0 Step -1 : _ContentList.RemoveAt(rList(i)) : Next
|
||||||
|
rList.Clear()
|
||||||
|
End If
|
||||||
|
End Try
|
||||||
|
End Sub
|
||||||
|
#End Region
|
||||||
|
#Region "CreateFileFromUrl"
|
||||||
|
Protected Overloads Overrides Function CreateFileFromUrl(ByVal URL As String) As SFile
|
||||||
|
Return CreateFileFromUrl(URL, UTypes.Undefined)
|
||||||
|
End Function
|
||||||
|
Protected Overloads Function CreateFileFromUrl(ByVal URL As String, ByVal Type As UTypes) As SFile
|
||||||
|
Dim f As SFile = MyBase.CreateFileFromUrl(URL)
|
||||||
|
Dim force As Boolean = False
|
||||||
|
f.Separator = "\"
|
||||||
|
With URL.Split("/")
|
||||||
|
If .ListExists Then
|
||||||
|
With DirectCast(RegexReplace(.Last, RegEx_FilePattern), List(Of String))
|
||||||
|
If .ListExists(4) Then
|
||||||
|
f.Name = .Item(1).IfNullOrEmpty(f.Name)
|
||||||
|
f.Extension = .Item(3)
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
If Not f.Extension.IsEmptyString AndAlso f.Extension.ToLower = "m3u8" Then force = True : Type = UTypes.m3u8
|
||||||
|
If f.Extension.IsEmptyString Or force Then
|
||||||
|
Select Case Type
|
||||||
|
Case UTypes.Picture : f.Extension = "jpg"
|
||||||
|
Case UTypes.GIF : f.Extension = "gif"
|
||||||
|
Case UTypes.m3u8 : f.Name = "Video" : f.Extension = "mp4"
|
||||||
|
End Select
|
||||||
|
End If
|
||||||
|
Return f
|
||||||
|
End Function
|
||||||
|
#End Region
|
||||||
|
#Region "DownloadContent"
|
||||||
|
Protected Overrides Sub DownloadContent(ByVal Token As CancellationToken)
|
||||||
|
DownloadContentDefault(Token)
|
||||||
|
End Sub
|
||||||
|
Protected Overrides Function DownloadM3U8(ByVal URL As String, ByVal Media As UserMedia, ByVal DestinationFile As SFile, ByVal Token As CancellationToken) As SFile
|
||||||
|
Return M3U8.Download(URL, DestinationFile, Token, Progress, Not IsSingleObjectDownload)
|
||||||
|
End Function
|
||||||
|
#End Region
|
||||||
|
#Region "DownloadSingleObject"
|
||||||
|
Protected Overrides Sub DownloadSingleObject_GetPosts(ByVal Data As IYouTubeMediaContainer, ByVal Token As CancellationToken)
|
||||||
|
_TokenUpdateCount = 0
|
||||||
|
UpdateToken()
|
||||||
|
Dim l As List(Of String) = RegexReplace(Data.URL, RegEx_SinglePostPattern)
|
||||||
|
If l.ListExists(3) Then
|
||||||
|
NameTrue = l(1)
|
||||||
|
_ContentList.Add(New UserMedia(Data.URL) With {.State = UStates.Missing, .Post = l(2)})
|
||||||
|
ReparseMissing(Token)
|
||||||
|
End If
|
||||||
|
MyBase.DownloadSingleObject_GetPosts(Data, Token)
|
||||||
|
End Sub
|
||||||
|
#End Region
|
||||||
|
#Region "Exception"
|
||||||
|
Protected Overrides Function DownloadingException(ByVal ex As Exception, ByVal Message As String, Optional ByVal FromPE As Boolean = False,
|
||||||
|
Optional ByVal EObj As Object = Nothing) As Integer
|
||||||
|
If Responser.StatusCode = Net.HttpStatusCode.BadRequest Then '400
|
||||||
|
If _TokenUpdateCount = 0 AndAlso UpdateToken(True) Then
|
||||||
|
Return 1
|
||||||
|
Else
|
||||||
|
Return 0
|
||||||
|
End If
|
||||||
|
Else
|
||||||
|
Return 0
|
||||||
|
End If
|
||||||
|
End Function
|
||||||
|
#End Region
|
||||||
|
End Class
|
||||||
|
End Namespace
|
||||||
@@ -18,6 +18,8 @@ Namespace API.Facebook
|
|||||||
Friend ReadOnly Regex_FileName As RParams = RParams.DM("([^/\?]+\..{3,4})(?=(\?|\Z))", 0, EDP.ReturnValue)
|
Friend ReadOnly Regex_FileName As RParams = RParams.DM("([^/\?]+\..{3,4})(?=(\?|\Z))", 0, EDP.ReturnValue)
|
||||||
Friend ReadOnly Regex_ProfileUrlID As RParams = RParams.DMS("profile.php\?id=(\d+)", 1, EDP.ReturnValue)
|
Friend ReadOnly Regex_ProfileUrlID As RParams = RParams.DMS("profile.php\?id=(\d+)", 1, EDP.ReturnValue)
|
||||||
Friend ReadOnly Regex_VideoPageID As RParams = RParams.DMS("pageid.:.(\d+)", 1, RegexOptions.IgnoreCase, EDP.ReturnValue)
|
Friend ReadOnly Regex_VideoPageID As RParams = RParams.DMS("pageid.:.(\d+)", 1, RegexOptions.IgnoreCase, EDP.ReturnValue)
|
||||||
|
Friend ReadOnly Regex_ReelsPageID As RParams = RParams.DMS("\{[^\}]*""tab_key"":""owner_reels"",?[^\}]*""id"":""([^\}""]+)""", 1, RegexOptions.IgnoreCase, EDP.ReturnValue)
|
||||||
|
Friend ReadOnly Regex_ReelsFilePattern As RParams = RParams.DM("[^/]+\.mp4", 0, EDP.ReturnValue)
|
||||||
Friend ReadOnly Regex_StoryBucket As RParams = RParams.DMS("story_bucket[^\>]*?(\d+)", 1, EDP.ReturnValue)
|
Friend ReadOnly Regex_StoryBucket As RParams = RParams.DMS("story_bucket[^\>]*?(\d+)", 1, EDP.ReturnValue)
|
||||||
|
|
||||||
Friend ReadOnly Regex_VideoIDFromURL As RParams = RParams.DMS("facebook.com/([^/]+/videos/|watch/\D*[\?&]{1}v=)(\d+)", 2, EDP.ReturnValue)
|
Friend ReadOnly Regex_VideoIDFromURL As RParams = RParams.DMS("facebook.com/([^/]+/videos/|watch/\D*[\?&]{1}v=)(\d+)", 2, EDP.ReturnValue)
|
||||||
|
|||||||
@@ -36,8 +36,13 @@ Namespace API.Facebook
|
|||||||
Friend ReadOnly Property ParsePhotoBlock As PropertyValue
|
Friend ReadOnly Property ParsePhotoBlock As PropertyValue
|
||||||
<PropertyOption(ControlText:="Download videos", IsAuth:=False, Category:=DN.CAT_UserDefs), PXML, PClonable>
|
<PropertyOption(ControlText:="Download videos", IsAuth:=False, Category:=DN.CAT_UserDefs), PXML, PClonable>
|
||||||
Friend ReadOnly Property ParseVideoBlock As PropertyValue
|
Friend ReadOnly Property ParseVideoBlock As PropertyValue
|
||||||
|
<PropertyOption(ControlText:="Download reels", IsAuth:=False, Category:=DN.CAT_UserDefs), PXML, PClonable>
|
||||||
|
Friend ReadOnly Property ParseReelsBlock As PropertyValue
|
||||||
<PropertyOption(ControlText:="Download stories", IsAuth:=False, Category:=DN.CAT_UserDefs), PXML, PClonable>
|
<PropertyOption(ControlText:="Download stories", IsAuth:=False, Category:=DN.CAT_UserDefs), PXML, PClonable>
|
||||||
Friend ReadOnly Property ParseStoriesBlock As PropertyValue
|
Friend ReadOnly Property ParseStoriesBlock As PropertyValue
|
||||||
|
<DoNotUse> Friend Overrides Property DownloadText As PropertyValue
|
||||||
|
<DoNotUse> Friend Overrides Property DownloadTextPosts As PropertyValue
|
||||||
|
<DoNotUse> Friend Overrides Property DownloadTextSpecialFolder As PropertyValue
|
||||||
#End Region
|
#End Region
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Initializer"
|
#Region "Initializer"
|
||||||
@@ -52,6 +57,7 @@ Namespace API.Facebook
|
|||||||
Header_Accept = New PropertyValue(String.Empty, GetType(String))
|
Header_Accept = New PropertyValue(String.Empty, GetType(String))
|
||||||
ParsePhotoBlock = New PropertyValue(True)
|
ParsePhotoBlock = New PropertyValue(True)
|
||||||
ParseVideoBlock = New PropertyValue(True)
|
ParseVideoBlock = New PropertyValue(True)
|
||||||
|
ParseReelsBlock = New PropertyValue(False)
|
||||||
ParseStoriesBlock = New PropertyValue(True)
|
ParseStoriesBlock = New PropertyValue(True)
|
||||||
|
|
||||||
UrlPatternUser = "https://www.facebook.com/{0}"
|
UrlPatternUser = "https://www.facebook.com/{0}"
|
||||||
|
|||||||
@@ -23,9 +23,11 @@ Namespace API.Facebook
|
|||||||
Private Const Name_IsNoNameProfile As String = "IsNoNameProfile"
|
Private Const Name_IsNoNameProfile As String = "IsNoNameProfile"
|
||||||
Private Const Name_OptionsParsed As String = "OptionsParsed"
|
Private Const Name_OptionsParsed As String = "OptionsParsed"
|
||||||
Private Const Name_VideoPageID As String = "VideoPageID"
|
Private Const Name_VideoPageID As String = "VideoPageID"
|
||||||
|
Private Const Name_ReelsPageID As String = "ReelsPageID"
|
||||||
Private Const Name_StoryBucket As String = "StoryBucket"
|
Private Const Name_StoryBucket As String = "StoryBucket"
|
||||||
Private Const Name_ParsePhotoBlock As String = "ParsePhotoBlock"
|
Private Const Name_ParsePhotoBlock As String = "ParsePhotoBlock"
|
||||||
Private Const Name_ParseVideoBlock As String = "ParseVideoBlock"
|
Private Const Name_ParseVideoBlock As String = "ParseVideoBlock"
|
||||||
|
Private Const Name_ParseReelsBlock As String = "ParseReelsBlock"
|
||||||
Private Const Name_ParseStoriesBlock As String = "ParseStoriesBlock"
|
Private Const Name_ParseStoriesBlock As String = "ParseStoriesBlock"
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Declarations"
|
#Region "Declarations"
|
||||||
@@ -37,15 +39,18 @@ Namespace API.Facebook
|
|||||||
Private IsNoNameProfile As Boolean = False
|
Private IsNoNameProfile As Boolean = False
|
||||||
Private OptionsParsed As Boolean = False
|
Private OptionsParsed As Boolean = False
|
||||||
Private Property VideoPageID As String = String.Empty
|
Private Property VideoPageID As String = String.Empty
|
||||||
|
Private Property ReelsPageID As String = String.Empty
|
||||||
Private Property StoryBucket As String = String.Empty
|
Private Property StoryBucket As String = String.Empty
|
||||||
Friend Property ParsePhotoBlock As Boolean = True
|
Friend Property ParsePhotoBlock As Boolean = True
|
||||||
Friend Property ParseVideoBlock As Boolean = True
|
Friend Property ParseVideoBlock As Boolean = True
|
||||||
|
Friend Property ParseReelsBlock As Boolean = False
|
||||||
Friend Property ParseStoriesBlock As Boolean = True
|
Friend Property ParseStoriesBlock As Boolean = True
|
||||||
Private Enum PageBlock As Integer
|
Private Enum PageBlock As Integer
|
||||||
Timeline = Sections.Timeline
|
Timeline = Sections.Timeline
|
||||||
Stories = Sections.Stories
|
Stories = Sections.Stories
|
||||||
Photos = 100
|
Photos = 100
|
||||||
Videos = 101
|
Videos = 101
|
||||||
|
Reels = Sections.Reels
|
||||||
Undefined = -1
|
Undefined = -1
|
||||||
End Enum
|
End Enum
|
||||||
#End Region
|
#End Region
|
||||||
@@ -67,6 +72,7 @@ Namespace API.Facebook
|
|||||||
With DirectCast(Obj, UserExchangeOptions)
|
With DirectCast(Obj, UserExchangeOptions)
|
||||||
ParsePhotoBlock = .ParsePhotoBlock
|
ParsePhotoBlock = .ParsePhotoBlock
|
||||||
ParseVideoBlock = .ParseVideoBlock
|
ParseVideoBlock = .ParseVideoBlock
|
||||||
|
ParseReelsBlock = .ParseReelsBlock
|
||||||
ParseStoriesBlock = .ParseStoriesBlock
|
ParseStoriesBlock = .ParseStoriesBlock
|
||||||
End With
|
End With
|
||||||
End If
|
End If
|
||||||
@@ -90,18 +96,22 @@ Namespace API.Facebook
|
|||||||
End If
|
End If
|
||||||
OptionsParsed = .Value(Name_OptionsParsed).FromXML(Of Boolean)(False)
|
OptionsParsed = .Value(Name_OptionsParsed).FromXML(Of Boolean)(False)
|
||||||
VideoPageID = .Value(Name_VideoPageID)
|
VideoPageID = .Value(Name_VideoPageID)
|
||||||
|
ReelsPageID = .Value(Name_ReelsPageID)
|
||||||
StoryBucket = .Value(Name_StoryBucket)
|
StoryBucket = .Value(Name_StoryBucket)
|
||||||
ParsePhotoBlock = .Value(Name_ParsePhotoBlock).FromXML(Of Boolean)(True)
|
ParsePhotoBlock = .Value(Name_ParsePhotoBlock).FromXML(Of Boolean)(True)
|
||||||
ParseVideoBlock = .Value(Name_ParseVideoBlock).FromXML(Of Boolean)(True)
|
ParseVideoBlock = .Value(Name_ParseVideoBlock).FromXML(Of Boolean)(True)
|
||||||
|
ParseReelsBlock = .Value(Name_ParseReelsBlock).FromXML(Of Boolean)(False)
|
||||||
ParseStoriesBlock = .Value(Name_ParseStoriesBlock).FromXML(Of Boolean)(True)
|
ParseStoriesBlock = .Value(Name_ParseStoriesBlock).FromXML(Of Boolean)(True)
|
||||||
Else
|
Else
|
||||||
updateNames.Invoke
|
updateNames.Invoke
|
||||||
.Add(Name_IsNoNameProfile, IsNoNameProfile.BoolToInteger)
|
.Add(Name_IsNoNameProfile, IsNoNameProfile.BoolToInteger)
|
||||||
.Add(Name_OptionsParsed, OptionsParsed.BoolToInteger)
|
.Add(Name_OptionsParsed, OptionsParsed.BoolToInteger)
|
||||||
.Add(Name_VideoPageID, VideoPageID)
|
.Add(Name_VideoPageID, VideoPageID)
|
||||||
|
.Add(Name_ReelsPageID, ReelsPageID)
|
||||||
.Add(Name_StoryBucket, StoryBucket)
|
.Add(Name_StoryBucket, StoryBucket)
|
||||||
.Add(Name_ParsePhotoBlock, ParsePhotoBlock.BoolToInteger)
|
.Add(Name_ParsePhotoBlock, ParsePhotoBlock.BoolToInteger)
|
||||||
.Add(Name_ParseVideoBlock, ParseVideoBlock.BoolToInteger)
|
.Add(Name_ParseVideoBlock, ParseVideoBlock.BoolToInteger)
|
||||||
|
.Add(Name_ParseReelsBlock, ParseReelsBlock.BoolToInteger)
|
||||||
.Add(Name_ParseStoriesBlock, ParseStoriesBlock.BoolToInteger)
|
.Add(Name_ParseStoriesBlock, ParseStoriesBlock.BoolToInteger)
|
||||||
End If
|
End If
|
||||||
End With
|
End With
|
||||||
@@ -146,6 +156,7 @@ Namespace API.Facebook
|
|||||||
Else
|
Else
|
||||||
If DownloadImages And ParsePhotoBlock Then DownloadData_Photo(String.Empty, Token)
|
If DownloadImages And ParsePhotoBlock Then DownloadData_Photo(String.Empty, Token)
|
||||||
If DownloadVideos And ParseVideoBlock Then DownloadData_Video(String.Empty, Token)
|
If DownloadVideos And ParseVideoBlock Then DownloadData_Video(String.Empty, Token)
|
||||||
|
If DownloadVideos And ParseReelsBlock Then DownloadData_Reels(String.Empty, Token)
|
||||||
If (DownloadImages Or DownloadVideos) And ParseStoriesBlock Then DownloadData_Stories(Token)
|
If (DownloadImages Or DownloadVideos) And ParseStoriesBlock Then DownloadData_Stories(Token)
|
||||||
End If
|
End If
|
||||||
LoadSavePostsKV(False)
|
LoadSavePostsKV(False)
|
||||||
@@ -158,10 +169,12 @@ Namespace API.Facebook
|
|||||||
Private Const Header_fb_fr_name_Video As String = "PagesCometChannelTabAllVideosCardImplPaginationQuery"
|
Private Const Header_fb_fr_name_Video As String = "PagesCometChannelTabAllVideosCardImplPaginationQuery"
|
||||||
Private Const Header_fb_fr_name_Stories As String = "StoriesSuspenseContentPaneRootWithEntryPointQuery"
|
Private Const Header_fb_fr_name_Stories As String = "StoriesSuspenseContentPaneRootWithEntryPointQuery"
|
||||||
Private Const Header_fb_fr_name_SavedPosts As String = "CometSaveDashboardAllItemsPaginationQuery"
|
Private Const Header_fb_fr_name_SavedPosts As String = "CometSaveDashboardAllItemsPaginationQuery"
|
||||||
|
Private Const Header_fb_fr_name_Reels As String = "ProfileCometAppCollectionReelsRendererPaginationQuery"
|
||||||
Private Const DocID_Photo As String = "6684543058255697"
|
Private Const DocID_Photo As String = "6684543058255697"
|
||||||
Private Const DocID_Video As String = "24545934291687581"
|
Private Const DocID_Video As String = "24545934291687581"
|
||||||
Private Const DocID_Stories As String = "6771064226315961"
|
Private Const DocID_Stories As String = "6771064226315961"
|
||||||
Private Const DocID_SavedPosts As String = "7112228098805003"
|
Private Const DocID_SavedPosts As String = "7112228098805003"
|
||||||
|
Private Const DocID_Reels As String = "28517740954539304"
|
||||||
Private Const Graphql_UrlPattern As String = "https://www.facebook.com/api/graphql?lsd={0}&doc_id={1}&server_timestamps=true&fb_dtsg={3}&fb_api_req_friendly_name={2}&variables={4}"
|
Private Const Graphql_UrlPattern As String = "https://www.facebook.com/api/graphql?lsd={0}&doc_id={1}&server_timestamps=true&fb_dtsg={3}&fb_api_req_friendly_name={2}&variables={4}"
|
||||||
Private Const VideoHtmlUrlPattern As String = "https://www.facebook.com/watch/?v={0}"
|
Private Const VideoHtmlUrlPattern As String = "https://www.facebook.com/watch/?v={0}"
|
||||||
Private Sub DownloadData_Photo(ByVal Cursor As String, ByVal Token As CancellationToken)
|
Private Sub DownloadData_Photo(ByVal Cursor As String, ByVal Token As CancellationToken)
|
||||||
@@ -238,7 +251,7 @@ Namespace API.Facebook
|
|||||||
Dim newPostsDetected As Boolean = False
|
Dim newPostsDetected As Boolean = False
|
||||||
Dim pid As PostKV
|
Dim pid As PostKV
|
||||||
|
|
||||||
If VideoPageID.IsEmptyString Then GetVideoPageID(Token)
|
If VideoPageID.IsEmptyString Then GetVideoPageID(False, Token)
|
||||||
If VideoPageID.IsEmptyString Then Throw New TokensException("Unable to obtain 'VideoPageID'", False)
|
If VideoPageID.IsEmptyString Then Throw New TokensException("Unable to obtain 'VideoPageID'", False)
|
||||||
ValidateBaseTokens()
|
ValidateBaseTokens()
|
||||||
|
|
||||||
@@ -355,6 +368,123 @@ Namespace API.Facebook
|
|||||||
ProcessException(ex, Token, $"data (stories) downloading error [{URL}]",, Responser)
|
ProcessException(ex, Token, $"data (stories) downloading error [{URL}]",, Responser)
|
||||||
End Try
|
End Try
|
||||||
End Sub
|
End Sub
|
||||||
|
Private Sub DownloadData_Reels(ByVal Cursor As String, ByVal Token As CancellationToken)
|
||||||
|
Dim URL$ = String.Empty
|
||||||
|
Const VarPattern$ = """count"":10,""cursor"":{0},""feedLocation"":""COMET_MEDIA_VIEWER"",""feedbackSource"":65,""focusCommentID"":null,""renderLocation"":null,""scale"":1,""useDefaultActor"":true,""id"":""{1}"",""__relay_internal__pv__FBReelsMediaFooter_comet_enable_reels_ads_gkrelayprovider"":true,""__relay_internal__pv__IsWorkUserrelayprovider"":false"
|
||||||
|
Try
|
||||||
|
Dim nextCursor$ = String.Empty
|
||||||
|
Dim newPostsDetected As Boolean = False
|
||||||
|
Dim nodeFound As Boolean = False
|
||||||
|
Dim pid As PostKV = Nothing
|
||||||
|
Dim __urlBase$ = String.Empty
|
||||||
|
Dim lines As List(Of String)
|
||||||
|
Dim j As EContainer, rr As EContainer
|
||||||
|
Dim jDataRoot As EContainer = Nothing
|
||||||
|
Dim indx% = -1
|
||||||
|
Dim s As New List(Of Sizes)
|
||||||
|
Dim videoIdNode$() = {"profile_reel_node", "node", "video", "id"}
|
||||||
|
|
||||||
|
Dim obtainBasePostData As Action = Sub()
|
||||||
|
If indx.ValueBetween(0, jDataRoot.Count - 1) Then
|
||||||
|
With jDataRoot(indx)
|
||||||
|
pid = New PostKV(String.Empty, .Item(videoIdNode).XmlIfNothingValue.
|
||||||
|
IfNullOrEmpty(.Value({"node"}, "id")), PageBlock.Reels)
|
||||||
|
pid.Code = $"Reels:{pid.ID}"
|
||||||
|
nextCursor = .Value("cursor")
|
||||||
|
If Not .Item(videoIdNode).XmlIfNothing.IsEmptyString Then
|
||||||
|
__urlBase = $"https://www.facebook.com/reel/{pid.ID}"
|
||||||
|
Else
|
||||||
|
__urlBase = String.Empty
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
Else
|
||||||
|
pid = Nothing
|
||||||
|
nextCursor = String.Empty
|
||||||
|
__urlBase = String.Empty
|
||||||
|
End If
|
||||||
|
End Sub
|
||||||
|
Dim createFile As Func(Of String, SFile, SFile) = Function(ByVal __url As String, ByVal cFile As SFile) As SFile
|
||||||
|
Dim f As New SFile(RegexReplace(__url, Regex_ReelsFilePattern))
|
||||||
|
If Not f.IsEmptyString Then Return f Else Return cFile
|
||||||
|
End Function
|
||||||
|
|
||||||
|
If ReelsPageID.IsEmptyString Then GetVideoPageID(True, Token)
|
||||||
|
If ReelsPageID.IsEmptyString Then Throw New TokensException("Unable to obtain 'ReelsPageID'", False)
|
||||||
|
ValidateBaseTokens()
|
||||||
|
|
||||||
|
URL = String.Format(Graphql_UrlPattern, Token_lsd, DocID_Reels, Header_fb_fr_name_Reels, Token_dtsg_Var,
|
||||||
|
SymbolsConverter.ASCII.EncodeSymbolsOnly("{" & String.Format(VarPattern, If(Cursor.IsEmptyString, "null", $"""{Cursor}"""), ReelsPageID) & "}"))
|
||||||
|
|
||||||
|
ResponserApplyDefs(Header_fb_fr_name_Reels)
|
||||||
|
ThrowAny(Token)
|
||||||
|
|
||||||
|
WaitTimer()
|
||||||
|
Dim r$ = Responser.GetResponse(URL)
|
||||||
|
If Not r.IsEmptyString Then
|
||||||
|
lines = r.StringToList(Of String)(vbCrLf).ListIfNothing
|
||||||
|
If lines.ListExists Then
|
||||||
|
For Each line$ In lines
|
||||||
|
j = JsonDocument.Parse(line, EDP.ReturnValue)
|
||||||
|
If j.ListExists Then
|
||||||
|
jDataRoot = j({"data", "node", "aggregated_fb_shorts", "edges"})
|
||||||
|
If jDataRoot.ListExists Then
|
||||||
|
|
||||||
|
With j({"extensions", "all_video_dash_prefetch_representations"})
|
||||||
|
If .ListExists Then
|
||||||
|
ProgressPre.ChangeMax(.Count)
|
||||||
|
For indx = 0 To .Count - 1
|
||||||
|
ProgressPre.Perform()
|
||||||
|
|
||||||
|
obtainBasePostData()
|
||||||
|
If Not pid.ID.IsEmptyString AndAlso Not PostKvExists(pid) Then
|
||||||
|
newPostsDetected = True
|
||||||
|
PostsKVIDs.ListAddValue(pid, LNC)
|
||||||
|
_TempPostsList.Add(pid.Code)
|
||||||
|
|
||||||
|
With .ItemF({indx, "representations"})
|
||||||
|
If .ListExists Then
|
||||||
|
s.Clear()
|
||||||
|
For Each rr In .Self : s.Add(New Sizes(rr.Value("width"), rr.Value("base_url"))) : Next
|
||||||
|
If s.Count > 0 Then s.RemoveAll(Function(ss) ss.Value = 0 Or ss.Data.IsEmptyString)
|
||||||
|
If s.Count > 0 Then
|
||||||
|
s.Sort()
|
||||||
|
_TempMediaList.ListAddValue(New UserMedia(s(0).Data, UTypes.Video) With {
|
||||||
|
.URL_BASE = __urlBase.IfNullOrEmpty(.URL_BASE),
|
||||||
|
.Post = pid.ID,
|
||||||
|
.File = createFile(s(0).Data, .File),
|
||||||
|
.SpecialFolder = "Reels*"
|
||||||
|
}, LNC)
|
||||||
|
s.Clear()
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
|
||||||
|
|
||||||
|
If Limit > 0 And _TempMediaList.Count >= Limit Then j.Dispose() : Exit Sub
|
||||||
|
Else
|
||||||
|
j.Dispose()
|
||||||
|
Exit Sub
|
||||||
|
End If
|
||||||
|
|
||||||
|
Next
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
|
||||||
|
End If
|
||||||
|
|
||||||
|
j.Dispose()
|
||||||
|
End If
|
||||||
|
Next
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
|
||||||
|
If newPostsDetected And Not nextCursor.IsEmptyString Then DownloadData_Reels(nextCursor, Token)
|
||||||
|
Catch tex As TokensException When Not tex.BasicTokens
|
||||||
|
TokensException.SendToLog(Me, tex, "data (reels)")
|
||||||
|
Catch ex As Exception
|
||||||
|
ProcessException(ex, Token, $"data (reels) downloading error [{URL}]",, Responser)
|
||||||
|
End Try
|
||||||
|
End Sub
|
||||||
Private Sub DownloadData_SavedPosts(ByVal Cursor As String, ByVal Token As CancellationToken)
|
Private Sub DownloadData_SavedPosts(ByVal Cursor As String, ByVal Token As CancellationToken)
|
||||||
Dim URL$ = String.Empty
|
Dim URL$ = String.Empty
|
||||||
Const VarPattern$ = """content_filter"":[],""count"":10,""cursor"":{0},""scale"":1,""use_case"":""SAVE_DEFAULT"""
|
Const VarPattern$ = """content_filter"":[],""count"":10,""cursor"":{0},""scale"":1,""use_case"":""SAVE_DEFAULT"""
|
||||||
@@ -507,13 +637,19 @@ Namespace API.Facebook
|
|||||||
Return True
|
Return True
|
||||||
End If
|
End If
|
||||||
End Function
|
End Function
|
||||||
Private Sub GetVideoPageID(ByVal Token As CancellationToken)
|
Private Sub GetVideoPageID(ByVal GetReels As Boolean, ByVal Token As CancellationToken)
|
||||||
Dim URL$ = $"{GetProfileUrl()}\videos"
|
Dim URL$ = $"{GetProfileUrl()}{IIf(IsNoNameProfile, "&sk=", "/")}{IIf(GetReels, IIf(IsNoNameProfile, "reels_tab", "reels"), "videos")}"
|
||||||
Dim resp As Responser = HtmlResponserCreate()
|
Dim resp As Responser = HtmlResponserCreate()
|
||||||
Try
|
Try
|
||||||
WaitTimer()
|
WaitTimer()
|
||||||
Dim r$ = resp.GetResponse(URL)
|
Dim r$ = resp.GetResponse(URL)
|
||||||
If Not r.IsEmptyString Then VideoPageID = RegexReplace(r, Regex_VideoPageID)
|
If Not r.IsEmptyString Then
|
||||||
|
If GetReels Then
|
||||||
|
ReelsPageID = RegexReplace(r, Regex_ReelsPageID)
|
||||||
|
Else
|
||||||
|
VideoPageID = RegexReplace(r, Regex_VideoPageID)
|
||||||
|
End If
|
||||||
|
End If
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
ProcessException(ex, Token, "get video page ID",, resp)
|
ProcessException(ex, Token, "get video page ID",, resp)
|
||||||
Finally
|
Finally
|
||||||
@@ -658,17 +794,39 @@ Namespace API.Facebook
|
|||||||
HtmlResponserDispose(resp)
|
HtmlResponserDispose(resp)
|
||||||
End Try
|
End Try
|
||||||
End Sub
|
End Sub
|
||||||
|
Private Structure VideoResolution : Implements IComparable(Of VideoResolution)
|
||||||
|
Friend W As Integer
|
||||||
|
Friend H As Integer
|
||||||
|
Friend B As Integer
|
||||||
|
Friend U As String
|
||||||
|
Friend ReadOnly Property Wrong As Boolean
|
||||||
|
Get
|
||||||
|
Return W = 0 Or H = 0 Or B = 0 Or U.IsEmptyString
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
|
Private Function CompareTo(ByVal Other As VideoResolution) As Integer Implements IComparable(Of VideoResolution).CompareTo
|
||||||
|
Return CLng(Math.Max(W, H) * B).CompareTo(CLng(Math.Max(Other.W, Other.H) * Other.B)) * -1
|
||||||
|
End Function
|
||||||
|
End Structure
|
||||||
Protected Function ReparseSingleVideo(ByVal m As UserMedia, ByVal resp As Responser, ByRef result As Boolean) As UserMedia
|
Protected Function ReparseSingleVideo(ByVal m As UserMedia, ByVal resp As Responser, ByRef result As Boolean) As UserMedia
|
||||||
Const nameSD$ = "browser_native_sd_url"
|
Const nameSD$ = "browser_native_sd_url"
|
||||||
Const nameHD$ = "browser_native_hd_url"
|
Const nameHD$ = "browser_native_hd_url"
|
||||||
|
Const nameDPR$ = "all_video_dash_prefetch_representations"
|
||||||
Const pattern$ = "<script type=""application/json""[^\>]*data-sjs>([^<]+?{0}[^<]+)<"
|
Const pattern$ = "<script type=""application/json""[^\>]*data-sjs>([^<]+?{0}[^<]+)<"
|
||||||
Dim URL$ = String.Empty
|
Dim URL$ = String.Empty
|
||||||
Dim j As EContainer = Nothing
|
Dim j As EContainer = Nothing
|
||||||
Try
|
Try
|
||||||
Dim r$, script$, __url$
|
Dim r$ = String.Empty, script$ = String.Empty, __url$ = String.Empty
|
||||||
|
Dim isNewNodes As Boolean = False
|
||||||
|
Dim __date As Date? = Nothing
|
||||||
Dim jNode As EContainer
|
Dim jNode As EContainer
|
||||||
Dim jf As Predicate(Of EContainer) = Function(ee) Not ee.Name.IsEmptyString AndAlso (ee.Name.ToLower = nameSD Or ee.Name.ToLower = nameHD)
|
Dim jf As Predicate(Of EContainer) = Function(ee) Not ee.Name.IsEmptyString AndAlso (ee.Name.ToLower = nameSD Or ee.Name.ToLower = nameHD)
|
||||||
Dim re As RParams = RParams.DMS("", 1, RegexOptions.IgnoreCase, EDP.ReturnValue)
|
Dim re As RParams = RParams.DMS("", 1, RegexOptions.IgnoreCase, EDP.ReturnValue)
|
||||||
|
Dim nf As New XML.Base.NodeParams(nameDPR, True, True, True, True, 20)
|
||||||
|
Dim __extractScript As Action(Of String) = Sub(ByVal inputName As String)
|
||||||
|
re.Pattern = String.Format(pattern, inputName)
|
||||||
|
script = RegexReplace(r, re)
|
||||||
|
End Sub
|
||||||
If m.Post.ID.IsEmptyString Then
|
If m.Post.ID.IsEmptyString Then
|
||||||
URL = m.URL_BASE
|
URL = m.URL_BASE
|
||||||
Else
|
Else
|
||||||
@@ -677,30 +835,47 @@ Namespace API.Facebook
|
|||||||
WaitTimer()
|
WaitTimer()
|
||||||
r = resp.GetResponse(URL)
|
r = resp.GetResponse(URL)
|
||||||
If Not r.IsEmptyString Then
|
If Not r.IsEmptyString Then
|
||||||
re.Pattern = String.Format(pattern, nameHD)
|
__extractScript(nameHD)
|
||||||
script = RegexReplace(r, re)
|
If script.IsEmptyString Then __extractScript(nameSD)
|
||||||
If script.IsEmptyString Then
|
If script.IsEmptyString Then __extractScript(nameDPR) : isNewNodes = True
|
||||||
re.Pattern = String.Format(pattern, nameSD)
|
|
||||||
script = RegexReplace(r, re)
|
|
||||||
End If
|
|
||||||
If Not script.IsEmptyString Then
|
If Not script.IsEmptyString Then
|
||||||
j = JsonDocument.Parse(script)
|
j = JsonDocument.Parse(script)
|
||||||
If j.ListExists Then
|
If j.ListExists Then
|
||||||
j.SetSourceReferences()
|
j.SetSourceReferences()
|
||||||
jNode = j.Find(jf, True)
|
If isNewNodes Then
|
||||||
If Not jNode Is Nothing Then
|
jNode = j.GetNode({nf})
|
||||||
With DirectCast(jNode.Source, EContainer)
|
If Not jNode Is Nothing Then
|
||||||
__url = .Value(nameHD).IfNullOrEmpty(.Value(nameSD))
|
With jNode.ItemF({0, "representations"})
|
||||||
If Not __url.IsEmptyString Then
|
If .ListExists Then
|
||||||
m.URL = __url
|
Dim intE As New ErrorsDescriber(False, False, False, 0)
|
||||||
m.URL_BASE = URL
|
Dim intC As Func(Of String, Integer) = Function(__input) AConvert(Of Integer)(__input, intE)
|
||||||
m.Type = UTypes.Video
|
Dim dataV As List(Of VideoResolution) = .Select(Function(jj) New VideoResolution With {
|
||||||
m.File = CreateFileFromUrl(__url)
|
.W = intC(jj.Value("width")),
|
||||||
m.Post.Date = AConvert(Of Date)(.Value("publish_time"), UnixDate32Provider, Nothing)
|
.H = intC(jj.Value("height")),
|
||||||
result = True
|
.B = intC(jj.Value("bandwidth")),
|
||||||
Return m
|
.U = jj.Value("base_url")}).ListIfNothing
|
||||||
End If
|
If dataV.ListExists Then dataV.RemoveAll(Function(dd) dd.Wrong)
|
||||||
End With
|
If dataV.ListExists Then dataV.Sort() : __url = dataV(0).U : dataV.Clear() : __date = m.Post.Date
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
End If
|
||||||
|
Else
|
||||||
|
jNode = j.Find(jf, True)
|
||||||
|
If Not jNode Is Nothing Then
|
||||||
|
With DirectCast(jNode.Source, EContainer)
|
||||||
|
__url = .Value(nameHD).IfNullOrEmpty(.Value(nameSD))
|
||||||
|
If Not __url.IsEmptyString Then __date = AConvert(Of Date)(.Value("publish_time"), UnixDate32Provider, Nothing)
|
||||||
|
End With
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
If Not __url.IsEmptyString Then
|
||||||
|
m.URL = __url
|
||||||
|
m.URL_BASE = URL
|
||||||
|
m.Type = UTypes.Video
|
||||||
|
m.File = CreateFileFromUrl(__url)
|
||||||
|
m.Post.Date = __date
|
||||||
|
result = True
|
||||||
|
Return m
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
@@ -738,7 +913,10 @@ Namespace API.Facebook
|
|||||||
#End Region
|
#End Region
|
||||||
#Region "DownloadSingleObject"
|
#Region "DownloadSingleObject"
|
||||||
Protected Overrides Sub DownloadSingleObject_GetPosts(ByVal Data As IYouTubeMediaContainer, ByVal Token As CancellationToken)
|
Protected Overrides Sub DownloadSingleObject_GetPosts(ByVal Data As IYouTubeMediaContainer, ByVal Token As CancellationToken)
|
||||||
_ContentList.Add(New UserMedia(Data.URL, UTypes.VideoPre) With {.Post = CStr(AConvert(Of String)(Data.URL, Regex_VideoIDFromURL, String.Empty))})
|
_ContentList.Add(New UserMedia(Data.URL, UTypes.VideoPre) With {
|
||||||
|
.Post = CStr(AConvert(Of String)(Data.URL, Regex_VideoIDFromURL, String.Empty)),
|
||||||
|
.State = UStates.Missing
|
||||||
|
})
|
||||||
ReparseMissing(Token)
|
ReparseMissing(Token)
|
||||||
End Sub
|
End Sub
|
||||||
#End Region
|
#End Region
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ Namespace API.Facebook
|
|||||||
Friend Property ParsePhotoBlock As Boolean = True
|
Friend Property ParsePhotoBlock As Boolean = True
|
||||||
<PSetting(NameOf(SiteSettings.ParseVideoBlock), NameOf(MySettings))>
|
<PSetting(NameOf(SiteSettings.ParseVideoBlock), NameOf(MySettings))>
|
||||||
Friend Property ParseVideoBlock As Boolean = True
|
Friend Property ParseVideoBlock As Boolean = True
|
||||||
|
<PSetting(NameOf(SiteSettings.ParseReelsBlock), NameOf(MySettings))>
|
||||||
|
Friend Property ParseReelsBlock As Boolean = False
|
||||||
<PSetting(NameOf(SiteSettings.ParseStoriesBlock), NameOf(MySettings))>
|
<PSetting(NameOf(SiteSettings.ParseStoriesBlock), NameOf(MySettings))>
|
||||||
Friend Property ParseStoriesBlock As Boolean = True
|
Friend Property ParseStoriesBlock As Boolean = True
|
||||||
Private ReadOnly Property MySettings As SiteSettings
|
Private ReadOnly Property MySettings As SiteSettings
|
||||||
@@ -20,12 +22,14 @@ Namespace API.Facebook
|
|||||||
MySettings = u.HostCollection.Default.Source
|
MySettings = u.HostCollection.Default.Source
|
||||||
ParsePhotoBlock = u.ParsePhotoBlock
|
ParsePhotoBlock = u.ParsePhotoBlock
|
||||||
ParseVideoBlock = u.ParseVideoBlock
|
ParseVideoBlock = u.ParseVideoBlock
|
||||||
|
ParseReelsBlock = u.ParseReelsBlock
|
||||||
ParseStoriesBlock = u.ParseStoriesBlock
|
ParseStoriesBlock = u.ParseStoriesBlock
|
||||||
End Sub
|
End Sub
|
||||||
Friend Sub New(ByVal s As SiteSettings)
|
Friend Sub New(ByVal s As SiteSettings)
|
||||||
MySettings = s
|
MySettings = s
|
||||||
ParsePhotoBlock = s.ParsePhotoBlock.Value
|
ParsePhotoBlock = s.ParsePhotoBlock.Value
|
||||||
ParseVideoBlock = s.ParseVideoBlock.Value
|
ParseVideoBlock = s.ParseVideoBlock.Value
|
||||||
|
ParseReelsBlock = s.ParseReelsBlock.Value
|
||||||
ParseStoriesBlock = s.ParseStoriesBlock.Value
|
ParseStoriesBlock = s.ParseStoriesBlock.Value
|
||||||
End Sub
|
End Sub
|
||||||
End Class
|
End Class
|
||||||
|
|||||||
@@ -7,9 +7,8 @@
|
|||||||
' This program is distributed in the hope that it will be useful,
|
' This program is distributed in the hope that it will be useful,
|
||||||
' but WITHOUT ANY WARRANTY
|
' but WITHOUT ANY WARRANTY
|
||||||
Imports SCrawler.Plugin.Attributes
|
Imports SCrawler.Plugin.Attributes
|
||||||
Imports DN = SCrawler.API.Base.DeclaredNames
|
|
||||||
Namespace API.Instagram
|
Namespace API.Instagram
|
||||||
Friend NotInheritable Class EditorExchangeOptions
|
Friend NotInheritable Class EditorExchangeOptions : Inherits Base.EditorExchangeOptionsBase
|
||||||
#Region "Download"
|
#Region "Download"
|
||||||
<PSetting(Caption:="Get timeline", ToolTip:="Download user timeline")>
|
<PSetting(Caption:="Get timeline", ToolTip:="Download user timeline")>
|
||||||
Friend Property GetTimeline As Boolean
|
Friend Property GetTimeline As Boolean
|
||||||
@@ -36,13 +35,13 @@ Namespace API.Instagram
|
|||||||
#End Region
|
#End Region
|
||||||
<PSetting(Caption:="Place the extracted image into the video folder")>
|
<PSetting(Caption:="Place the extracted image into the video folder")>
|
||||||
Friend Property PutImageVideoFolder As Boolean
|
Friend Property PutImageVideoFolder As Boolean
|
||||||
<PSetting(Address:=SettingAddress.User, Caption:=DN.UserNameChangeCaption, ToolTip:=DN.UserNameChangeToolTip)>
|
Friend Overrides Property UserName As String
|
||||||
Friend Property UserName As String = String.Empty
|
|
||||||
<PSetting(Address:=SettingAddress.User, Caption:="Force update UserName", ToolTip:="Try to force update UserName if it is not found on the site")>
|
<PSetting(Address:=SettingAddress.User, Caption:="Force update UserName", ToolTip:="Try to force update UserName if it is not found on the site")>
|
||||||
Friend Property ForceUpdateUserName As Boolean = False
|
Friend Property ForceUpdateUserName As Boolean = False
|
||||||
<PSetting(Address:=SettingAddress.User, Caption:="Force update user information")>
|
<PSetting(Address:=SettingAddress.User, Caption:="Force update user information")>
|
||||||
Friend Property ForceUpdateUserInfo As Boolean = False
|
Friend Property ForceUpdateUserInfo As Boolean = False
|
||||||
Friend Sub New(ByVal u As UserData)
|
Friend Sub New(ByVal u As UserData)
|
||||||
|
MyBase.New(u)
|
||||||
With u
|
With u
|
||||||
GetTimeline = .GetTimeline
|
GetTimeline = .GetTimeline
|
||||||
GetReels = .GetReels
|
GetReels = .GetReels
|
||||||
@@ -58,12 +57,12 @@ Namespace API.Instagram
|
|||||||
|
|
||||||
PutImageVideoFolder = .PutImageVideoFolder
|
PutImageVideoFolder = .PutImageVideoFolder
|
||||||
|
|
||||||
UserName = .NameTrue(True)
|
|
||||||
ForceUpdateUserName = .ForceUpdateUserName
|
ForceUpdateUserName = .ForceUpdateUserName
|
||||||
ForceUpdateUserInfo = .ForceUpdateUserInfo
|
ForceUpdateUserInfo = .ForceUpdateUserInfo
|
||||||
End With
|
End With
|
||||||
End Sub
|
End Sub
|
||||||
Friend Sub New(ByVal s As SiteSettings)
|
Friend Sub New(ByVal s As SiteSettings)
|
||||||
|
MyBase.New(s)
|
||||||
With s
|
With s
|
||||||
GetTimeline = CBool(.GetTimeline.Value)
|
GetTimeline = CBool(.GetTimeline.Value)
|
||||||
GetReels = CBool(.GetReels.Value)
|
GetReels = CBool(.GetReels.Value)
|
||||||
|
|||||||
@@ -196,6 +196,18 @@ Namespace API.Instagram
|
|||||||
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:="Next profile timer",
|
||||||
|
ControlToolTip:="The time value (in milliseconds) the program will wait before processing the next profile." &
|
||||||
|
vbCr & "-2 to use max timer." & vbCr & "-1 to disable." & vbCr & "The default value is -2" & TimersUrgentTip,
|
||||||
|
AllowNull:=False, Category:=DN.CAT_Timers), PXML, PClonable>
|
||||||
|
Friend ReadOnly Property SleepTimerRequestsNextProfile As PropertyValue
|
||||||
|
Friend ReadOnly Property SleepTimerRequestsNextProfileMax As Integer
|
||||||
|
Get
|
||||||
|
Return {RequestsWaitTimer_Any, RequestsWaitTimer, SleepTimerOnPostsLimit}.Max(Function(obj) CInt(obj.Value))
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
|
<Provider(NameOf(SleepTimerRequestsNextProfile), FieldsChecker:=True)>
|
||||||
|
Private ReadOnly Property SleepTimerRequestsNextProfileProvider As IFormatProvider
|
||||||
#End Region
|
#End Region
|
||||||
#Region "New user defaults"
|
#Region "New user defaults"
|
||||||
<PropertyOption(ControlText:="Get timeline", ControlToolTip:="Default value for new users", Category:=DN.CAT_UserDefs), PXML, PClonable>
|
<PropertyOption(ControlText:="Get timeline", ControlToolTip:="Default value for new users", Category:=DN.CAT_UserDefs), PXML, PClonable>
|
||||||
@@ -493,6 +505,8 @@ Namespace API.Instagram
|
|||||||
RequestsWaitTimerTaskCountProvider = New TimersChecker(1)
|
RequestsWaitTimerTaskCountProvider = New TimersChecker(1)
|
||||||
SleepTimerOnPostsLimit = New PropertyValue(60000)
|
SleepTimerOnPostsLimit = New PropertyValue(60000)
|
||||||
SleepTimerOnPostsLimitProvider = New TimersChecker(10000)
|
SleepTimerOnPostsLimitProvider = New TimersChecker(10000)
|
||||||
|
SleepTimerRequestsNextProfile = New PropertyValue(-2)
|
||||||
|
SleepTimerRequestsNextProfileProvider = New TimersChecker(-2)
|
||||||
|
|
||||||
GetTimeline = New PropertyValue(True)
|
GetTimeline = New PropertyValue(True)
|
||||||
GetTimeline_VideoPic = New PropertyValue(True)
|
GetTimeline_VideoPic = New PropertyValue(True)
|
||||||
@@ -579,6 +593,7 @@ Namespace API.Instagram
|
|||||||
MDD.Reset()
|
MDD.Reset()
|
||||||
If ActiveSessionRequestsExists Then RefreshMyLastRequests(Now)
|
If ActiveSessionRequestsExists Then RefreshMyLastRequests(Now)
|
||||||
ActiveSessionRequestsExists = False
|
ActiveSessionRequestsExists = False
|
||||||
|
ActiveSessionLastProfileRequests = False
|
||||||
_NextWNM = UserData.WNM.Notify
|
_NextWNM = UserData.WNM.Notify
|
||||||
_NextTagged = True
|
_NextTagged = True
|
||||||
SkipUntilNextSession = False
|
SkipUntilNextSession = False
|
||||||
@@ -596,6 +611,7 @@ Namespace API.Instagram
|
|||||||
Private ActiveJobs As Integer = 0
|
Private ActiveJobs As Integer = 0
|
||||||
Private ActiveSessionDate As Date
|
Private ActiveSessionDate As Date
|
||||||
Private ActiveSessionRequestsExists As Boolean = False
|
Private ActiveSessionRequestsExists As Boolean = False
|
||||||
|
Friend ActiveSessionLastProfileRequests As Boolean = False
|
||||||
Private _NextWNM As UserData.WNM = UserData.WNM.Notify
|
Private _NextWNM As UserData.WNM = UserData.WNM.Notify
|
||||||
Private _NextTagged As Boolean = True
|
Private _NextTagged As Boolean = True
|
||||||
Friend Overrides Sub DownloadStarted(ByVal What As Download)
|
Friend Overrides Sub DownloadStarted(ByVal What As Download)
|
||||||
@@ -632,6 +648,7 @@ Namespace API.Instagram
|
|||||||
_NextWNM = .WaitNotificationMode
|
_NextWNM = .WaitNotificationMode
|
||||||
If _NextWNM = UserData.WNM.SkipTemp Or _NextWNM = UserData.WNM.SkipCurrent Then _NextWNM = UserData.WNM.Notify
|
If _NextWNM = UserData.WNM.SkipTemp Or _NextWNM = UserData.WNM.SkipCurrent Then _NextWNM = UserData.WNM.Notify
|
||||||
_NextTagged = .TaggedCheckSession
|
_NextTagged = .TaggedCheckSession
|
||||||
|
If MyLastRequestsCount <> .RequestsCountSession Then ActiveSessionLastProfileRequests = True
|
||||||
MyLastRequestsCount = .RequestsCountSession
|
MyLastRequestsCount = .RequestsCountSession
|
||||||
If .RequestsCountSession > 0 Then ActiveSessionRequestsExists = True
|
If .RequestsCountSession > 0 Then ActiveSessionRequestsExists = True
|
||||||
_FieldsChangerSuspended = True
|
_FieldsChangerSuspended = True
|
||||||
@@ -732,9 +749,6 @@ Namespace API.Instagram
|
|||||||
Using f As New InternalSettingsForm(Options, Me, False) : f.ShowDialog() : End Using
|
Using f As New InternalSettingsForm(Options, Me, False) : f.ShowDialog() : End Using
|
||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
Friend Overrides Function GetUserUrl(ByVal User As IPluginContentProvider) As String
|
|
||||||
Return String.Format(UrlPatternUser, DirectCast(User, UserData).NameTrue)
|
|
||||||
End Function
|
|
||||||
Friend Overrides Function GetUserPostUrl(ByVal User As UserDataBase, ByVal Media As UserMedia) As String
|
Friend Overrides Function GetUserPostUrl(ByVal User As UserDataBase, ByVal Media As UserMedia) As String
|
||||||
Try
|
Try
|
||||||
Dim code$ = DirectCast(User, UserData).GetPostCodeById(Media.Post.ID)
|
Dim code$ = DirectCast(User, UserData).GetPostCodeById(Media.Post.ID)
|
||||||
|
|||||||
@@ -37,7 +37,6 @@ Namespace API.Instagram
|
|||||||
Private Const Name_GetTagged_VideoPic As String = "GetTaggedData_VideoPic"
|
Private Const Name_GetTagged_VideoPic As String = "GetTaggedData_VideoPic"
|
||||||
Private Const Name_PutImageVideoFolder As String = "PutImageVideoFolder"
|
Private Const Name_PutImageVideoFolder As String = "PutImageVideoFolder"
|
||||||
Private Const Name_TaggedChecked As String = "TaggedChecked"
|
Private Const Name_TaggedChecked As String = "TaggedChecked"
|
||||||
Private Const Name_NameTrue As String = "NameTrue"
|
|
||||||
Private Const Name_ForceUpdateUserName As String = "ForceUpdateUserName"
|
Private Const Name_ForceUpdateUserName As String = "ForceUpdateUserName"
|
||||||
Private Const Name_ForceUpdateUserInfo As String = "ForceUpdateUserInfo"
|
Private Const Name_ForceUpdateUserInfo As String = "ForceUpdateUserInfo"
|
||||||
#End Region
|
#End Region
|
||||||
@@ -113,12 +112,6 @@ Namespace API.Instagram
|
|||||||
Case Else : Return True
|
Case Else : Return True
|
||||||
End Select
|
End Select
|
||||||
End Function
|
End Function
|
||||||
Protected _NameTrue As String = String.Empty
|
|
||||||
Friend ReadOnly Property NameTrue(Optional ByVal Exact As Boolean = False) As String
|
|
||||||
Get
|
|
||||||
Return If(Exact, _NameTrue, _NameTrue.IfNullOrEmpty(Name))
|
|
||||||
End Get
|
|
||||||
End Property
|
|
||||||
Private UserNameRequested As Boolean = False
|
Private UserNameRequested As Boolean = False
|
||||||
Friend Property ForceUpdateUserName As Boolean = False
|
Friend Property ForceUpdateUserName As Boolean = False
|
||||||
Friend Property ForceUpdateUserInfo As Boolean = False
|
Friend Property ForceUpdateUserInfo As Boolean = False
|
||||||
@@ -141,7 +134,6 @@ Namespace API.Instagram
|
|||||||
GetTaggedData = .Value(Name_GetTagged).FromXML(Of Boolean)(CBool(MySiteSettings.GetTagged.Value))
|
GetTaggedData = .Value(Name_GetTagged).FromXML(Of Boolean)(CBool(MySiteSettings.GetTagged.Value))
|
||||||
GetTaggedData_VideoPic = .Value(Name_GetTagged_VideoPic).FromXML(Of Boolean)(CBool(MySiteSettings.GetTagged_VideoPic.Value))
|
GetTaggedData_VideoPic = .Value(Name_GetTagged_VideoPic).FromXML(Of Boolean)(CBool(MySiteSettings.GetTagged_VideoPic.Value))
|
||||||
TaggedChecked = .Value(Name_TaggedChecked).FromXML(Of Boolean)(False)
|
TaggedChecked = .Value(Name_TaggedChecked).FromXML(Of Boolean)(False)
|
||||||
_NameTrue = .Value(Name_NameTrue)
|
|
||||||
ForceUpdateUserName = .Value(Name_ForceUpdateUserName).FromXML(Of Boolean)(False)
|
ForceUpdateUserName = .Value(Name_ForceUpdateUserName).FromXML(Of Boolean)(False)
|
||||||
ForceUpdateUserInfo = .Value(Name_ForceUpdateUserInfo).FromXML(Of Boolean)(False)
|
ForceUpdateUserInfo = .Value(Name_ForceUpdateUserInfo).FromXML(Of Boolean)(False)
|
||||||
Else
|
Else
|
||||||
@@ -159,7 +151,6 @@ Namespace API.Instagram
|
|||||||
.Add(Name_GetTagged_VideoPic, GetTaggedData_VideoPic.BoolToInteger)
|
.Add(Name_GetTagged_VideoPic, GetTaggedData_VideoPic.BoolToInteger)
|
||||||
.Add(Name_PutImageVideoFolder, PutImageVideoFolder.BoolToInteger)
|
.Add(Name_PutImageVideoFolder, PutImageVideoFolder.BoolToInteger)
|
||||||
.Add(Name_TaggedChecked, TaggedChecked.BoolToInteger)
|
.Add(Name_TaggedChecked, TaggedChecked.BoolToInteger)
|
||||||
.Add(Name_NameTrue, _NameTrue)
|
|
||||||
.Add(Name_ForceUpdateUserName, ForceUpdateUserName.BoolToInteger)
|
.Add(Name_ForceUpdateUserName, ForceUpdateUserName.BoolToInteger)
|
||||||
.Add(Name_ForceUpdateUserInfo, ForceUpdateUserInfo.BoolToInteger)
|
.Add(Name_ForceUpdateUserInfo, ForceUpdateUserInfo.BoolToInteger)
|
||||||
End If
|
End If
|
||||||
@@ -173,6 +164,7 @@ Namespace API.Instagram
|
|||||||
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)
|
||||||
|
.ApplyBase(Me)
|
||||||
GetTimeline = .GetTimeline
|
GetTimeline = .GetTimeline
|
||||||
GetReels = .GetReels
|
GetReels = .GetReels
|
||||||
GetStories = .GetStories
|
GetStories = .GetStories
|
||||||
@@ -187,7 +179,6 @@ Namespace API.Instagram
|
|||||||
|
|
||||||
PutImageVideoFolder = .PutImageVideoFolder
|
PutImageVideoFolder = .PutImageVideoFolder
|
||||||
|
|
||||||
_NameTrue = .UserName
|
|
||||||
ForceUpdateUserName = .ForceUpdateUserName
|
ForceUpdateUserName = .ForceUpdateUserName
|
||||||
ForceUpdateUserInfo = .ForceUpdateUserInfo
|
ForceUpdateUserInfo = .ForceUpdateUserInfo
|
||||||
End With
|
End With
|
||||||
@@ -394,6 +385,20 @@ Namespace API.Instagram
|
|||||||
|
|
||||||
Dim s As Sections = Sections.Timeline
|
Dim s As Sections = Sections.Timeline
|
||||||
Dim errorFound As Boolean = False
|
Dim errorFound As Boolean = False
|
||||||
|
Dim firstWait As Boolean = False
|
||||||
|
Dim __firstWait As Action = Sub()
|
||||||
|
With MySiteSettings
|
||||||
|
If Not firstWait And .ActiveSessionLastProfileRequests And CInt(.SleepTimerRequestsNextProfile.Value) <> -1 Then
|
||||||
|
Dim ____v% = 0
|
||||||
|
If CInt(.SleepTimerRequestsNextProfile.Value) = -2 Then
|
||||||
|
____v = .SleepTimerRequestsNextProfileMax
|
||||||
|
Else
|
||||||
|
____v = CInt(.SleepTimerRequestsNextProfile.Value)
|
||||||
|
End If
|
||||||
|
If ____v > 0 Then firstWait = True : Thread.Sleep(____v)
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
End Sub
|
||||||
Try
|
Try
|
||||||
Err5xx = -1
|
Err5xx = -1
|
||||||
ErrHandling = -1
|
ErrHandling = -1
|
||||||
@@ -410,6 +415,7 @@ Namespace API.Instagram
|
|||||||
If dt.Invoke And Not LastCursor.IsEmptyString Then
|
If dt.Invoke And Not LastCursor.IsEmptyString Then
|
||||||
s = IIf(IsSavedPosts, Sections.SavedPosts, Sections.Timeline)
|
s = IIf(IsSavedPosts, Sections.SavedPosts, Sections.Timeline)
|
||||||
upClaimRequest.Invoke
|
upClaimRequest.Invoke
|
||||||
|
__firstWait.Invoke
|
||||||
DownloadData(LastCursor, s, Token)
|
DownloadData(LastCursor, s, Token)
|
||||||
ProgressPre.Done()
|
ProgressPre.Done()
|
||||||
ThrowAny(Token)
|
ThrowAny(Token)
|
||||||
@@ -419,6 +425,7 @@ Namespace API.Instagram
|
|||||||
s = IIf(IsSavedPosts, Sections.SavedPosts, Sections.Timeline)
|
s = IIf(IsSavedPosts, Sections.SavedPosts, Sections.Timeline)
|
||||||
upClaimRequest.Invoke
|
upClaimRequest.Invoke
|
||||||
ChangeResponserMode(_UseGQL)
|
ChangeResponserMode(_UseGQL)
|
||||||
|
__firstWait.Invoke
|
||||||
DownloadData(String.Empty, s, Token)
|
DownloadData(String.Empty, s, Token)
|
||||||
ProgressPre.Done()
|
ProgressPre.Done()
|
||||||
ThrowAny(Token)
|
ThrowAny(Token)
|
||||||
@@ -434,6 +441,7 @@ Namespace API.Instagram
|
|||||||
DefaultParser_ElemNode = {"node", "media"}
|
DefaultParser_ElemNode = {"node", "media"}
|
||||||
upClaimRequest.Invoke
|
upClaimRequest.Invoke
|
||||||
ChangeResponserMode(True)
|
ChangeResponserMode(True)
|
||||||
|
__firstWait.Invoke
|
||||||
DownloadData(String.Empty, s, Token)
|
DownloadData(String.Empty, s, Token)
|
||||||
GetReelsGQL_SetEnvir = False
|
GetReelsGQL_SetEnvir = False
|
||||||
ProgressPre.Done()
|
ProgressPre.Done()
|
||||||
@@ -443,6 +451,7 @@ Namespace API.Instagram
|
|||||||
If CBool(MySiteSettings.DownloadStories.Value) And GetStories Then
|
If CBool(MySiteSettings.DownloadStories.Value) And GetStories Then
|
||||||
s = Sections.Stories
|
s = Sections.Stories
|
||||||
upClaimRequest.Invoke
|
upClaimRequest.Invoke
|
||||||
|
__firstWait.Invoke
|
||||||
DownloadData(String.Empty, s, Token)
|
DownloadData(String.Empty, s, Token)
|
||||||
ProgressPre.Done()
|
ProgressPre.Done()
|
||||||
End If
|
End If
|
||||||
@@ -451,6 +460,7 @@ Namespace API.Instagram
|
|||||||
If CBool(MySiteSettings.DownloadStoriesUser.Value) And GetStoriesUser Then
|
If CBool(MySiteSettings.DownloadStoriesUser.Value) And GetStoriesUser Then
|
||||||
s = Sections.UserStories
|
s = Sections.UserStories
|
||||||
upClaimRequest.Invoke
|
upClaimRequest.Invoke
|
||||||
|
__firstWait.Invoke
|
||||||
DownloadData(String.Empty, s, Token)
|
DownloadData(String.Empty, s, Token)
|
||||||
ProgressPre.Done()
|
ProgressPre.Done()
|
||||||
End If
|
End If
|
||||||
@@ -459,6 +469,7 @@ Namespace API.Instagram
|
|||||||
If CBool(MySiteSettings.DownloadTagged.Value) And GetTaggedData Then
|
If CBool(MySiteSettings.DownloadTagged.Value) And GetTaggedData Then
|
||||||
s = Sections.Tagged
|
s = Sections.Tagged
|
||||||
upClaimRequest.Invoke
|
upClaimRequest.Invoke
|
||||||
|
__firstWait.Invoke
|
||||||
DownloadData(String.Empty, s, Token)
|
DownloadData(String.Empty, s, Token)
|
||||||
ProgressPre.Done()
|
ProgressPre.Done()
|
||||||
DefaultParser_ElemNode = Nothing
|
DefaultParser_ElemNode = Nothing
|
||||||
@@ -480,17 +491,24 @@ Namespace API.Instagram
|
|||||||
End Try
|
End Try
|
||||||
End Sub
|
End Sub
|
||||||
Protected Sub ValidateExtension()
|
Protected Sub ValidateExtension()
|
||||||
|
Dim tmpList As List(Of UserMedia) = Nothing
|
||||||
Try
|
Try
|
||||||
Const heic$ = "heic"
|
Const heic$ = "heic"
|
||||||
If _TempMediaList.Count > 0 AndAlso _TempMediaList.Exists(Function(mm) mm.File.Extension = heic) Then
|
If _TempMediaList.Count > 0 AndAlso _TempMediaList.Exists(Function(mm) mm.File.Extension = heic) Then
|
||||||
Dim m As UserMedia
|
Dim m As UserMedia
|
||||||
For i% = 0 To _TempMediaList.Count - 1
|
tmpList = New List(Of UserMedia)
|
||||||
m = _TempMediaList(i)
|
tmpList.ListAddList(_TempMediaList)
|
||||||
|
_TempMediaList.Clear()
|
||||||
|
For i% = 0 To tmpList.Count - 1
|
||||||
|
m = tmpList(i)
|
||||||
|
_TempMediaList.Add(m)
|
||||||
If m.Type = UTypes.Picture AndAlso Not m.File.Extension.IsEmptyString AndAlso m.File.Extension = heic Then _
|
If m.Type = UTypes.Picture AndAlso Not m.File.Extension.IsEmptyString AndAlso m.File.Extension = heic Then _
|
||||||
m.File.Extension = "jpg" : _TempMediaList(i) = m
|
m.File.Extension = "jpg" : _TempMediaList.Add(m)
|
||||||
Next
|
Next
|
||||||
|
tmpList.Clear()
|
||||||
End If
|
End If
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
|
If tmpList.ListExists Then _TempMediaList.Clear() : _TempMediaList.ListAddList(tmpList) : tmpList.Clear()
|
||||||
End Try
|
End Try
|
||||||
End Sub
|
End Sub
|
||||||
Protected Overridable Sub UpdateResponser()
|
Protected Overridable Sub UpdateResponser()
|
||||||
@@ -970,10 +988,12 @@ NextPageBlock:
|
|||||||
Dim PostIDKV As PostKV
|
Dim PostIDKV As PostKV
|
||||||
Dim Pinned As Boolean
|
Dim Pinned As Boolean
|
||||||
Dim PostDate$, PostOriginUrl$
|
Dim PostDate$, PostOriginUrl$
|
||||||
|
Dim PostText$ = String.Empty
|
||||||
Dim i%, before%
|
Dim i%, before%
|
||||||
Dim usePinFunc As Boolean = Not DefaultParser_Pinned Is Nothing
|
Dim usePinFunc As Boolean = Not DefaultParser_Pinned Is Nothing
|
||||||
Dim skipPostFuncExists As Boolean = Not DefaultParser_SkipPost Is Nothing
|
Dim skipPostFuncExists As Boolean = Not DefaultParser_SkipPost Is Nothing
|
||||||
Dim nn As EContainer
|
Dim nn As EContainer
|
||||||
|
Dim textMedia As UserMedia
|
||||||
If SpecFolder.IsEmptyString Then
|
If SpecFolder.IsEmptyString Then
|
||||||
Select Case Section
|
Select Case Section
|
||||||
Case Sections.Tagged : SpecFolder = TaggedFolder
|
Case Sections.Tagged : SpecFolder = TaggedFolder
|
||||||
@@ -1008,9 +1028,17 @@ NextPageBlock:
|
|||||||
Case DateResult.Exit : If Not Pinned Then Return False
|
Case DateResult.Exit : If Not Pinned Then Return False
|
||||||
End Select
|
End Select
|
||||||
End If
|
End If
|
||||||
|
If DownloadTextPosts Then PostText = DefaultParser_GetCaption(.Self)
|
||||||
before = _TempMediaList.Count
|
before = _TempMediaList.Count
|
||||||
ObtainMedia(.Self, PostIDKV.ID, SpecFolder, PostDate,, PostOriginUrl, State, Attempts,, Section)
|
ObtainMedia(.Self, PostIDKV.ID, SpecFolder, PostDate,, PostOriginUrl, State, Attempts,, Section, PostText)
|
||||||
If Not before = _TempMediaList.Count Then _TotalPostsParsed += 1
|
If Not before = _TempMediaList.Count Then
|
||||||
|
_TotalPostsParsed += 1
|
||||||
|
ElseIf DownloadTextPosts And DownloadText And Not PostText.IsEmptyString Then
|
||||||
|
textMedia = MediaFromData(UTypes.Text, PostIDKV.ID, PostIDKV.ID, PostDate, SpecFolder, PostOriginUrl, State, Attempts, PostText)
|
||||||
|
textMedia.URL = PostIDKV.ID
|
||||||
|
textMedia.PostTextFile = $"{PostIDKV.ID}.txt"
|
||||||
|
_TempMediaList.ListAddValue(textMedia, LNC)
|
||||||
|
End If
|
||||||
If _Limit > 0 And _TotalPostsParsed >= _Limit Then Return False
|
If _Limit > 0 And _TotalPostsParsed >= _Limit Then Return False
|
||||||
End If
|
End If
|
||||||
Else
|
Else
|
||||||
@@ -1023,6 +1051,9 @@ NextPageBlock:
|
|||||||
Return False
|
Return False
|
||||||
End If
|
End If
|
||||||
End Function
|
End Function
|
||||||
|
Protected Overridable Function DefaultParser_GetCaption(ByVal e As EContainer) As String
|
||||||
|
Return e.Value({"caption"}, "text")
|
||||||
|
End Function
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Code ID converters"
|
#Region "Code ID converters"
|
||||||
Protected Function CodeToID(ByVal Code As String) As String
|
Protected Function CodeToID(ByVal Code As String) As String
|
||||||
@@ -1071,7 +1102,8 @@ NextPageBlock:
|
|||||||
Optional ByVal PostOriginUrl As String = Nothing,
|
Optional ByVal PostOriginUrl As String = Nothing,
|
||||||
Optional ByVal State As UStates = UStates.Unknown, Optional ByVal Attempts As Integer = 0,
|
Optional ByVal State As UStates = UStates.Unknown, Optional ByVal Attempts As Integer = 0,
|
||||||
Optional ByVal TryExtractImage As Boolean = False,
|
Optional ByVal TryExtractImage As Boolean = False,
|
||||||
Optional ByVal Section As Sections = ObtainMedia_NoSection)
|
Optional ByVal Section As Sections = ObtainMedia_NoSection,
|
||||||
|
Optional ByVal Text As String = Nothing)
|
||||||
Try
|
Try
|
||||||
Dim maxSize As Func(Of EContainer, Integer) = Function(ByVal _ss As EContainer) As Integer
|
Dim maxSize As Func(Of EContainer, Integer) = Function(ByVal _ss As EContainer) As Integer
|
||||||
Dim w% = AConvert(Of Integer)(_ss.Value("width"), 0)
|
Dim w% = AConvert(Of Integer)(_ss.Value("width"), 0)
|
||||||
@@ -1106,6 +1138,7 @@ NextPageBlock:
|
|||||||
End Function
|
End Function
|
||||||
If Not ObtainMedia_SizeFuncVid Is Nothing Then ssVid = ObtainMedia_SizeFuncVid
|
If Not ObtainMedia_SizeFuncVid Is Nothing Then ssVid = ObtainMedia_SizeFuncVid
|
||||||
If Not ObtainMedia_SizeFuncPic Is Nothing Then ssPic = ObtainMedia_SizeFuncPic
|
If Not ObtainMedia_SizeFuncPic Is Nothing Then ssPic = ObtainMedia_SizeFuncPic
|
||||||
|
If DownloadTextPosts And Text.IsEmptyString Then Text = DefaultParser_GetCaption(n)
|
||||||
If n.Count > 0 Then
|
If n.Count > 0 Then
|
||||||
Dim l As New List(Of Sizes)
|
Dim l As New List(Of Sizes)
|
||||||
Dim d As EContainer
|
Dim d As EContainer
|
||||||
@@ -1147,7 +1180,7 @@ NextPageBlock:
|
|||||||
If l.Count > 0 Then l.RemoveAll(wrongData)
|
If l.Count > 0 Then l.RemoveAll(wrongData)
|
||||||
If l.Count > 0 Then
|
If l.Count > 0 Then
|
||||||
l.Sort()
|
l.Sort()
|
||||||
_TempMediaList.ListAddValue(MediaFromData(UTypes.Picture, l.First.Data, PostID, DateObj, SpecialFolder, PostOriginUrl, State, Attempts), LNC)
|
_TempMediaList.ListAddValue(MediaFromData(UTypes.Picture, l.First.Data, PostID, DateObj, SpecialFolder, PostOriginUrl, State, Attempts, Text), LNC)
|
||||||
l.Clear()
|
l.Clear()
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
@@ -1164,19 +1197,19 @@ NextPageBlock:
|
|||||||
If l.Count > 0 Then l.RemoveAll(wrongData)
|
If l.Count > 0 Then l.RemoveAll(wrongData)
|
||||||
If l.Count > 0 Then
|
If l.Count > 0 Then
|
||||||
l.Sort()
|
l.Sort()
|
||||||
_TempMediaList.ListAddValue(MediaFromData(UTypes.Video, l.First.Data, PostID, DateObj, SpecialFolder, PostOriginUrl, State, Attempts), LNC)
|
_TempMediaList.ListAddValue(MediaFromData(UTypes.Video, l.First.Data, PostID, DateObj, SpecialFolder, PostOriginUrl, State, Attempts, Text), LNC)
|
||||||
l.Clear()
|
l.Clear()
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
End With
|
End With
|
||||||
End If
|
End If
|
||||||
If Not TryExtractImage And Not Section = ObtainMedia_NoSection And ExtractImageFrom(Section) Then _
|
If Not TryExtractImage And Not Section = ObtainMedia_NoSection And ExtractImageFrom(Section) Then _
|
||||||
ObtainMedia(n, PostID, SpecialFolder, DateObj, InitialType, PostOriginUrl, State, Attempts, True, Section)
|
ObtainMedia(n, PostID, SpecialFolder, DateObj, InitialType, PostOriginUrl, State, Attempts, True, Section, Text)
|
||||||
Case 8 'gallery
|
Case 8 'gallery
|
||||||
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 : ObtainMedia(d, PostID, SpecialFolder, DateObj, 8, PostOriginUrl) : Next
|
For Each d In .Self : ObtainMedia(d, PostID, SpecialFolder, DateObj, 8, PostOriginUrl,,,,, Text) : Next
|
||||||
End If
|
End If
|
||||||
End With
|
End With
|
||||||
End Select
|
End Select
|
||||||
@@ -1212,11 +1245,8 @@ NextPageBlock:
|
|||||||
Dim f As New SFile With {.Path = DownloadContentDefault_GetRootDir(), .Name = "ProfilePicture", .Extension = "jpg"}
|
Dim f As New SFile With {.Path = DownloadContentDefault_GetRootDir(), .Name = "ProfilePicture", .Extension = "jpg"}
|
||||||
f = SFile.IndexReindex(f)
|
f = SFile.IndexReindex(f)
|
||||||
If Not f.Exists Then
|
If Not f.Exists Then
|
||||||
Dim profilePicture$ = .Value("profile_pic_url_hd")
|
If SimpleDownloadAvatar(.Value("profile_pic_url_hd"), Function(ff) f).IsEmptyString Then _
|
||||||
If profilePicture.IsEmptyString OrElse Not GetWebFile(profilePicture, f, EDP.ReturnValue) Then
|
SimpleDownloadAvatar(.Value("profile_pic_url"), Function(ff) f)
|
||||||
profilePicture = .Value("profile_pic_url")
|
|
||||||
If Not profilePicture.IsEmptyString Then GetWebFile(profilePicture, f, EDP.ReturnValue)
|
|
||||||
End If
|
|
||||||
End If
|
End If
|
||||||
End With
|
End With
|
||||||
End If
|
End If
|
||||||
@@ -1249,11 +1279,10 @@ NextPageBlock:
|
|||||||
If Not newName.IsEmptyString Then
|
If Not newName.IsEmptyString Then
|
||||||
Dim oldName$ = NameTrue
|
Dim oldName$ = NameTrue
|
||||||
If Not newName = oldName Then
|
If Not newName = oldName Then
|
||||||
MyMainLOG = $"{ToStringForLog()}: username changed from '{oldName}' to '{newName}'"
|
Dim uStr$ = $"username changed from '{oldName}' to '{newName}'"
|
||||||
_NameTrue = newName
|
LogError(Nothing, uStr)
|
||||||
Dim descr$ = $"Username changed from '{oldName}' to '{newName}' ({Now.ToStringDate(ADateTime.Formats.BaseDateTime)})!"
|
NameTrue = newName
|
||||||
descr.StringAppendLine(UserDescription)
|
UserDescriptionUpdate(uStr, True, True, True)
|
||||||
UserDescription = descr
|
|
||||||
_ForceSaveUserInfo = True
|
_ForceSaveUserInfo = True
|
||||||
End If
|
End If
|
||||||
Return True
|
Return True
|
||||||
@@ -1444,13 +1473,16 @@ NextPageBlock:
|
|||||||
#Region "Create media"
|
#Region "Create media"
|
||||||
Private Function MediaFromData(ByVal t As UTypes, ByVal _URL As String, ByVal PostID As String, ByVal PostDate As String,
|
Private Function MediaFromData(ByVal t As UTypes, ByVal _URL As String, ByVal PostID As String, ByVal PostDate As String,
|
||||||
Optional ByVal SpecialFolder As String = Nothing, Optional ByVal PostOriginUrl As String = Nothing,
|
Optional ByVal SpecialFolder As String = Nothing, Optional ByVal PostOriginUrl As String = Nothing,
|
||||||
Optional ByVal State As UStates = UStates.Unknown, Optional ByVal Attempts As Integer = 0) As UserMedia
|
Optional ByVal State As UStates = UStates.Unknown, Optional ByVal Attempts As Integer = 0,
|
||||||
|
Optional ByVal Text As String = Nothing) As UserMedia
|
||||||
_URL = LinkFormatterSecure(RegexReplace(_URL.Replace("\", String.Empty), LinkPattern))
|
_URL = LinkFormatterSecure(RegexReplace(_URL.Replace("\", String.Empty), LinkPattern))
|
||||||
Dim m As New UserMedia(_URL, t) With {.URL_BASE = PostOriginUrl.IfNullOrEmpty(_URL), .Post = New UserPost With {.ID = PostID}}
|
Dim m As New UserMedia(_URL, t) With {.URL_BASE = PostOriginUrl.IfNullOrEmpty(_URL), .Post = New UserPost With {.ID = PostID}}
|
||||||
If Not m.URL.IsEmptyString Then m.File = CStr(RegexReplace(m.URL, FilesPattern))
|
If Not m.URL.IsEmptyString Then m.File = CStr(RegexReplace(m.URL, FilesPattern))
|
||||||
If Not PostDate.IsEmptyString Then m.Post.Date = AConvert(Of Date)(PostDate, UnixDate32Provider, Nothing) Else m.Post.Date = Nothing
|
If Not PostDate.IsEmptyString Then m.Post.Date = AConvert(Of Date)(PostDate, UnixDate32Provider, Nothing) Else m.Post.Date = Nothing
|
||||||
m.SpecialFolder = SpecialFolder
|
m.SpecialFolder = SpecialFolder
|
||||||
If State = UStates.Missing Then m.State = UStates.Missing : m.Attempts = Attempts
|
If State = UStates.Missing Then m.State = UStates.Missing : m.Attempts = Attempts
|
||||||
|
m.PostText = Text
|
||||||
|
m.PostTextFileSpecialFolder = DownloadTextSpecialFolder
|
||||||
Return m
|
Return m
|
||||||
End Function
|
End Function
|
||||||
#End Region
|
#End Region
|
||||||
|
|||||||
@@ -34,6 +34,9 @@ Namespace API.JustForFans
|
|||||||
Case NameOf(UserAgent) : If Not HeaderValue.IsEmptyString Then Responser.UserAgent = HeaderValue
|
Case NameOf(UserAgent) : If Not HeaderValue.IsEmptyString Then Responser.UserAgent = HeaderValue
|
||||||
End Select
|
End Select
|
||||||
End Sub
|
End Sub
|
||||||
|
<DoNotUse> Friend Overrides Property DownloadText As PropertyValue
|
||||||
|
<DoNotUse> Friend Overrides Property DownloadTextPosts As PropertyValue
|
||||||
|
<DoNotUse> Friend Overrides Property DownloadTextSpecialFolder As PropertyValue
|
||||||
Friend Sub New(ByVal AccName As String, ByVal Temp As Boolean)
|
Friend Sub New(ByVal AccName As String, ByVal Temp As Boolean)
|
||||||
MyBase.New("JustForFans", "justfor.fans", AccName, Temp, My.Resources.SiteResources.JFFIcon_64, My.Resources.SiteResources.JFFPic_76)
|
MyBase.New("JustForFans", "justfor.fans", AccName, Temp, My.Resources.SiteResources.JFFIcon_64, My.Resources.SiteResources.JFFPic_76)
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,9 @@ Imports PersonalUtilities.Functions.RegularExpressions
|
|||||||
Namespace API.LPSG
|
Namespace API.LPSG
|
||||||
<Manifest("AndyProgram_LPSG")>
|
<Manifest("AndyProgram_LPSG")>
|
||||||
Friend Class SiteSettings : Inherits Base.SiteSettingsBase
|
Friend Class SiteSettings : Inherits Base.SiteSettingsBase
|
||||||
|
<DoNotUse> Friend Overrides Property DownloadText As PropertyValue
|
||||||
|
<DoNotUse> Friend Overrides Property DownloadTextPosts As PropertyValue
|
||||||
|
<DoNotUse> Friend Overrides Property DownloadTextSpecialFolder As PropertyValue
|
||||||
Friend Sub New(ByVal AccName As String, ByVal Temp As Boolean)
|
Friend Sub New(ByVal AccName As String, ByVal Temp As Boolean)
|
||||||
MyBase.New("LPSG", "www.lpsg.com", AccName, Temp, My.Resources.SiteResources.LPSGIcon_48, My.Resources.SiteResources.LPSGPic_32)
|
MyBase.New("LPSG", "www.lpsg.com", AccName, Temp, My.Resources.SiteResources.LPSGIcon_48, My.Resources.SiteResources.LPSGPic_32)
|
||||||
UrlPatternUser = "https://www.lpsg.com/threads/{0}/"
|
UrlPatternUser = "https://www.lpsg.com/threads/{0}/"
|
||||||
|
|||||||
@@ -106,7 +106,8 @@ Namespace API.LPSG
|
|||||||
End Sub
|
End Sub
|
||||||
Protected Overrides Function DownloadingException(ByVal ex As Exception, ByVal Message As String, Optional ByVal FromPE As Boolean = False,
|
Protected Overrides Function DownloadingException(ByVal ex As Exception, ByVal Message As String, Optional ByVal FromPE As Boolean = False,
|
||||||
Optional ByVal EObj As Object = Nothing) As Integer
|
Optional ByVal EObj As Object = Nothing) As Integer
|
||||||
If Responser.StatusCode = Net.HttpStatusCode.ServiceUnavailable Then '503
|
If Responser.StatusCode = Net.HttpStatusCode.ServiceUnavailable Or
|
||||||
|
Responser.StatusCode = Net.HttpStatusCode.Forbidden Then '503, 403
|
||||||
MyMainLOG = $"{ToStringForLog()}: LPSG not available"
|
MyMainLOG = $"{ToStringForLog()}: LPSG not available"
|
||||||
Return 1
|
Return 1
|
||||||
ElseIf Responser.StatusCode = Net.HttpStatusCode.NotFound Then '404
|
ElseIf Responser.StatusCode = Net.HttpStatusCode.NotFound Then '404
|
||||||
|
|||||||
@@ -76,6 +76,9 @@ Namespace API.Mastodon
|
|||||||
<PropertyOption(IsAuth:=False, ControlText:="User related to my domain",
|
<PropertyOption(IsAuth:=False, ControlText:="User related to my domain",
|
||||||
ControlToolTip:="Open user profiles and user posts through my domain."), PXML, PClonable>
|
ControlToolTip:="Open user profiles and user posts through my domain."), PXML, PClonable>
|
||||||
Friend ReadOnly Property UserRelatedToMyDomain As PropertyValue
|
Friend ReadOnly Property UserRelatedToMyDomain As PropertyValue
|
||||||
|
<DoNotUse> Friend Overrides Property DownloadText As PropertyValue
|
||||||
|
<DoNotUse> Friend Overrides Property DownloadTextPosts As PropertyValue
|
||||||
|
<DoNotUse> Friend Overrides Property DownloadTextSpecialFolder As PropertyValue
|
||||||
#End Region
|
#End Region
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Initializer"
|
#Region "Initializer"
|
||||||
@@ -171,12 +174,12 @@ Namespace API.Mastodon
|
|||||||
With DirectCast(User, UserData)
|
With DirectCast(User, UserData)
|
||||||
If UserRelatedToMyDomain.Value Then
|
If UserRelatedToMyDomain.Value Then
|
||||||
If MyDomain.Value = .UserDomain Then
|
If MyDomain.Value = .UserDomain Then
|
||||||
Return $"https://{ .UserDomain}/@{ .TrueName}"
|
Return $"https://{ .UserDomain}/@{ .NameTrue}"
|
||||||
Else
|
Else
|
||||||
Return $"https://{MyDomain.Value}/@{ .TrueName}@{ .UserDomain}"
|
Return $"https://{MyDomain.Value}/@{ .NameTrue}@{ .UserDomain}"
|
||||||
End If
|
End If
|
||||||
Else
|
Else
|
||||||
Return $"https://{ .UserDomain}/@{ .TrueName}"
|
Return $"https://{ .UserDomain}/@{ .NameTrue}"
|
||||||
End If
|
End If
|
||||||
End With
|
End With
|
||||||
End Function
|
End Function
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ Namespace API.Mastodon
|
|||||||
_UserDomain = d
|
_UserDomain = d
|
||||||
End Set
|
End Set
|
||||||
End Property
|
End Property
|
||||||
Friend Property TrueName As String = String.Empty
|
|
||||||
Private ReadOnly Property MySettings As SiteSettings
|
Private ReadOnly Property MySettings As SiteSettings
|
||||||
Get
|
Get
|
||||||
Return HOST.Source
|
Return HOST.Source
|
||||||
@@ -52,22 +51,21 @@ Namespace API.Mastodon
|
|||||||
Dim l$() = Name.Split("@")
|
Dim l$() = Name.Split("@")
|
||||||
If l.ListExists(2) Then
|
If l.ListExists(2) Then
|
||||||
_UserDomain = l(0)
|
_UserDomain = l(0)
|
||||||
TrueName = l(1)
|
NameTrue = l(1)
|
||||||
Else
|
Else
|
||||||
_UserDomain = MySettings.MyDomain.Value
|
_UserDomain = MySettings.MyDomain.Value
|
||||||
TrueName = Name
|
NameTrue = Name
|
||||||
End If
|
End If
|
||||||
If FriendlyName.IsEmptyString Then FriendlyName = TrueName
|
If FriendlyName.IsEmptyString Then FriendlyName = NameTrue
|
||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
If Loading Then
|
If Loading Then
|
||||||
_UserDomain = Container.Value(Name_UserDomain)
|
_UserDomain = Container.Value(Name_UserDomain)
|
||||||
TrueName = Container.Value(Name_TrueName)
|
|
||||||
obtainNames.Invoke
|
obtainNames.Invoke
|
||||||
Else
|
Else
|
||||||
obtainNames.Invoke
|
obtainNames.Invoke
|
||||||
Container.Add(Name_UserDomain, _UserDomain)
|
Container.Add(Name_UserDomain, _UserDomain)
|
||||||
Container.Add(Name_TrueName, TrueName)
|
Container.Add(Name_TrueName, NameTrue(True))
|
||||||
Container.Value(Name_FriendlyName) = FriendlyName
|
Container.Value(Name_FriendlyName) = FriendlyName
|
||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
@@ -208,12 +206,12 @@ Namespace API.Mastodon
|
|||||||
Dim url$ = $"https://{MyCredentials.Domain}/api/v1/accounts/lookup?acct="
|
Dim url$ = $"https://{MyCredentials.Domain}/api/v1/accounts/lookup?acct="
|
||||||
If Not UserDomain.IsEmptyString Then
|
If Not UserDomain.IsEmptyString Then
|
||||||
If UserDomain = MyCredentials.Domain Then
|
If UserDomain = MyCredentials.Domain Then
|
||||||
url &= $"@{TrueName}"
|
url &= $"@{NameTrue}"
|
||||||
Else
|
Else
|
||||||
url &= $"@{TrueName}@{UserDomain}"
|
url &= $"@{NameTrue}@{UserDomain}"
|
||||||
End If
|
End If
|
||||||
Else
|
Else
|
||||||
url &= $"@{TrueName}"
|
url &= $"@{NameTrue}"
|
||||||
End If
|
End If
|
||||||
Dim r$ = Responser.GetResponse(url)
|
Dim r$ = Responser.GetResponse(url)
|
||||||
If Not r.IsEmptyString Then
|
If Not r.IsEmptyString Then
|
||||||
|
|||||||
@@ -3,5 +3,4 @@ https://github.com/riley-access-labs/onlyfans-dynamic-rules-1/blob/main/dynamicR
|
|||||||
https://github.com/riley-access-labs/onlyfans-dynamic-rules-1/blob/patch-1/dynamicRules.json
|
https://github.com/riley-access-labs/onlyfans-dynamic-rules-1/blob/patch-1/dynamicRules.json
|
||||||
https://github.com/DATAHOARDERS/dynamic-rules/blob/main/onlyfans.json
|
https://github.com/DATAHOARDERS/dynamic-rules/blob/main/onlyfans.json
|
||||||
https://github.com/DIGITALCRIMINAL/dynamic-rules/blob/main/onlyfans.json
|
https://github.com/DIGITALCRIMINAL/dynamic-rules/blob/main/onlyfans.json
|
||||||
https://github.com/deviint/onlyfans-dynamic-rules/blob/main/dynamicRules.json
|
|
||||||
https://github.com/rafa-9/dynamic-rules/blob/main/rules.json
|
https://github.com/rafa-9/dynamic-rules/blob/main/rules.json
|
||||||
@@ -4,8 +4,8 @@ https://github.com/riley-access-labs/onlyfans-dynamic-rules-1/blob/main/dynamicR
|
|||||||
https://github.com/riley-access-labs/onlyfans-dynamic-rules-1/blob/patch-1/dynamicRules.json
|
https://github.com/riley-access-labs/onlyfans-dynamic-rules-1/blob/patch-1/dynamicRules.json
|
||||||
https://github.com/DATAHOARDERS/dynamic-rules/blob/main/onlyfans.json
|
https://github.com/DATAHOARDERS/dynamic-rules/blob/main/onlyfans.json
|
||||||
https://github.com/DIGITALCRIMINAL/dynamic-rules/blob/main/onlyfans.json
|
https://github.com/DIGITALCRIMINAL/dynamic-rules/blob/main/onlyfans.json
|
||||||
https://github.com/deviint/onlyfans-dynamic-rules/blob/main/dynamicRules.json
|
|
||||||
https://github.com/rafa-9/dynamic-rules/blob/main/rules.json
|
https://github.com/rafa-9/dynamic-rules/blob/main/rules.json
|
||||||
|
|
||||||
https://github.com/SneakyOvis/onlyfans-dynamic-rules/blob/main/rules.json
|
https://github.com/SneakyOvis/onlyfans-dynamic-rules/blob/main/rules.json
|
||||||
https://github.com/Growik/onlyfans-dynamic-rules/blob/main/rules.json
|
https://github.com/Growik/onlyfans-dynamic-rules/blob/main/rules.json
|
||||||
|
https://github.com/deviint/onlyfans-dynamic-rules/blob/main/dynamicRules.json
|
||||||
@@ -36,12 +36,20 @@ Namespace API.OnlyFans
|
|||||||
Private Const HeaderUserID As String = "User-Id"
|
Private Const HeaderUserID As String = "User-Id"
|
||||||
Friend Const HeaderXBC As String = "X-Bc"
|
Friend Const HeaderXBC As String = "X-Bc"
|
||||||
Friend Const HeaderAppToken As String = "App-Token"
|
Friend Const HeaderAppToken As String = "App-Token"
|
||||||
|
Private Const AppTokenDefault As String = "33d57ade8c02dbc5a333db99ff9ae26a"
|
||||||
|
Private Const BackendDefault As String = "aio"
|
||||||
|
Private Const Backendhttpx As String = "httpx"
|
||||||
<PropertyOption(ControlText:=HeaderUserID, AllowNull:=False, IsAuth:=True), PClonable(Clone:=False)>
|
<PropertyOption(ControlText:=HeaderUserID, AllowNull:=False, IsAuth:=True), PClonable(Clone:=False)>
|
||||||
Friend ReadOnly Property HH_USER_ID As PropertyValue
|
Friend ReadOnly Property HH_USER_ID As PropertyValue
|
||||||
<PropertyOption(ControlText:=HeaderXBC, AllowNull:=False, IsAuth:=True), PClonable(Clone:=False)>
|
<PropertyOption(ControlText:=HeaderXBC, AllowNull:=False, IsAuth:=True), PClonable(Clone:=False)>
|
||||||
Private ReadOnly Property HH_X_BC As PropertyValue
|
Private ReadOnly Property HH_X_BC As PropertyValue
|
||||||
<PropertyOption(ControlText:=HeaderAppToken, AllowNull:=False, IsAuth:=True), PClonable(Clone:=False)>
|
<PropertyOption(ControlText:=HeaderAppToken, AllowNull:=False, IsAuth:=True), PClonable(Clone:=False)>
|
||||||
Private ReadOnly Property HH_APP_TOKEN As PropertyValue
|
Private ReadOnly Property HH_APP_TOKEN As PropertyValue
|
||||||
|
<PropertyUpdater(NameOf(HH_APP_TOKEN))>
|
||||||
|
Private Function UpdateAppToken() As Boolean
|
||||||
|
HH_APP_TOKEN.Value = AppTokenDefault
|
||||||
|
Return True
|
||||||
|
End Function
|
||||||
<PropertyOption(ControlText:=HeaderBrowser, ControlToolTip:="Can be null", AllowNull:=True,
|
<PropertyOption(ControlText:=HeaderBrowser, ControlToolTip:="Can be null", AllowNull:=True,
|
||||||
InheritanceName:=SettingsCLS.HEADER_DEF_sec_ch_ua, IsAuth:=True), PClonable, PXML(OnlyForChecked:=True)>
|
InheritanceName:=SettingsCLS.HEADER_DEF_sec_ch_ua, IsAuth:=True), PClonable, PXML(OnlyForChecked:=True)>
|
||||||
Private ReadOnly Property HH_BROWSER As PropertyValue
|
Private ReadOnly Property HH_BROWSER As PropertyValue
|
||||||
@@ -193,6 +201,24 @@ Namespace API.OnlyFans
|
|||||||
End If
|
End If
|
||||||
Return False
|
Return False
|
||||||
End Function
|
End Function
|
||||||
|
<PClonable, PXML("OFS_BACKEND")> Private ReadOnly Property OFS_BACKEND_XML As PropertyValue
|
||||||
|
<PropertyOption(ControlText:="backend", ControlToolTip:="The value of 'advanced_options' in the configuration" & vbCr &
|
||||||
|
"If you can't download the video, try using 'httpx'", AllowNull:=False, Category:=CAT_OFS)>
|
||||||
|
Friend ReadOnly Property OFS_BACKEND As PropertyValue
|
||||||
|
Get
|
||||||
|
If Not DefaultInstance Is Nothing Then
|
||||||
|
Return DirectCast(DefaultInstance, SiteSettings).OFS_BACKEND_XML
|
||||||
|
Else
|
||||||
|
Return OFS_BACKEND_XML
|
||||||
|
End If
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
|
<PropertyUpdater(NameOf(OFS_BACKEND))>
|
||||||
|
Private Function OFS_BACKEND_Update() As Boolean
|
||||||
|
DirectCast(If(DefaultInstance, Me), SiteSettings).OFS_BACKEND_XML.Value =
|
||||||
|
CStr(IIf(MsgBoxE({"Select a value for the 'backend' option", "'backend' value"}, vbQuestion,,, {BackendDefault, Backendhttpx}) = 0, BackendDefault, Backendhttpx))
|
||||||
|
Return True
|
||||||
|
End Function
|
||||||
#End Region
|
#End Region
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Initializer"
|
#Region "Initializer"
|
||||||
@@ -225,13 +251,13 @@ Namespace API.OnlyFans
|
|||||||
.Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.AcceptEncoding))
|
.Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.AcceptEncoding))
|
||||||
HH_USER_ID = New PropertyValue(.Value(HeaderUserID), GetType(String), Sub(v) UpdateHeader(NameOf(HH_USER_ID), v))
|
HH_USER_ID = New PropertyValue(.Value(HeaderUserID), GetType(String), Sub(v) UpdateHeader(NameOf(HH_USER_ID), v))
|
||||||
HH_X_BC = New PropertyValue(.Value(HeaderXBC), GetType(String), Sub(v) UpdateHeader(NameOf(HH_X_BC), v))
|
HH_X_BC = New PropertyValue(.Value(HeaderXBC), GetType(String), Sub(v) UpdateHeader(NameOf(HH_X_BC), v))
|
||||||
HH_APP_TOKEN = New PropertyValue(.Value(HeaderAppToken), GetType(String), Sub(v) UpdateHeader(NameOf(HH_APP_TOKEN), v))
|
HH_APP_TOKEN = New PropertyValue(.Value(HeaderAppToken).IfNullOrEmpty(AppTokenDefault), GetType(String), Sub(v) UpdateHeader(NameOf(HH_APP_TOKEN), v))
|
||||||
HH_BROWSER = New PropertyValue(.Value(HeaderBrowser), GetType(String), Sub(v) UpdateHeader(NameOf(HH_BROWSER), v))
|
HH_BROWSER = New PropertyValue(.Value(HeaderBrowser), GetType(String), Sub(v) UpdateHeader(NameOf(HH_BROWSER), v))
|
||||||
End With
|
End With
|
||||||
UserAgent = New PropertyValue(IIf(.UserAgentExists, .UserAgent, String.Empty), GetType(String), Sub(v) UpdateHeader(NameOf(UserAgent), v))
|
UserAgent = New PropertyValue(IIf(.UserAgentExists, .UserAgent, String.Empty), GetType(String), Sub(v) UpdateHeader(NameOf(UserAgent), v))
|
||||||
End With
|
End With
|
||||||
|
|
||||||
EnableCookiesUpdate = New PropertyValue(True)
|
EnableCookiesUpdate = New PropertyValue(False)
|
||||||
|
|
||||||
DownloadTimeline = New PropertyValue(True)
|
DownloadTimeline = New PropertyValue(True)
|
||||||
DownloadStories = New PropertyValue(True)
|
DownloadStories = New PropertyValue(True)
|
||||||
@@ -255,6 +281,7 @@ Namespace API.OnlyFans
|
|||||||
Keydb_Api_XML = New PropertyValue(String.Empty, GetType(String))
|
Keydb_Api_XML = New PropertyValue(String.Empty, GetType(String))
|
||||||
OFS_KEYS_Key_XML = New PropertyValue(String.Empty, GetType(String))
|
OFS_KEYS_Key_XML = New PropertyValue(String.Empty, GetType(String))
|
||||||
OFS_KEYS_ClientID_XML = New PropertyValue(String.Empty, GetType(String))
|
OFS_KEYS_ClientID_XML = New PropertyValue(String.Empty, GetType(String))
|
||||||
|
OFS_BACKEND_XML = New PropertyValue(BackendDefault)
|
||||||
|
|
||||||
UpdateRules401_XML = New PropertyValue(False)
|
UpdateRules401_XML = New PropertyValue(False)
|
||||||
|
|
||||||
@@ -262,6 +289,15 @@ Namespace API.OnlyFans
|
|||||||
UrlPatternUser = "https://onlyfans.com/{0}"
|
UrlPatternUser = "https://onlyfans.com/{0}"
|
||||||
ImageVideoContains = "onlyfans.com"
|
ImageVideoContains = "onlyfans.com"
|
||||||
End Sub
|
End Sub
|
||||||
|
Private Const SettingsVersionCurrent As Integer = 1
|
||||||
|
Friend Overrides Sub EndInit()
|
||||||
|
If CInt(SettingsVersion.Value) < SettingsVersionCurrent Then
|
||||||
|
If CStr(HH_APP_TOKEN.Value).IsEmptyString Then HH_APP_TOKEN.Value = AppTokenDefault
|
||||||
|
EnableCookiesUpdate.Value = False
|
||||||
|
SettingsVersion.Value = SettingsVersionCurrent
|
||||||
|
End If
|
||||||
|
MyBase.EndInit()
|
||||||
|
End Sub
|
||||||
#End Region
|
#End Region
|
||||||
#Region "GetInstance"
|
#Region "GetInstance"
|
||||||
Friend Overrides Function GetInstance(ByVal What As ISiteSettings.Download) As IPluginContentProvider
|
Friend Overrides Function GetInstance(ByVal What As ISiteSettings.Download) As IPluginContentProvider
|
||||||
@@ -312,7 +348,7 @@ Namespace API.OnlyFans
|
|||||||
#Region "GetUserUrl, GetUserPostUrl, UserOptions"
|
#Region "GetUserUrl, GetUserPostUrl, UserOptions"
|
||||||
Friend Const UserPostPattern As String = "https://onlyfans.com/{0}/{1}"
|
Friend Const UserPostPattern As String = "https://onlyfans.com/{0}/{1}"
|
||||||
Friend Overrides Function GetUserUrl(ByVal User As IPluginContentProvider) As String
|
Friend Overrides Function GetUserUrl(ByVal User As IPluginContentProvider) As String
|
||||||
Return String.Format(UrlPatternUser, If(User.ID.IsEmptyString, User.Name, $"u{User.ID}"))
|
Return String.Format(UrlPatternUser, If(User.ID.IsEmptyString, User.NameTrue.IfNullOrEmpty(User.Name), $"u{User.ID}"))
|
||||||
End Function
|
End Function
|
||||||
Friend Overrides Function GetUserPostUrl(ByVal User As UserDataBase, ByVal Media As UserMedia) As String
|
Friend Overrides Function GetUserPostUrl(ByVal User As UserDataBase, ByVal Media As UserMedia) As String
|
||||||
If Not Media.Post.ID.IsEmptyString Then
|
If Not Media.Post.ID.IsEmptyString Then
|
||||||
@@ -328,7 +364,8 @@ Namespace API.OnlyFans
|
|||||||
If p.IsEmptyString Then
|
If p.IsEmptyString Then
|
||||||
Return GetUserUrl(User)
|
Return GetUserUrl(User)
|
||||||
Else
|
Else
|
||||||
Return String.Format(UserPostPattern, p, If(User.ID.IsEmptyString, User.Name, $"u{User.ID}"))
|
'Return String.Format(UserPostPattern, p, If(User.ID.IsEmptyString, User.Name, $"u{User.ID}"))
|
||||||
|
Return String.Format(UserPostPattern, p, User.NameTrue)
|
||||||
End If
|
End If
|
||||||
Else
|
Else
|
||||||
Return String.Empty
|
Return String.Empty
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ Namespace API.OnlyFans
|
|||||||
Friend Overrides Sub ExchangeOptionsSet(ByVal Obj As Object)
|
Friend Overrides Sub ExchangeOptionsSet(ByVal Obj As Object)
|
||||||
If Not Obj Is Nothing AndAlso TypeOf Obj Is UserExchangeOptions Then
|
If Not Obj Is Nothing AndAlso TypeOf Obj Is UserExchangeOptions Then
|
||||||
With DirectCast(Obj, UserExchangeOptions)
|
With DirectCast(Obj, UserExchangeOptions)
|
||||||
|
.ApplyBase(Me)
|
||||||
MediaDownloadTimeline = .DownloadTimeline
|
MediaDownloadTimeline = .DownloadTimeline
|
||||||
MediaDownloadStories = .DownloadStories
|
MediaDownloadStories = .DownloadStories
|
||||||
MediaDownloadHighlights = .DownloadHighlights
|
MediaDownloadHighlights = .DownloadHighlights
|
||||||
@@ -84,6 +85,7 @@ Namespace API.OnlyFans
|
|||||||
Private _OFScraperExists As Boolean = False
|
Private _OFScraperExists As Boolean = False
|
||||||
Private OFSCache As CacheKeeper = Nothing
|
Private OFSCache As CacheKeeper = Nothing
|
||||||
Private _AbsMediaIndex As Integer = 0
|
Private _AbsMediaIndex As Integer = 0
|
||||||
|
Private _DownloadedPostsSession As Integer = 0
|
||||||
Private FunctionErr As Integer = FunctionErrDef
|
Private FunctionErr As Integer = FunctionErrDef
|
||||||
Private Const FunctionErrDef As Integer = -100
|
Private Const FunctionErrDef As Integer = -100
|
||||||
Private Sub ValidateOFScraper()
|
Private Sub ValidateOFScraper()
|
||||||
@@ -95,6 +97,7 @@ Namespace API.OnlyFans
|
|||||||
If Not MySettings.SessionAborted Then
|
If Not MySettings.SessionAborted Then
|
||||||
ValidateOFScraper()
|
ValidateOFScraper()
|
||||||
_AbsMediaIndex = 0
|
_AbsMediaIndex = 0
|
||||||
|
_DownloadedPostsSession = 0
|
||||||
FunctionErr = FunctionErrDef
|
FunctionErr = FunctionErrDef
|
||||||
If Not CCookie Is Nothing Then CCookie.Dispose()
|
If Not CCookie Is Nothing Then CCookie.Dispose()
|
||||||
CCookie = Responser.Cookies.Copy
|
CCookie = Responser.Cookies.Copy
|
||||||
@@ -144,7 +147,7 @@ Namespace API.OnlyFans
|
|||||||
Dim tmpCursor$ = String.Empty
|
Dim tmpCursor$ = String.Empty
|
||||||
Dim hasMore As Boolean = False
|
Dim hasMore As Boolean = False
|
||||||
Dim path$ = String.Empty
|
Dim path$ = String.Empty
|
||||||
Dim postDate$, postID$
|
Dim postDate$, postID$, txt$
|
||||||
Dim n As EContainer
|
Dim n As EContainer
|
||||||
Dim mediaList As List(Of UserMedia)
|
Dim mediaList As List(Of UserMedia)
|
||||||
Dim mediaResult As Boolean
|
Dim mediaResult As Boolean
|
||||||
@@ -189,9 +192,21 @@ Namespace API.OnlyFans
|
|||||||
Case DateResult.Exit : Exit Sub
|
Case DateResult.Exit : Exit Sub
|
||||||
End Select
|
End Select
|
||||||
|
|
||||||
|
txt = n.Value("text")
|
||||||
|
|
||||||
mediaResult = False
|
mediaResult = False
|
||||||
mediaList = TryCreateMedia(n, postID, postDate, mediaResult)
|
mediaList = TryCreateMedia(n, postID, postDate, mediaResult,,,,, txt)
|
||||||
If mediaResult Then _TempMediaList.ListAddList(mediaList, LNC)
|
If mediaResult Then
|
||||||
|
_TempMediaList.ListAddList(mediaList, LNC)
|
||||||
|
_DownloadedPostsSession += 1
|
||||||
|
ElseIf Not txt.IsEmptyString Then
|
||||||
|
_TempMediaList.ListAddValue(New UserMedia(postID, UTypes.Text) With {
|
||||||
|
.Post = New UserPost(postID, AConvert(Of Date)(postDate, DateProvider, Nothing)),
|
||||||
|
.PostText = txt,
|
||||||
|
.PostTextFileSpecialFolder = DownloadTextSpecialFolder,
|
||||||
|
.PostTextFile = $"{postID}.txt"
|
||||||
|
}, LNC)
|
||||||
|
End If
|
||||||
Next
|
Next
|
||||||
Else
|
Else
|
||||||
hasMore = False
|
hasMore = False
|
||||||
@@ -202,7 +217,10 @@ Namespace API.OnlyFans
|
|||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
|
|
||||||
If hasMore Then
|
If DownloadTopCount.HasValue AndAlso DownloadTopCount.Value <= _DownloadedPostsSession Then
|
||||||
|
_complete = True
|
||||||
|
Exit Sub
|
||||||
|
ElseIf hasMore Then
|
||||||
If IsSavedPosts Then tmpCursor = CInt(Cursor.IfNullOrEmpty(0)) + 10
|
If IsSavedPosts Then tmpCursor = CInt(Cursor.IfNullOrEmpty(0)) + 10
|
||||||
DownloadTimeline(tmpCursor, Token)
|
DownloadTimeline(tmpCursor, Token)
|
||||||
End If
|
End If
|
||||||
@@ -405,7 +423,7 @@ Namespace API.OnlyFans
|
|||||||
Private Function TryCreateMedia(ByVal n As EContainer, ByVal PostID As String, Optional ByVal PostDate As String = Nothing,
|
Private Function TryCreateMedia(ByVal n As EContainer, ByVal PostID As String, Optional ByVal PostDate As String = Nothing,
|
||||||
Optional ByRef Result As Boolean = False, Optional ByVal IsHL As Boolean = False,
|
Optional ByRef Result As Boolean = False, Optional ByVal IsHL As Boolean = False,
|
||||||
Optional ByVal SpecFolder As String = Nothing, Optional ByVal PostUserID As String = Nothing,
|
Optional ByVal SpecFolder As String = Nothing, Optional ByVal PostUserID As String = Nothing,
|
||||||
Optional ByVal TryUseOFS As Boolean = True) As List(Of UserMedia)
|
Optional ByVal TryUseOFS As Boolean = True, Optional ByVal PostText As String = Nothing) As List(Of UserMedia)
|
||||||
Dim postUrl$, postUrlBase$, ext$
|
Dim postUrl$, postUrlBase$, ext$
|
||||||
Dim t As UTypes
|
Dim t As UTypes
|
||||||
Dim mList As New List(Of UserMedia)
|
Dim mList As New List(Of UserMedia)
|
||||||
@@ -438,7 +456,9 @@ Namespace API.OnlyFans
|
|||||||
If Not t = UTypes.Undefined And (Not postUrl.IsEmptyString Or t = UTypes.VideoPre) Then
|
If Not t = UTypes.Undefined And (Not postUrl.IsEmptyString Or t = UTypes.VideoPre) Then
|
||||||
Dim media As New UserMedia(postUrl.IfNullOrEmpty(IIf(t = UTypes.VideoPre, $"{t}{_AbsMediaIndex}", String.Empty)), t) With {
|
Dim media As New UserMedia(postUrl.IfNullOrEmpty(IIf(t = UTypes.VideoPre, $"{t}{_AbsMediaIndex}", String.Empty)), t) With {
|
||||||
.Post = New UserPost(PostID, AConvert(Of Date)(PostDate, DateProvider, Nothing)),
|
.Post = New UserPost(PostID, AConvert(Of Date)(PostDate, DateProvider, Nothing)),
|
||||||
.SpecialFolder = SpecFolder
|
.SpecialFolder = SpecFolder,
|
||||||
|
.PostText = PostText,
|
||||||
|
.PostTextFileSpecialFolder = DownloadTextSpecialFolder
|
||||||
}
|
}
|
||||||
If postUrlBase.IsEmptyString And Not IsSingleObjectDownload Then postUrlBase = GetPostUrl(Me, media)
|
If postUrlBase.IsEmptyString And Not IsSingleObjectDownload Then postUrlBase = GetPostUrl(Me, media)
|
||||||
If Not postUrlBase.IsEmptyString Then media.URL_BASE = postUrlBase
|
If Not postUrlBase.IsEmptyString Then media.URL_BASE = postUrlBase
|
||||||
@@ -451,32 +471,28 @@ Namespace API.OnlyFans
|
|||||||
End With
|
End With
|
||||||
Return mList
|
Return mList
|
||||||
End Function
|
End Function
|
||||||
Private Sub GetUserID()
|
Private _NameUpdated As Boolean = False
|
||||||
|
Private Sub GetUserID(Optional ByVal UpdateNameOnly As Boolean = False)
|
||||||
Const brTag$ = "<br />"
|
Const brTag$ = "<br />"
|
||||||
Dim path$ = $"/api2/v2/users/{Name}"
|
Dim path$ = $"/api2/v2/users/{IIf(UpdateNameOnly, $"u{ID}", Name)}"
|
||||||
Dim url$ = String.Format(BaseUrlPattern, path)
|
Dim url$ = String.Format(BaseUrlPattern, path)
|
||||||
Try
|
Try
|
||||||
If ID.IsEmptyString AndAlso UpdateSignature(path) Then
|
If (ID.IsEmptyString Or UpdateNameOnly) AndAlso UpdateSignature(path) Then
|
||||||
Dim r$ = Responser.GetResponse(url)
|
Dim r$ = Responser.GetResponse(url)
|
||||||
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
|
||||||
|
NameTrue = j.Value("username")
|
||||||
|
_NameUpdated = True
|
||||||
|
If UpdateNameOnly Then Exit Sub
|
||||||
ID = j.Value("id")
|
ID = j.Value("id")
|
||||||
If Not ID.IsEmptyString Then _ForceSaveUserInfo = True
|
If Not ID.IsEmptyString Then _ForceSaveUserInfo = True
|
||||||
UserSiteNameUpdate(j.Value("name"))
|
UserSiteNameUpdate(j.Value("name"))
|
||||||
Dim descr$ = j.Value("about")
|
Dim descr$ = j.Value("about")
|
||||||
If Not descr.IsEmptyString Then descr = descr.Replace(brTag, String.Empty)
|
If Not descr.IsEmptyString Then descr = descr.Replace(brTag, String.Empty)
|
||||||
UserDescriptionUpdate(descr)
|
UserDescriptionUpdate(descr)
|
||||||
Dim a As Action(Of String) = Sub(ByVal address As String)
|
SimpleDownloadAvatar(j.Value("avatar"))
|
||||||
If Not address.IsEmptyString Then
|
SimpleDownloadAvatar(j.Value("header"))
|
||||||
Dim f As SFile = address
|
|
||||||
f.Separator = "\"
|
|
||||||
f.Path = DownloadContentDefault_GetRootDir()
|
|
||||||
If Not f.Exists Then GetWebFile(address, f, EDP.None)
|
|
||||||
End If
|
|
||||||
End Sub
|
|
||||||
a.Invoke(j.Value("avatar"))
|
|
||||||
a.Invoke(j.Value("header"))
|
|
||||||
End If
|
End If
|
||||||
End Using
|
End Using
|
||||||
End If
|
End If
|
||||||
@@ -608,6 +624,7 @@ Namespace API.OnlyFans
|
|||||||
Const requestPattern$ = """{0}"" manual --config ""{1}"" --url {2}"
|
Const requestPattern$ = """{0}"" manual --config ""{1}"" --url {2}"
|
||||||
Dim conf As SFile = OFS_CreateConfig()
|
Dim conf As SFile = OFS_CreateConfig()
|
||||||
If conf.Exists Then
|
If conf.Exists Then
|
||||||
|
If Not _NameUpdated Then GetUserID(True)
|
||||||
Dim command$ = String.Format(requestPattern, MySettings.OFScraperPath.Value, conf, URL)
|
Dim command$ = String.Format(requestPattern, MySettings.OFScraperPath.Value, conf, URL)
|
||||||
'#If DEBUG Then
|
'#If DEBUG Then
|
||||||
'Debug.WriteLine(command)
|
'Debug.WriteLine(command)
|
||||||
@@ -665,6 +682,7 @@ Namespace API.OnlyFans
|
|||||||
|
|
||||||
updateConf("key-mode-default", CStr(MySettings.KeyModeDefault.Value).IfNullOrEmpty(SiteSettings.KeyModeDefault_Default), m1)
|
updateConf("key-mode-default", CStr(MySettings.KeyModeDefault.Value).IfNullOrEmpty(SiteSettings.KeyModeDefault_Default), m1)
|
||||||
updateConf("keydb_api", CStr(MySettings.Keydb_Api.Value), m1)
|
updateConf("keydb_api", CStr(MySettings.Keydb_Api.Value), m1)
|
||||||
|
updateConf("backend", CStr(MySettings.OFS_BACKEND.Value), m1)
|
||||||
|
|
||||||
If Not CStr(MySettings.OFS_KEYS_Key.Value).IsEmptyString And Not CStr(MySettings.OFS_KEYS_ClientID.Value).IsEmptyString Then
|
If Not CStr(MySettings.OFS_KEYS_Key.Value).IsEmptyString And Not CStr(MySettings.OFS_KEYS_ClientID.Value).IsEmptyString Then
|
||||||
updateConf("private-key", CStr(MySettings.OFS_KEYS_Key.Value).Replace("\", "/"), m3)
|
updateConf("private-key", CStr(MySettings.OFS_KEYS_Key.Value).Replace("\", "/"), m3)
|
||||||
@@ -738,6 +756,7 @@ Namespace API.OnlyFans
|
|||||||
If IsSingleObjectDownload Then
|
If IsSingleObjectDownload Then
|
||||||
URL = Media.URL_BASE
|
URL = Media.URL_BASE
|
||||||
Else
|
Else
|
||||||
|
If Not _NameUpdated Then GetUserID(True)
|
||||||
URL = GetPostUrl(Me, Media)
|
URL = GetPostUrl(Me, Media)
|
||||||
End If
|
End If
|
||||||
If Not URL.IsEmptyString Then
|
If Not URL.IsEmptyString Then
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
' but WITHOUT ANY WARRANTY
|
' but WITHOUT ANY WARRANTY
|
||||||
Imports SCrawler.Plugin.Attributes
|
Imports SCrawler.Plugin.Attributes
|
||||||
Namespace API.OnlyFans
|
Namespace API.OnlyFans
|
||||||
Friend Class UserExchangeOptions
|
Friend Class UserExchangeOptions : Inherits Base.EditorExchangeOptionsBase
|
||||||
<PSetting(NameOf(SiteSettings.DownloadTimeline), NameOf(MySettings))>
|
<PSetting(NameOf(SiteSettings.DownloadTimeline), NameOf(MySettings))>
|
||||||
Friend Property DownloadTimeline As Boolean
|
Friend Property DownloadTimeline As Boolean
|
||||||
<PSetting(NameOf(SiteSettings.DownloadStories), NameOf(MySettings))>
|
<PSetting(NameOf(SiteSettings.DownloadStories), NameOf(MySettings))>
|
||||||
@@ -18,7 +18,12 @@ Namespace API.OnlyFans
|
|||||||
<PSetting(NameOf(SiteSettings.DownloadChatMedia), NameOf(MySettings))>
|
<PSetting(NameOf(SiteSettings.DownloadChatMedia), NameOf(MySettings))>
|
||||||
Friend Property DownloadChatMedia As Boolean
|
Friend Property DownloadChatMedia As Boolean
|
||||||
Private ReadOnly MySettings As SiteSettings
|
Private ReadOnly MySettings As SiteSettings
|
||||||
|
<PSetting(Address:=SettingAddress.None)> Friend Overrides Property UserName As String
|
||||||
|
Private Sub New()
|
||||||
|
End Sub
|
||||||
Friend Sub New(ByVal u As UserData)
|
Friend Sub New(ByVal u As UserData)
|
||||||
|
MyBase.New(u)
|
||||||
|
_ApplyBase_Name = False
|
||||||
DownloadTimeline = u.MediaDownloadTimeline
|
DownloadTimeline = u.MediaDownloadTimeline
|
||||||
DownloadStories = u.MediaDownloadStories
|
DownloadStories = u.MediaDownloadStories
|
||||||
DownloadHighlights = u.MediaDownloadHighlights
|
DownloadHighlights = u.MediaDownloadHighlights
|
||||||
@@ -26,6 +31,8 @@ Namespace API.OnlyFans
|
|||||||
MySettings = u.HOST.Source
|
MySettings = u.HOST.Source
|
||||||
End Sub
|
End Sub
|
||||||
Friend Sub New(ByVal s As SiteSettings)
|
Friend Sub New(ByVal s As SiteSettings)
|
||||||
|
MyBase.New(s)
|
||||||
|
_ApplyBase_Name = False
|
||||||
DownloadTimeline = s.DownloadTimeline.Value
|
DownloadTimeline = s.DownloadTimeline.Value
|
||||||
DownloadStories = s.DownloadStories.Value
|
DownloadStories = s.DownloadStories.Value
|
||||||
DownloadHighlights = s.DownloadHighlights.Value
|
DownloadHighlights = s.DownloadHighlights.Value
|
||||||
|
|||||||
@@ -7,11 +7,18 @@
|
|||||||
' This program is distributed in the hope that it will be useful,
|
' This program is distributed in the hope that it will be useful,
|
||||||
' but WITHOUT ANY WARRANTY
|
' but WITHOUT ANY WARRANTY
|
||||||
Imports System.Globalization
|
Imports System.Globalization
|
||||||
|
Imports System.Text.RegularExpressions
|
||||||
Imports PersonalUtilities.Tools.Web.Clients
|
Imports PersonalUtilities.Tools.Web.Clients
|
||||||
|
Imports PersonalUtilities.Functions.RegularExpressions
|
||||||
Namespace API.Pinterest
|
Namespace API.Pinterest
|
||||||
Friend Module Declarations
|
Friend Module Declarations
|
||||||
Friend ReadOnly DateProvider As ADateTime = GetDateProvider()
|
Friend ReadOnly DateProvider As ADateTime = GetDateProvider()
|
||||||
Friend ReadOnly PwsHeader As New HttpHeader("x-pinterest-pws-handler", "www/[username]/pins.js")
|
Friend ReadOnly PwsHeader As New HttpHeader("x-pinterest-pws-handler", "www/[username]/pins.js")
|
||||||
|
Friend ReadOnly GdlUrlPattern As RParams = RParams.DM(Base.GDL.GDLBatch.UrlLibStart.Replace("[", "\[").Replace("]", "\]") &
|
||||||
|
"([^""]+?)""(GET [^""]+)""", 0, EDP.ReturnValue)
|
||||||
|
Friend ReadOnly SubBoardRegEx As RParams = RParams.DMS("\[pinterest\]\[debug\] Using PinterestSectionExtractor for '[^']+id:(\d+)'", 1,
|
||||||
|
RegexOptions.IgnoreCase, EDP.ReturnValue)
|
||||||
|
Friend ReadOnly BoardInfoRootNode As String() = {"resource_response", "data"}
|
||||||
Private Function GetDateProvider() As ADateTime
|
Private Function GetDateProvider() As ADateTime
|
||||||
Dim n As DateTimeFormatInfo = CultureInfo.GetCultureInfo("en-us").DateTimeFormat.Clone
|
Dim n As DateTimeFormatInfo = CultureInfo.GetCultureInfo("en-us").DateTimeFormat.Clone
|
||||||
n.FullDateTimePattern = "ddd dd MMM yyyy HH:mm:ss"
|
n.FullDateTimePattern = "ddd dd MMM yyyy HH:mm:ss"
|
||||||
|
|||||||
20
SCrawler/API/Pinterest/EditorExchangeOptions.vb
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
' Copyright (C) Andy https://github.com/AAndyProgram
|
||||||
|
' This program is free software: you can redistribute it and/or modify
|
||||||
|
' it under the terms of the GNU General Public License as published by
|
||||||
|
' the Free Software Foundation, either version 3 of the License, or
|
||||||
|
' (at your option) any later version.
|
||||||
|
'
|
||||||
|
' This program is distributed in the hope that it will be useful,
|
||||||
|
' but WITHOUT ANY WARRANTY
|
||||||
|
Imports SCrawler.Plugin.Attributes
|
||||||
|
Namespace API.Pinterest
|
||||||
|
Friend Class EditorExchangeOptions
|
||||||
|
<PSetting(Caption:="Get Sub-Boards", ToolTip:="Extract the Sub-Boards from the boards and download them")>
|
||||||
|
Friend Property ExtractSubBoards As Boolean = True
|
||||||
|
Friend Sub New(ByVal u As UserData)
|
||||||
|
ExtractSubBoards = u.ExtractSubBoards
|
||||||
|
End Sub
|
||||||
|
Friend Sub New()
|
||||||
|
End Sub
|
||||||
|
End Class
|
||||||
|
End Namespace
|
||||||
@@ -11,7 +11,7 @@ Imports SCrawler.Plugin
|
|||||||
Imports SCrawler.Plugin.Attributes
|
Imports SCrawler.Plugin.Attributes
|
||||||
Imports PersonalUtilities.Functions.RegularExpressions
|
Imports PersonalUtilities.Functions.RegularExpressions
|
||||||
Namespace API.Pinterest
|
Namespace API.Pinterest
|
||||||
<Manifest("AndyProgram_Pinterest"), SavedPosts, SeparatedTasks>
|
<Manifest("AndyProgram_Pinterest"), SavedPosts, SeparatedTasks, SpecialForm(False)>
|
||||||
Friend Class SiteSettings : Inherits SiteSettingsBase
|
Friend Class SiteSettings : Inherits SiteSettingsBase
|
||||||
#Region "Declarations"
|
#Region "Declarations"
|
||||||
<PropertyOption(ControlText:=DeclaredNames.ConcurrentDownloadsCaption,
|
<PropertyOption(ControlText:=DeclaredNames.ConcurrentDownloadsCaption,
|
||||||
@@ -21,6 +21,9 @@ Namespace API.Pinterest
|
|||||||
Private ReadOnly Property MyConcurrentDownloadsProvider As IFormatProvider
|
Private ReadOnly Property MyConcurrentDownloadsProvider As IFormatProvider
|
||||||
<PropertyOption(ControlText:=DeclaredNames.SavedPostsUserNameCaption, ControlToolTip:=DeclaredNames.SavedPostsUserNameToolTip), PXML, PClonable(Clone:=False)>
|
<PropertyOption(ControlText:=DeclaredNames.SavedPostsUserNameCaption, ControlToolTip:=DeclaredNames.SavedPostsUserNameToolTip), PXML, PClonable(Clone:=False)>
|
||||||
Friend ReadOnly Property SavedPostsUserName As PropertyValue
|
Friend ReadOnly Property SavedPostsUserName As PropertyValue
|
||||||
|
<DoNotUse> Friend Overrides Property DownloadText As PropertyValue
|
||||||
|
<DoNotUse> Friend Overrides Property DownloadTextPosts As PropertyValue
|
||||||
|
<DoNotUse> Friend Overrides Property DownloadTextSpecialFolder As PropertyValue
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Initializer"
|
#Region "Initializer"
|
||||||
Friend Sub New(ByVal AccName As String, ByVal Temp As Boolean)
|
Friend Sub New(ByVal AccName As String, ByVal Temp As Boolean)
|
||||||
@@ -30,7 +33,8 @@ Namespace API.Pinterest
|
|||||||
MyConcurrentDownloadsProvider = New ConcurrentDownloadsProvider
|
MyConcurrentDownloadsProvider = New ConcurrentDownloadsProvider
|
||||||
CheckNetscapeCookiesOnEndInit = True
|
CheckNetscapeCookiesOnEndInit = True
|
||||||
UseNetscapeCookies = True
|
UseNetscapeCookies = True
|
||||||
UserRegex = RParams.DMS("https?://w{0,3}.?[^/]*?.?pinterest.com/([^/]+)/?(?(_)|([^/]*))", 0, RegexReturn.ListByMatch, EDP.ReturnValue)
|
UserRegex = RParams.DMS("https?://w{0,3}.?[^/]*?.?pinterest.com/([^/]+)/?(?(_)|([^/]*))/?([^/\?]*)", 0, RegexReturn.ListByMatch, EDP.ReturnValue)
|
||||||
|
UserOptionsType = GetType(EditorExchangeOptions)
|
||||||
End Sub
|
End Sub
|
||||||
#End Region
|
#End Region
|
||||||
#Region "GetInstance, Available"
|
#Region "GetInstance, Available"
|
||||||
@@ -41,13 +45,14 @@ Namespace API.Pinterest
|
|||||||
Return Settings.GalleryDLFile.Exists And (Not What = ISiteSettings.Download.SavedPosts OrElse ACheck(SavedPostsUserName.Value))
|
Return Settings.GalleryDLFile.Exists And (Not What = ISiteSettings.Download.SavedPosts OrElse ACheck(SavedPostsUserName.Value))
|
||||||
End Function
|
End Function
|
||||||
#End Region
|
#End Region
|
||||||
#Region "IsMyUser, IsMyImageVideo, GetUserUrl, GetUserPostUrl"
|
#Region "IsMyUser, IsMyImageVideo, GetUserUrl, GetUserPostUrl, UserOptions"
|
||||||
Friend Overrides Function IsMyUser(ByVal UserURL As String) As ExchangeOptions
|
Friend Overrides Function IsMyUser(ByVal UserURL As String) As ExchangeOptions
|
||||||
If Not UserURL.IsEmptyString Then
|
If Not UserURL.IsEmptyString Then
|
||||||
Dim l As List(Of String) = RegexReplace(UserURL, UserRegex)
|
Dim l As List(Of String) = RegexReplace(UserURL, UserRegex)
|
||||||
If l.ListExists(3) Then
|
If l.ListExists(3) Then
|
||||||
Dim n$ = l(1)
|
Dim n$ = l(1)
|
||||||
If Not l(2).IsEmptyString Then n &= $"@{l(2)}"
|
If Not l(2).IsEmptyString Then n &= $"@{l(2)}"
|
||||||
|
If l.Count > 3 AndAlso Not l(3).IsEmptyString Then n &= $"@{l(3)}"
|
||||||
Return New ExchangeOptions(Site, n) With {.Exists = True}
|
Return New ExchangeOptions(Site, n) With {.Exists = True}
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
|
|||||||
@@ -7,10 +7,12 @@
|
|||||||
' This program is distributed in the hope that it will be useful,
|
' This program is distributed in the hope that it will be useful,
|
||||||
' but WITHOUT ANY WARRANTY
|
' but WITHOUT ANY WARRANTY
|
||||||
Imports System.Threading
|
Imports System.Threading
|
||||||
|
Imports System.Text.RegularExpressions
|
||||||
Imports SCrawler.API.Base
|
Imports SCrawler.API.Base
|
||||||
Imports SCrawler.API.Base.GDL
|
Imports SCrawler.API.Base.GDL
|
||||||
Imports SCrawler.API.YouTube.Objects
|
Imports SCrawler.API.YouTube.Objects
|
||||||
Imports PersonalUtilities.Functions.XML
|
Imports PersonalUtilities.Functions.XML
|
||||||
|
Imports PersonalUtilities.Functions.RegularExpressions
|
||||||
Imports PersonalUtilities.Tools.Web.Documents.JSON
|
Imports PersonalUtilities.Tools.Web.Documents.JSON
|
||||||
Namespace API.Pinterest
|
Namespace API.Pinterest
|
||||||
Friend Class UserData : Inherits UserDataBase
|
Friend Class UserData : Inherits UserDataBase
|
||||||
@@ -18,6 +20,8 @@ Namespace API.Pinterest
|
|||||||
Private Const Name_IsUser As String = "IsUser"
|
Private Const Name_IsUser As String = "IsUser"
|
||||||
Private Const Name_TrueUserName As String = "TrueUserName"
|
Private Const Name_TrueUserName As String = "TrueUserName"
|
||||||
Private Const Name_TrueBoardName As String = "TrueBoardName"
|
Private Const Name_TrueBoardName As String = "TrueBoardName"
|
||||||
|
Private Const Name_ExtractSubBoards As String = "ExtractSubBoards"
|
||||||
|
Private Const Name_IsSubBoard As String = "IsSubBoard"
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Structures"
|
#Region "Structures"
|
||||||
Private Structure BoardInfo
|
Private Structure BoardInfo
|
||||||
@@ -38,6 +42,8 @@ Namespace API.Pinterest
|
|||||||
Friend Property TrueUserName As String
|
Friend Property TrueUserName As String
|
||||||
Friend Property TrueBoardName As String
|
Friend Property TrueBoardName As String
|
||||||
Friend Property IsUser_NB As Boolean
|
Friend Property IsUser_NB As Boolean
|
||||||
|
Private Property IsSubBoard As Boolean = False
|
||||||
|
Friend Property ExtractSubBoards As Boolean = True
|
||||||
Private Const BoardLabelName As String = "Board"
|
Private Const BoardLabelName As String = "Board"
|
||||||
Friend Overrides ReadOnly Property SpecialLabels As IEnumerable(Of String)
|
Friend Overrides ReadOnly Property SpecialLabels As IEnumerable(Of String)
|
||||||
Get
|
Get
|
||||||
@@ -45,14 +51,18 @@ Namespace API.Pinterest
|
|||||||
End Get
|
End Get
|
||||||
End Property
|
End Property
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Load"
|
#Region "Load, Exchange"
|
||||||
Private Function ReconfUserName() As Boolean
|
Private Function ReconfUserName() As Boolean
|
||||||
If TrueUserName.IsEmptyString Then
|
If TrueUserName.IsEmptyString Then
|
||||||
Dim n$() = Name.Split("@")
|
Dim n$() = Name.Split("@")
|
||||||
If n.ListExists Then
|
If n.ListExists Then
|
||||||
TrueUserName = n(0)
|
TrueUserName = n(0)
|
||||||
IsUser_NB = True
|
IsUser_NB = True
|
||||||
If n.Length > 1 Then TrueBoardName = n(1) : IsUser_NB = False
|
If n.Length > 1 Then
|
||||||
|
TrueBoardName = n(1)
|
||||||
|
If n.Length > 2 AndAlso Not n(2).IsEmptyString Then TrueBoardName &= $"/{n(2)}" : IsSubBoard = True
|
||||||
|
IsUser_NB = False
|
||||||
|
End If
|
||||||
If Not IsSavedPosts And Not IsSingleObjectDownload Then
|
If Not IsSavedPosts And Not IsSingleObjectDownload Then
|
||||||
Dim l$ = IIf(IsUser_NB, UserLabelName, BoardLabelName)
|
Dim l$ = IIf(IsUser_NB, UserLabelName, BoardLabelName)
|
||||||
Settings.Labels.Add(l)
|
Settings.Labels.Add(l)
|
||||||
@@ -70,15 +80,25 @@ Namespace API.Pinterest
|
|||||||
TrueUserName = .Value(Name_TrueUserName)
|
TrueUserName = .Value(Name_TrueUserName)
|
||||||
TrueBoardName = .Value(Name_TrueBoardName)
|
TrueBoardName = .Value(Name_TrueBoardName)
|
||||||
IsUser_NB = .Value(Name_IsUser).FromXML(Of Boolean)(False)
|
IsUser_NB = .Value(Name_IsUser).FromXML(Of Boolean)(False)
|
||||||
|
ExtractSubBoards = .Value(Name_ExtractSubBoards).FromXML(Of Boolean)(True)
|
||||||
|
IsSubBoard = .Value(Name_IsSubBoard).FromXML(Of Boolean)(False)
|
||||||
ReconfUserName()
|
ReconfUserName()
|
||||||
Else
|
Else
|
||||||
If ReconfUserName() Then .Value(Name_LabelsName) = LabelsString
|
If ReconfUserName() Then .Value(Name_LabelsName) = LabelsString
|
||||||
.Add(Name_TrueUserName, TrueUserName)
|
.Add(Name_TrueUserName, TrueUserName)
|
||||||
.Add(Name_TrueBoardName, TrueBoardName)
|
.Add(Name_TrueBoardName, TrueBoardName)
|
||||||
.Add(Name_IsUser, IsUser_NB.BoolToInteger)
|
.Add(Name_IsUser, IsUser_NB.BoolToInteger)
|
||||||
|
.Add(Name_ExtractSubBoards, ExtractSubBoards.BoolToInteger)
|
||||||
|
.Add(Name_IsSubBoard, IsSubBoard.BoolToInteger)
|
||||||
End If
|
End If
|
||||||
End With
|
End With
|
||||||
End Sub
|
End Sub
|
||||||
|
Friend Overrides Function ExchangeOptionsGet() As Object
|
||||||
|
Return New EditorExchangeOptions(Me)
|
||||||
|
End Function
|
||||||
|
Friend Overrides Sub ExchangeOptionsSet(ByVal Obj As Object)
|
||||||
|
If Not Obj Is Nothing AndAlso TypeOf Obj Is EditorExchangeOptions Then ExtractSubBoards = DirectCast(Obj, EditorExchangeOptions).ExtractSubBoards
|
||||||
|
End Sub
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Download overrides"
|
#Region "Download overrides"
|
||||||
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
|
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
|
||||||
@@ -125,6 +145,19 @@ Namespace API.Pinterest
|
|||||||
End Sub
|
End Sub
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Get boards, images"
|
#Region "Get boards, images"
|
||||||
|
Private Function GetBoardInfo(ByVal e As EContainer) As BoardInfo
|
||||||
|
If Not e Is Nothing Then
|
||||||
|
Dim b As New BoardInfo With {
|
||||||
|
.URL = e.Value("url"),
|
||||||
|
.Title = TitleHtmlConverter(e.Value("name")).IfNullOrEmpty(TitleHtmlConverter(e.Value("title"))),
|
||||||
|
.ID = e.Value("id")
|
||||||
|
}
|
||||||
|
If Not b.URL.IsEmptyString Then b.URL = $"https://www.pinterest.com/{b.URL.StringTrimStart("/").StringTrimEnd("/")}/"
|
||||||
|
Return b
|
||||||
|
Else
|
||||||
|
Return Nothing
|
||||||
|
End If
|
||||||
|
End Function
|
||||||
Private Function GetBoards(ByVal Token As CancellationToken) As List(Of BoardInfo)
|
Private Function GetBoards(ByVal Token As CancellationToken) As List(Of BoardInfo)
|
||||||
Dim URL$ = $"https://www.pinterest.com/{TrueUserName}/"
|
Dim URL$ = $"https://www.pinterest.com/{TrueUserName}/"
|
||||||
Try
|
Try
|
||||||
@@ -132,11 +165,12 @@ Namespace API.Pinterest
|
|||||||
Dim b As BoardInfo
|
Dim b As BoardInfo
|
||||||
Dim r$
|
Dim r$
|
||||||
Dim j As EContainer, jj As EContainer
|
Dim j As EContainer, jj As EContainer
|
||||||
Dim rootNode$() = {"resource_response", "data"}
|
|
||||||
Dim jErr As New ErrorsDescriber(EDP.SendToLog + EDP.ReturnValue)
|
Dim jErr As New ErrorsDescriber(EDP.SendToLog + EDP.ReturnValue)
|
||||||
Dim urls As List(Of String) = GetDataFromGalleryDL(URL, True, Token)
|
Dim urls As New List(Of String)
|
||||||
|
urls.ListAddList(GetDataFromGalleryDL(URL, True, Token), LNC)
|
||||||
If urls.ListExists Then urls.RemoveAll(Function(__url) Not __url.Contains("BoardsResource/get/"))
|
If urls.ListExists Then urls.RemoveAll(Function(__url) Not __url.Contains("BoardsResource/get/"))
|
||||||
If urls.ListExists Then
|
If urls.ListExists Then
|
||||||
|
Responser.Headers.Add(PwsHeader)
|
||||||
ProgressPre.ChangeMax(urls.Count)
|
ProgressPre.ChangeMax(urls.Count)
|
||||||
For Each URL In urls
|
For Each URL In urls
|
||||||
ProgressPre.Perform()
|
ProgressPre.Perform()
|
||||||
@@ -145,17 +179,10 @@ Namespace API.Pinterest
|
|||||||
If Not r.IsEmptyString Then
|
If Not r.IsEmptyString Then
|
||||||
j = JsonDocument.Parse(r, jErr)
|
j = JsonDocument.Parse(r, jErr)
|
||||||
If Not j Is Nothing Then
|
If Not j Is Nothing Then
|
||||||
If If(j(rootNode)?.Count, 0) > 0 Then
|
If If(j(BoardInfoRootNode)?.Count, 0) > 0 Then
|
||||||
For Each jj In j(rootNode)
|
For Each jj In j(BoardInfoRootNode)
|
||||||
b = New BoardInfo With {
|
b = GetBoardInfo(jj)
|
||||||
.URL = jj.Value("url"),
|
If Not b.URL.IsEmptyString Then boards.Add(b)
|
||||||
.Title = TitleHtmlConverter(jj.Value("name")),
|
|
||||||
.ID = jj.Value("id")
|
|
||||||
}
|
|
||||||
If Not b.URL.IsEmptyString Then
|
|
||||||
b.URL = $"https://www.pinterest.com/{b.URL.StringTrimStart("/").StringTrimEnd("/")}/"
|
|
||||||
boards.Add(b)
|
|
||||||
End If
|
|
||||||
Next
|
Next
|
||||||
End If
|
End If
|
||||||
j.Dispose()
|
j.Dispose()
|
||||||
@@ -167,98 +194,161 @@ Namespace API.Pinterest
|
|||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
ProcessException(ex, Token, $"data (gallery-dl boards) downloading error [{URL}]")
|
ProcessException(ex, Token, $"data (gallery-dl boards) downloading error [{URL}]")
|
||||||
Return Nothing
|
Return Nothing
|
||||||
|
Finally
|
||||||
|
Responser.Headers.Remove(PwsHeader)
|
||||||
End Try
|
End Try
|
||||||
End Function
|
End Function
|
||||||
Private Sub DownloadBoardImages(ByRef Board As BoardInfo, ByVal Token As CancellationToken)
|
Private Sub DownloadBoardImages(ByRef Board As BoardInfo, ByVal Token As CancellationToken)
|
||||||
Dim bUrl$ = String.Empty
|
Dim bUrl As GDLURL = Nothing
|
||||||
Try
|
Try
|
||||||
Dim r$
|
Dim r$
|
||||||
Dim j As EContainer, jj As EContainer
|
Dim j As EContainer, jj As EContainer
|
||||||
Dim u As UserMedia
|
Dim u As UserMedia
|
||||||
Dim folder$ = If(IsUser_NB, Board.Title.IfNullOrEmpty(Board.ID), String.Empty)
|
Dim __getBoardTitle As Func(Of BoardInfo, String) = Function(__board) __board.Title.IfNullOrEmpty(__board.ID)
|
||||||
|
Dim folderDef$ = If(IsUser_NB, __getBoardTitle(Board), String.Empty)
|
||||||
Dim titleExists As Boolean = Not Board.Title.IsEmptyString
|
Dim titleExists As Boolean = Not Board.Title.IsEmptyString
|
||||||
Dim i% = -1
|
Dim i% = -1
|
||||||
Dim jErr As New ErrorsDescriber(EDP.SendToLog + EDP.ReturnValue)
|
Dim jErr As New ErrorsDescriber(EDP.SendToLog + EDP.ReturnValue)
|
||||||
Dim rootNode$() = {"resource_response", "data"}
|
Dim rErr As New ErrorsDescriber(EDP.ReturnValue)
|
||||||
Dim images As List(Of Sizes)
|
Dim images As List(Of Sizes)
|
||||||
Dim imgSelector As Func(Of EContainer, Sizes) = Function(img) New Sizes(img.Value("width"), img.Value("url"))
|
Dim imgSelector As Func(Of EContainer, Sizes) = Function(img) New Sizes(img.Value("width"), img.Value("url"))
|
||||||
Dim fullData As Predicate(Of EContainer) = Function(e) e.Count > 5
|
Dim fullData As Predicate(Of EContainer) = Function(e) e.Count > 5
|
||||||
Dim l As List(Of String) = GetDataFromGalleryDL(Board.URL, False, Token)
|
Dim subBoard As BoardInfo = Nothing
|
||||||
If l.ListExists Then l.RemoveAll(Function(ll) Not ll.Contains("BoardFeedResource/get/"))
|
Dim subBoardAppender As Func(Of String) = Function() _
|
||||||
|
If(Not __getBoardTitle(subBoard).IsEmptyString,
|
||||||
|
$"{IIf(folderDef.IsEmptyString, String.Empty, "\")}{__getBoardTitle(subBoard)}",
|
||||||
|
String.Empty)
|
||||||
|
Dim __getSubBoard As Func(Of Boolean) = Function() ExtractSubBoards Or (IsSubBoard And i = -1)
|
||||||
|
Dim sbCount% = 0
|
||||||
|
Dim __getBoardInfo As Action(Of GDLURL) = Sub(ByVal sb As GDLURL)
|
||||||
|
sbCount += 1
|
||||||
|
r = Responser.GetResponse(sb.URL,, rErr)
|
||||||
|
If Not r.IsEmptyString Then
|
||||||
|
Using jsb As EContainer = JsonDocument.Parse(r, jErr)
|
||||||
|
If jsb.ListExists Then subBoard = GetBoardInfo(jsb(BoardInfoRootNode)) : Exit Sub
|
||||||
|
End Using
|
||||||
|
End If
|
||||||
|
subBoard = Nothing
|
||||||
|
End Sub
|
||||||
|
Dim l As List(Of GDLURL) = GetDataFromGalleryDL(Board.URL, False, Token)
|
||||||
|
If l.ListExists Then l.RemoveAll(Function(ll) ll.URL.IsEmptyString)
|
||||||
If l.ListExists Then
|
If l.ListExists Then
|
||||||
Responser.Headers.Add(PwsHeader)
|
Responser.Headers.Add(PwsHeader)
|
||||||
ProgressPre.ChangeMax(l.Count)
|
ProgressPre.ChangeMax(l.Count)
|
||||||
For Each bUrl In l
|
For Each bUrl In l
|
||||||
ProgressPre.Perform()
|
ProgressPre.Perform()
|
||||||
ThrowAny(Token)
|
ThrowAny(Token)
|
||||||
r = Responser.GetResponse(bUrl,, EDP.ReturnValue)
|
|
||||||
If Not r.IsEmptyString Then
|
|
||||||
j = JsonDocument.Parse(r, jErr)
|
|
||||||
If Not j Is Nothing Then
|
|
||||||
If If(j(rootNode)?.Count, 0) > 0 Then
|
|
||||||
ProgressPre.ChangeMax(j(rootNode).Count)
|
|
||||||
For Each jj In j(rootNode)
|
|
||||||
ProgressPre.Perform()
|
|
||||||
With jj
|
|
||||||
If .Contains("images") Then
|
|
||||||
images = .Item("images").Select(imgSelector).ToList
|
|
||||||
If images.Count > 0 Then
|
|
||||||
images.Sort()
|
|
||||||
i += 1
|
|
||||||
u = New UserMedia(images(0).Data) With {
|
|
||||||
.Post = New UserPost(jj.Value("id"), AConvert(Of Date)(jj.Value("created_at"), DateProvider, Nothing)),
|
|
||||||
.Type = UserMedia.Types.Picture,
|
|
||||||
.SpecialFolder = folder
|
|
||||||
}
|
|
||||||
If i = 0 Then
|
|
||||||
If Board.Title.IsEmptyString Or Board.ID.IsEmptyString Then
|
|
||||||
Board.Title = TitleHtmlConverter(.Value({"board"}, "name"))
|
|
||||||
Board.ID = .Value({"board"}, "id")
|
|
||||||
End If
|
|
||||||
Board.UserID = .Value({"board", "owner"}, "id")
|
|
||||||
Board.UserTitle = TitleHtmlConverter(.Value({"board", "owner"}, "full_name"))
|
|
||||||
If Not titleExists And IsUser_NB Then
|
|
||||||
If Not Board.Title.IsEmptyString Then
|
|
||||||
folder = Board.Title
|
|
||||||
ElseIf Not Board.ID.IsEmptyString Then
|
|
||||||
folder = Board.ID
|
|
||||||
End If
|
|
||||||
u.SpecialFolder = folder
|
|
||||||
End If
|
|
||||||
End If
|
|
||||||
|
|
||||||
If Not u.URL.IsEmptyString Then
|
If bUrl.URL.Contains("BoardFeedResource/get/") Or (bUrl.URL.Contains("BoardSectionPinsResource/get/") And (ExtractSubBoards Or (IsSubBoard And sbCount = 1))) Then
|
||||||
If u.Post.Date.HasValue Then
|
r = Responser.GetResponse(bUrl.URL,, rErr)
|
||||||
Select Case CheckDatesLimit(u.Post.Date.Value, Nothing)
|
If Not r.IsEmptyString Then
|
||||||
Case DateResult.Skip : _TempPostsList.ListAddValue(u.Post.ID, LNC) : Continue For
|
j = JsonDocument.Parse(r, jErr)
|
||||||
Case DateResult.Exit : Exit Sub
|
If Not j Is Nothing Then
|
||||||
End Select
|
If If(j(BoardInfoRootNode)?.Count, 0) > 0 Then
|
||||||
|
ProgressPre.ChangeMax(j(BoardInfoRootNode).Count)
|
||||||
|
For Each jj In j(BoardInfoRootNode)
|
||||||
|
ProgressPre.Perform()
|
||||||
|
With jj
|
||||||
|
If .Contains("images") Then
|
||||||
|
images = .Item("images").Select(imgSelector).ToList
|
||||||
|
If images.Count > 0 Then
|
||||||
|
images.Sort()
|
||||||
|
i += 1
|
||||||
|
u = New UserMedia(images(0).Data) With {
|
||||||
|
.Post = New UserPost(jj.Value("id"), AConvert(Of Date)(jj.Value("created_at"), DateProvider, Nothing)),
|
||||||
|
.Type = UserMedia.Types.Picture,
|
||||||
|
.SpecialFolder = folderDef & subBoardAppender.Invoke
|
||||||
|
}
|
||||||
|
If i = 0 Then
|
||||||
|
If Board.Title.IsEmptyString Or Board.ID.IsEmptyString Then
|
||||||
|
Board.Title = TitleHtmlConverter(.Value({"board"}, "name"))
|
||||||
|
Board.ID = .Value({"board"}, "id")
|
||||||
|
End If
|
||||||
|
Board.UserID = .Value({"board", "owner"}, "id")
|
||||||
|
Board.UserTitle = TitleHtmlConverter(.Value({"board", "owner"}, "full_name"))
|
||||||
|
If Not titleExists And IsUser_NB Then
|
||||||
|
folderDef = Board.Title.IfNullOrEmpty(Board.ID).IfNullOrEmpty(folderDef)
|
||||||
|
u.SpecialFolder = folderDef & subBoardAppender.Invoke
|
||||||
|
End If
|
||||||
End If
|
End If
|
||||||
If Not _TempPostsList.Contains(u.Post.ID) Then
|
|
||||||
_TempPostsList.ListAddValue(u.Post.ID, LNC)
|
If Not u.URL.IsEmptyString Then
|
||||||
_TempMediaList.ListAddValue(u, LNC)
|
If u.Post.Date.HasValue Then
|
||||||
Else
|
Select Case CheckDatesLimit(u.Post.Date.Value, Nothing)
|
||||||
Exit For
|
Case DateResult.Skip : _TempPostsList.ListAddValue(u.Post.ID, LNC) : Continue For
|
||||||
|
Case DateResult.Exit : Exit Sub
|
||||||
|
End Select
|
||||||
|
End If
|
||||||
|
If Not _TempPostsList.Contains(u.Post.ID) Then
|
||||||
|
_TempPostsList.ListAddValue(u.Post.ID, LNC)
|
||||||
|
_TempMediaList.ListAddValue(u, LNC)
|
||||||
|
Else
|
||||||
|
Exit For
|
||||||
|
End If
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
End If
|
End With
|
||||||
End With
|
Next
|
||||||
Next
|
End If
|
||||||
|
j.Dispose()
|
||||||
End If
|
End If
|
||||||
j.Dispose()
|
End If
|
||||||
|
ElseIf bUrl.URL.Contains("BoardSectionResource/get/") And (ExtractSubBoards Or (IsSubBoard And i = -1)) Then
|
||||||
|
__getBoardInfo(bUrl)
|
||||||
|
If IsSubBoard And i = -1 And Board.Title.IsEmptyString Then
|
||||||
|
Board.Title = subBoard.Title
|
||||||
|
If Board.ID.IsEmptyString Then Board.ID = subBoard.ID
|
||||||
|
subBoard = Nothing
|
||||||
|
folderDef = String.Empty
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
|
|
||||||
Next
|
Next
|
||||||
End If
|
End If
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
ProcessException(ex, Token, $"data (gallery-dl images) downloading error [{bUrl}]")
|
ProcessException(ex, Token, $"data (gallery-dl images) downloading error [{bUrl.URL}]")
|
||||||
Finally
|
Finally
|
||||||
Responser.Headers.Remove(PwsHeader)
|
Responser.Headers.Remove(PwsHeader)
|
||||||
End Try
|
End Try
|
||||||
End Sub
|
End Sub
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Gallery-DL Support"
|
#Region "Gallery-DL Support"
|
||||||
|
Private Structure GDLURL : Implements IRegExCreator
|
||||||
|
Friend URL As String
|
||||||
|
Friend BoardId As String
|
||||||
|
Public Shared Widening Operator CType(ByVal u As String) As GDLURL
|
||||||
|
Return New GDLURL With {.URL = u}
|
||||||
|
End Operator
|
||||||
|
Public Shared Widening Operator CType(ByVal u As GDLURL) As String
|
||||||
|
Return u.URL
|
||||||
|
End Operator
|
||||||
|
Private Function CreateFromArray(ByVal ParamsArray() As String) As Object Implements IRegExCreator.CreateFromArray
|
||||||
|
If ParamsArray.ListExists(2) Then
|
||||||
|
Dim u$ = ParamsArray(0).StringTrim.StringTrimEnd("/"), u2$
|
||||||
|
If Not u.IsEmptyString Then
|
||||||
|
u2 = ParamsArray(1).StringTrim
|
||||||
|
If Not u2.IsEmptyString AndAlso u2.StartsWith("GET", StringComparison.OrdinalIgnoreCase) Then
|
||||||
|
u2 = u2.Remove(0, 3).StringTrim.StringTrimStart("/")
|
||||||
|
If Not u2.IsEmptyString Then URL = $"{u}/{u2}"
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
Return Me
|
||||||
|
End Function
|
||||||
|
Public Shared Operator =(ByVal x As GDLURL, ByVal y As GDLURL) As Boolean
|
||||||
|
Return x.URL = y.URL
|
||||||
|
End Operator
|
||||||
|
Public Shared Operator <>(ByVal x As GDLURL, ByVal y As GDLURL) As Boolean
|
||||||
|
Return Not x.URL = y.URL
|
||||||
|
End Operator
|
||||||
|
Public Overrides Function ToString() As String
|
||||||
|
Return URL
|
||||||
|
End Function
|
||||||
|
Public Overrides Function Equals(ByVal Obj As Object) As Boolean
|
||||||
|
Return URL = CType(Obj, String)
|
||||||
|
End Function
|
||||||
|
End Structure
|
||||||
Private Class GDLBatch : Inherits GDL.GDLBatch
|
Private Class GDLBatch : Inherits GDL.GDLBatch
|
||||||
Private ReadOnly Property Source As UserData
|
Private ReadOnly Property Source As UserData
|
||||||
Private ReadOnly IsBoardsRequested As Boolean
|
Private ReadOnly IsBoardsRequested As Boolean
|
||||||
@@ -289,14 +379,30 @@ Namespace API.Pinterest
|
|||||||
End If
|
End If
|
||||||
End Function
|
End Function
|
||||||
End Class
|
End Class
|
||||||
Private Function GetDataFromGalleryDL(ByVal URL As String, ByVal IsBoardsRequested As Boolean, ByVal Token As CancellationToken) As List(Of String)
|
Private Function GetDataFromGalleryDL(ByVal URL As String, ByVal IsBoardsRequested As Boolean, ByVal Token As CancellationToken) As List(Of GDLURL)
|
||||||
Dim command$ = $"""{Settings.GalleryDLFile.File}"" --verbose --simulate "
|
Dim command$ = $"""{Settings.GalleryDLFile.File}"" --verbose --simulate "
|
||||||
Try
|
Try
|
||||||
If Not URL.IsEmptyString Then
|
If Not URL.IsEmptyString Then
|
||||||
|
Dim urls As New List(Of GDLURL)
|
||||||
|
Dim u As GDLURL
|
||||||
|
Dim s$ = String.Empty
|
||||||
If MySettings.CookiesNetscapeFile.Exists Then command &= $"--cookies ""{MySettings.CookiesNetscapeFile}"" "
|
If MySettings.CookiesNetscapeFile.Exists Then command &= $"--cookies ""{MySettings.CookiesNetscapeFile}"" "
|
||||||
command &= URL
|
command &= URL
|
||||||
Using batch As New GDLBatch(Me, IsBoardsRequested, Token)
|
Using batch As New GDLBatch(Me, IsBoardsRequested, Token)
|
||||||
Return GetUrlsFromGalleryDl(batch, command)
|
With batch
|
||||||
|
.Execute(command)
|
||||||
|
If .ErrorOutputData.Count > 0 Then
|
||||||
|
For Each eValue$ In .ErrorOutputData
|
||||||
|
s = CStr(RegexReplace(eValue, SubBoardRegEx)).IfNullOrEmpty(s)
|
||||||
|
u = RegexFields(Of GDLURL)(eValue, {GdlUrlPattern}, {1, 2}, EDP.ReturnValue).ListIfNothing.FirstOrDefault
|
||||||
|
If Not u.URL.IsEmptyString Then
|
||||||
|
If Not s.IsEmptyString Then u.BoardId = s
|
||||||
|
urls.Add(u)
|
||||||
|
End If
|
||||||
|
Next
|
||||||
|
Return urls
|
||||||
|
End If
|
||||||
|
End With
|
||||||
End Using
|
End Using
|
||||||
End If
|
End If
|
||||||
Return Nothing
|
Return Nothing
|
||||||
|
|||||||
@@ -36,11 +36,12 @@ Namespace API.PornHub
|
|||||||
Friend ReadOnly Regex_Gif_UrlName As RParams = RParams.DMS("""name"":.*?""([^""]*)""[^\}]+?""contentUrl"":.*?""([^""]+)""", 0, RegexReturn.ListByMatch, EDP.ReturnValue)
|
Friend ReadOnly Regex_Gif_UrlName As RParams = RParams.DMS("""name"":.*?""([^""]*)""[^\}]+?""contentUrl"":.*?""([^""]+)""", 0, RegexReturn.ListByMatch, EDP.ReturnValue)
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Declarations photo"
|
#Region "Declarations photo"
|
||||||
Friend ReadOnly Regex_Photo_ModelHub_PhotoBlocks As RParams = RParams.DM("var PHOTOS_ARRAY_(\d+) = \{[\r\n\s]*?(urls:.*?\[[^]]*\])", 0, RegexReturn.List, EDP.ReturnValue)
|
|
||||||
Friend ReadOnly Regex_Photo_PornHub_PhotoBlocks As RParams = RParams.DM("photoAlbumListContainer[\r\n\s\S]+?title=""([^""]+)""[\r\n\s\S]+?a href=""(/album/\d+)""", 0, RegexReturn.List)
|
Friend ReadOnly Regex_Photo_PornHub_PhotoBlocks As RParams = RParams.DM("photoAlbumListContainer[\r\n\s\S]+?title=""([^""]+)""[\r\n\s\S]+?a href=""(/album/\d+)""", 0, RegexReturn.List)
|
||||||
Friend ReadOnly Regex_Photo_PornHub_AlbumPhotoArr As RParams = RParams.DMS("\<a href=""(/photo/\d+)""", 1, RegexReturn.List, EDP.ReturnValue,
|
Friend ReadOnly Regex_Photo_PornHub_PhotoBlocks2 As RParams = RParams.DM("albumInfoTitle"" href=""([^""]+)""\>([^\<]+)", 0, RegexReturn.List)
|
||||||
|
Friend ReadOnly Regex_Photo_PornHub_AlbumPhotoArr As RParams = RParams.DMS("href=""(/photo/\d+)""", 1, RegexReturn.List, EDP.ReturnValue,
|
||||||
CType(Function(Input$) If(Input.IsEmptyString, String.Empty, $"https://www.pornhub.com{Input.Trim}"), Func(Of String, String)))
|
CType(Function(Input$) If(Input.IsEmptyString, String.Empty, $"https://www.pornhub.com{Input.Trim}"), Func(Of String, String)))
|
||||||
Friend ReadOnly Regex_Photo_PornHub_SinglePhoto As RParams = RParams.DMS("(?<!thumbImage.+?)<img src=""(https://[^""]+\d+[^""]+)""", 1, EDP.ReturnValue)
|
Friend ReadOnly Regex_Photo_PornHub_SinglePhoto As RParams = RParams.DM("data-image=""([^""]+)""\s*src=""([^""]+)""", 0, RegexReturn.ListByMatch, EDP.ReturnValue)
|
||||||
|
Friend ReadOnly Regex_Photo_PornHub_SinglePhoto2 As RParams = RParams.DMS("image:src"" content=""([^""]+)""", 1, EDP.ReturnValue)
|
||||||
Friend ReadOnly Regex_Photo_File As RParams = RParams.DM("\d+\.[\w]{3,4}", 0, EDP.ReturnValue)
|
Friend ReadOnly Regex_Photo_File As RParams = RParams.DM("\d+\.[\w]{3,4}", 0, EDP.ReturnValue)
|
||||||
#End Region
|
#End Region
|
||||||
End Module
|
End Module
|
||||||
|
|||||||
@@ -29,12 +29,11 @@ Namespace API.PornHub
|
|||||||
Friend ReadOnly Property DownloadGifs As PropertyValue
|
Friend ReadOnly Property DownloadGifs As PropertyValue
|
||||||
<PropertyOption(ControlText:="Download GIFs as mp4", ControlToolTip:="Download gifs in 'mp4' format instead of native 'webm'"), PXML, PClonable>
|
<PropertyOption(ControlText:="Download GIFs as mp4", ControlToolTip:="Download gifs in 'mp4' format instead of native 'webm'"), PXML, PClonable>
|
||||||
Friend ReadOnly Property DownloadGifsAsMp4 As PropertyValue
|
Friend ReadOnly Property DownloadGifsAsMp4 As PropertyValue
|
||||||
<PropertyOption(ControlText:="Photo ModelHub only",
|
|
||||||
ControlToolTip:="Download photo only from ModelHub. Prornstar photos hosted on PornHub itself will not be downloaded." & vbCr &
|
|
||||||
"Attention! Downloading photos hosted on PornHub is a very heavy job."), PXML, PClonable>
|
|
||||||
Friend ReadOnly Property DownloadPhotoOnlyFromModelHub As PropertyValue
|
|
||||||
<PropertyOption(ControlText:=DeclaredNames.SavedPostsUserNameCaption, ControlToolTip:=DeclaredNames.SavedPostsUserNameToolTip), PXML, PClonable(Clone:=False)>
|
<PropertyOption(ControlText:=DeclaredNames.SavedPostsUserNameCaption, ControlToolTip:=DeclaredNames.SavedPostsUserNameToolTip), PXML, PClonable(Clone:=False)>
|
||||||
Friend ReadOnly Property SavedPostsUserName As PropertyValue
|
Friend ReadOnly Property SavedPostsUserName As PropertyValue
|
||||||
|
<DoNotUse> Friend Overrides Property DownloadText As PropertyValue
|
||||||
|
<DoNotUse> Friend Overrides Property DownloadTextPosts As PropertyValue
|
||||||
|
<DoNotUse> Friend Overrides Property DownloadTextSpecialFolder As PropertyValue
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Initializer"
|
#Region "Initializer"
|
||||||
Friend Sub New(ByVal AccName As String, ByVal Temp As Boolean)
|
Friend Sub New(ByVal AccName As String, ByVal Temp As Boolean)
|
||||||
@@ -48,7 +47,6 @@ Namespace API.PornHub
|
|||||||
DownloadFavorite = New PropertyValue(False)
|
DownloadFavorite = New PropertyValue(False)
|
||||||
DownloadGifsAsMp4 = New PropertyValue(True)
|
DownloadGifsAsMp4 = New PropertyValue(True)
|
||||||
DownloadGifs = New PropertyValue(CInt(CheckState.Indeterminate), GetType(Integer))
|
DownloadGifs = New PropertyValue(CInt(CheckState.Indeterminate), GetType(Integer))
|
||||||
DownloadPhotoOnlyFromModelHub = New PropertyValue(True)
|
|
||||||
SavedPostsUserName = New PropertyValue(String.Empty, GetType(String))
|
SavedPostsUserName = New PropertyValue(String.Empty, GetType(String))
|
||||||
|
|
||||||
_SubscriptionsAllowed = True
|
_SubscriptionsAllowed = True
|
||||||
|
|||||||
@@ -20,15 +20,12 @@ Namespace API.PornHub
|
|||||||
#Region "Declarations"
|
#Region "Declarations"
|
||||||
#Region "XML names"
|
#Region "XML names"
|
||||||
Private Const Name_PersonType As String = "PersonType"
|
Private Const Name_PersonType As String = "PersonType"
|
||||||
Private Const Name_NameTrue As String = "NameTrue"
|
|
||||||
Private Const Name_PhotoPageModel As String = "PhotoPageModel"
|
|
||||||
Private Const Name_DownloadUHD As String = "DownloadUHD"
|
Private Const Name_DownloadUHD As String = "DownloadUHD"
|
||||||
Private Const Name_DownloadUploaded As String = "DownloadUploaded"
|
Private Const Name_DownloadUploaded As String = "DownloadUploaded"
|
||||||
Private Const Name_DownloadTagged As String = "DownloadTagged"
|
Private Const Name_DownloadTagged As String = "DownloadTagged"
|
||||||
Private Const Name_DownloadPrivate As String = "DownloadPrivate"
|
Private Const Name_DownloadPrivate As String = "DownloadPrivate"
|
||||||
Private Const Name_DownloadFavorite As String = "DownloadFavorite"
|
Private Const Name_DownloadFavorite As String = "DownloadFavorite"
|
||||||
Private Const Name_DownloadGifs As String = "DownloadGifs"
|
Private Const Name_DownloadGifs As String = "DownloadGifs"
|
||||||
Private Const Name_DownloadPhotoOnlyFromModelHub As String = "DownloadPhotoOnlyFromModelHub"
|
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Structures"
|
#Region "Structures"
|
||||||
Private Structure FlashVar : Implements IRegExCreator
|
Private Structure FlashVar : Implements IRegExCreator
|
||||||
@@ -98,11 +95,6 @@ Namespace API.PornHub
|
|||||||
End Structure
|
End Structure
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Enums"
|
#Region "Enums"
|
||||||
Private Enum PhotoPageModels As Integer
|
|
||||||
Undefined = 0
|
|
||||||
PornHubPage = 1
|
|
||||||
ModelHubPage = 2
|
|
||||||
End Enum
|
|
||||||
Private Enum VideoTypes
|
Private Enum VideoTypes
|
||||||
Undefined
|
Undefined
|
||||||
Uploaded
|
Uploaded
|
||||||
@@ -121,7 +113,6 @@ Namespace API.PornHub
|
|||||||
#End Region
|
#End Region
|
||||||
#Region "Person"
|
#Region "Person"
|
||||||
Friend Property PersonType As String
|
Friend Property PersonType As String
|
||||||
Friend Property NameTrue As String
|
|
||||||
Friend Overrides Property FriendlyName As String
|
Friend Overrides Property FriendlyName As String
|
||||||
Get
|
Get
|
||||||
If _FriendlyName.IsEmptyString Then Return NameTrue Else Return _FriendlyName
|
If _FriendlyName.IsEmptyString Then Return NameTrue Else Return _FriendlyName
|
||||||
@@ -137,14 +128,12 @@ Namespace API.PornHub
|
|||||||
Return IsUser Or SiteMode = SiteModes.Playlists
|
Return IsUser Or SiteMode = SiteModes.Playlists
|
||||||
End Get
|
End Get
|
||||||
End Property
|
End Property
|
||||||
Private Property PhotoPageModel As PhotoPageModels = PhotoPageModels.Undefined
|
|
||||||
Friend Property DownloadUHD As Boolean = False
|
Friend Property DownloadUHD As Boolean = False
|
||||||
Friend Property DownloadUploaded As Boolean = True
|
Friend Property DownloadUploaded As Boolean = True
|
||||||
Friend Property DownloadTagged As Boolean = False
|
Friend Property DownloadTagged As Boolean = False
|
||||||
Friend Property DownloadPrivate As Boolean = False
|
Friend Property DownloadPrivate As Boolean = False
|
||||||
Friend Property DownloadFavorite As Boolean = False
|
Friend Property DownloadFavorite As Boolean = False
|
||||||
Friend Property DownloadGifs As Boolean
|
Friend Property DownloadGifs As Boolean
|
||||||
Friend Property DownloadPhotoOnlyFromModelHub As Boolean = True
|
|
||||||
Friend Overrides ReadOnly Property IsUser As Boolean
|
Friend Overrides ReadOnly Property IsUser As Boolean
|
||||||
Get
|
Get
|
||||||
Return SiteMode = SiteModes.User
|
Return SiteMode = SiteModes.User
|
||||||
@@ -182,7 +171,6 @@ Namespace API.PornHub
|
|||||||
DownloadPrivate = .DownloadPrivate
|
DownloadPrivate = .DownloadPrivate
|
||||||
DownloadFavorite = .DownloadFavorite
|
DownloadFavorite = .DownloadFavorite
|
||||||
DownloadGifs = .DownloadGifs
|
DownloadGifs = .DownloadGifs
|
||||||
DownloadPhotoOnlyFromModelHub = .DownloadPhotoOnlyFromModelHub
|
|
||||||
QueryString = .QueryString
|
QueryString = .QueryString
|
||||||
End With
|
End With
|
||||||
End If
|
End If
|
||||||
@@ -207,7 +195,7 @@ Namespace API.PornHub
|
|||||||
If Not Force OrElse (Not IsUser AndAlso Not SiteMode = SiteModes.Playlists AndAlso Not NewUrl.IsEmptyString AndAlso MyFileSettings.Exists) Then
|
If Not Force OrElse (Not IsUser AndAlso Not SiteMode = SiteModes.Playlists AndAlso Not NewUrl.IsEmptyString AndAlso MyFileSettings.Exists) Then
|
||||||
Dim eObj As Plugin.ExchangeOptions = Nothing
|
Dim eObj As Plugin.ExchangeOptions = Nothing
|
||||||
If Force Then eObj = MySettings.IsMyUser(NewUrl)
|
If Force Then eObj = MySettings.IsMyUser(NewUrl)
|
||||||
If (Force And Not eObj.UserName.IsEmptyString) Or (Not Force And Not Name.IsEmptyString And NameTrue.IsEmptyString) Then
|
If (Force And Not eObj.UserName.IsEmptyString) Or (Not Force And Not Name.IsEmptyString And NameTrue(True).IsEmptyString) Then
|
||||||
If Not If(Force, eObj.Options, Options).IsEmptyString Then
|
If Not If(Force, eObj.Options, Options).IsEmptyString Then
|
||||||
If (IsUser Or SiteMode = SiteModes.Playlists) And Force Then
|
If (IsUser Or SiteMode = SiteModes.Playlists) And Force Then
|
||||||
Return False
|
Return False
|
||||||
@@ -244,29 +232,23 @@ Namespace API.PornHub
|
|||||||
With Container
|
With Container
|
||||||
If Loading Then
|
If Loading Then
|
||||||
PersonType = .Value(Name_PersonType)
|
PersonType = .Value(Name_PersonType)
|
||||||
NameTrue = .Value(Name_NameTrue)
|
|
||||||
PhotoPageModel = .Value(Name_PhotoPageModel).FromXML(Of Integer)(PhotoPageModels.Undefined)
|
|
||||||
DownloadUHD = .Value(Name_DownloadUHD).FromXML(Of Boolean)(False)
|
DownloadUHD = .Value(Name_DownloadUHD).FromXML(Of Boolean)(False)
|
||||||
DownloadUploaded = .Value(Name_DownloadUploaded).FromXML(Of Boolean)(True)
|
DownloadUploaded = .Value(Name_DownloadUploaded).FromXML(Of Boolean)(True)
|
||||||
DownloadTagged = .Value(Name_DownloadTagged).FromXML(Of Boolean)(False)
|
DownloadTagged = .Value(Name_DownloadTagged).FromXML(Of Boolean)(False)
|
||||||
DownloadPrivate = .Value(Name_DownloadPrivate).FromXML(Of Boolean)(False)
|
DownloadPrivate = .Value(Name_DownloadPrivate).FromXML(Of Boolean)(False)
|
||||||
DownloadFavorite = .Value(Name_DownloadFavorite).FromXML(Of Boolean)(False)
|
DownloadFavorite = .Value(Name_DownloadFavorite).FromXML(Of Boolean)(False)
|
||||||
DownloadGifs = .Value(Name_DownloadGifs).FromXML(Of Integer)(False)
|
DownloadGifs = .Value(Name_DownloadGifs).FromXML(Of Integer)(False)
|
||||||
DownloadPhotoOnlyFromModelHub = .Value(Name_DownloadPhotoOnlyFromModelHub).FromXML(Of Boolean)(True)
|
|
||||||
SiteMode = .Value(Name_SiteMode).FromXML(Of Integer)(SiteModes.User)
|
SiteMode = .Value(Name_SiteMode).FromXML(Of Integer)(SiteModes.User)
|
||||||
UpdateUserOptions()
|
UpdateUserOptions()
|
||||||
Else
|
Else
|
||||||
If UpdateUserOptions() Then .Value(Name_LabelsName) = LabelsString
|
If UpdateUserOptions() Then .Value(Name_LabelsName) = LabelsString : .Value(Name_TrueName) = NameTrue(True)
|
||||||
.Add(Name_PersonType, PersonType)
|
.Add(Name_PersonType, PersonType)
|
||||||
.Add(Name_NameTrue, NameTrue)
|
|
||||||
.Add(Name_PhotoPageModel, CInt(PhotoPageModel))
|
|
||||||
.Add(Name_DownloadUHD, DownloadUHD.BoolToInteger)
|
.Add(Name_DownloadUHD, DownloadUHD.BoolToInteger)
|
||||||
.Add(Name_DownloadUploaded, DownloadUploaded.BoolToInteger)
|
.Add(Name_DownloadUploaded, DownloadUploaded.BoolToInteger)
|
||||||
.Add(Name_DownloadTagged, DownloadTagged.BoolToInteger)
|
.Add(Name_DownloadTagged, DownloadTagged.BoolToInteger)
|
||||||
.Add(Name_DownloadPrivate, DownloadPrivate.BoolToInteger)
|
.Add(Name_DownloadPrivate, DownloadPrivate.BoolToInteger)
|
||||||
.Add(Name_DownloadFavorite, DownloadFavorite.BoolToInteger)
|
.Add(Name_DownloadFavorite, DownloadFavorite.BoolToInteger)
|
||||||
.Add(Name_DownloadGifs, DownloadGifs.BoolToInteger)
|
.Add(Name_DownloadGifs, DownloadGifs.BoolToInteger)
|
||||||
.Add(Name_DownloadPhotoOnlyFromModelHub, DownloadPhotoOnlyFromModelHub.BoolToInteger)
|
|
||||||
.Add(Name_SiteMode, CInt(SiteMode))
|
.Add(Name_SiteMode, CInt(SiteMode))
|
||||||
|
|
||||||
'Debug.WriteLine(GetNonUserUrl(0))
|
'Debug.WriteLine(GetNonUserUrl(0))
|
||||||
@@ -283,6 +265,7 @@ Namespace API.PornHub
|
|||||||
Private _PageVideosRepeat As Integer = 0
|
Private _PageVideosRepeat As Integer = 0
|
||||||
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
|
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
|
||||||
Try
|
Try
|
||||||
|
UpdateM3U8URLS = False
|
||||||
PlaylistToken = String.Empty
|
PlaylistToken = String.Empty
|
||||||
Responser.ResetStatus()
|
Responser.ResetStatus()
|
||||||
_PageVideosRepeat = 0
|
_PageVideosRepeat = 0
|
||||||
@@ -295,7 +278,6 @@ Namespace API.PornHub
|
|||||||
|
|
||||||
Dim limit% = If(DownloadTopCount, -1)
|
Dim limit% = If(DownloadTopCount, -1)
|
||||||
If DownloadVideos Then
|
If DownloadVideos Then
|
||||||
|
|
||||||
If SiteMode = SiteModes.Playlists Then
|
If SiteMode = SiteModes.Playlists Then
|
||||||
Responser.Mode = Responser.Modes.Default
|
Responser.Mode = Responser.Modes.Default
|
||||||
GetPlaylistToken(Token)
|
GetPlaylistToken(Token)
|
||||||
@@ -519,25 +501,12 @@ Namespace API.PornHub
|
|||||||
Dim pFile$ = RegexReplace(URL, Regex_Photo_File)
|
Dim pFile$ = RegexReplace(URL, Regex_Photo_File)
|
||||||
If Not pFile.IsEmptyString Then Return New SFile(pFile) Else Return File
|
If Not pFile.IsEmptyString Then Return New SFile(pFile) Else Return File
|
||||||
End Function
|
End Function
|
||||||
Private Const PhotoUrlPattern_ModelHub As String = "https://www.modelhub.com/{0}/photos"
|
|
||||||
Private Const PhotoUrlPattern_PornHub As String = "https://www.pornhub.com/{0}/{1}/photos"
|
Private Const PhotoUrlPattern_PornHub As String = "https://www.pornhub.com/{0}/{1}/photos"
|
||||||
Private Sub DownloadUserPhotos(ByVal Token As CancellationToken)
|
Private Sub DownloadUserPhotos(ByVal Token As CancellationToken)
|
||||||
Try
|
Try
|
||||||
If IsSavedPosts Then
|
If IsSavedPosts Then
|
||||||
DownloadUserPhotos_SavedPosts(Token)
|
DownloadUserPhotos_SavedPosts(Token)
|
||||||
ElseIf PersonType = PersonTypeModel Then
|
Else
|
||||||
If PhotoPageModel = PhotoPageModels.Undefined Then
|
|
||||||
If DownloadUserPhotos_ModelHub(Token) Then PhotoPageModel = PhotoPageModels.ModelHubPage
|
|
||||||
ThrowAny(Token)
|
|
||||||
If PhotoPageModel = PhotoPageModels.Undefined AndAlso Not DownloadPhotoOnlyFromModelHub AndAlso
|
|
||||||
DownloadUserPhotos_PornHub(Token) Then PhotoPageModel = PhotoPageModels.PornHubPage
|
|
||||||
Else
|
|
||||||
Select Case PhotoPageModel
|
|
||||||
Case PhotoPageModels.ModelHubPage : DownloadUserPhotos_ModelHub(Token)
|
|
||||||
Case PhotoPageModels.PornHubPage : If Not DownloadPhotoOnlyFromModelHub Then DownloadUserPhotos_PornHub(Token)
|
|
||||||
End Select
|
|
||||||
End If
|
|
||||||
ElseIf Not DownloadPhotoOnlyFromModelHub Then
|
|
||||||
DownloadUserPhotos_PornHub(Token)
|
DownloadUserPhotos_PornHub(Token)
|
||||||
End If
|
End If
|
||||||
ThrowAny(Token)
|
ThrowAny(Token)
|
||||||
@@ -545,48 +514,6 @@ Namespace API.PornHub
|
|||||||
ProcessException(ex, Token, "photos downloading error")
|
ProcessException(ex, Token, "photos downloading error")
|
||||||
End Try
|
End Try
|
||||||
End Sub
|
End Sub
|
||||||
Private Function DownloadUserPhotos_ModelHub(ByVal Token As CancellationToken) As Boolean
|
|
||||||
Dim URL$ = String.Empty
|
|
||||||
Try
|
|
||||||
Dim j As EContainer
|
|
||||||
Dim jErr As New ErrorsDescriber(EDP.SendToLog + EDP.ReturnValue)
|
|
||||||
Dim albumName$
|
|
||||||
If PersonType = PersonTypeModel Then
|
|
||||||
URL = String.Format(PhotoUrlPattern_ModelHub, NameTrue)
|
|
||||||
Dim r$ = Responser.GetResponse(URL)
|
|
||||||
If Not r.IsEmptyString Then
|
|
||||||
Dim l As List(Of PhotoBlock) = RegexFields(Of PhotoBlock)(r, {Regex_Photo_ModelHub_PhotoBlocks}, {1, 2}, EDP.ReturnValue)
|
|
||||||
If l.ListExists Then l.RemoveAll(Function(ll) ll.Data.IsEmptyString)
|
|
||||||
If l.ListExists Then
|
|
||||||
ProgressPre.ChangeMax(l.Count)
|
|
||||||
Dim albumRegex As RParams = RParams.DMS("", 1, EDP.ReturnValue)
|
|
||||||
For Each block As PhotoBlock In l
|
|
||||||
ProgressPre.Perform()
|
|
||||||
If Not _TempPostsList.Contains(block.AlbumID) Then _TempPostsList.Add(block.AlbumID) Else Continue For
|
|
||||||
albumRegex.Pattern = "<li id=""" & block.AlbumID & """ class=""modelBox"">[\r\n\s]*?<div class=""modelPhoto"">[\r\n\s]*?\<[^\>]*?alt=""([^""]*)"""
|
|
||||||
albumName = StringTrim(RegexReplace(r, albumRegex))
|
|
||||||
If albumName.IsEmptyString Then albumName = block.AlbumID
|
|
||||||
j = JsonDocument.Parse("{" & block.Data & "}", jErr)
|
|
||||||
If Not j Is Nothing Then
|
|
||||||
If If(j("urls")?.Count, 0) > 0 Then
|
|
||||||
_TempMediaList.ListAddList(j("urls").Select(Function(jj) _
|
|
||||||
New UserMedia(jj.ItemF({0}).XmlIfNothingValue, UTypes.Picture) With {
|
|
||||||
.SpecialFolder = $"Albums\{albumName}\",
|
|
||||||
.File = CreatePhotoFile(.URL, .File)}), LNC)
|
|
||||||
End If
|
|
||||||
j.Dispose()
|
|
||||||
End If
|
|
||||||
Next
|
|
||||||
l.Clear()
|
|
||||||
End If
|
|
||||||
End If
|
|
||||||
End If
|
|
||||||
Return True
|
|
||||||
Catch ex As Exception
|
|
||||||
ThrowAny(Token)
|
|
||||||
Return False
|
|
||||||
End Try
|
|
||||||
End Function
|
|
||||||
Private Overloads Function DownloadUserPhotos_PornHub(ByVal Token As CancellationToken) As Boolean
|
Private Overloads Function DownloadUserPhotos_PornHub(ByVal Token As CancellationToken) As Boolean
|
||||||
Try
|
Try
|
||||||
Dim albumName$
|
Dim albumName$
|
||||||
@@ -594,6 +521,7 @@ Namespace API.PornHub
|
|||||||
Dim r$ = Responser.GetResponse(String.Format(PhotoUrlPattern_PornHub, PersonType, NameTrue))
|
Dim r$ = Responser.GetResponse(String.Format(PhotoUrlPattern_PornHub, PersonType, NameTrue))
|
||||||
If Not r.IsEmptyString Then
|
If Not r.IsEmptyString Then
|
||||||
Dim l As List(Of PhotoBlock) = RegexFields(Of PhotoBlock)(r, {Regex_Photo_PornHub_PhotoBlocks}, {2, 1}, EDP.ReturnValue)
|
Dim l As List(Of PhotoBlock) = RegexFields(Of PhotoBlock)(r, {Regex_Photo_PornHub_PhotoBlocks}, {2, 1}, EDP.ReturnValue)
|
||||||
|
l.ListAddList(RegexFields(Of PhotoBlock)(r, {Regex_Photo_PornHub_PhotoBlocks2}, {1, 2}, EDP.ReturnValue))
|
||||||
If l.ListExists Then l.RemoveAll(Function(ll) ll.AlbumID.IsEmptyString)
|
If l.ListExists Then l.RemoveAll(Function(ll) ll.AlbumID.IsEmptyString)
|
||||||
If l.ListExists Then
|
If l.ListExists Then
|
||||||
ProgressPre.ChangeMax(l.Count)
|
ProgressPre.ChangeMax(l.Count)
|
||||||
@@ -618,6 +546,14 @@ Namespace API.PornHub
|
|||||||
Return False
|
Return False
|
||||||
End Try
|
End Try
|
||||||
End Function
|
End Function
|
||||||
|
Private Function DownloadUserPhotos_PornHub_ParseSinglePhoto(ByVal r As String) As String
|
||||||
|
Dim url$ = String.Empty
|
||||||
|
With DirectCast(RegexReplace(r, Regex_Photo_PornHub_SinglePhoto), List(Of String))
|
||||||
|
If .ListExists(3) Then url = .Item(2).IfNullOrEmpty(.Item(1)).StringTrim
|
||||||
|
End With
|
||||||
|
If url.IsEmptyString Then url = RegexReplace(r, Regex_Photo_PornHub_SinglePhoto2)
|
||||||
|
Return url
|
||||||
|
End Function
|
||||||
Private Overloads Function DownloadUserPhotos_PornHub(ByVal Page As Integer, ByVal AlbumID As String, ByVal AlbumName As String,
|
Private Overloads Function DownloadUserPhotos_PornHub(ByVal Page As Integer, ByVal AlbumID As String, ByVal AlbumName As String,
|
||||||
ByVal Token As CancellationToken) As Boolean
|
ByVal Token As CancellationToken) As Boolean
|
||||||
Try
|
Try
|
||||||
@@ -633,7 +569,7 @@ Namespace API.PornHub
|
|||||||
Try
|
Try
|
||||||
r = Responser.GetResponse(url)
|
r = Responser.GetResponse(url)
|
||||||
If Not r.IsEmptyString Then
|
If Not r.IsEmptyString Then
|
||||||
url = RegexReplace(r, Regex_Photo_PornHub_SinglePhoto)
|
url = DownloadUserPhotos_PornHub_ParseSinglePhoto(r)
|
||||||
If Not url.IsEmptyString Then _
|
If Not url.IsEmptyString Then _
|
||||||
_TempMediaList.ListAddValue(New UserMedia(url, UTypes.Picture) With {
|
_TempMediaList.ListAddValue(New UserMedia(url, UTypes.Picture) With {
|
||||||
.SpecialFolder = $"Albums\{AlbumName}\",
|
.SpecialFolder = $"Albums\{AlbumName}\",
|
||||||
@@ -679,7 +615,7 @@ Namespace API.PornHub
|
|||||||
Try
|
Try
|
||||||
r = Responser.GetResponse(m.URL)
|
r = Responser.GetResponse(m.URL)
|
||||||
If Not r.IsEmptyString Then
|
If Not r.IsEmptyString Then
|
||||||
NewUrl = RegexReplace(r, Regex_Photo_PornHub_SinglePhoto)
|
NewUrl = DownloadUserPhotos_PornHub_ParseSinglePhoto(r)
|
||||||
If Not NewUrl.IsEmptyString Then
|
If Not NewUrl.IsEmptyString Then
|
||||||
m.URL = NewUrl
|
m.URL = NewUrl
|
||||||
pFile = RegexReplace(NewUrl, Regex_Photo_File)
|
pFile = RegexReplace(NewUrl, Regex_Photo_File)
|
||||||
@@ -852,11 +788,34 @@ Namespace API.PornHub
|
|||||||
End Sub
|
End Sub
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Download content"
|
#Region "Download content"
|
||||||
|
Private UpdateM3U8URLS As Boolean = False
|
||||||
|
Private UpdateM3U8URLS_Error As Boolean = False
|
||||||
Protected Overrides Sub DownloadContent(ByVal Token As CancellationToken)
|
Protected Overrides Sub DownloadContent(ByVal Token As CancellationToken)
|
||||||
DownloadContentDefault(Token)
|
Try : DownloadContentDefault(Token) : Finally : UpdateM3U8URLS = False : End Try
|
||||||
End Sub
|
End Sub
|
||||||
Protected Overrides Function DownloadM3U8(ByVal URL As String, ByVal Media As UserMedia, ByVal DestinationFile As SFile, ByVal Token As CancellationToken) As SFile
|
Protected Overloads Overrides Function DownloadM3U8(ByVal URL As String, ByVal Media As UserMedia, ByVal DestinationFile As SFile,
|
||||||
Return M3U8.Download(URL, Responser, DestinationFile, DownloadUHD, Token, Progress, Not IsSingleObjectDownload)
|
ByVal Token As CancellationToken) As SFile
|
||||||
|
UpdateM3U8URLS_Error = False
|
||||||
|
Return DownloadM3U8(URL, Media, DestinationFile, Token, UpdateM3U8URLS)
|
||||||
|
End Function
|
||||||
|
Private Overloads Function DownloadM3U8(ByVal URL As String, ByVal Media As UserMedia, ByVal DestinationFile As SFile,
|
||||||
|
ByVal Token As CancellationToken, ByVal Second As Boolean) As SFile
|
||||||
|
Try
|
||||||
|
If Second Then
|
||||||
|
Dim r$ = Responser.Curl(Media.URL_BASE,, EDP.ReturnValue)
|
||||||
|
If Not r.IsEmptyString Then Media.URL = CreateVideoURL(r).IfNullOrEmpty(URL) : URL = Media.URL
|
||||||
|
End If
|
||||||
|
Dim f As SFile = M3U8.Download(URL, Responser, DestinationFile, DownloadUHD, Token, Progress, Not IsSingleObjectDownload)
|
||||||
|
If Not f.Exists And Not Second Then UpdateM3U8URLS = True : f = DownloadM3U8(URL, Media, DestinationFile, Token, True)
|
||||||
|
Return f
|
||||||
|
Catch ex As Exception
|
||||||
|
If Not UpdateM3U8URLS_Error Then
|
||||||
|
UpdateM3U8URLS_Error = True
|
||||||
|
Thread.Sleep(1000)
|
||||||
|
Return DownloadM3U8(URL, Media, DestinationFile, Token, True)
|
||||||
|
End If
|
||||||
|
Return Nothing
|
||||||
|
End Try
|
||||||
End Function
|
End Function
|
||||||
#End Region
|
#End Region
|
||||||
#Region "CreateVideoURL"
|
#Region "CreateVideoURL"
|
||||||
@@ -953,6 +912,7 @@ Namespace API.PornHub
|
|||||||
#End Region
|
#End Region
|
||||||
#Region "DownloadSingleObject"
|
#Region "DownloadSingleObject"
|
||||||
Protected Overrides Sub DownloadSingleObject_GetPosts(ByVal Data As IYouTubeMediaContainer, ByVal Token As CancellationToken)
|
Protected Overrides Sub DownloadSingleObject_GetPosts(ByVal Data As IYouTubeMediaContainer, ByVal Token As CancellationToken)
|
||||||
|
UpdateM3U8URLS = False
|
||||||
_TempMediaList.Add(New UserMedia(Data.URL, UTypes.VideoPre))
|
_TempMediaList.Add(New UserMedia(Data.URL, UTypes.VideoPre))
|
||||||
ReparseVideo(Token, True, Data)
|
ReparseVideo(Token, True, Data)
|
||||||
End Sub
|
End Sub
|
||||||
|
|||||||
@@ -21,8 +21,6 @@ Namespace API.PornHub
|
|||||||
Friend Property DownloadFavorite As Boolean
|
Friend Property DownloadFavorite As Boolean
|
||||||
<PSetting(Caption:="Download gifs")>
|
<PSetting(Caption:="Download gifs")>
|
||||||
Friend Property DownloadGifs As Boolean
|
Friend Property DownloadGifs As Boolean
|
||||||
<PSetting(NameOf(SiteSettings.DownloadPhotoOnlyFromModelHub), NameOf(MySettings), Caption:="Download photo only from ModelHub")>
|
|
||||||
Friend Property DownloadPhotoOnlyFromModelHub As Boolean
|
|
||||||
Private ReadOnly Property MySettings As SiteSettings
|
Private ReadOnly Property MySettings As SiteSettings
|
||||||
Friend Sub New(ByVal u As UserData)
|
Friend Sub New(ByVal u As UserData)
|
||||||
DownloadUHD = u.DownloadUHD
|
DownloadUHD = u.DownloadUHD
|
||||||
@@ -31,7 +29,6 @@ Namespace API.PornHub
|
|||||||
DownloadPrivate = u.DownloadPrivate
|
DownloadPrivate = u.DownloadPrivate
|
||||||
DownloadFavorite = u.DownloadFavorite
|
DownloadFavorite = u.DownloadFavorite
|
||||||
DownloadGifs = u.DownloadGifs
|
DownloadGifs = u.DownloadGifs
|
||||||
DownloadPhotoOnlyFromModelHub = u.DownloadPhotoOnlyFromModelHub
|
|
||||||
QueryString = u.QueryString
|
QueryString = u.QueryString
|
||||||
MySettings = u.HOST.Source
|
MySettings = u.HOST.Source
|
||||||
End Sub
|
End Sub
|
||||||
@@ -43,7 +40,6 @@ Namespace API.PornHub
|
|||||||
DownloadPrivate = s.DownloadPrivate.Value
|
DownloadPrivate = s.DownloadPrivate.Value
|
||||||
DownloadFavorite = s.DownloadFavorite.Value
|
DownloadFavorite = s.DownloadFavorite.Value
|
||||||
DownloadGifs = Not v = CheckState.Unchecked
|
DownloadGifs = Not v = CheckState.Unchecked
|
||||||
DownloadPhotoOnlyFromModelHub = s.DownloadPhotoOnlyFromModelHub.Value
|
|
||||||
MySettings = s
|
MySettings = s
|
||||||
End Sub
|
End Sub
|
||||||
End Class
|
End Class
|
||||||
|
|||||||
@@ -88,14 +88,22 @@ Namespace API.Reddit
|
|||||||
End Property
|
End Property
|
||||||
Friend Property ViewMode As View = View.New Implements IRedditView.ViewMode
|
Friend Property ViewMode As View = View.New Implements IRedditView.ViewMode
|
||||||
Friend Property ViewPeriod As Period = Period.All Implements IRedditView.ViewPeriod
|
Friend Property ViewPeriod As Period = Period.All Implements IRedditView.ViewPeriod
|
||||||
|
Friend Property DownloadText As Boolean = False Implements IRedditView.DownloadText
|
||||||
|
Friend Property DownloadTextPosts As Boolean = False Implements IRedditView.DownloadTextPosts
|
||||||
|
Friend Property DownloadTextSpecialFolder As Boolean = False Implements IRedditView.DownloadTextSpecialFolder
|
||||||
Friend Property RedGifsAccount As String = String.Empty Implements IRedditView.RedGifsAccount
|
Friend Property RedGifsAccount As String = String.Empty Implements IRedditView.RedGifsAccount
|
||||||
Friend Property RedditAccount As String = String.Empty Implements IRedditView.RedditAccount
|
Friend Property RedditAccount As String = String.Empty Implements IRedditView.RedditAccount
|
||||||
Friend Sub SetView(ByVal Options As IRedditView) Implements IRedditView.SetView
|
Friend Sub SetView(ByVal Options As IRedditView) Implements IRedditView.SetView
|
||||||
If Not Options Is Nothing Then
|
If Not Options Is Nothing Then
|
||||||
ViewMode = Options.ViewMode
|
With Options
|
||||||
ViewPeriod = Options.ViewPeriod
|
ViewMode = .ViewMode
|
||||||
RedditAccount = Options.RedditAccount
|
ViewPeriod = .ViewPeriod
|
||||||
RedGifsAccount = Options.RedGifsAccount
|
DownloadText = .DownloadText
|
||||||
|
DownloadTextPosts = .DownloadTextPosts
|
||||||
|
DownloadTextSpecialFolder = .DownloadTextSpecialFolder
|
||||||
|
RedditAccount = .RedditAccount
|
||||||
|
RedGifsAccount = .RedGifsAccount
|
||||||
|
End With
|
||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
#Region "Statistics support"
|
#Region "Statistics support"
|
||||||
|
|||||||
@@ -21,6 +21,6 @@ Namespace API.Reddit
|
|||||||
Friend ReadOnly UrlBasePattern As RParams = RParams.DM("(?<=/)([^/]+?\.[\w]{3,4})(?=(\?|\Z))", 0)
|
Friend ReadOnly UrlBasePattern As RParams = RParams.DM("(?<=/)([^/]+?\.[\w]{3,4})(?=(\?|\Z))", 0)
|
||||||
Friend ReadOnly VideoRegEx As RParams = RParams.DM("http.{0,1}://[^" & Chr(34) & "]+?mp4", 0)
|
Friend ReadOnly VideoRegEx As RParams = RParams.DM("http.{0,1}://[^" & Chr(34) & "]+?mp4", 0)
|
||||||
Private ReadOnly EUR_PROVIDER As New ANumbers(ANumbers.Cultures.EUR)
|
Private ReadOnly EUR_PROVIDER As New ANumbers(ANumbers.Cultures.EUR)
|
||||||
Friend ReadOnly UnixDate32ProviderReddit As New CustomProvider(Function(v, d, p, n, e) ADateTime.ParseUnix32(AConvert(Of Double)(v, EUR_PROVIDER, v), n, e))
|
<Obsolete("Use 'UnixDate32Provider'", True)> Friend ReadOnly UnixDate32ProviderReddit As New CustomProvider(Function(v, d, p, n, e) ADateTime.ParseUnix32(AConvert(Of Double)(v, EUR_PROVIDER, v), n, e))
|
||||||
End Module
|
End Module
|
||||||
End Namespace
|
End Namespace
|
||||||
@@ -12,6 +12,8 @@ Namespace API.Reddit
|
|||||||
[New] = 0
|
[New] = 0
|
||||||
Hot = 1
|
Hot = 1
|
||||||
Top = 2
|
Top = 2
|
||||||
|
Best = 3
|
||||||
|
Rising = 4
|
||||||
End Enum
|
End Enum
|
||||||
Enum Period As Integer
|
Enum Period As Integer
|
||||||
All = 0
|
All = 0
|
||||||
@@ -23,6 +25,9 @@ Namespace API.Reddit
|
|||||||
End Enum
|
End Enum
|
||||||
Property ViewMode As View
|
Property ViewMode As View
|
||||||
Property ViewPeriod As Period
|
Property ViewPeriod As Period
|
||||||
|
Property DownloadText As Boolean
|
||||||
|
Property DownloadTextPosts As Boolean
|
||||||
|
Property DownloadTextSpecialFolder As Boolean
|
||||||
Property RedGifsAccount As String
|
Property RedGifsAccount As String
|
||||||
Property RedditAccount As String
|
Property RedditAccount As String
|
||||||
Sub SetView(ByVal Options As IRedditView)
|
Sub SetView(ByVal Options As IRedditView)
|
||||||
@@ -34,14 +39,27 @@ Namespace API.Reddit
|
|||||||
Friend Const Name_RedditAccount As String = "RedditAccount"
|
Friend Const Name_RedditAccount As String = "RedditAccount"
|
||||||
Friend Property ViewMode As IRedditView.View Implements IRedditView.ViewMode
|
Friend Property ViewMode As IRedditView.View Implements IRedditView.ViewMode
|
||||||
Friend Property ViewPeriod As IRedditView.Period Implements IRedditView.ViewPeriod
|
Friend Property ViewPeriod As IRedditView.Period Implements IRedditView.ViewPeriod
|
||||||
|
Friend Property DownloadText As Boolean Implements IRedditView.DownloadText
|
||||||
|
Friend Property DownloadTextPosts As Boolean Implements IRedditView.DownloadTextPosts
|
||||||
|
Friend Property DownloadTextSpecialFolder As Boolean Implements IRedditView.DownloadTextSpecialFolder
|
||||||
Friend Property RedGifsAccount As String Implements IRedditView.RedGifsAccount
|
Friend Property RedGifsAccount As String Implements IRedditView.RedGifsAccount
|
||||||
Friend Property RedditAccount As String Implements IRedditView.RedditAccount
|
Friend Property RedditAccount As String Implements IRedditView.RedditAccount
|
||||||
|
Friend Sub New()
|
||||||
|
End Sub
|
||||||
|
Friend Sub New(ByVal Options As IRedditView)
|
||||||
|
SetView(Options)
|
||||||
|
End Sub
|
||||||
Friend Sub SetView(ByVal Options As IRedditView) Implements IRedditView.SetView
|
Friend Sub SetView(ByVal Options As IRedditView) Implements IRedditView.SetView
|
||||||
If Not Options Is Nothing Then
|
If Not Options Is Nothing Then
|
||||||
ViewMode = Options.ViewMode
|
With Options
|
||||||
ViewPeriod = Options.ViewPeriod
|
ViewMode = .ViewMode
|
||||||
RedGifsAccount = Options.RedGifsAccount
|
ViewPeriod = .ViewPeriod
|
||||||
RedditAccount = Options.RedditAccount
|
DownloadText = .DownloadText
|
||||||
|
DownloadTextPosts = .DownloadTextPosts
|
||||||
|
DownloadTextSpecialFolder = .DownloadTextSpecialFolder
|
||||||
|
RedGifsAccount = .RedGifsAccount
|
||||||
|
RedditAccount = .RedditAccount
|
||||||
|
End With
|
||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
End Class
|
End Class
|
||||||
|
|||||||
154
SCrawler/API/Reddit/RedditViewSettingsForm.Designer.vb
generated
@@ -22,17 +22,21 @@ Namespace API.Reddit
|
|||||||
Private components As System.ComponentModel.IContainer
|
Private components As System.ComponentModel.IContainer
|
||||||
<System.Diagnostics.DebuggerStepThrough()>
|
<System.Diagnostics.DebuggerStepThrough()>
|
||||||
Private Sub InitializeComponent()
|
Private Sub InitializeComponent()
|
||||||
|
Me.components = New System.ComponentModel.Container()
|
||||||
Dim CONTAINER_MAIN As System.Windows.Forms.ToolStripContainer
|
Dim CONTAINER_MAIN As System.Windows.Forms.ToolStripContainer
|
||||||
Dim TP_VIEW_MODE As System.Windows.Forms.TableLayoutPanel
|
Dim TP_VIEW_MODE As System.Windows.Forms.TableLayoutPanel
|
||||||
Dim LBL_VIEW_MODE As System.Windows.Forms.Label
|
Dim LBL_VIEW_MODE As System.Windows.Forms.Label
|
||||||
Dim LBL_PERIOD As System.Windows.Forms.Label
|
Dim LBL_PERIOD As System.Windows.Forms.Label
|
||||||
Dim ActionButton1 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
Dim ActionButton3 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||||
Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(RedditViewSettingsForm))
|
Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(RedditViewSettingsForm))
|
||||||
Dim ActionButton2 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
Dim ActionButton4 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||||
|
Dim TP_TEXT As System.Windows.Forms.TableLayoutPanel
|
||||||
Me.TP_MAIN = New System.Windows.Forms.TableLayoutPanel()
|
Me.TP_MAIN = New System.Windows.Forms.TableLayoutPanel()
|
||||||
Me.OPT_VIEW_MODE_NEW = New System.Windows.Forms.RadioButton()
|
Me.OPT_VIEW_MODE_NEW = New System.Windows.Forms.RadioButton()
|
||||||
Me.OPT_VIEW_MODE_HOT = New System.Windows.Forms.RadioButton()
|
Me.OPT_VIEW_MODE_HOT = New System.Windows.Forms.RadioButton()
|
||||||
Me.OPT_VIEW_MODE_TOP = New System.Windows.Forms.RadioButton()
|
Me.OPT_VIEW_MODE_TOP = New System.Windows.Forms.RadioButton()
|
||||||
|
Me.OPT_VIEW_MODE_BEST = New System.Windows.Forms.RadioButton()
|
||||||
|
Me.OPT_VIEW_MODE_RISING = New System.Windows.Forms.RadioButton()
|
||||||
Me.TP_PERIOD = New System.Windows.Forms.TableLayoutPanel()
|
Me.TP_PERIOD = New System.Windows.Forms.TableLayoutPanel()
|
||||||
Me.OPT_PERIOD_ALL = New System.Windows.Forms.RadioButton()
|
Me.OPT_PERIOD_ALL = New System.Windows.Forms.RadioButton()
|
||||||
Me.OPT_PERIOD_HOUR = New System.Windows.Forms.RadioButton()
|
Me.OPT_PERIOD_HOUR = New System.Windows.Forms.RadioButton()
|
||||||
@@ -42,10 +46,15 @@ Namespace API.Reddit
|
|||||||
Me.OPT_PERIOD_YEAR = New System.Windows.Forms.RadioButton()
|
Me.OPT_PERIOD_YEAR = New System.Windows.Forms.RadioButton()
|
||||||
Me.CMB_REDGIFS_ACC = New PersonalUtilities.Forms.Controls.ComboBoxExtended()
|
Me.CMB_REDGIFS_ACC = New PersonalUtilities.Forms.Controls.ComboBoxExtended()
|
||||||
Me.CMB_REDDIT_ACC = New PersonalUtilities.Forms.Controls.ComboBoxExtended()
|
Me.CMB_REDDIT_ACC = New PersonalUtilities.Forms.Controls.ComboBoxExtended()
|
||||||
|
Me.CH_TXT_DOWN_TXT = New System.Windows.Forms.CheckBox()
|
||||||
|
Me.CH_TXT_DOWN_POSTS = New System.Windows.Forms.CheckBox()
|
||||||
|
Me.TT_MAIN = New System.Windows.Forms.ToolTip(Me.components)
|
||||||
|
Me.CH_TXT_DOWN_SPEC_FOLDER = New System.Windows.Forms.CheckBox()
|
||||||
CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer()
|
CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer()
|
||||||
TP_VIEW_MODE = New System.Windows.Forms.TableLayoutPanel()
|
TP_VIEW_MODE = New System.Windows.Forms.TableLayoutPanel()
|
||||||
LBL_VIEW_MODE = New System.Windows.Forms.Label()
|
LBL_VIEW_MODE = New System.Windows.Forms.Label()
|
||||||
LBL_PERIOD = New System.Windows.Forms.Label()
|
LBL_PERIOD = New System.Windows.Forms.Label()
|
||||||
|
TP_TEXT = New System.Windows.Forms.TableLayoutPanel()
|
||||||
CONTAINER_MAIN.ContentPanel.SuspendLayout()
|
CONTAINER_MAIN.ContentPanel.SuspendLayout()
|
||||||
CONTAINER_MAIN.SuspendLayout()
|
CONTAINER_MAIN.SuspendLayout()
|
||||||
Me.TP_MAIN.SuspendLayout()
|
Me.TP_MAIN.SuspendLayout()
|
||||||
@@ -53,6 +62,7 @@ Namespace API.Reddit
|
|||||||
Me.TP_PERIOD.SuspendLayout()
|
Me.TP_PERIOD.SuspendLayout()
|
||||||
CType(Me.CMB_REDGIFS_ACC, System.ComponentModel.ISupportInitialize).BeginInit()
|
CType(Me.CMB_REDGIFS_ACC, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||||
CType(Me.CMB_REDDIT_ACC, System.ComponentModel.ISupportInitialize).BeginInit()
|
CType(Me.CMB_REDDIT_ACC, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||||
|
TP_TEXT.SuspendLayout()
|
||||||
Me.SuspendLayout()
|
Me.SuspendLayout()
|
||||||
'
|
'
|
||||||
'CONTAINER_MAIN
|
'CONTAINER_MAIN
|
||||||
@@ -61,13 +71,13 @@ Namespace API.Reddit
|
|||||||
'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(477, 169)
|
CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(477, 222)
|
||||||
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(477, 169)
|
CONTAINER_MAIN.Size = New System.Drawing.Size(477, 222)
|
||||||
CONTAINER_MAIN.TabIndex = 0
|
CONTAINER_MAIN.TabIndex = 0
|
||||||
CONTAINER_MAIN.TopToolStripPanelVisible = False
|
CONTAINER_MAIN.TopToolStripPanelVisible = False
|
||||||
'
|
'
|
||||||
@@ -78,18 +88,20 @@ Namespace API.Reddit
|
|||||||
Me.TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
Me.TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
Me.TP_MAIN.Controls.Add(TP_VIEW_MODE, 0, 0)
|
Me.TP_MAIN.Controls.Add(TP_VIEW_MODE, 0, 0)
|
||||||
Me.TP_MAIN.Controls.Add(Me.TP_PERIOD, 0, 1)
|
Me.TP_MAIN.Controls.Add(Me.TP_PERIOD, 0, 1)
|
||||||
Me.TP_MAIN.Controls.Add(Me.CMB_REDGIFS_ACC, 0, 3)
|
Me.TP_MAIN.Controls.Add(Me.CMB_REDGIFS_ACC, 0, 4)
|
||||||
Me.TP_MAIN.Controls.Add(Me.CMB_REDDIT_ACC, 0, 2)
|
Me.TP_MAIN.Controls.Add(Me.CMB_REDDIT_ACC, 0, 3)
|
||||||
|
Me.TP_MAIN.Controls.Add(TP_TEXT, 0, 2)
|
||||||
Me.TP_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
|
Me.TP_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
Me.TP_MAIN.Location = New System.Drawing.Point(0, 0)
|
Me.TP_MAIN.Location = New System.Drawing.Point(0, 0)
|
||||||
Me.TP_MAIN.Name = "TP_MAIN"
|
Me.TP_MAIN.Name = "TP_MAIN"
|
||||||
Me.TP_MAIN.RowCount = 5
|
Me.TP_MAIN.RowCount = 6
|
||||||
Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
|
|
||||||
Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 56.0!))
|
Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 56.0!))
|
||||||
|
Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 56.0!))
|
||||||
|
Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
|
||||||
Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
|
Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
|
||||||
Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
|
Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.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(477, 169)
|
Me.TP_MAIN.Size = New System.Drawing.Size(477, 222)
|
||||||
Me.TP_MAIN.TabIndex = 0
|
Me.TP_MAIN.TabIndex = 0
|
||||||
'
|
'
|
||||||
'TP_VIEW_MODE
|
'TP_VIEW_MODE
|
||||||
@@ -103,14 +115,16 @@ Namespace API.Reddit
|
|||||||
TP_VIEW_MODE.Controls.Add(Me.OPT_VIEW_MODE_NEW, 1, 0)
|
TP_VIEW_MODE.Controls.Add(Me.OPT_VIEW_MODE_NEW, 1, 0)
|
||||||
TP_VIEW_MODE.Controls.Add(Me.OPT_VIEW_MODE_HOT, 2, 0)
|
TP_VIEW_MODE.Controls.Add(Me.OPT_VIEW_MODE_HOT, 2, 0)
|
||||||
TP_VIEW_MODE.Controls.Add(Me.OPT_VIEW_MODE_TOP, 3, 0)
|
TP_VIEW_MODE.Controls.Add(Me.OPT_VIEW_MODE_TOP, 3, 0)
|
||||||
|
TP_VIEW_MODE.Controls.Add(Me.OPT_VIEW_MODE_BEST, 1, 1)
|
||||||
|
TP_VIEW_MODE.Controls.Add(Me.OPT_VIEW_MODE_RISING, 2, 1)
|
||||||
TP_VIEW_MODE.Dock = System.Windows.Forms.DockStyle.Fill
|
TP_VIEW_MODE.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
TP_VIEW_MODE.Location = New System.Drawing.Point(1, 1)
|
TP_VIEW_MODE.Location = New System.Drawing.Point(1, 1)
|
||||||
TP_VIEW_MODE.Margin = New System.Windows.Forms.Padding(0)
|
TP_VIEW_MODE.Margin = New System.Windows.Forms.Padding(0)
|
||||||
TP_VIEW_MODE.Name = "TP_VIEW_MODE"
|
TP_VIEW_MODE.Name = "TP_VIEW_MODE"
|
||||||
TP_VIEW_MODE.RowCount = 1
|
TP_VIEW_MODE.RowCount = 2
|
||||||
TP_VIEW_MODE.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
TP_VIEW_MODE.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
|
||||||
TP_VIEW_MODE.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
|
TP_VIEW_MODE.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
|
||||||
TP_VIEW_MODE.Size = New System.Drawing.Size(475, 28)
|
TP_VIEW_MODE.Size = New System.Drawing.Size(475, 56)
|
||||||
TP_VIEW_MODE.TabIndex = 0
|
TP_VIEW_MODE.TabIndex = 0
|
||||||
'
|
'
|
||||||
'LBL_VIEW_MODE
|
'LBL_VIEW_MODE
|
||||||
@@ -160,6 +174,30 @@ Namespace API.Reddit
|
|||||||
Me.OPT_VIEW_MODE_TOP.Text = "Top"
|
Me.OPT_VIEW_MODE_TOP.Text = "Top"
|
||||||
Me.OPT_VIEW_MODE_TOP.UseVisualStyleBackColor = True
|
Me.OPT_VIEW_MODE_TOP.UseVisualStyleBackColor = True
|
||||||
'
|
'
|
||||||
|
'OPT_VIEW_MODE_BEST
|
||||||
|
'
|
||||||
|
Me.OPT_VIEW_MODE_BEST.AutoSize = True
|
||||||
|
Me.OPT_VIEW_MODE_BEST.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.OPT_VIEW_MODE_BEST.Location = New System.Drawing.Point(121, 31)
|
||||||
|
Me.OPT_VIEW_MODE_BEST.Name = "OPT_VIEW_MODE_BEST"
|
||||||
|
Me.OPT_VIEW_MODE_BEST.Size = New System.Drawing.Size(112, 22)
|
||||||
|
Me.OPT_VIEW_MODE_BEST.TabIndex = 4
|
||||||
|
Me.OPT_VIEW_MODE_BEST.TabStop = True
|
||||||
|
Me.OPT_VIEW_MODE_BEST.Text = "Best"
|
||||||
|
Me.OPT_VIEW_MODE_BEST.UseVisualStyleBackColor = True
|
||||||
|
'
|
||||||
|
'OPT_VIEW_MODE_RISING
|
||||||
|
'
|
||||||
|
Me.OPT_VIEW_MODE_RISING.AutoSize = True
|
||||||
|
Me.OPT_VIEW_MODE_RISING.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.OPT_VIEW_MODE_RISING.Location = New System.Drawing.Point(239, 31)
|
||||||
|
Me.OPT_VIEW_MODE_RISING.Name = "OPT_VIEW_MODE_RISING"
|
||||||
|
Me.OPT_VIEW_MODE_RISING.Size = New System.Drawing.Size(112, 22)
|
||||||
|
Me.OPT_VIEW_MODE_RISING.TabIndex = 5
|
||||||
|
Me.OPT_VIEW_MODE_RISING.TabStop = True
|
||||||
|
Me.OPT_VIEW_MODE_RISING.Text = "Rising"
|
||||||
|
Me.OPT_VIEW_MODE_RISING.UseVisualStyleBackColor = True
|
||||||
|
'
|
||||||
'TP_PERIOD
|
'TP_PERIOD
|
||||||
'
|
'
|
||||||
Me.TP_PERIOD.ColumnCount = 4
|
Me.TP_PERIOD.ColumnCount = 4
|
||||||
@@ -175,7 +213,7 @@ Namespace API.Reddit
|
|||||||
Me.TP_PERIOD.Controls.Add(Me.OPT_PERIOD_MONTH, 2, 1)
|
Me.TP_PERIOD.Controls.Add(Me.OPT_PERIOD_MONTH, 2, 1)
|
||||||
Me.TP_PERIOD.Controls.Add(Me.OPT_PERIOD_YEAR, 3, 1)
|
Me.TP_PERIOD.Controls.Add(Me.OPT_PERIOD_YEAR, 3, 1)
|
||||||
Me.TP_PERIOD.Dock = System.Windows.Forms.DockStyle.Fill
|
Me.TP_PERIOD.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
Me.TP_PERIOD.Location = New System.Drawing.Point(1, 30)
|
Me.TP_PERIOD.Location = New System.Drawing.Point(1, 58)
|
||||||
Me.TP_PERIOD.Margin = New System.Windows.Forms.Padding(0)
|
Me.TP_PERIOD.Margin = New System.Windows.Forms.Padding(0)
|
||||||
Me.TP_PERIOD.Name = "TP_PERIOD"
|
Me.TP_PERIOD.Name = "TP_PERIOD"
|
||||||
Me.TP_PERIOD.RowCount = 2
|
Me.TP_PERIOD.RowCount = 2
|
||||||
@@ -269,17 +307,17 @@ Namespace API.Reddit
|
|||||||
'
|
'
|
||||||
'CMB_REDGIFS_ACC
|
'CMB_REDGIFS_ACC
|
||||||
'
|
'
|
||||||
ActionButton1.BackgroundImage = CType(resources.GetObject("ActionButton1.BackgroundImage"), System.Drawing.Image)
|
ActionButton3.BackgroundImage = CType(resources.GetObject("ActionButton3.BackgroundImage"), System.Drawing.Image)
|
||||||
ActionButton1.Name = "ArrowDown"
|
ActionButton3.Name = "ArrowDown"
|
||||||
ActionButton1.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.ArrowDown
|
ActionButton3.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.ArrowDown
|
||||||
Me.CMB_REDGIFS_ACC.Buttons.Add(ActionButton1)
|
Me.CMB_REDGIFS_ACC.Buttons.Add(ActionButton3)
|
||||||
Me.CMB_REDGIFS_ACC.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.Label
|
Me.CMB_REDGIFS_ACC.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.Label
|
||||||
Me.CMB_REDGIFS_ACC.CaptionSizeType = System.Windows.Forms.SizeType.Percent
|
Me.CMB_REDGIFS_ACC.CaptionSizeType = System.Windows.Forms.SizeType.Percent
|
||||||
Me.CMB_REDGIFS_ACC.CaptionText = "RedGifs account"
|
Me.CMB_REDGIFS_ACC.CaptionText = "RedGifs account"
|
||||||
Me.CMB_REDGIFS_ACC.CaptionVisible = True
|
Me.CMB_REDGIFS_ACC.CaptionVisible = True
|
||||||
Me.CMB_REDGIFS_ACC.CaptionWidth = 26.0R
|
Me.CMB_REDGIFS_ACC.CaptionWidth = 26.0R
|
||||||
Me.CMB_REDGIFS_ACC.Dock = System.Windows.Forms.DockStyle.Fill
|
Me.CMB_REDGIFS_ACC.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
Me.CMB_REDGIFS_ACC.Location = New System.Drawing.Point(4, 119)
|
Me.CMB_REDGIFS_ACC.Location = New System.Drawing.Point(4, 173)
|
||||||
Me.CMB_REDGIFS_ACC.Name = "CMB_REDGIFS_ACC"
|
Me.CMB_REDGIFS_ACC.Name = "CMB_REDGIFS_ACC"
|
||||||
Me.CMB_REDGIFS_ACC.Size = New System.Drawing.Size(469, 22)
|
Me.CMB_REDGIFS_ACC.Size = New System.Drawing.Size(469, 22)
|
||||||
Me.CMB_REDGIFS_ACC.TabIndex = 4
|
Me.CMB_REDGIFS_ACC.TabIndex = 4
|
||||||
@@ -287,35 +325,89 @@ Namespace API.Reddit
|
|||||||
'
|
'
|
||||||
'CMB_REDDIT_ACC
|
'CMB_REDDIT_ACC
|
||||||
'
|
'
|
||||||
ActionButton2.BackgroundImage = CType(resources.GetObject("ActionButton2.BackgroundImage"), System.Drawing.Image)
|
ActionButton4.BackgroundImage = CType(resources.GetObject("ActionButton4.BackgroundImage"), System.Drawing.Image)
|
||||||
ActionButton2.Name = "ArrowDown"
|
ActionButton4.Name = "ArrowDown"
|
||||||
ActionButton2.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.ArrowDown
|
ActionButton4.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.ArrowDown
|
||||||
Me.CMB_REDDIT_ACC.Buttons.Add(ActionButton2)
|
Me.CMB_REDDIT_ACC.Buttons.Add(ActionButton4)
|
||||||
Me.CMB_REDDIT_ACC.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.Label
|
Me.CMB_REDDIT_ACC.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.Label
|
||||||
Me.CMB_REDDIT_ACC.CaptionSizeType = System.Windows.Forms.SizeType.Percent
|
Me.CMB_REDDIT_ACC.CaptionSizeType = System.Windows.Forms.SizeType.Percent
|
||||||
Me.CMB_REDDIT_ACC.CaptionText = "Reddit account"
|
Me.CMB_REDDIT_ACC.CaptionText = "Reddit account"
|
||||||
Me.CMB_REDDIT_ACC.CaptionVisible = True
|
Me.CMB_REDDIT_ACC.CaptionVisible = True
|
||||||
Me.CMB_REDDIT_ACC.CaptionWidth = 26.0R
|
Me.CMB_REDDIT_ACC.CaptionWidth = 26.0R
|
||||||
Me.CMB_REDDIT_ACC.Dock = System.Windows.Forms.DockStyle.Fill
|
Me.CMB_REDDIT_ACC.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
Me.CMB_REDDIT_ACC.Location = New System.Drawing.Point(4, 90)
|
Me.CMB_REDDIT_ACC.Location = New System.Drawing.Point(4, 144)
|
||||||
Me.CMB_REDDIT_ACC.Name = "CMB_REDDIT_ACC"
|
Me.CMB_REDDIT_ACC.Name = "CMB_REDDIT_ACC"
|
||||||
Me.CMB_REDDIT_ACC.Size = New System.Drawing.Size(469, 22)
|
Me.CMB_REDDIT_ACC.Size = New System.Drawing.Size(469, 22)
|
||||||
Me.CMB_REDDIT_ACC.TabIndex = 3
|
Me.CMB_REDDIT_ACC.TabIndex = 3
|
||||||
Me.CMB_REDDIT_ACC.TextBoxBorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
|
Me.CMB_REDDIT_ACC.TextBoxBorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
|
||||||
'
|
'
|
||||||
|
'TP_TEXT
|
||||||
|
'
|
||||||
|
TP_TEXT.ColumnCount = 3
|
||||||
|
TP_TEXT.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333!))
|
||||||
|
TP_TEXT.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333!))
|
||||||
|
TP_TEXT.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333!))
|
||||||
|
TP_TEXT.Controls.Add(Me.CH_TXT_DOWN_TXT, 0, 0)
|
||||||
|
TP_TEXT.Controls.Add(Me.CH_TXT_DOWN_POSTS, 1, 0)
|
||||||
|
TP_TEXT.Controls.Add(Me.CH_TXT_DOWN_SPEC_FOLDER, 2, 0)
|
||||||
|
TP_TEXT.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
TP_TEXT.Location = New System.Drawing.Point(1, 115)
|
||||||
|
TP_TEXT.Margin = New System.Windows.Forms.Padding(0)
|
||||||
|
TP_TEXT.Name = "TP_TEXT"
|
||||||
|
TP_TEXT.RowCount = 1
|
||||||
|
TP_TEXT.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
|
TP_TEXT.Size = New System.Drawing.Size(475, 25)
|
||||||
|
TP_TEXT.TabIndex = 5
|
||||||
|
'
|
||||||
|
'CH_TXT_DOWN_TXT
|
||||||
|
'
|
||||||
|
Me.CH_TXT_DOWN_TXT.AutoSize = True
|
||||||
|
Me.CH_TXT_DOWN_TXT.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.CH_TXT_DOWN_TXT.Location = New System.Drawing.Point(3, 3)
|
||||||
|
Me.CH_TXT_DOWN_TXT.Name = "CH_TXT_DOWN_TXT"
|
||||||
|
Me.CH_TXT_DOWN_TXT.Size = New System.Drawing.Size(152, 19)
|
||||||
|
Me.CH_TXT_DOWN_TXT.TabIndex = 0
|
||||||
|
Me.CH_TXT_DOWN_TXT.Text = "Download text"
|
||||||
|
Me.TT_MAIN.SetToolTip(Me.CH_TXT_DOWN_TXT, "Download text (if available) for posts with image and video")
|
||||||
|
Me.CH_TXT_DOWN_TXT.UseVisualStyleBackColor = True
|
||||||
|
'
|
||||||
|
'CH_TXT_DOWN_POSTS
|
||||||
|
'
|
||||||
|
Me.CH_TXT_DOWN_POSTS.AutoSize = True
|
||||||
|
Me.CH_TXT_DOWN_POSTS.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.CH_TXT_DOWN_POSTS.Location = New System.Drawing.Point(161, 3)
|
||||||
|
Me.CH_TXT_DOWN_POSTS.Name = "CH_TXT_DOWN_POSTS"
|
||||||
|
Me.CH_TXT_DOWN_POSTS.Size = New System.Drawing.Size(152, 19)
|
||||||
|
Me.CH_TXT_DOWN_POSTS.TabIndex = 1
|
||||||
|
Me.CH_TXT_DOWN_POSTS.Text = "Download text posts"
|
||||||
|
Me.TT_MAIN.SetToolTip(Me.CH_TXT_DOWN_POSTS, "Download text (if available) for text posts (no image and video)")
|
||||||
|
Me.CH_TXT_DOWN_POSTS.UseVisualStyleBackColor = True
|
||||||
|
'
|
||||||
|
'CH_TXT_DOWN_SPEC_FOLDER
|
||||||
|
'
|
||||||
|
Me.CH_TXT_DOWN_SPEC_FOLDER.AutoSize = True
|
||||||
|
Me.CH_TXT_DOWN_SPEC_FOLDER.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.CH_TXT_DOWN_SPEC_FOLDER.Location = New System.Drawing.Point(319, 3)
|
||||||
|
Me.CH_TXT_DOWN_SPEC_FOLDER.Name = "CH_TXT_DOWN_SPEC_FOLDER"
|
||||||
|
Me.CH_TXT_DOWN_SPEC_FOLDER.Size = New System.Drawing.Size(153, 19)
|
||||||
|
Me.CH_TXT_DOWN_SPEC_FOLDER.TabIndex = 2
|
||||||
|
Me.CH_TXT_DOWN_SPEC_FOLDER.Text = "Text special folder"
|
||||||
|
Me.TT_MAIN.SetToolTip(Me.CH_TXT_DOWN_SPEC_FOLDER, "If checked, text files will be saved to a separate folder")
|
||||||
|
Me.CH_TXT_DOWN_SPEC_FOLDER.UseVisualStyleBackColor = True
|
||||||
|
'
|
||||||
'RedditViewSettingsForm
|
'RedditViewSettingsForm
|
||||||
'
|
'
|
||||||
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(477, 169)
|
Me.ClientSize = New System.Drawing.Size(477, 222)
|
||||||
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.RedditIcon_128
|
Me.Icon = Global.SCrawler.My.Resources.SiteResources.RedditIcon_128
|
||||||
Me.KeyPreview = True
|
Me.KeyPreview = True
|
||||||
Me.MaximizeBox = False
|
Me.MaximizeBox = False
|
||||||
Me.MaximumSize = New System.Drawing.Size(493, 208)
|
Me.MaximumSize = New System.Drawing.Size(493, 261)
|
||||||
Me.MinimizeBox = False
|
Me.MinimizeBox = False
|
||||||
Me.MinimumSize = New System.Drawing.Size(493, 208)
|
Me.MinimumSize = New System.Drawing.Size(493, 261)
|
||||||
Me.Name = "RedditViewSettingsForm"
|
Me.Name = "RedditViewSettingsForm"
|
||||||
Me.ShowInTaskbar = False
|
Me.ShowInTaskbar = False
|
||||||
Me.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide
|
Me.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide
|
||||||
@@ -330,6 +422,8 @@ Namespace API.Reddit
|
|||||||
Me.TP_PERIOD.PerformLayout()
|
Me.TP_PERIOD.PerformLayout()
|
||||||
CType(Me.CMB_REDGIFS_ACC, System.ComponentModel.ISupportInitialize).EndInit()
|
CType(Me.CMB_REDGIFS_ACC, System.ComponentModel.ISupportInitialize).EndInit()
|
||||||
CType(Me.CMB_REDDIT_ACC, System.ComponentModel.ISupportInitialize).EndInit()
|
CType(Me.CMB_REDDIT_ACC, System.ComponentModel.ISupportInitialize).EndInit()
|
||||||
|
TP_TEXT.ResumeLayout(False)
|
||||||
|
TP_TEXT.PerformLayout()
|
||||||
Me.ResumeLayout(False)
|
Me.ResumeLayout(False)
|
||||||
|
|
||||||
End Sub
|
End Sub
|
||||||
@@ -346,5 +440,11 @@ Namespace API.Reddit
|
|||||||
Private WithEvents CMB_REDGIFS_ACC As PersonalUtilities.Forms.Controls.ComboBoxExtended
|
Private WithEvents CMB_REDGIFS_ACC As PersonalUtilities.Forms.Controls.ComboBoxExtended
|
||||||
Private WithEvents CMB_REDDIT_ACC As PersonalUtilities.Forms.Controls.ComboBoxExtended
|
Private WithEvents CMB_REDDIT_ACC As PersonalUtilities.Forms.Controls.ComboBoxExtended
|
||||||
Private WithEvents TP_MAIN As TableLayoutPanel
|
Private WithEvents TP_MAIN As TableLayoutPanel
|
||||||
|
Private WithEvents OPT_VIEW_MODE_BEST As RadioButton
|
||||||
|
Private WithEvents OPT_VIEW_MODE_RISING As RadioButton
|
||||||
|
Private WithEvents CH_TXT_DOWN_TXT As CheckBox
|
||||||
|
Private WithEvents TT_MAIN As ToolTip
|
||||||
|
Private WithEvents CH_TXT_DOWN_POSTS As CheckBox
|
||||||
|
Private WithEvents CH_TXT_DOWN_SPEC_FOLDER As CheckBox
|
||||||
End Class
|
End Class
|
||||||
End Namespace
|
End Namespace
|
||||||
@@ -130,184 +130,195 @@
|
|||||||
<value>False</value>
|
<value>False</value>
|
||||||
</metadata>
|
</metadata>
|
||||||
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||||
<data name="ActionButton1.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ActionButton3.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAYAAAD0eNT6AAAABGdBTUEAALGPC/xhBQAAE65JREFUeF7t
|
iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAYAAAD0eNT6AAAABGdBTUEAALGPC/xhBQAAE0xJREFUeF7t
|
||||||
3X2sJWddB/DdLi2lQG2hdOHuvfM887J7Cxca4ELTQMDWKigIFpBAEAgi9g+CJpJo9Q8NJhgBiYZIYspL
|
3X2MZWddB/BZSkspUFsoXZidOc/vnOfsTmGgARaaBgK2VkFBsIAEgkAQsX8QNJFEq39oMMEoSDREElOB
|
||||||
GlAKCkhEC4KgQlsLQkqhKi/lrYWWlxaw3dLddrerz/Q89+7dc2fbfTn3npf5fJJv2rS758z85nnOzJz5
|
EFAKCkhEAUGqQlsLQkoBlZfy1kJ5awH7QrvtbldzdndmZ597Snd37szce8/nk3xTQjsz5/zOefbO3vO9
|
||||||
nZktAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
58zNAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
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
|
||||||
k/LT6hD+Mu2oR/4rgXTW/+X02r+U3woAmDTtz/GaIv5F2nH/ZHhHfpS5J+Vf01n/S9LLbhu8OgAw0dpb
|
mQO/EFTVctfezxEXtlX9vLaqX9z9s6mqC5YWF+fLrwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
8TYL5XPTmfvb0o78v/MOvWtHvybtzXzKT1Qx/n5d1wv5pQCAaXXvAUFRLLXd+3WMFzZF+cKUl7X/rIri
|
|
||||||
gsWFhbn8RwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6LEtW/4flgYiLD1qeX0A
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
AAAASUVORK5CYII=
|
AAAAAAAAAAAAYIj+H5YGIizEb/aEAAAAAElFTkSuQmCC
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ActionButton2.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ActionButton4.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAYAAAD0eNT6AAAABGdBTUEAALGPC/xhBQAAE65JREFUeF7t
|
iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAYAAAD0eNT6AAAABGdBTUEAALGPC/xhBQAAE0xJREFUeF7t
|
||||||
3X2sJWddB/DdLi2lQG2hdOHuvfM887J7Cxca4ELTQMDWKigIFpBAEAgi9g+CJpJo9Q8NJhgBiYZIYspL
|
3X2MZWddB/BZSkspUFsoXZidOc/vnOfsTmGgARaaBgK2VkFBsIAEgkAQsX8QNJFEq39oMMEoSDREElOB
|
||||||
GlAKCkhEC4KgQlsLQkqhKi/lrYWWlxaw3dLddrerz/Q89+7dc2fbfTn3npf5fJJv2rS758z85nnOzJz5
|
EFAKCkhEAUGqQlsLQkoBlZfy1kJ5awH7QrvtbldzdndmZ597Snd37szce8/nk3xTQjsz5/zOefbO3vO9
|
||||||
nZktAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
58zNAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
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
|
||||||
k/LT6hD+Mu2oR/4rgXTW/+X02r+U3woAmDTtz/GaIv5F2nH/ZHhHfpS5J+Vf01n/S9LLbhu8OgAw0dpb
|
mQO/EFTVctfezxEXtlX9vLaqX9z9s6mqC5YWF+fLrwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
8TYL5XPTmfvb0o78v/MOvWtHvybtzXzKT1Qx/n5d1wv5pQCAaXXvAUFRLLXd+3WMFzZF+cKUl7X/rIri
|
|
||||||
gsWFhbn8RwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6LEtW/4flgYiLD1qeX0A
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
AAAASUVORK5CYII=
|
AAAAAAAAAAAAYIj+H5YGIizEb/aEAAAAAElFTkSuQmCC
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
|
<metadata name="TP_TEXT.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</metadata>
|
||||||
|
<metadata name="TT_MAIN.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<value>17, 17</value>
|
||||||
|
</metadata>
|
||||||
|
<metadata name="TT_MAIN.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<value>17, 17</value>
|
||||||
|
</metadata>
|
||||||
|
<metadata name="LBL_VIEW_MODE.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</metadata>
|
||||||
|
<metadata name="LBL_PERIOD.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</metadata>
|
||||||
</root>
|
</root>
|
||||||
@@ -38,6 +38,8 @@ Namespace API.Reddit
|
|||||||
Select Case MyOptions.ViewMode
|
Select Case MyOptions.ViewMode
|
||||||
Case CView.Hot : OPT_VIEW_MODE_HOT.Checked = True
|
Case CView.Hot : OPT_VIEW_MODE_HOT.Checked = True
|
||||||
Case CView.Top : OPT_VIEW_MODE_TOP.Checked = True
|
Case CView.Top : OPT_VIEW_MODE_TOP.Checked = True
|
||||||
|
Case CView.Best : OPT_VIEW_MODE_BEST.Checked = True
|
||||||
|
Case CView.Rising : OPT_VIEW_MODE_RISING.Checked = True
|
||||||
Case Else : OPT_VIEW_MODE_NEW.Checked = True
|
Case Else : OPT_VIEW_MODE_NEW.Checked = True
|
||||||
End Select
|
End Select
|
||||||
Select Case MyOptions.ViewPeriod
|
Select Case MyOptions.ViewPeriod
|
||||||
@@ -50,11 +52,15 @@ Namespace API.Reddit
|
|||||||
End Select
|
End Select
|
||||||
ChangePeriodEnabled()
|
ChangePeriodEnabled()
|
||||||
|
|
||||||
|
CH_TXT_DOWN_TXT.Checked = MyOptions.DownloadText
|
||||||
|
CH_TXT_DOWN_POSTS.Checked = MyOptions.DownloadTextPosts
|
||||||
|
CH_TXT_DOWN_SPEC_FOLDER.Checked = MyOptions.DownloadTextSpecialFolder
|
||||||
|
|
||||||
PopulateCMB(Settings(RedditSiteKey), CMB_REDDIT_ACC, MyOptions.RedditAccount)
|
PopulateCMB(Settings(RedditSiteKey), CMB_REDDIT_ACC, MyOptions.RedditAccount)
|
||||||
PopulateCMB(Settings(RedGifs.RedGifsSiteKey), CMB_REDGIFS_ACC, MyOptions.RedGifsAccount)
|
PopulateCMB(Settings(RedGifs.RedGifsSiteKey), CMB_REDGIFS_ACC, MyOptions.RedGifsAccount)
|
||||||
If IsUserSettings Then
|
If IsUserSettings Then
|
||||||
TP_MAIN.Controls.Remove(CMB_REDDIT_ACC)
|
TP_MAIN.Controls.Remove(CMB_REDDIT_ACC)
|
||||||
TP_MAIN.RowStyles(2).Height = 0
|
TP_MAIN.RowStyles(3).Height = 0
|
||||||
TP_MAIN.Refresh()
|
TP_MAIN.Refresh()
|
||||||
Dim s As Size = Size
|
Dim s As Size = Size
|
||||||
s.Height -= 28
|
s.Height -= 28
|
||||||
@@ -100,6 +106,8 @@ Namespace API.Reddit
|
|||||||
Select Case True
|
Select Case True
|
||||||
Case OPT_VIEW_MODE_HOT.Checked : .ViewMode = CView.Hot
|
Case OPT_VIEW_MODE_HOT.Checked : .ViewMode = CView.Hot
|
||||||
Case OPT_VIEW_MODE_TOP.Checked : .ViewMode = CView.Top
|
Case OPT_VIEW_MODE_TOP.Checked : .ViewMode = CView.Top
|
||||||
|
Case OPT_VIEW_MODE_BEST.Checked : .ViewMode = CView.Best
|
||||||
|
Case OPT_VIEW_MODE_RISING.Checked : .ViewMode = CView.Rising
|
||||||
Case Else : .ViewMode = CView.New
|
Case Else : .ViewMode = CView.New
|
||||||
End Select
|
End Select
|
||||||
Select Case True
|
Select Case True
|
||||||
@@ -110,6 +118,9 @@ Namespace API.Reddit
|
|||||||
Case OPT_PERIOD_YEAR.Checked : .ViewPeriod = CPeriod.Year
|
Case OPT_PERIOD_YEAR.Checked : .ViewPeriod = CPeriod.Year
|
||||||
Case Else : .ViewPeriod = CPeriod.All
|
Case Else : .ViewPeriod = CPeriod.All
|
||||||
End Select
|
End Select
|
||||||
|
.DownloadText = CH_TXT_DOWN_TXT.Checked
|
||||||
|
.DownloadTextPosts = CH_TXT_DOWN_POSTS.Checked
|
||||||
|
.DownloadTextSpecialFolder = CH_TXT_DOWN_SPEC_FOLDER.Checked
|
||||||
.RedGifsAccount = CMB_REDGIFS_ACC.Text
|
.RedGifsAccount = CMB_REDGIFS_ACC.Text
|
||||||
If Not IsUserSettings Then .RedditAccount = CMB_REDDIT_ACC.Text
|
If Not IsUserSettings Then .RedditAccount = CMB_REDDIT_ACC.Text
|
||||||
End With
|
End With
|
||||||
|
|||||||
@@ -96,6 +96,7 @@ Namespace API.Reddit
|
|||||||
With Responser
|
With Responser
|
||||||
Dim d% = .Decoders.Count
|
Dim d% = .Decoders.Count
|
||||||
.Decoders.ListAddList({SymbolsConverter.Converters.Unicode, SymbolsConverter.Converters.HTML}, LAP.NotContainsOnly)
|
.Decoders.ListAddList({SymbolsConverter.Converters.Unicode, SymbolsConverter.Converters.HTML}, LAP.NotContainsOnly)
|
||||||
|
.Accept = "application/json"
|
||||||
token = .Headers.Value(DeclaredNames.Header_Authorization)
|
token = .Headers.Value(DeclaredNames.Header_Authorization)
|
||||||
End With
|
End With
|
||||||
|
|
||||||
@@ -104,7 +105,7 @@ Namespace API.Reddit
|
|||||||
ApiClientID = New PropertyValue(String.Empty, GetType(String))
|
ApiClientID = New PropertyValue(String.Empty, GetType(String))
|
||||||
ApiClientSecret = New PropertyValue(String.Empty, GetType(String))
|
ApiClientSecret = New PropertyValue(String.Empty, GetType(String))
|
||||||
BearerToken = New PropertyValue(token, GetType(String), Sub(v) Responser.Headers.Add(DeclaredNames.Header_Authorization, v))
|
BearerToken = New PropertyValue(token, GetType(String), Sub(v) Responser.Headers.Add(DeclaredNames.Header_Authorization, v))
|
||||||
BearerTokenUseCurl = New PropertyValue(True)
|
BearerTokenUseCurl = New PropertyValue(False)
|
||||||
TokenUpdateInterval = New PropertyValue(360)
|
TokenUpdateInterval = New PropertyValue(360)
|
||||||
TokenUpdateIntervalProvider = New TokenRefreshIntervalProvider
|
TokenUpdateIntervalProvider = New TokenRefreshIntervalProvider
|
||||||
BearerTokenDateUpdate = New PropertyValue(Now.AddYears(-1))
|
BearerTokenDateUpdate = New PropertyValue(Now.AddYears(-1))
|
||||||
@@ -123,11 +124,11 @@ Namespace API.Reddit
|
|||||||
ImageVideoContains = "reddit.com"
|
ImageVideoContains = "reddit.com"
|
||||||
UserRegex = RParams.DM("[htps:/]{7,8}.*?reddit.com/([user]{1,4})/([^/\?&]+)", 0, RegexReturn.ListByMatch, EDP.ReturnValue)
|
UserRegex = RParams.DM("[htps:/]{7,8}.*?reddit.com/([user]{1,4})/([^/\?&]+)", 0, RegexReturn.ListByMatch, EDP.ReturnValue)
|
||||||
End Sub
|
End Sub
|
||||||
Private Const SettingsVersionCurrent As Integer = 1
|
Private Const SettingsVersionCurrent As Integer = 2
|
||||||
Friend Overrides Sub EndInit()
|
Friend Overrides Sub EndInit()
|
||||||
If CInt(SettingsVersion.Value) < SettingsVersionCurrent Then
|
If CInt(SettingsVersion.Value) < SettingsVersionCurrent Then
|
||||||
SettingsVersion.Value = SettingsVersionCurrent
|
SettingsVersion.Value = SettingsVersionCurrent
|
||||||
TokenUpdateInterval.Value = 360
|
BearerTokenUseCurl.Value = False
|
||||||
End If
|
End If
|
||||||
MyBase.EndInit()
|
MyBase.EndInit()
|
||||||
End Sub
|
End Sub
|
||||||
@@ -172,7 +173,7 @@ Namespace API.Reddit
|
|||||||
End If
|
End If
|
||||||
End Function
|
End Function
|
||||||
Friend Overrides Function Available(ByVal What As Download, ByVal Silent As Boolean) As Boolean
|
Friend Overrides Function Available(ByVal What As Download, ByVal Silent As Boolean) As Boolean
|
||||||
Return AvailableTrueValue(What)
|
Return AvailableTrueValue(What) AndAlso UpdateTokenIfRequired()
|
||||||
End Function
|
End Function
|
||||||
Private Function AvailableTrueValue(ByVal What As Download) As Boolean
|
Private Function AvailableTrueValue(ByVal What As Download) As Boolean
|
||||||
Return Not What = Download.SavedPosts OrElse (Responser.CookiesExists And ACheck(SavedPostsUserName.Value))
|
Return Not What = Download.SavedPosts OrElse (Responser.CookiesExists And ACheck(SavedPostsUserName.Value))
|
||||||
@@ -199,7 +200,7 @@ Namespace API.Reddit
|
|||||||
End If
|
End If
|
||||||
End Function
|
End Function
|
||||||
Friend Overrides Function GetUserUrl(ByVal User As IPluginContentProvider) As String
|
Friend Overrides Function GetUserUrl(ByVal User As IPluginContentProvider) As String
|
||||||
With DirectCast(User, UserData) : Return String.Format(UrlPatternUser, IIf(.IsChannel, ChannelOption, "user"), .TrueName) : End With
|
With DirectCast(User, UserData) : Return String.Format(UrlPatternUser, IIf(.IsChannel, ChannelOption, "user"), .NameTrue) : End With
|
||||||
End Function
|
End Function
|
||||||
Friend Overrides Function GetUserPostUrl(ByVal User As UserDataBase, ByVal Media As UserMedia) As String
|
Friend Overrides Function GetUserPostUrl(ByVal User As UserDataBase, ByVal Media As UserMedia) As String
|
||||||
If Not Media.Post.ID.IsEmptyString Then
|
If Not Media.Post.ID.IsEmptyString Then
|
||||||
@@ -250,6 +251,7 @@ Namespace API.Reddit
|
|||||||
Return False
|
Return False
|
||||||
End Function
|
End Function
|
||||||
Private Function UpdateTokenIfRequired() As Boolean
|
Private Function UpdateTokenIfRequired() As Boolean
|
||||||
|
UpdateRedGifsToken()
|
||||||
If (CBool(UseTokenForTimelines.Value) Or CBool(UseTokenForSavedPosts.Value)) AndAlso CredentialsExists Then
|
If (CBool(UseTokenForTimelines.Value) Or CBool(UseTokenForSavedPosts.Value)) AndAlso CredentialsExists Then
|
||||||
If CDate(BearerTokenDateUpdate.Value).AddMinutes(TokenUpdateInterval.Value) <= Now Then Return UpdateToken()
|
If CDate(BearerTokenDateUpdate.Value).AddMinutes(TokenUpdateInterval.Value) <= Now Then Return UpdateToken()
|
||||||
End If
|
End If
|
||||||
|
|||||||
@@ -33,7 +33,8 @@ Namespace API.Reddit
|
|||||||
End Property
|
End Property
|
||||||
Private ReadOnly Property DateTrueProvider(ByVal IsChannel As Boolean) As IFormatProvider
|
Private ReadOnly Property DateTrueProvider(ByVal IsChannel As Boolean) As IFormatProvider
|
||||||
Get
|
Get
|
||||||
Return If(IsChannel, UnixDate32ProviderReddit, UnixDate64Provider)
|
Return UnixDate32Provider
|
||||||
|
'Return If(IsChannel, UnixDate32ProviderReddit, UnixDate64Provider)
|
||||||
End Get
|
End Get
|
||||||
End Property
|
End Property
|
||||||
Private ReadOnly Property UseM3U8 As Boolean
|
Private ReadOnly Property UseM3U8 As Boolean
|
||||||
@@ -42,7 +43,6 @@ Namespace API.Reddit
|
|||||||
End Get
|
End Get
|
||||||
End Property
|
End Property
|
||||||
Friend Property IsChannel As Boolean = False
|
Friend Property IsChannel As Boolean = False
|
||||||
Friend Property TrueName As String = String.Empty
|
|
||||||
Friend Overrides ReadOnly Property SpecialLabels As IEnumerable(Of String)
|
Friend Overrides ReadOnly Property SpecialLabels As IEnumerable(Of String)
|
||||||
Get
|
Get
|
||||||
Return {CannelsLabelName, CannelsLabelName_ChannelsForm, UserLabelName}
|
Return {CannelsLabelName, CannelsLabelName_ChannelsForm, UserLabelName}
|
||||||
@@ -127,10 +127,15 @@ Namespace API.Reddit
|
|||||||
Friend Property ViewPeriod As CPeriod Implements IRedditView.ViewPeriod
|
Friend Property ViewPeriod As CPeriod Implements IRedditView.ViewPeriod
|
||||||
Friend Sub SetView(ByVal Options As IRedditView) Implements IRedditView.SetView
|
Friend Sub SetView(ByVal Options As IRedditView) Implements IRedditView.SetView
|
||||||
If Not Options Is Nothing Then
|
If Not Options Is Nothing Then
|
||||||
ViewMode = Options.ViewMode
|
With Options
|
||||||
ViewPeriod = Options.ViewPeriod
|
ViewMode = .ViewMode
|
||||||
RedGifsAccount = Options.RedGifsAccount
|
ViewPeriod = .ViewPeriod
|
||||||
RedditAccount = Options.RedditAccount
|
DownloadText = .DownloadText
|
||||||
|
DownloadTextPosts = .DownloadTextPosts
|
||||||
|
DownloadTextSpecialFolder = .DownloadTextSpecialFolder
|
||||||
|
RedGifsAccount = .RedGifsAccount
|
||||||
|
RedditAccount = .RedditAccount
|
||||||
|
End With
|
||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
Private ReadOnly Property View As String
|
Private ReadOnly Property View As String
|
||||||
@@ -138,6 +143,8 @@ Namespace API.Reddit
|
|||||||
Select Case ViewMode
|
Select Case ViewMode
|
||||||
Case CView.Hot : Return "hot"
|
Case CView.Hot : Return "hot"
|
||||||
Case CView.Top : Return "top"
|
Case CView.Top : Return "top"
|
||||||
|
Case CView.Best : Return "best"
|
||||||
|
Case CView.Rising : Return "rising"
|
||||||
Case Else : Return "new"
|
Case Else : Return "new"
|
||||||
End Select
|
End Select
|
||||||
End Get
|
End Get
|
||||||
@@ -158,6 +165,9 @@ Namespace API.Reddit
|
|||||||
End If
|
End If
|
||||||
End Get
|
End Get
|
||||||
End Property
|
End Property
|
||||||
|
Friend Overrides Property DownloadText As Boolean Implements IRedditView.DownloadText
|
||||||
|
Friend Overrides Property DownloadTextPosts As Boolean Implements IRedditView.DownloadTextPosts
|
||||||
|
Friend Overrides Property DownloadTextSpecialFolder As Boolean Implements IRedditView.DownloadTextSpecialFolder
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Initializer"
|
#Region "Initializer"
|
||||||
Friend Sub New()
|
Friend Sub New()
|
||||||
@@ -173,16 +183,16 @@ Namespace API.Reddit
|
|||||||
#End Region
|
#End Region
|
||||||
#Region "Load and Update user info"
|
#Region "Load and Update user info"
|
||||||
Private Function UpdateNames() As Boolean
|
Private Function UpdateNames() As Boolean
|
||||||
If TrueName.IsEmptyString Then
|
If NameTrue(True).IsEmptyString Then
|
||||||
Dim n$() = Name.Split("@")
|
Dim n$() = Name.Split("@")
|
||||||
If n.ListExists Then
|
If n.ListExists Then
|
||||||
If n.Length = 2 Then
|
If n.Length = 2 Then
|
||||||
TrueName = n(0)
|
NameTrue = n(0)
|
||||||
IsChannel = True
|
IsChannel = True
|
||||||
ElseIf IsChannel Then
|
ElseIf IsChannel Then
|
||||||
TrueName = Name
|
NameTrue = Name
|
||||||
Else
|
Else
|
||||||
TrueName = n(0)
|
NameTrue = n(0)
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
If Not IsSavedPosts Then
|
If Not IsSavedPosts Then
|
||||||
@@ -201,7 +211,6 @@ Namespace API.Reddit
|
|||||||
ViewMode = .Value(Name_ViewMode).FromXML(Of Integer)(CInt(CView.New))
|
ViewMode = .Value(Name_ViewMode).FromXML(Of Integer)(CInt(CView.New))
|
||||||
ViewPeriod = .Value(Name_ViewPeriod).FromXML(Of Integer)(CInt(CPeriod.All))
|
ViewPeriod = .Value(Name_ViewPeriod).FromXML(Of Integer)(CInt(CPeriod.All))
|
||||||
IsChannel = .Value(Name_IsChannel).FromXML(Of Boolean)(False)
|
IsChannel = .Value(Name_IsChannel).FromXML(Of Boolean)(False)
|
||||||
TrueName = .Value(Name_TrueName)
|
|
||||||
RedGifsAccount = .Value(Name_RedGifsAccount)
|
RedGifsAccount = .Value(Name_RedGifsAccount)
|
||||||
RedditAccount = .Value(Name_RedditAccount)
|
RedditAccount = .Value(Name_RedditAccount)
|
||||||
UpdateNames()
|
UpdateNames()
|
||||||
@@ -210,14 +219,14 @@ Namespace API.Reddit
|
|||||||
.Add(Name_ViewMode, CInt(ViewMode))
|
.Add(Name_ViewMode, CInt(ViewMode))
|
||||||
.Add(Name_ViewPeriod, CInt(ViewPeriod))
|
.Add(Name_ViewPeriod, CInt(ViewPeriod))
|
||||||
.Add(Name_IsChannel, IsChannel.BoolToInteger)
|
.Add(Name_IsChannel, IsChannel.BoolToInteger)
|
||||||
.Add(Name_TrueName, TrueName)
|
.Add(Name_TrueName, NameTrue(True))
|
||||||
.Add(Name_RedGifsAccount, RedGifsAccount)
|
.Add(Name_RedGifsAccount, RedGifsAccount)
|
||||||
.Add(Name_RedditAccount, RedditAccount)
|
.Add(Name_RedditAccount, RedditAccount)
|
||||||
End If
|
End If
|
||||||
End With
|
End With
|
||||||
End Sub
|
End Sub
|
||||||
Friend Overrides Function ExchangeOptionsGet() As Object
|
Friend Overrides Function ExchangeOptionsGet() As Object
|
||||||
Return New RedditViewExchange With {.ViewMode = ViewMode, .ViewPeriod = ViewPeriod, .RedGifsAccount = RedGifsAccount, .RedditAccount = RedditAccount}
|
Return New RedditViewExchange(Me)
|
||||||
End Function
|
End Function
|
||||||
Friend Overrides Sub ExchangeOptionsSet(ByVal Obj As Object)
|
Friend Overrides Sub ExchangeOptionsSet(ByVal Obj As Object)
|
||||||
If Not Obj Is Nothing AndAlso TypeOf Obj Is IRedditView Then SetView(DirectCast(Obj, IRedditView))
|
If Not Obj Is Nothing AndAlso TypeOf Obj Is IRedditView Then SetView(DirectCast(Obj, IRedditView))
|
||||||
@@ -230,7 +239,7 @@ Namespace API.Reddit
|
|||||||
If CreatedByChannel And Settings.FromChannelDownloadTopUse And Settings.FromChannelDownloadTop > 0 Then _
|
If CreatedByChannel And Settings.FromChannelDownloadTopUse And Settings.FromChannelDownloadTop > 0 Then _
|
||||||
DownloadTopCount = Settings.FromChannelDownloadTop.Value
|
DownloadTopCount = Settings.FromChannelDownloadTop.Value
|
||||||
If IsChannel Or IsSavedPosts Then UseMD5Comparison = False
|
If IsChannel Or IsSavedPosts Then UseMD5Comparison = False
|
||||||
If IsSavedPosts Then TrueName = MySiteSettings.SavedPostsUserName.Value
|
If IsSavedPosts Then NameTrue = MySiteSettings.SavedPostsUserName.Value
|
||||||
UpdateNames()
|
UpdateNames()
|
||||||
If IsChannelForm Then
|
If IsChannelForm Then
|
||||||
UseMD5Comparison = False
|
UseMD5Comparison = False
|
||||||
@@ -276,8 +285,13 @@ Namespace API.Reddit
|
|||||||
Else
|
Else
|
||||||
GetUserInfo()
|
GetUserInfo()
|
||||||
End If
|
End If
|
||||||
If SaveToCache AndAlso Not Responser.Decoders.Contains(SymbolsConverter.Converters.HTML) Then _
|
If SaveToCache Then
|
||||||
Responser.Decoders.Add(SymbolsConverter.Converters.HTML)
|
DownloadText = False
|
||||||
|
DownloadTextPosts = False
|
||||||
|
DownloadTextSpecialFolder = False
|
||||||
|
If Not Responser.Decoders.Contains(SymbolsConverter.Converters.HTML) Then _
|
||||||
|
Responser.Decoders.Add(SymbolsConverter.Converters.HTML)
|
||||||
|
End If
|
||||||
DownloadDataChannel(String.Empty, Token)
|
DownloadDataChannel(String.Empty, Token)
|
||||||
If ChannelInfo Is Nothing Then _TempPostsList.ListAddList(_TempMediaList.Select(Function(m) m.Post.ID), LNC)
|
If ChannelInfo Is Nothing Then _TempPostsList.ListAddList(_TempMediaList.Select(Function(m) m.Post.ID), LNC)
|
||||||
Else
|
Else
|
||||||
@@ -310,55 +324,59 @@ Namespace API.Reddit
|
|||||||
Dim NewPostDetected As Boolean = False
|
Dim NewPostDetected As Boolean = False
|
||||||
Dim ExistsDetected As Boolean = False
|
Dim ExistsDetected As Boolean = False
|
||||||
Dim IsCrossPost As Predicate(Of EContainer) = Function(e) Not e.Value(Node_CrosspostRootId).IsEmptyString Or Not e.Value(Node_CrosspostParentId).IsEmptyString Or Not e.Value(Node_CrosspostParent).IsEmptyString
|
Dim IsCrossPost As Predicate(Of EContainer) = Function(e) Not e.Value(Node_CrosspostRootId).IsEmptyString Or Not e.Value(Node_CrosspostParentId).IsEmptyString Or Not e.Value(Node_CrosspostParent).IsEmptyString
|
||||||
Dim CheckNode As Predicate(Of EContainer) = Function(e) Not ParseUserMediaOnly OrElse If(e("author")?.Value, "/").ToLower.Equals(TrueName.StringToLower)
|
Dim CheckNode As Predicate(Of EContainer) = Function(e) Not ParseUserMediaOnly OrElse If(e("author")?.Value, "/").ToLower.Equals(NameTrue.StringToLower)
|
||||||
Dim _PostID As Func(Of String) = Function() PostTmp.IfNullOrEmpty(PostID)
|
Dim _PostID As Func(Of String) = Function() PostTmp.IfNullOrEmpty(PostID)
|
||||||
|
|
||||||
URL = $"https://gateway.reddit.com/desktopapi/v1/user/{TrueName}/posts?rtj=only&allow_quarantined=true&allow_over18=1&include=identity&after={POST}&dist=25&sort={View}&t={Period}&layout=classic"
|
'URL = $"https://gateway.reddit.com/desktopapi/v1/user/{NameTrue}/posts?rtj=only&allow_quarantined=true&allow_over18=1&include=identity&after={POST}&dist=25&sort={View}&t={Period}&layout=classic"
|
||||||
|
URL = $"https://oauth.reddit.com/user/{NameTrue}/submitted.json?rtj=only&allow_quarantined=true&allow_over18=1&include=identity&after={POST}&dist=25&sort={View}&t={Period}&layout=classic"
|
||||||
ThrowAny(Token)
|
ThrowAny(Token)
|
||||||
Dim r$ = Responser.GetResponse(URL)
|
Dim r$ = Responser.GetResponse(URL)
|
||||||
If Not r.IsEmptyString Then
|
If Not r.IsEmptyString Then
|
||||||
Using w As EContainer = JsonDocument.Parse(r).XmlIfNothing
|
Using w As EContainer = JsonDocument.Parse(r).XmlIfNothing
|
||||||
If w.Count > 0 Then
|
If w.Count > 0 Then
|
||||||
n = w.GetNode(JsonNodesJson)
|
'n = w.GetNode(JsonNodesJson)
|
||||||
If Not n Is Nothing AndAlso n.Count > 0 Then
|
n = w.GetNode(ChannelJsonNodes)
|
||||||
|
If n.ListExists Then
|
||||||
ProgressPre.ChangeMax(n.Count)
|
ProgressPre.ChangeMax(n.Count)
|
||||||
For Each nn In n
|
For Each nn In n
|
||||||
ProgressPre.Perform()
|
ProgressPre.Perform()
|
||||||
ThrowAny(Token)
|
ThrowAny(Token)
|
||||||
If nn.Count > 0 Then
|
With nn("data")
|
||||||
If CheckNode(nn) Then
|
If .ListExists Then
|
||||||
|
If CheckNode(.Self) Then
|
||||||
|
|
||||||
'Obtain post ID
|
'Obtain post ID
|
||||||
PostTmp = nn.Name
|
PostTmp = .Value("name") '.Name
|
||||||
If PostTmp.IsEmptyString Then PostTmp = nn.Value("id")
|
If PostTmp.IsEmptyString Then PostTmp = .Value("id")
|
||||||
If PostTmp.IsEmptyString Then Continue For
|
If PostTmp.IsEmptyString Then Continue For
|
||||||
'Check for CrossPost
|
'Check for CrossPost
|
||||||
If IsCrossPost(nn) Then
|
If IsCrossPost(.Self) Then
|
||||||
_CrossPosts.ListAddList({nn.Value(Node_CrosspostRootId),
|
_CrossPosts.ListAddList({ .Value(Node_CrosspostRootId),
|
||||||
nn.Value(Node_CrosspostParentId),
|
.Value(Node_CrosspostParentId),
|
||||||
nn.Value(Node_CrosspostParent)}, LNC)
|
.Value(Node_CrosspostParent)}, LNC)
|
||||||
Continue For
|
Continue For
|
||||||
Else
|
Else
|
||||||
If Not _CrossPosts.Contains(PostTmp) Then PostID = PostTmp : PostTmp = String.Empty
|
If Not _CrossPosts.Contains(PostTmp) Then PostID = PostTmp : PostTmp = String.Empty
|
||||||
|
End If
|
||||||
|
|
||||||
|
'Download decision
|
||||||
|
If Not _TempPostsList.Contains(_PostID()) Then
|
||||||
|
NewPostDetected = True
|
||||||
|
_TempPostsList.Add(_PostID())
|
||||||
|
Else
|
||||||
|
If Not _CrossPosts.Contains(_PostID()) Then ExistsDetected = True
|
||||||
|
Continue For
|
||||||
|
End If
|
||||||
|
PostDate = If(.Item("created")?.Value, String.Empty)
|
||||||
|
Select Case CheckDatesLimit(PostDate, DateTrueProvider(IsChannel))
|
||||||
|
Case DateResult.Skip : Continue For
|
||||||
|
Case DateResult.Exit : Exit Sub
|
||||||
|
End Select
|
||||||
|
|
||||||
|
ParseContainer(.Self, _PostID(), PostDate,,, GetTextDocument(.Self))
|
||||||
End If
|
End If
|
||||||
|
|
||||||
'Download decision
|
|
||||||
If Not _TempPostsList.Contains(_PostID()) Then
|
|
||||||
NewPostDetected = True
|
|
||||||
_TempPostsList.Add(_PostID())
|
|
||||||
Else
|
|
||||||
If Not _CrossPosts.Contains(_PostID()) Then ExistsDetected = True
|
|
||||||
Continue For
|
|
||||||
End If
|
|
||||||
If nn.Contains("created") Then PostDate = nn("created").Value Else PostDate = String.Empty
|
|
||||||
Select Case CheckDatesLimit(PostDate, DateTrueProvider(IsChannel))
|
|
||||||
Case DateResult.Skip : Continue For
|
|
||||||
Case DateResult.Exit : Exit Sub
|
|
||||||
End Select
|
|
||||||
|
|
||||||
ParseContainer(nn, _PostID(), PostDate)
|
|
||||||
End If
|
End If
|
||||||
End If
|
End With
|
||||||
Next
|
Next
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
@@ -394,10 +412,10 @@ Namespace API.Reddit
|
|||||||
Dim lDate As Date?
|
Dim lDate As Date?
|
||||||
|
|
||||||
If IsSavedPosts Then
|
If IsSavedPosts Then
|
||||||
URL = $"https://www.reddit.com/user/{TrueName}/saved.json?after={POST}"
|
URL = $"https://www.reddit.com/user/{NameTrue}/saved.json?after={POST}"
|
||||||
If Not POST.IsEmptyString Then Thread.Sleep(savedPostsSleepTimer)
|
If Not POST.IsEmptyString Then Thread.Sleep(savedPostsSleepTimer)
|
||||||
Else
|
Else
|
||||||
URL = $"https://reddit.com/r/{TrueName}/{View}.json?allow_quarantined=true&allow_over18=1&include=identity&after={POST}&dist=25&sort={View}&t={Period}&layout=classic"
|
URL = $"https://reddit.com/r/{NameTrue}/{View}.json?allow_quarantined=true&allow_over18=1&include=identity&after={POST}&dist=25&sort={View}&t={Period}&layout=classic"
|
||||||
End If
|
End If
|
||||||
|
|
||||||
ThrowAny(Token)
|
ThrowAny(Token)
|
||||||
@@ -452,7 +470,7 @@ Namespace API.Reddit
|
|||||||
Continue For
|
Continue For
|
||||||
End If
|
End If
|
||||||
|
|
||||||
ParseContainer(s, PostID, PostDate, _UserID)
|
ParseContainer(s, PostID, PostDate, _UserID,, If(Not SaveToCache, GetTextDocument(s), String.Empty))
|
||||||
End If
|
End If
|
||||||
Next
|
Next
|
||||||
End If
|
End If
|
||||||
@@ -480,7 +498,7 @@ Namespace API.Reddit
|
|||||||
Private Sub GetUserInfo()
|
Private Sub GetUserInfo()
|
||||||
Try
|
Try
|
||||||
If Not IsSavedPosts And ChannelInfo Is Nothing Then
|
If Not IsSavedPosts And ChannelInfo Is Nothing Then
|
||||||
Dim r$ = Responser.GetResponse($"https://reddit.com/{IIf(IsChannel, "r", "user")}/{TrueName}/about.json",, EDP.ReturnValue)
|
Dim r$ = Responser.GetResponse($"https://reddit.com/{IIf(IsChannel, "r", "user")}/{NameTrue}/about.json",, EDP.ReturnValue)
|
||||||
If Not r.IsEmptyString Then
|
If Not r.IsEmptyString Then
|
||||||
Using j As EContainer = JsonDocument.Parse(r)
|
Using j As EContainer = JsonDocument.Parse(r)
|
||||||
If Not j Is Nothing AndAlso j.Contains({"data", "subreddit"}) Then
|
If Not j Is Nothing AndAlso j.Contains({"data", "subreddit"}) Then
|
||||||
@@ -489,20 +507,10 @@ Namespace API.Reddit
|
|||||||
UserSiteNameUpdate(.Value("title"))
|
UserSiteNameUpdate(.Value("title"))
|
||||||
UserDescriptionUpdate(.Value("public_description"))
|
UserDescriptionUpdate(.Value("public_description"))
|
||||||
Dim dir As SFile = MyFile.CutPath
|
Dim dir As SFile = MyFile.CutPath
|
||||||
Dim __getFile As Action(Of String) = Sub(ByVal img As String)
|
Dim fileCrFunc As Func(Of String, SFile) = Function(img) CreateFileFromUrl(img)
|
||||||
If Not img.IsEmptyString Then
|
|
||||||
Dim f As SFile = CreateFileFromUrl(img)
|
|
||||||
If Not f.Name.IsEmptyString Then
|
|
||||||
If f.Extension.IsEmptyString Then f.Extension = "jpg"
|
|
||||||
f.Path = dir.Path
|
|
||||||
If Not f.Exists Then GetWebFile(img, f, EDP.ReturnValue)
|
|
||||||
If f.Exists Then IconBannerDownloaded = True
|
|
||||||
End If
|
|
||||||
End If
|
|
||||||
End Sub
|
|
||||||
If DownloadIconBanner Then
|
If DownloadIconBanner Then
|
||||||
__getFile.Invoke(.Value("icon_img"))
|
SimpleDownloadAvatar(.Value("icon_img"), fileCrFunc)
|
||||||
__getFile.Invoke(.Value("banner_img"))
|
SimpleDownloadAvatar(.Value("banner_img"), fileCrFunc)
|
||||||
End If
|
End If
|
||||||
End With
|
End With
|
||||||
End If
|
End If
|
||||||
@@ -515,7 +523,7 @@ Namespace API.Reddit
|
|||||||
#End Region
|
#End Region
|
||||||
#Region "ParseContainer"
|
#Region "ParseContainer"
|
||||||
Private Function ParseContainer(ByVal e As EContainer, ByVal PostID As String, ByVal PostDate As String, Optional ByVal UserID As String = Nothing,
|
Private Function ParseContainer(ByVal e As EContainer, ByVal PostID As String, ByVal PostDate As String, Optional ByVal UserID As String = Nothing,
|
||||||
Optional ByVal AllowReparse As Boolean = True) As Boolean
|
Optional ByVal AllowReparse As Boolean = True, Optional ByVal PostText As String = Nothing) As Boolean
|
||||||
If Not e Is Nothing Then
|
If Not e Is Nothing Then
|
||||||
Dim UPicType As Func(Of String, UTypes) = Function(input) IIf(input = "image", UTypes.Picture, UTypes.GIF)
|
Dim UPicType As Func(Of String, UTypes) = Function(input) IIf(input = "image", UTypes.Picture, UTypes.GIF)
|
||||||
Dim eCount As Predicate(Of EContainer) = Function(item) item.Count > 0
|
Dim eCount As Predicate(Of EContainer) = Function(item) item.Count > 0
|
||||||
@@ -525,24 +533,24 @@ Namespace API.Reddit
|
|||||||
If SaveToCache Then
|
If SaveToCache Then
|
||||||
tmpUrl = e.Value({"media", "oembed"}, "thumbnail_url")
|
tmpUrl = e.Value({"media", "oembed"}, "thumbnail_url")
|
||||||
If Not tmpUrl.IsEmptyString Then
|
If Not tmpUrl.IsEmptyString Then
|
||||||
_TempMediaList.ListAddValue(MediaFromData(UTypes.Picture, tmpUrl, PostID, PostDate, UserID), LNC)
|
_TempMediaList.ListAddValue(MediaFromData(UTypes.Picture, tmpUrl, PostID, PostDate, UserID,, PostText), LNC)
|
||||||
_TotalPostsDownloaded += 1
|
_TotalPostsDownloaded += 1
|
||||||
Else
|
Else
|
||||||
added = False
|
added = False
|
||||||
End If
|
End If
|
||||||
Else
|
Else
|
||||||
_TempMediaList.ListAddValue(MediaFromData(UTypes.VideoPre, tmpUrl, PostID, PostDate, UserID), LNC)
|
_TempMediaList.ListAddValue(MediaFromData(UTypes.VideoPre, tmpUrl, PostID, PostDate, UserID,, PostText), LNC)
|
||||||
_TotalPostsDownloaded += 1
|
_TotalPostsDownloaded += 1
|
||||||
End If
|
End If
|
||||||
ElseIf CreateImgurMedia(tmpUrl, PostID, PostDate, UserID, IsChannel) Then
|
ElseIf CreateImgurMedia(tmpUrl, PostID, PostDate, UserID, IsChannel, PostText) Then
|
||||||
_TotalPostsDownloaded += 1
|
_TotalPostsDownloaded += 1
|
||||||
ElseIf DownloadGallery(e, PostID, PostDate, UserID, SaveToCache) Then
|
ElseIf DownloadGallery(e, PostID, PostDate, UserID, SaveToCache, PostText) Then
|
||||||
_TotalPostsDownloaded += 1
|
_TotalPostsDownloaded += 1
|
||||||
ElseIf Not If(e({"media"}, "type")?.Value, String.Empty).IsEmptyString Then
|
ElseIf Not If(e({"media"}, "type")?.Value, String.Empty).IsEmptyString Then
|
||||||
With e("media")
|
With e("media")
|
||||||
Dim t$ = .Item("type").Value
|
Dim t$ = .Item("type").Value
|
||||||
Select Case t
|
Select Case t
|
||||||
Case "gallery" : If DownloadGallery(.Self, PostID, PostDate) Then _TotalPostsDownloaded += 1 Else added = False
|
Case "gallery" : If DownloadGallery(.Self, PostID, PostDate,,, PostText) Then _TotalPostsDownloaded += 1 Else added = False
|
||||||
Case "image", "gifvideo"
|
Case "image", "gifvideo"
|
||||||
|
|
||||||
Dim resolution As Sizes = Nothing
|
Dim resolution As Sizes = Nothing
|
||||||
@@ -577,17 +585,17 @@ Namespace API.Reddit
|
|||||||
End If
|
End If
|
||||||
|
|
||||||
If Not chosenVal.IsEmptyString Then
|
If Not chosenVal.IsEmptyString Then
|
||||||
_TempMediaList.ListAddValue(MediaFromData(UPicType(t), chosenVal, PostID, PostDate, UserID), LNC)
|
_TempMediaList.ListAddValue(MediaFromData(UPicType(t), chosenVal, PostID, PostDate, UserID,, PostText), LNC)
|
||||||
_TotalPostsDownloaded += 1
|
_TotalPostsDownloaded += 1
|
||||||
Else
|
Else
|
||||||
added = False
|
added = False
|
||||||
End If
|
End If
|
||||||
Case "video"
|
Case "video"
|
||||||
If UseM3U8 AndAlso .Item("hlsUrl").XmlIfNothingValue("/").ToLower.Contains("m3u8") Then
|
If UseM3U8 AndAlso .Item("hlsUrl").XmlIfNothingValue("/").ToLower.Contains("m3u8") Then
|
||||||
_TempMediaList.ListAddValue(MediaFromData(UTypes.m3u8, .Value("hlsUrl"), PostID, PostDate, UserID), LNC)
|
_TempMediaList.ListAddValue(MediaFromData(UTypes.m3u8, .Value("hlsUrl"), PostID, PostDate, UserID,, PostText), LNC)
|
||||||
_TotalPostsDownloaded += 1
|
_TotalPostsDownloaded += 1
|
||||||
ElseIf Not UseM3U8 AndAlso .Item("fallback_url").XmlIfNothingValue("/").ToLower.Contains("mp4") Then
|
ElseIf Not UseM3U8 AndAlso .Item("fallback_url").XmlIfNothingValue("/").ToLower.Contains("mp4") Then
|
||||||
_TempMediaList.ListAddValue(MediaFromData(UTypes.Video, .Value("fallback_url"), PostID, PostDate, UserID), LNC)
|
_TempMediaList.ListAddValue(MediaFromData(UTypes.Video, .Value("fallback_url"), PostID, PostDate, UserID,, PostText), LNC)
|
||||||
_TotalPostsDownloaded += 1
|
_TotalPostsDownloaded += 1
|
||||||
Else
|
Else
|
||||||
added = False
|
added = False
|
||||||
@@ -600,16 +608,16 @@ Namespace API.Reddit
|
|||||||
If SaveToCache Then
|
If SaveToCache Then
|
||||||
tmpUrl = GetVideoRedditPreview(e)
|
tmpUrl = GetVideoRedditPreview(e)
|
||||||
If Not tmpUrl.IsEmptyString Then
|
If Not tmpUrl.IsEmptyString Then
|
||||||
_TempMediaList.ListAddValue(MediaFromData(UTypes.Picture, tmpUrl, PostID, PostDate, UserID, False), LNC)
|
_TempMediaList.ListAddValue(MediaFromData(UTypes.Picture, tmpUrl, PostID, PostDate, UserID, False, PostText), LNC)
|
||||||
_TotalPostsDownloaded += 1
|
_TotalPostsDownloaded += 1
|
||||||
Else
|
Else
|
||||||
added = False
|
added = False
|
||||||
End If
|
End If
|
||||||
ElseIf UseM3U8 AndAlso Not If(e({"media", "reddit_video"}, "hls_url")?.Value, String.Empty).IsEmptyString Then
|
ElseIf UseM3U8 AndAlso Not If(e({"media", "reddit_video"}, "hls_url")?.Value, String.Empty).IsEmptyString Then
|
||||||
_TempMediaList.ListAddValue(MediaFromData(UTypes.m3u8, e.Value({"media", "reddit_video"}, "hls_url"), PostID, PostDate, UserID), LNC)
|
_TempMediaList.ListAddValue(MediaFromData(UTypes.m3u8, e.Value({"media", "reddit_video"}, "hls_url"), PostID, PostDate, UserID,, PostText), LNC)
|
||||||
_TotalPostsDownloaded += 1
|
_TotalPostsDownloaded += 1
|
||||||
Else
|
Else
|
||||||
_TempMediaList.ListAddValue(MediaFromData(UTypes.Video, tmpUrl, PostID, PostDate, UserID), LNC)
|
_TempMediaList.ListAddValue(MediaFromData(UTypes.Video, tmpUrl, PostID, PostDate, UserID,, PostText), LNC)
|
||||||
_TotalPostsDownloaded += 1
|
_TotalPostsDownloaded += 1
|
||||||
End If
|
End If
|
||||||
Else
|
Else
|
||||||
@@ -618,7 +626,7 @@ Namespace API.Reddit
|
|||||||
If Not added Then
|
If Not added Then
|
||||||
If AllowReparse Then
|
If AllowReparse Then
|
||||||
If If(e.ItemF({"crosspost_parent_list", 0})?.Count, 0) > 0 Then
|
If If(e.ItemF({"crosspost_parent_list", 0})?.Count, 0) > 0 Then
|
||||||
added = ParseContainer(e.ItemF({"crosspost_parent_list", 0}), PostID, PostDate, UserID, True)
|
added = ParseContainer(e.ItemF({"crosspost_parent_list", 0}), PostID, PostDate, UserID, True, PostText)
|
||||||
Else
|
Else
|
||||||
Dim tPostId$ = e.Value(Node_CrosspostParent).IfNullOrEmpty(e.Value(Node_CrosspostParentId)).IfNullOrEmpty(e.Value(Node_CrosspostRootId))
|
Dim tPostId$ = e.Value(Node_CrosspostParent).IfNullOrEmpty(e.Value(Node_CrosspostParentId)).IfNullOrEmpty(e.Value(Node_CrosspostRootId))
|
||||||
If Not PostID.IsEmptyString Then
|
If Not PostID.IsEmptyString Then
|
||||||
@@ -627,7 +635,7 @@ Namespace API.Reddit
|
|||||||
Using j As EContainer = JsonDocument.Parse(r, EDP.ReturnValue)
|
Using j As EContainer = JsonDocument.Parse(r, EDP.ReturnValue)
|
||||||
If j.ListExists Then
|
If j.ListExists Then
|
||||||
With j.ItemF({0, "data", "children", 0, "data"})
|
With j.ItemF({0, "data", "children", 0, "data"})
|
||||||
If .ListExists Then added = ParseContainer(.Self, PostID, PostDate, UserID, False)
|
If .ListExists Then added = ParseContainer(.Self, PostID, PostDate, UserID, False, PostText)
|
||||||
End With
|
End With
|
||||||
End If
|
End If
|
||||||
End Using
|
End Using
|
||||||
@@ -649,7 +657,7 @@ Namespace API.Reddit
|
|||||||
End Select
|
End Select
|
||||||
End With
|
End With
|
||||||
If Not tmpType = UTypes.Undefined Then
|
If Not tmpType = UTypes.Undefined Then
|
||||||
_TempMediaList.ListAddValue(MediaFromData(tmpType, node.Value, PostID, PostDate, UserID), LNC)
|
_TempMediaList.ListAddValue(MediaFromData(tmpType, node.Value, PostID, PostDate, UserID,, PostText), LNC)
|
||||||
added = True
|
added = True
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
@@ -672,7 +680,7 @@ Namespace API.Reddit
|
|||||||
If Not tmpUrl.IsEmptyString Then tmpType = UTypes.Picture
|
If Not tmpUrl.IsEmptyString Then tmpType = UTypes.Picture
|
||||||
End If
|
End If
|
||||||
If Not tmpUrl.IsEmptyString And Not tmpType = UTypes.Undefined Then
|
If Not tmpUrl.IsEmptyString And Not tmpType = UTypes.Undefined Then
|
||||||
Dim m As UserMedia = MediaFromData(tmpType, tmpUrl, PostID, PostDate, UserID)
|
Dim m As UserMedia = MediaFromData(tmpType, tmpUrl, PostID, PostDate, UserID,, PostText)
|
||||||
If tmpType = UTypes.Video Then m.File.Extension = "mp4"
|
If tmpType = UTypes.Video Then m.File.Extension = "mp4"
|
||||||
_TempMediaList.ListAddValue(m, LNC)
|
_TempMediaList.ListAddValue(m, LNC)
|
||||||
_TotalPostsDownloaded += 1
|
_TotalPostsDownloaded += 1
|
||||||
@@ -683,6 +691,7 @@ Namespace API.Reddit
|
|||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
|
If Not added And Not PostText.IsEmptyString Then _TempMediaList.ListAddValue(MediaFromData(UTypes.Text, String.Empty, PostID, PostDate, UserID,, PostText))
|
||||||
Return added
|
Return added
|
||||||
Else
|
Else
|
||||||
Return False
|
Return False
|
||||||
@@ -705,28 +714,45 @@ Namespace API.Reddit
|
|||||||
Return False
|
Return False
|
||||||
End Try
|
End Try
|
||||||
End Function
|
End Function
|
||||||
|
Private Function GetTextDocument(ByVal e As EContainer) As String
|
||||||
|
Dim t$ = String.Empty
|
||||||
|
Try
|
||||||
|
t = e.Value("title")
|
||||||
|
With e({"rtjson", "document"})
|
||||||
|
If .ListExists Then
|
||||||
|
For Each tt As EContainer In .Self
|
||||||
|
t.StringAppendLine(vbCrLf,, False)
|
||||||
|
t.StringAppendLine(If(tt.ItemF({"c", 0, "t"})?.Value, String.Empty))
|
||||||
|
Next
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
Catch
|
||||||
|
End Try
|
||||||
|
Return t
|
||||||
|
End Function
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Download Base Functions"
|
#Region "Download Base Functions"
|
||||||
Private Function CreateImgurMedia(ByVal _URL As String, ByVal PostID As String, ByVal PostDate As String,
|
Private Function CreateImgurMedia(ByVal _URL As String, ByVal PostID As String, ByVal PostDate As String,
|
||||||
Optional ByVal _UserID As String = "", Optional ByVal IsChannel As Boolean = False) As Boolean
|
Optional ByVal _UserID As String = "", Optional ByVal IsChannel As Boolean = False,
|
||||||
|
Optional ByVal PostText As String = Nothing) As Boolean
|
||||||
If Not _URL.IsEmptyString AndAlso _URL.Contains("imgur") Then
|
If Not _URL.IsEmptyString AndAlso _URL.Contains("imgur") Then
|
||||||
If _URL.StringContains({".jpg", ".png", ".jpeg"}) Then
|
If _URL.StringContains({".jpg", ".png", ".jpeg"}) Then
|
||||||
_TempMediaList.ListAddValue(MediaFromData(UTypes.Picture, _URL, PostID, PostDate, _UserID), LNC)
|
_TempMediaList.ListAddValue(MediaFromData(UTypes.Picture, _URL, PostID, PostDate, _UserID,, PostText), LNC)
|
||||||
ElseIf _URL.Contains(".gifv") Then
|
ElseIf _URL.Contains(".gifv") Then
|
||||||
If SaveToCache Then
|
If SaveToCache Then
|
||||||
_TempMediaList.ListAddValue(MediaFromData(UTypes.Picture, _URL.Replace(".gifv", ".gif"), PostID, PostDate, _UserID), LNC)
|
_TempMediaList.ListAddValue(MediaFromData(UTypes.Picture, _URL.Replace(".gifv", ".gif"), PostID, PostDate, _UserID,, PostText), LNC)
|
||||||
Else
|
Else
|
||||||
_TempMediaList.ListAddValue(MediaFromData(UTypes.Video, _URL.Replace(".gifv", ".mp4"), PostID, PostDate, _UserID), LNC)
|
_TempMediaList.ListAddValue(MediaFromData(UTypes.Video, _URL.Replace(".gifv", ".mp4"), PostID, PostDate, _UserID,, PostText), LNC)
|
||||||
End If
|
End If
|
||||||
ElseIf _URL.Contains(".mp4") Then
|
ElseIf _URL.Contains(".mp4") Then
|
||||||
_TempMediaList.ListAddValue(MediaFromData(UTypes.Video, _URL, PostID, PostDate, _UserID), LNC)
|
_TempMediaList.ListAddValue(MediaFromData(UTypes.Video, _URL, PostID, PostDate, _UserID,, PostText), LNC)
|
||||||
ElseIf _URL.Contains(".gif") Then
|
ElseIf _URL.Contains(".gif") Then
|
||||||
_TempMediaList.ListAddValue(MediaFromData(UTypes.GIF, _URL, PostID, PostDate, _UserID), LNC)
|
_TempMediaList.ListAddValue(MediaFromData(UTypes.GIF, _URL, PostID, PostDate, _UserID,, PostText), LNC)
|
||||||
Else
|
Else
|
||||||
Dim obj As IEnumerable(Of UserMedia) = Imgur.Envir.GetVideoInfo(_URL, EDP.ReturnValue)
|
Dim obj As IEnumerable(Of UserMedia) = Imgur.Envir.GetVideoInfo(_URL, EDP.ReturnValue)
|
||||||
If Not obj.ListExists Then
|
If Not obj.ListExists Then
|
||||||
If Not TryFile(_URL) Then _URL &= ".jpg"
|
If Not TryFile(_URL) Then _URL &= ".jpg"
|
||||||
_TempMediaList.ListAddValue(MediaFromData(UTypes.Picture, _URL, PostID, PostDate, _UserID), LNC)
|
_TempMediaList.ListAddValue(MediaFromData(UTypes.Picture, _URL, PostID, PostDate, _UserID,, PostText), LNC)
|
||||||
Else
|
Else
|
||||||
Dim ut As UTypes
|
Dim ut As UTypes
|
||||||
Dim m As UserMedia
|
Dim m As UserMedia
|
||||||
@@ -741,7 +767,7 @@ Namespace API.Reddit
|
|||||||
Case "gif" : ut = UTypes.GIF
|
Case "gif" : ut = UTypes.GIF
|
||||||
Case Else : ut = UTypes.Picture : .File.Extension = "jpg"
|
Case Else : ut = UTypes.Picture : .File.Extension = "jpg"
|
||||||
End Select
|
End Select
|
||||||
m = MediaFromData(ut, _URL, PostID, PostDate, _UserID)
|
m = MediaFromData(ut, _URL, PostID, PostDate, _UserID,, PostText)
|
||||||
m.URL = .URL
|
m.URL = .URL
|
||||||
m.File = .File.File
|
m.File = .File.File
|
||||||
_TempMediaList.ListAddValue(m, LNC)
|
_TempMediaList.ListAddValue(m, LNC)
|
||||||
@@ -757,7 +783,8 @@ Namespace API.Reddit
|
|||||||
End If
|
End If
|
||||||
End Function
|
End Function
|
||||||
Private Function DownloadGallery(ByVal e As EContainer, ByVal PostID As String, ByVal PostDate As String,
|
Private Function DownloadGallery(ByVal e As EContainer, ByVal PostID As String, ByVal PostDate As String,
|
||||||
Optional ByVal _UserID As String = Nothing, Optional ByVal FirstOnly As Boolean = False) As Boolean
|
Optional ByVal _UserID As String = Nothing, Optional ByVal FirstOnly As Boolean = False,
|
||||||
|
Optional ByVal PostText As String = Nothing) As Boolean
|
||||||
Try
|
Try
|
||||||
Dim added As Boolean = False
|
Dim added As Boolean = False
|
||||||
Dim node As EContainer = Nothing
|
Dim node As EContainer = Nothing
|
||||||
@@ -771,7 +798,7 @@ Namespace API.Reddit
|
|||||||
For Each n As EContainer In node
|
For Each n As EContainer In node
|
||||||
t = n.ItemF({"s", "u"})
|
t = n.ItemF({"s", "u"})
|
||||||
If Not t Is Nothing AndAlso Not t.Value.IsEmptyString Then
|
If Not t Is Nothing AndAlso Not t.Value.IsEmptyString Then
|
||||||
_TempMediaList.ListAddValue(MediaFromData(UTypes.Picture, t.Value, PostID, PostDate, _UserID), LNC)
|
_TempMediaList.ListAddValue(MediaFromData(UTypes.Picture, t.Value, PostID, PostDate, _UserID,, PostText), LNC)
|
||||||
added = True
|
added = True
|
||||||
If FirstOnly Then Exit For
|
If FirstOnly Then Exit For
|
||||||
End If
|
End If
|
||||||
@@ -888,7 +915,7 @@ Namespace API.Reddit
|
|||||||
If Not r.IsEmptyString Then
|
If Not r.IsEmptyString Then
|
||||||
v = RegexReplace(r, VideoRegEx)
|
v = RegexReplace(r, VideoRegEx)
|
||||||
If Not v.IsEmptyString Then
|
If Not v.IsEmptyString Then
|
||||||
_TempMediaList(i) = New UserMedia With {.Type = UTypes.Video, .URL = v, .File = v, .Post = m.Post}
|
_TempMediaList(i) = New UserMedia With {.Type = UTypes.Video, .URL = v, .File = v, .Post = m.Post, .PostText = m.PostText, .PostTextFile = m.PostTextFile}
|
||||||
Else
|
Else
|
||||||
_TempMediaList.RemoveAt(i)
|
_TempMediaList.RemoveAt(i)
|
||||||
End If
|
End If
|
||||||
@@ -936,7 +963,7 @@ Namespace API.Reddit
|
|||||||
If j.Count > 0 Then
|
If j.Count > 0 Then
|
||||||
lastCount = _TempMediaList.Count
|
lastCount = _TempMediaList.Count
|
||||||
With j.GetNode(SingleJsonNodes)
|
With j.GetNode(SingleJsonNodes)
|
||||||
If .ListExists AndAlso ParseContainer(.Self, m.Post.ID, String.Empty) Then
|
If .ListExists AndAlso ParseContainer(.Self, m.Post.ID, String.Empty,,, GetTextDocument(.Self)) Then
|
||||||
If lastCount <> _TempMediaList.Count Then
|
If lastCount <> _TempMediaList.Count Then
|
||||||
For li = IIf(lastCount < 0, 0, lastCount) To _TempMediaList.Count - 1
|
For li = IIf(lastCount < 0, 0, lastCount) To _TempMediaList.Count - 1
|
||||||
m2 = _TempMediaList(i)
|
m2 = _TempMediaList(i)
|
||||||
@@ -983,13 +1010,15 @@ Namespace API.Reddit
|
|||||||
#End Region
|
#End Region
|
||||||
#Region "Structure creator"
|
#Region "Structure creator"
|
||||||
Private Function MediaFromData(ByVal t As UTypes, ByVal _URL As String, ByVal PostID As String, ByVal PostDate As String,
|
Private Function MediaFromData(ByVal t As UTypes, ByVal _URL As String, ByVal PostID As String, ByVal PostDate As String,
|
||||||
Optional ByVal _UserID As String = "", Optional ByVal ReplacePreview As Boolean = True) As UserMedia
|
Optional ByVal _UserID As String = "", Optional ByVal ReplacePreview As Boolean = True,
|
||||||
|
Optional ByVal PostText As String = Nothing) As UserMedia
|
||||||
If _URL.IsEmptyString And t = UTypes.Picture Then Return Nothing
|
If _URL.IsEmptyString And t = UTypes.Picture Then Return Nothing
|
||||||
_URL = LinkFormatterSecure(RegexReplace(_URL.Replace("\", String.Empty), LinkPattern))
|
_URL = LinkFormatterSecure(RegexReplace(_URL.Replace("\", String.Empty), LinkPattern))
|
||||||
Dim m As New UserMedia(_URL, t) With {.Post = New UserPost With {.ID = PostID, .UserID = _UserID}}
|
Dim m As New UserMedia(_URL, t) With {.Post = New UserPost With {.ID = PostID, .UserID = _UserID}}
|
||||||
If t = UTypes.Picture Or t = UTypes.GIF Then m.File = CreateFileFromUrl(m.URL) Else m.File = Nothing
|
If t = UTypes.Picture Or t = UTypes.GIF Then m.File = CreateFileFromUrl(m.URL) Else m.File = Nothing
|
||||||
If ReplacePreview And m.URL.Contains("preview") And Not t = UTypes.Picture Then m.URL = $"https://i.redd.it/{m.File.File}"
|
If ReplacePreview And m.URL.Contains("preview") And Not t = UTypes.Picture Then m.URL = $"https://i.redd.it/{m.File.File}"
|
||||||
If Not PostDate.IsEmptyString Then m.Post.Date = AConvert(Of Date)(PostDate, DateTrueProvider(IsChannel Or IsSavedPosts), Nothing) Else m.Post.Date = Nothing
|
If Not PostDate.IsEmptyString Then m.Post.Date = AConvert(Of Date)(PostDate, DateTrueProvider(IsChannel Or IsSavedPosts), Nothing) Else m.Post.Date = Nothing
|
||||||
|
If Not PostText.IsEmptyString Then m.PostText = PostText
|
||||||
Return m
|
Return m
|
||||||
End Function
|
End Function
|
||||||
Private Function TryFile(ByVal URL As String) As Boolean
|
Private Function TryFile(ByVal URL As String) As Boolean
|
||||||
|
|||||||
@@ -31,6 +31,9 @@ Namespace API.RedGifs
|
|||||||
<Provider(NameOf(TokenUpdateInterval), FieldsChecker:=True)>
|
<Provider(NameOf(TokenUpdateInterval), FieldsChecker:=True)>
|
||||||
Private ReadOnly Property TokenUpdateIntervalProvider As IFormatProvider
|
Private ReadOnly Property TokenUpdateIntervalProvider As IFormatProvider
|
||||||
#End Region
|
#End Region
|
||||||
|
<DoNotUse> Friend Overrides Property DownloadText As PropertyValue
|
||||||
|
<DoNotUse> Friend Overrides Property DownloadTextPosts As PropertyValue
|
||||||
|
<DoNotUse> Friend Overrides Property DownloadTextSpecialFolder As PropertyValue
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Initializer"
|
#Region "Initializer"
|
||||||
Friend Sub New(ByVal AccName As String, ByVal Temp As Boolean)
|
Friend Sub New(ByVal AccName As String, ByVal Temp As Boolean)
|
||||||
|
|||||||
@@ -27,6 +27,9 @@ Namespace API.ThisVid
|
|||||||
"If true, then public videos will be stored in the 'Public' folder, private - in the 'Private' folder." & vbCr &
|
"If true, then public videos will be stored in the 'Public' folder, private - in the 'Private' folder." & vbCr &
|
||||||
"If false, all videos will be stored in the 'Video' folder."), PClonable>
|
"If false, all videos will be stored in the 'Video' folder."), PClonable>
|
||||||
Friend ReadOnly Property DifferentFolders As PropertyValue
|
Friend ReadOnly Property DifferentFolders As PropertyValue
|
||||||
|
<DoNotUse> Friend Overrides Property DownloadText As PropertyValue
|
||||||
|
<DoNotUse> Friend Overrides Property DownloadTextPosts As PropertyValue
|
||||||
|
<DoNotUse> Friend Overrides Property DownloadTextSpecialFolder As PropertyValue
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Initializer"
|
#Region "Initializer"
|
||||||
Friend Sub New(ByVal AccName As String, ByVal Temp As Boolean)
|
Friend Sub New(ByVal AccName As String, ByVal Temp As Boolean)
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ Namespace API.ThisVid
|
|||||||
Friend Property DownloadPrivate As Boolean = True
|
Friend Property DownloadPrivate As Boolean = True
|
||||||
Friend Property DownloadFavourite As Boolean = False
|
Friend Property DownloadFavourite As Boolean = False
|
||||||
Friend Property DifferentFolders As Boolean = True
|
Friend Property DifferentFolders As Boolean = True
|
||||||
Friend Property TrueName As String = String.Empty
|
|
||||||
Friend Property SiteMode As SiteModes = SiteModes.User
|
Friend Property SiteMode As SiteModes = SiteModes.User
|
||||||
Private Property Arguments As String = String.Empty
|
Private Property Arguments As String = String.Empty
|
||||||
Friend Overrides ReadOnly Property SpecialLabels As IEnumerable(Of String)
|
Friend Overrides ReadOnly Property SpecialLabels As IEnumerable(Of String)
|
||||||
@@ -80,7 +79,7 @@ Namespace API.ThisVid
|
|||||||
If Not Force OrElse (Not SiteMode = SiteModes.User AndAlso Not NewUrl.IsEmptyString AndAlso MyFileSettings.Exists) Then
|
If Not Force OrElse (Not SiteMode = SiteModes.User AndAlso Not NewUrl.IsEmptyString AndAlso MyFileSettings.Exists) Then
|
||||||
Dim eObj As Plugin.ExchangeOptions = Nothing
|
Dim eObj As Plugin.ExchangeOptions = Nothing
|
||||||
If Force Then eObj = MySettings.IsMyUser(NewUrl)
|
If Force Then eObj = MySettings.IsMyUser(NewUrl)
|
||||||
If (Force And Not eObj.UserName.IsEmptyString) Or (Not Force And TrueName.IsEmptyString) Then
|
If (Force And Not eObj.UserName.IsEmptyString) Or (Not Force And NameTrue(True).IsEmptyString) Then
|
||||||
Dim n$() = If(Force, eObj.UserName, Name).Split("@")
|
Dim n$() = If(Force, eObj.UserName, Name).Split("@")
|
||||||
If n.ListExists(2) Then
|
If n.ListExists(2) Then
|
||||||
|
|
||||||
@@ -98,8 +97,8 @@ Namespace API.ThisVid
|
|||||||
End If
|
End If
|
||||||
__TrueName = n(1)
|
__TrueName = n(1)
|
||||||
|
|
||||||
If Force AndAlso (Not TrueName = __TrueName Or Not SiteMode = __Mode) Then
|
If Force AndAlso (Not NameTrue(True) = __TrueName Or Not SiteMode = __Mode) Then
|
||||||
If ValidateChangeSearchOptions(ToStringForLog, $"{__Mode}: {__TrueName}", $"{SiteMode}: {TrueName}") Then
|
If ValidateChangeSearchOptions(ToStringForLog, $"{__Mode}: {__TrueName}", $"{SiteMode}: {NameTrue(True)}") Then
|
||||||
__ForceApply = True
|
__ForceApply = True
|
||||||
Else
|
Else
|
||||||
Return False
|
Return False
|
||||||
@@ -109,21 +108,21 @@ Namespace API.ThisVid
|
|||||||
Arguments = __Arguments
|
Arguments = __Arguments
|
||||||
Options = If(Force, eObj.Options, Options)
|
Options = If(Force, eObj.Options, Options)
|
||||||
If Not Force Then
|
If Not Force Then
|
||||||
TrueName = __TrueName
|
NameTrue = __TrueName
|
||||||
SiteMode = __Mode
|
SiteMode = __Mode
|
||||||
Settings.Labels.Add(SearchRequestLabelName)
|
Settings.Labels.Add(SearchRequestLabelName)
|
||||||
Labels.ListAddValue(SearchRequestLabelName, LNC)
|
Labels.ListAddValue(SearchRequestLabelName, LNC)
|
||||||
Labels.Sort()
|
Labels.Sort()
|
||||||
UserSiteName = $"{SiteMode}: {TrueName}"
|
UserSiteName = $"{SiteMode}: {NameTrue}"
|
||||||
If FriendlyName.IsEmptyString Then FriendlyName = UserSiteName
|
If FriendlyName.IsEmptyString Then FriendlyName = UserSiteName
|
||||||
ElseIf Force And __ForceApply Then
|
ElseIf Force And __ForceApply Then
|
||||||
TrueName = __TrueName
|
NameTrue = __TrueName
|
||||||
SiteMode = __Mode
|
SiteMode = __Mode
|
||||||
End If
|
End If
|
||||||
Return True
|
Return True
|
||||||
Else
|
Else
|
||||||
SiteMode = SiteModes.User
|
SiteMode = SiteModes.User
|
||||||
TrueName = Name
|
NameTrue = Name
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
@@ -136,7 +135,6 @@ Namespace API.ThisVid
|
|||||||
DownloadPrivate = .Value(Name_DownloadPrivate).FromXML(Of Boolean)(True)
|
DownloadPrivate = .Value(Name_DownloadPrivate).FromXML(Of Boolean)(True)
|
||||||
DownloadFavourite = .Value(Name_DownloadFavourite).FromXML(Of Boolean)(False)
|
DownloadFavourite = .Value(Name_DownloadFavourite).FromXML(Of Boolean)(False)
|
||||||
DifferentFolders = .Value(Name_DifferentFolders).FromXML(Of Boolean)(True)
|
DifferentFolders = .Value(Name_DifferentFolders).FromXML(Of Boolean)(True)
|
||||||
TrueName = .Value(Name_TrueName)
|
|
||||||
SiteMode = .Value(Name_SiteMode).FromXML(Of Integer)(SiteModes.User)
|
SiteMode = .Value(Name_SiteMode).FromXML(Of Integer)(SiteModes.User)
|
||||||
Arguments = .Value(Name_Arguments)
|
Arguments = .Value(Name_Arguments)
|
||||||
UpdateUserOptions()
|
UpdateUserOptions()
|
||||||
@@ -150,7 +148,7 @@ Namespace API.ThisVid
|
|||||||
.Add(Name_DownloadPrivate, DownloadPrivate.BoolToInteger)
|
.Add(Name_DownloadPrivate, DownloadPrivate.BoolToInteger)
|
||||||
.Add(Name_DownloadFavourite, DownloadFavourite.BoolToInteger)
|
.Add(Name_DownloadFavourite, DownloadFavourite.BoolToInteger)
|
||||||
.Add(Name_DifferentFolders, DifferentFolders.BoolToInteger)
|
.Add(Name_DifferentFolders, DifferentFolders.BoolToInteger)
|
||||||
.Add(Name_TrueName, TrueName)
|
.Add(Name_TrueName, NameTrue(True))
|
||||||
.Add(Name_SiteMode, CInt(SiteMode))
|
.Add(Name_SiteMode, CInt(SiteMode))
|
||||||
.Add(Name_Arguments, Arguments)
|
.Add(Name_Arguments, Arguments)
|
||||||
|
|
||||||
@@ -259,18 +257,18 @@ Namespace API.ThisVid
|
|||||||
Dim url$ = String.Empty
|
Dim url$ = String.Empty
|
||||||
Select Case SiteMode
|
Select Case SiteMode
|
||||||
Case SiteModes.Tags
|
Case SiteModes.Tags
|
||||||
url = $"https://thisvid.com/{SiteSettings.P_Tags}/{TrueName}/"
|
url = $"https://thisvid.com/{SiteSettings.P_Tags}/{NameTrue}/"
|
||||||
If Not Arguments.IsEmptyString Then url &= $"{Arguments}/"
|
If Not Arguments.IsEmptyString Then url &= $"{Arguments}/"
|
||||||
If Page > 1 Then url &= $"{Page}/"
|
If Page > 1 Then url &= $"{Page}/"
|
||||||
Case SiteModes.Categories
|
Case SiteModes.Categories
|
||||||
url = $"https://thisvid.com/{SiteSettings.P_Categories}/{TrueName}/"
|
url = $"https://thisvid.com/{SiteSettings.P_Categories}/{NameTrue}/"
|
||||||
If Not Arguments.IsEmptyString Then url &= $"{Arguments}/"
|
If Not Arguments.IsEmptyString Then url &= $"{Arguments}/"
|
||||||
If Page > 1 Then url &= $"{Page}/"
|
If Page > 1 Then url &= $"{Page}/"
|
||||||
Case SiteModes.Search
|
Case SiteModes.Search
|
||||||
If Not Arguments.IsEmptyString Then
|
If Not Arguments.IsEmptyString Then
|
||||||
url = $"https://thisvid.com/{Arguments}/"
|
url = $"https://thisvid.com/{Arguments}/"
|
||||||
If Page > 1 Then url &= $"{Page}/"
|
If Page > 1 Then url &= $"{Page}/"
|
||||||
url &= $"?q={TrueName}/"
|
url &= $"?q={NameTrue}/"
|
||||||
End If
|
End If
|
||||||
End Select
|
End Select
|
||||||
Return url
|
Return url
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ Imports PersonalUtilities.Functions.RegularExpressions
|
|||||||
Imports IG = SCrawler.API.Instagram.SiteSettings
|
Imports IG = SCrawler.API.Instagram.SiteSettings
|
||||||
Imports DN = SCrawler.API.Base.DeclaredNames
|
Imports DN = SCrawler.API.Base.DeclaredNames
|
||||||
Namespace API.ThreadsNet
|
Namespace API.ThreadsNet
|
||||||
<Manifest("AndyProgram_ThreadsNet"), SavedPosts, SeparatedTasks(1)>
|
<Manifest("AndyProgram_ThreadsNet"), SavedPosts, SeparatedTasks(1), SpecialForm(False)>
|
||||||
Friend Class SiteSettings : Inherits SiteSettingsBase
|
Friend Class SiteSettings : Inherits SiteSettingsBase
|
||||||
#Region "Declarations"
|
#Region "Declarations"
|
||||||
#Region "Authorization"
|
#Region "Authorization"
|
||||||
@@ -89,7 +89,7 @@ Namespace API.ThreadsNet
|
|||||||
#End Region
|
#End Region
|
||||||
#Region "Initializer"
|
#Region "Initializer"
|
||||||
Friend Sub New(ByVal AccName As String, ByVal Temp As Boolean)
|
Friend Sub New(ByVal AccName As String, ByVal Temp As Boolean)
|
||||||
Me.New("Threads", "threads.net", AccName, Temp, My.Resources.SiteResources.ThreadsIcon_192, My.Resources.SiteResources.ThreadsIcon_192.ToBitmap)
|
Me.New("Threads", "threads.com", AccName, Temp, My.Resources.SiteResources.ThreadsIcon_192, My.Resources.SiteResources.ThreadsIcon_192.ToBitmap)
|
||||||
End Sub
|
End Sub
|
||||||
Protected Sub New(ByVal SiteName As String, ByVal CookiesDomain As String, ByVal AccName As String, ByVal Temp As Boolean,
|
Protected Sub New(ByVal SiteName As String, ByVal CookiesDomain As String, ByVal AccName As String, ByVal Temp As Boolean,
|
||||||
Optional ByVal __Icon As Icon = Nothing, Optional ByVal __Image As Image = Nothing)
|
Optional ByVal __Icon As Icon = Nothing, Optional ByVal __Image As Image = Nothing)
|
||||||
@@ -118,8 +118,8 @@ Namespace API.ThreadsNet
|
|||||||
browserExt = .Value(IG.Header_BrowserExt)
|
browserExt = .Value(IG.Header_BrowserExt)
|
||||||
platform = .Value(IG.Header_Platform_Verion)
|
platform = .Value(IG.Header_Platform_Verion)
|
||||||
End If
|
End If
|
||||||
.Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.Authority, "www.threads.net"))
|
.Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.Authority, "www.threads.com"))
|
||||||
.Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.Origin, "https://www.threads.net"))
|
.Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.Origin, "https://www.threads.com"))
|
||||||
.Add("Upgrade-Insecure-Requests", 1)
|
.Add("Upgrade-Insecure-Requests", 1)
|
||||||
.Add("Sec-Ch-Ua-Model", "")
|
.Add("Sec-Ch-Ua-Model", "")
|
||||||
.Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.SecChUaMobile, "?0"))
|
.Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.SecChUaMobile, "?0"))
|
||||||
@@ -152,9 +152,10 @@ Namespace API.ThreadsNet
|
|||||||
RequestsWaitTimer_AnyProvider = New IG.TimersChecker(0)
|
RequestsWaitTimer_AnyProvider = New IG.TimersChecker(0)
|
||||||
DownloadData_Impl = New PropertyValue(True)
|
DownloadData_Impl = New PropertyValue(True)
|
||||||
|
|
||||||
UrlPatternUser = "https://www.threads.net/@{0}"
|
UrlPatternUser = "https://www.threads.com/@{0}"
|
||||||
UserRegex = RParams.DMS(String.Format(UserRegexDefaultPattern, "threads.net/@"), 1)
|
UserRegex = RParams.DMS(String.Format(UserRegexDefaultPattern, "threads.(net|com)/@"), 2)
|
||||||
ImageVideoContains = "threads.net"
|
ImageVideoContains = "threads.com"
|
||||||
|
UserOptionsType = GetType(EditorExchangeOptionsBase)
|
||||||
End Sub
|
End Sub
|
||||||
#End Region
|
#End Region
|
||||||
#Region "UpdateResponserData"
|
#Region "UpdateResponserData"
|
||||||
@@ -180,14 +181,11 @@ Namespace API.ThreadsNet
|
|||||||
Friend Overrides Function BaseAuthExists() As Boolean
|
Friend Overrides Function BaseAuthExists() As Boolean
|
||||||
Return Responser.CookiesExists And {HH_CSRF_TOKEN, HH_IG_APP_ID}.All(Function(v) ACheck(Of String)(v.Value)) And CBool(DownloadData_Impl.Value)
|
Return Responser.CookiesExists And {HH_CSRF_TOKEN, HH_IG_APP_ID}.All(Function(v) ACheck(Of String)(v.Value)) And CBool(DownloadData_Impl.Value)
|
||||||
End Function
|
End Function
|
||||||
Friend Overrides Function GetUserUrl(ByVal User As IPluginContentProvider) As String
|
|
||||||
Return String.Format(UrlPatternUser, DirectCast(User, UserData).NameTrue)
|
|
||||||
End Function
|
|
||||||
Friend Overrides Function GetUserPostUrl(ByVal User As UserDataBase, ByVal Media As UserMedia) As String
|
Friend Overrides Function GetUserPostUrl(ByVal User As UserDataBase, ByVal Media As UserMedia) As String
|
||||||
Try
|
Try
|
||||||
Dim code$ = DirectCast(User, UserData).GetPostCodeById(Media.Post.ID)
|
Dim code$ = DirectCast(User, UserData).GetPostCodeById(Media.Post.ID)
|
||||||
Dim name$ = DirectCast(User, UserData).NameTrue
|
Dim name$ = DirectCast(User, UserData).NameTrue
|
||||||
If Not code.IsEmptyString Then Return $"https://www.threads.net/@{name}/post/{code}/" Else Return String.Empty
|
If Not code.IsEmptyString Then Return $"https://www.threads.com/@{name}/post/{code}/" Else Return String.Empty
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
Return ErrorsDescriber.Execute(EDP.SendToLog, ex, "Can't open user's post", String.Empty)
|
Return ErrorsDescriber.Execute(EDP.SendToLog, ex, "Can't open user's post", String.Empty)
|
||||||
End Try
|
End Try
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
' This program is distributed in the hope that it will be useful,
|
' This program is distributed in the hope that it will be useful,
|
||||||
' but WITHOUT ANY WARRANTY
|
' but WITHOUT ANY WARRANTY
|
||||||
Imports System.Threading
|
Imports System.Threading
|
||||||
|
Imports SCrawler.Plugin
|
||||||
Imports SCrawler.API.Base
|
Imports SCrawler.API.Base
|
||||||
Imports SCrawler.API.YouTube.Objects
|
Imports SCrawler.API.YouTube.Objects
|
||||||
Imports PersonalUtilities.Functions.XML
|
Imports PersonalUtilities.Functions.XML
|
||||||
@@ -51,9 +52,10 @@ Namespace API.ThreadsNet
|
|||||||
#End Region
|
#End Region
|
||||||
#Region "Exchange"
|
#Region "Exchange"
|
||||||
Friend Overrides Function ExchangeOptionsGet() As Object
|
Friend Overrides Function ExchangeOptionsGet() As Object
|
||||||
Return Nothing
|
Return New EditorExchangeOptionsBase(Me)
|
||||||
End Function
|
End Function
|
||||||
Friend Overrides Sub ExchangeOptionsSet(ByVal Obj As Object)
|
Friend Overrides Sub ExchangeOptionsSet(ByVal Obj As Object)
|
||||||
|
If Not Obj Is Nothing AndAlso TypeOf Obj Is EditorExchangeOptionsBase Then DirectCast(Obj, EditorExchangeOptionsBase).ApplyBase(Me)
|
||||||
End Sub
|
End Sub
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Initializer"
|
#Region "Initializer"
|
||||||
@@ -61,7 +63,7 @@ Namespace API.ThreadsNet
|
|||||||
ObtainMedia_SetReelsFunc()
|
ObtainMedia_SetReelsFunc()
|
||||||
ObtainMedia_AllowAbstract = True
|
ObtainMedia_AllowAbstract = True
|
||||||
DefaultParser_ElemNode = DefaultParser_ElemNode_Default
|
DefaultParser_ElemNode = DefaultParser_ElemNode_Default
|
||||||
DefaultParser_PostUrlCreator = Function(post) $"https://www.threads.net/@{NameTrue}/post/{post.Code}"
|
DefaultParser_PostUrlCreator = Function(post) $"https://www.threads.com/@{NameTrue}/post/{post.Code}"
|
||||||
_ResponserAutoUpdateCookies = True
|
_ResponserAutoUpdateCookies = True
|
||||||
_ResponserAddResponseReceivedHandler = True
|
_ResponserAddResponseReceivedHandler = True
|
||||||
DefaultParser_Pinned = AddressOf IsPinnedPost
|
DefaultParser_Pinned = AddressOf IsPinnedPost
|
||||||
@@ -73,12 +75,13 @@ Namespace API.ThreadsNet
|
|||||||
End Sub
|
End Sub
|
||||||
Private Sub DisableDownload()
|
Private Sub DisableDownload()
|
||||||
MySettings.DownloadData_Impl.Value = False
|
MySettings.DownloadData_Impl.Value = False
|
||||||
MyMainLOG = $"{Site} downloading is disabled until you update your credentials"
|
LogError(Nothing, $"{Site} downloading is disabled until you update your credentials")
|
||||||
End Sub
|
End Sub
|
||||||
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
|
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
|
||||||
If CBool(MySettings.DownloadData_Impl.Value) Then
|
If CBool(MySettings.DownloadData_Impl.Value) Then
|
||||||
Dim errorFound As Boolean = False
|
Dim errorFound As Boolean = False
|
||||||
Try
|
Try
|
||||||
|
_IdChanged = False
|
||||||
Responser.Method = "POST"
|
Responser.Method = "POST"
|
||||||
LoadSavePostsKV(True)
|
LoadSavePostsKV(True)
|
||||||
ResetBaseTokens()
|
ResetBaseTokens()
|
||||||
@@ -103,9 +106,9 @@ Namespace API.ThreadsNet
|
|||||||
End If
|
End If
|
||||||
If IsSavedPosts Then
|
If IsSavedPosts Then
|
||||||
DefaultParser_ElemNode = {"node", "thread_items", 0, "post"}
|
DefaultParser_ElemNode = {"node", "thread_items", 0, "post"}
|
||||||
DownloadSavedPosts(String.Empty, Token)
|
DownloadSavedPosts(String.Empty, 0, Token)
|
||||||
Else
|
Else
|
||||||
DownloadData(String.Empty, Token)
|
DownloadData(String.Empty, 0, Token)
|
||||||
End If
|
End If
|
||||||
If _TempMediaList.Count > 0 Then FirstLoadingDone = True : setMaxPostDate.Invoke(_TempMediaList)
|
If _TempMediaList.Count > 0 Then FirstLoadingDone = True : setMaxPostDate.Invoke(_TempMediaList)
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
@@ -125,10 +128,13 @@ Namespace API.ThreadsNet
|
|||||||
If IsSavedPosts Then
|
If IsSavedPosts Then
|
||||||
Return False
|
Return False
|
||||||
Else
|
Else
|
||||||
If MaxLastDownDate.HasValue Then
|
With Items(Index).ItemF(DefaultParser_ElemNode)
|
||||||
Dim d As Date? = AConvert(Of Date)(Items(Index).ItemF(DefaultParser_ElemNode_Default).Value("taken_at"), UnixDate32Provider, Nothing)
|
Return .Value({"text_post_app_info", "pinned_post_info"}, "is_pinned_to_profile").FromXML(Of Boolean)(False)
|
||||||
If d.HasValue Then Return d.Value < MaxLastDownDate.Value
|
If MaxLastDownDate.HasValue Then
|
||||||
End If
|
Dim d As Date? = AConvert(Of Date)(.Value("taken_at"), UnixDate32Provider, Nothing)
|
||||||
|
If d.HasValue Then Return d.Value <= MaxLastDownDate.Value
|
||||||
|
End If
|
||||||
|
End With
|
||||||
Return Not FirstLoadingDone
|
Return Not FirstLoadingDone
|
||||||
End If
|
End If
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
@@ -151,12 +157,14 @@ Namespace API.ThreadsNet
|
|||||||
Responser.Headers.Add(IGS.Header_CSRF_TOKEN, csrf)
|
Responser.Headers.Add(IGS.Header_CSRF_TOKEN, csrf)
|
||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
Private Const GQL_Q As String = "https://www.threads.net/api/graphql?lsd={0}&fb_dtsg={1}&doc_id={2}&fb_api_req_friendly_name={3}&server_timestamps=true&variables={4}"
|
'Private Const GQL_Q As String = "https://www.threads.com/api/graphql?lsd={0}&fb_dtsg={1}&doc_id={2}&fb_api_req_friendly_name={3}&server_timestamps=true&variables={4}"
|
||||||
Private Const GQL_P_DOC_ID As String = "6371597506283707"
|
Private Const GQL_Q2 As String = "https://www.threads.com/graphql/query"
|
||||||
Private Const GQL_P_NAME As String = "BarcelonaProfileThreadsTabRefetchableQuery"
|
Private Const PayloadData As String = "lsd={0}&fb_dtsg={1}&doc_id={2}&fb_api_req_friendly_name={3}&server_timestamps=true&variables={4}"
|
||||||
Private Const GQL_S_DOC_ID_1 As String = "7758166704280174"
|
Private Const GQL_P_DOC_ID As String = "9039187972876777" '"8779269398849532" '"6371597506283707"
|
||||||
Private Const GQL_S_NAME_1 As String = "BarcelonaSavedPageViewerQuery"
|
Private Const GQL_P_NAME As String = "BarcelonaProfileThreadsTabRefetchableDirectQuery" '"BarcelonaProfileThreadsTabRefetchableQuery"
|
||||||
Private Const GQL_S_DOC_ID_2 As String = "8617275414954442"
|
'Private Const GQL_S_DOC_ID_1 As String = "9227844190587889" '"7758166704280174"
|
||||||
|
'Private Const GQL_S_NAME_1 As String = "BarcelonaSavedPageViewerQuery"
|
||||||
|
Private Const GQL_S_DOC_ID_2 As String = "9116629201788321" '"8617275414954442"
|
||||||
Private Const GQL_S_NAME_2 As String = "BarcelonaSavedPageRefetchableQuery"
|
Private Const GQL_S_NAME_2 As String = "BarcelonaSavedPageRefetchableQuery"
|
||||||
Private Sub DownloadCheckCredentials()
|
Private Sub DownloadCheckCredentials()
|
||||||
If Not Valid Then
|
If Not Valid Then
|
||||||
@@ -166,108 +174,191 @@ Namespace API.ThreadsNet
|
|||||||
End If
|
End If
|
||||||
If Not Valid Then DisableDownload() : Throw New Plugin.ExitException("Some credentials are missing")
|
If Not Valid Then DisableDownload() : Throw New Plugin.ExitException("Some credentials are missing")
|
||||||
End Sub
|
End Sub
|
||||||
Private Overloads Sub DownloadData(ByVal Cursor As String, ByVal Token As CancellationToken)
|
Private Function CheckErrors(ByVal e As EContainer) As Boolean
|
||||||
Const var_init$ = """userID"":""{0}"""
|
Return e.ListExists AndAlso Not JsonErrorMessage(e).IsEmptyString
|
||||||
Const var_cursor$ = """after"":""{1}"",""before"":null,""first"":25,""last"":null,""userID"":""{0}"",""__relay_internal__pv__BarcelonaIsLoggedInrelayprovider"":true,""__relay_internal__pv__BarcelonaIsFeedbackHubEnabledrelayprovider"":false"
|
End Function
|
||||||
Dim URL$ = String.Empty
|
Private Function JsonErrorMessage(ByVal e As EContainer) As String
|
||||||
|
Return e.ItemF({"errors", 0, "summary"})?.Value
|
||||||
|
End Function
|
||||||
|
Private Sub ProcessJsonErrorException(ByVal uex As JsonErrorException, Optional ByVal ThrowEx As Boolean = True)
|
||||||
|
If uex.UserNotFound Then
|
||||||
|
UserExists = False
|
||||||
|
_ForceSaveUserInfo = True
|
||||||
|
_ForceSaveUserInfoOnException = True
|
||||||
|
ElseIf ThrowEx Then
|
||||||
|
Throw New ExitException(uex.ErrMessage) With {.SimpleLogLine = True}
|
||||||
|
Else
|
||||||
|
LogError(Nothing, uex.ErrMessage)
|
||||||
|
End If
|
||||||
|
End Sub
|
||||||
|
Private Class JsonErrorException : Inherits Exception
|
||||||
|
Friend Property UserNotFound As Boolean = False
|
||||||
|
Private _ErrMessage As String = String.Empty
|
||||||
|
Public Property ErrMessage As String
|
||||||
|
Get
|
||||||
|
Return _ErrMessage
|
||||||
|
End Get
|
||||||
|
Set(ByVal m As String)
|
||||||
|
_ErrMessage = m
|
||||||
|
UserNotFound = _ErrMessage.StringToLower = "not found"
|
||||||
|
End Set
|
||||||
|
End Property
|
||||||
|
Public Overrides ReadOnly Property Message As String
|
||||||
|
Get
|
||||||
|
Return _ErrMessage
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
|
Friend Sub New()
|
||||||
|
End Sub
|
||||||
|
Friend Sub New(ByVal Message As String)
|
||||||
|
ErrMessage = Message
|
||||||
|
End Sub
|
||||||
|
End Class
|
||||||
|
Private Overloads Sub DownloadData(ByVal Cursor As String, ByVal Round As Integer, ByVal Token As CancellationToken)
|
||||||
|
'Const var_init$ = """userID"":""{0}"""
|
||||||
|
'Const var_cursor$ = """after"":""{1}"",""before"":null,""first"":25,""last"":null,""userID"":""{0}"",""__relay_internal__pv__BarcelonaIsLoggedInrelayprovider"":true,""__relay_internal__pv__BarcelonaIsFeedbackHubEnabledrelayprovider"":false"
|
||||||
|
Const var_cursor2$ = """after"":{1},""before"":null,""first"":10,""last"":null,""userID"":""{0}"",""__relay_internal__pv__BarcelonaIsLoggedInrelayprovider"":true,""__relay_internal__pv__BarcelonaHasSelfReplyContextrelayprovider"":false,""__relay_internal__pv__BarcelonaShareableListsrelayprovider"":true,""__relay_internal__pv__BarcelonaIsSearchDiscoveryEnabledrelayprovider"":false,""__relay_internal__pv__BarcelonaOptionalCookiesEnabledrelayprovider"":true,""__relay_internal__pv__BarcelonaQuotedPostUFIEnabledrelayprovider"":false,""__relay_internal__pv__BarcelonaIsCrawlerrelayprovider"":false,""__relay_internal__pv__BarcelonaHasDisplayNamesrelayprovider"":false,""__relay_internal__pv__BarcelonaCanSeeSponsoredContentrelayprovider"":false,""__relay_internal__pv__BarcelonaShouldShowFediverseM075Featuresrelayprovider"":true,""__relay_internal__pv__BarcelonaShouldShowTagRedesignrelayprovider"":false,""__relay_internal__pv__BarcelonaIsInternalUserrelayprovider"":false"
|
||||||
Try
|
Try
|
||||||
DownloadCheckCredentials()
|
DownloadCheckCredentials()
|
||||||
|
|
||||||
Responser.Method = "POST"
|
With Responser
|
||||||
Responser.Referer = $"https://www.threads.net/@{NameTrue}"
|
.Method = "POST"
|
||||||
Responser.Headers.Add(GQL_HEADER_FB_LSD, Token_lsd)
|
.Referer = $"https://www.threads.com/@{NameTrue}"
|
||||||
Responser.Headers.Add(GQL_HEADER_FB_FRINDLY_NAME, GQL_P_NAME)
|
.ContentType = "application/x-www-form-urlencoded"
|
||||||
|
With .Headers
|
||||||
|
.Add(GQL_HEADER_FB_LSD, Token_lsd)
|
||||||
|
.Add(GQL_HEADER_FB_FRINDLY_NAME, GQL_P_NAME)
|
||||||
|
End With
|
||||||
|
End With
|
||||||
|
|
||||||
Dim nextCursor$ = String.Empty
|
Dim nextCursor$ = String.Empty
|
||||||
Dim dataFound As Boolean = False
|
Dim dataFound As Boolean = False
|
||||||
|
|
||||||
Dim vars$
|
Dim vars$ = String.Format(var_cursor2, ID, IIf(Cursor.IsEmptyString, "null", $"""{Cursor}"""))
|
||||||
If Cursor.IsEmptyString Then
|
'If Cursor.IsEmptyString Then
|
||||||
vars = String.Format(var_init, ID)
|
' vars = String.Format(var_init, ID)
|
||||||
Else
|
'Else
|
||||||
vars = String.Format(var_cursor, ID, Cursor)
|
' vars = String.Format(var_cursor, ID, Cursor)
|
||||||
End If
|
'End If
|
||||||
vars = SymbolsConverter.ASCII.EncodeSymbolsOnly("{" & vars & "}")
|
vars = String.Format(PayloadData, Token_lsd, Token_dtsg_Var, GQL_P_DOC_ID, GQL_P_NAME,
|
||||||
|
SymbolsConverter.ASCII.EncodeSymbolsOnly("{" & vars & "}"))
|
||||||
|
|
||||||
URL = String.Format(GQL_Q, Token_lsd, Token_dtsg_Var, GQL_P_DOC_ID, GQL_P_NAME, vars)
|
'URL = String.Format(GQL_Q, Token_lsd, Token_dtsg_Var, GQL_P_DOC_ID, GQL_P_NAME, vars)
|
||||||
|
|
||||||
Using j As EContainer = GetDocument(URL, Token)
|
Using j As EContainer = GetDocument(GQL_Q2, vars, Token)
|
||||||
If j.ListExists Then
|
If Not CheckErrors(j) Then
|
||||||
With j({"data", "mediaData"})
|
If j.ListExists Then
|
||||||
If .ListExists Then
|
With j({"data", "mediaData"})
|
||||||
nextCursor = .Value({"page_info"}, "end_cursor")
|
If .ListExists Then
|
||||||
With .Item({"edges"})
|
nextCursor = .Value({"page_info"}, "end_cursor")
|
||||||
If .ListExists Then dataFound = DefaultParser(.Self, Sections.Timeline, Token)
|
With .Item({"edges"})
|
||||||
End With
|
If .ListExists Then dataFound = DefaultParser(.Self, Sections.Timeline, Token)
|
||||||
End If
|
End With
|
||||||
End With
|
End If
|
||||||
|
End With
|
||||||
|
End If
|
||||||
|
Else
|
||||||
|
Throw New JsonErrorException(JsonErrorMessage(j))
|
||||||
End If
|
End If
|
||||||
End Using
|
End Using
|
||||||
|
|
||||||
If dataFound And Not nextCursor.IsEmptyString Then DownloadData(nextCursor, Token)
|
If dataFound And Not nextCursor.IsEmptyString Then DownloadData(nextCursor, 0, Token)
|
||||||
|
Catch uex As JsonErrorException
|
||||||
|
If Round > 0 Then
|
||||||
|
ProcessJsonErrorException(uex)
|
||||||
|
ElseIf Not _IdChanged AndAlso UpdateCredentials() Then
|
||||||
|
DownloadData(Cursor, Round + 1, Token)
|
||||||
|
Else
|
||||||
|
ProcessJsonErrorException(uex)
|
||||||
|
End If
|
||||||
|
Catch eex As ExitException
|
||||||
|
Throw eex
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
ProcessException(ex, Token, $"data downloading error [{URL}]")
|
ProcessException(ex, Token, "data downloading error")
|
||||||
End Try
|
End Try
|
||||||
End Sub
|
End Sub
|
||||||
Private Sub DownloadSavedPosts(ByVal Cursor As String, ByVal Token As CancellationToken)
|
Private Sub DownloadSavedPosts(ByVal Cursor As String, ByVal Round As Integer, ByVal Token As CancellationToken)
|
||||||
Const var_init$ = """__relay_internal__pv__BarcelonaIsLoggedInrelayprovider"":true,""__relay_internal__pv__BarcelonaIsInlineReelsEnabledrelayprovider"":false,""__relay_internal__pv__BarcelonaUseCometVideoPlaybackEnginerelayprovider"":false,""__relay_internal__pv__BarcelonaOptionalCookiesEnabledrelayprovider"":true,""__relay_internal__pv__BarcelonaIsTextFragmentsEnabledForPostCaptionsrelayprovider"":true,""__relay_internal__pv__BarcelonaShouldShowFediverseM075Featuresrelayprovider"":true"
|
'Const var_init$ = """__relay_internal__pv__BarcelonaIsLoggedInrelayprovider"":true,""__relay_internal__pv__BarcelonaIsInlineReelsEnabledrelayprovider"":false,""__relay_internal__pv__BarcelonaUseCometVideoPlaybackEnginerelayprovider"":false,""__relay_internal__pv__BarcelonaOptionalCookiesEnabledrelayprovider"":true,""__relay_internal__pv__BarcelonaIsTextFragmentsEnabledForPostCaptionsrelayprovider"":true,""__relay_internal__pv__BarcelonaShouldShowFediverseM075Featuresrelayprovider"":true"
|
||||||
Const var_cursor$ = """after"":""{0}"",""first"":25,""__relay_internal__pv__BarcelonaIsLoggedInrelayprovider"":true,""__relay_internal__pv__BarcelonaIsInlineReelsEnabledrelayprovider"":false,""__relay_internal__pv__BarcelonaUseCometVideoPlaybackEnginerelayprovider"":false,""__relay_internal__pv__BarcelonaOptionalCookiesEnabledrelayprovider"":true,""__relay_internal__pv__BarcelonaIsTextFragmentsEnabledForPostCaptionsrelayprovider"":true,""__relay_internal__pv__BarcelonaShouldShowFediverseM075Featuresrelayprovider"":true"
|
'Const var_cursor$ = """after"":""{0}"",""first"":25,""__relay_internal__pv__BarcelonaIsLoggedInrelayprovider"":true,""__relay_internal__pv__BarcelonaIsInlineReelsEnabledrelayprovider"":false,""__relay_internal__pv__BarcelonaUseCometVideoPlaybackEnginerelayprovider"":false,""__relay_internal__pv__BarcelonaOptionalCookiesEnabledrelayprovider"":true,""__relay_internal__pv__BarcelonaIsTextFragmentsEnabledForPostCaptionsrelayprovider"":true,""__relay_internal__pv__BarcelonaShouldShowFediverseM075Featuresrelayprovider"":true"
|
||||||
Dim URL$ = String.Empty
|
Const var_cursor2$ = """after"":{0},""first"":25,""__relay_internal__pv__BarcelonaQuotedPostUFIEnabledrelayprovider"":false,""__relay_internal__pv__BarcelonaIsLoggedInrelayprovider"":true,""__relay_internal__pv__BarcelonaHasSelfReplyContextrelayprovider"":false,""__relay_internal__pv__BarcelonaShareableListsrelayprovider"":true,""__relay_internal__pv__BarcelonaIsSearchDiscoveryEnabledrelayprovider"":false,""__relay_internal__pv__BarcelonaOptionalCookiesEnabledrelayprovider"":true,""__relay_internal__pv__BarcelonaIsCrawlerrelayprovider"":false,""__relay_internal__pv__BarcelonaHasDisplayNamesrelayprovider"":false,""__relay_internal__pv__BarcelonaCanSeeSponsoredContentrelayprovider"":false,""__relay_internal__pv__BarcelonaShouldShowFediverseM075Featuresrelayprovider"":true,""__relay_internal__pv__BarcelonaShouldShowTagRedesignrelayprovider"":false,""__relay_internal__pv__BarcelonaIsInternalUserrelayprovider"":false"
|
||||||
Try
|
Try
|
||||||
DownloadCheckCredentials()
|
DownloadCheckCredentials()
|
||||||
|
|
||||||
Responser.Method = "POST"
|
With Responser
|
||||||
Responser.Referer = "https://www.threads.net/"
|
.Method = "POST"
|
||||||
Responser.Headers.Add(GQL_HEADER_FB_LSD, Token_lsd)
|
.Referer = "https://www.threads.com/"
|
||||||
Responser.Headers.Add(GQL_HEADER_FB_FRINDLY_NAME, If(Cursor.IsEmptyString, GQL_S_NAME_1, GQL_S_NAME_2))
|
.ContentType = "application/x-www-form-urlencoded"
|
||||||
|
With .Headers
|
||||||
|
.Add(GQL_HEADER_FB_LSD, Token_lsd)
|
||||||
|
'.Add(GQL_HEADER_FB_FRINDLY_NAME, If(Cursor.IsEmptyString, GQL_S_NAME_1, GQL_S_NAME_2))
|
||||||
|
.Add(GQL_HEADER_FB_FRINDLY_NAME, GQL_S_NAME_2)
|
||||||
|
End With
|
||||||
|
End With
|
||||||
|
|
||||||
Dim nextCursor$ = String.Empty
|
Dim nextCursor$ = String.Empty
|
||||||
Dim dataFound As Boolean = False
|
Dim dataFound As Boolean = False
|
||||||
|
|
||||||
Dim vars$ = SymbolsConverter.ASCII.EncodeSymbolsOnly("{" & If(Cursor.IsEmptyString, var_init, String.Format(var_cursor, Cursor)) & "}")
|
'Dim vars$ = SymbolsConverter.ASCII.EncodeSymbolsOnly("{" & If(Cursor.IsEmptyString, var_init, String.Format(var_cursor, Cursor)) & "}")
|
||||||
|
Dim vars$ = String.Format(PayloadData, Token_lsd, Token_dtsg_Var, GQL_S_DOC_ID_2, GQL_S_NAME_2,
|
||||||
|
SymbolsConverter.ASCII.EncodeSymbolsOnly("{" & String.Format(var_cursor2, IIf(Cursor.IsEmptyString, "null", $"""{Cursor}""")) & "}"))
|
||||||
|
|
||||||
If Cursor.IsEmptyString Then
|
'If Cursor.IsEmptyString Then
|
||||||
URL = String.Format(GQL_Q, Token_lsd, Token_dtsg_Var, GQL_S_DOC_ID_1, GQL_S_NAME_1, vars)
|
' URL = String.Format(GQL_Q, Token_lsd, Token_dtsg_Var, GQL_S_DOC_ID_1, GQL_S_NAME_1, vars)
|
||||||
Else
|
'Else
|
||||||
URL = String.Format(GQL_Q, Token_lsd, Token_dtsg_Var, GQL_S_DOC_ID_2, GQL_S_NAME_2, vars)
|
' URL = String.Format(GQL_Q, Token_lsd, Token_dtsg_Var, GQL_S_DOC_ID_2, GQL_S_NAME_2, vars)
|
||||||
End If
|
'End If
|
||||||
|
|
||||||
Using j As EContainer = GetDocument(URL, Token)
|
Using j As EContainer = GetDocument(GQL_Q2, vars, Token)
|
||||||
If j.ListExists Then
|
If Not CheckErrors(j) Then
|
||||||
With j({"data", "xdt_viewer", "text_app_saved_media"})
|
If j.ListExists Then
|
||||||
If .ListExists Then
|
With j({"data", "xdt_text_app_viewer", "saved_media"})
|
||||||
nextCursor = .Value({"page_info"}, "end_cursor")
|
If .ListExists Then
|
||||||
With .Item({"edges"})
|
nextCursor = .Value({"page_info"}, "end_cursor")
|
||||||
If .ListExists Then dataFound = DefaultParser(.Self, Sections.Timeline, Token)
|
With .Item({"edges"})
|
||||||
End With
|
If .ListExists Then dataFound = DefaultParser(.Self, Sections.Timeline, Token)
|
||||||
End If
|
End With
|
||||||
End With
|
End If
|
||||||
|
End With
|
||||||
|
End If
|
||||||
|
Else
|
||||||
|
Throw New JsonErrorException(JsonErrorMessage(j))
|
||||||
End If
|
End If
|
||||||
End Using
|
End Using
|
||||||
|
|
||||||
If dataFound And Not nextCursor.IsEmptyString Then DownloadSavedPosts(nextCursor, Token)
|
If dataFound And Not nextCursor.IsEmptyString Then DownloadSavedPosts(nextCursor, 0, Token)
|
||||||
|
Catch uex As JsonErrorException
|
||||||
|
If Round > 0 Then
|
||||||
|
ProcessJsonErrorException(uex)
|
||||||
|
ElseIf Not _IdChanged AndAlso UpdateCredentials() Then
|
||||||
|
DownloadSavedPosts(Cursor, Round + 1, Token)
|
||||||
|
Else
|
||||||
|
ProcessJsonErrorException(uex)
|
||||||
|
End If
|
||||||
|
Catch eex As ExitException
|
||||||
|
Throw eex
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
ProcessException(ex, Token, $"saved posts downloading error [{URL}]")
|
ProcessException(ex, Token, "saved posts downloading error")
|
||||||
End Try
|
End Try
|
||||||
End Sub
|
End Sub
|
||||||
Private Function GetDocument(ByVal URL As String, ByVal Token As CancellationToken, Optional ByVal Round As Integer = 0) As EContainer
|
Private Function GetDocument(ByVal URL As String, ByVal PayLoad As String, ByVal Token As CancellationToken, Optional ByVal Round As Integer = 0) As EContainer
|
||||||
Try
|
Try
|
||||||
ThrowAny(Token)
|
ThrowAny(Token)
|
||||||
If Round > 0 AndAlso Not UpdateCredentials() Then DisableDownload() : Throw New Exception("Failed to update credentials")
|
If Round > 0 AndAlso Not UpdateCredentials() Then DisableDownload() : Throw New Exception("Failed to update credentials")
|
||||||
ThrowAny(Token)
|
ThrowAny(Token)
|
||||||
WaitTimer()
|
WaitTimer()
|
||||||
Dim r$ = Responser.GetResponse(URL)
|
Dim r$ = Responser.GetResponse(URL, PayLoad)
|
||||||
If Not r.IsEmptyString Then Return JsonDocument.Parse(r) Else Throw New Exception("Failed to get a response")
|
If Not r.IsEmptyString Then Return JsonDocument.Parse(r) Else Throw New Exception("Failed to get a response")
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
If Round = 0 Then
|
If Round = 0 Then
|
||||||
Return GetDocument(URL, Token, Round + 1)
|
Return GetDocument(URL, PayLoad, Token, Round + 1)
|
||||||
Else
|
Else
|
||||||
Throw ex
|
Throw ex
|
||||||
End If
|
End If
|
||||||
End Try
|
End Try
|
||||||
End Function
|
End Function
|
||||||
|
Private _IdChanged As Boolean = False
|
||||||
Private Function UpdateCredentials(Optional ByVal e As ErrorsDescriber = Nothing) As Boolean
|
Private Function UpdateCredentials(Optional ByVal e As ErrorsDescriber = Nothing) As Boolean
|
||||||
Dim URL$ = If(IsSavedPosts, "https://www.threads.net/", $"https://www.threads.net/@{NameTrue}")
|
Dim URL$ = If(IsSavedPosts, "https://www.threads.com/", $"https://www.threads.com/@{NameTrue}")
|
||||||
ResetBaseTokens()
|
ResetBaseTokens()
|
||||||
Dim headers As New HttpHeaderCollection
|
Dim headers As New HttpHeaderCollection
|
||||||
headers.AddRange(Responser.Headers)
|
headers.AddRange(Responser.Headers)
|
||||||
@@ -278,8 +369,8 @@ Namespace API.ThreadsNet
|
|||||||
With .Headers
|
With .Headers
|
||||||
.Clear()
|
.Clear()
|
||||||
.Add("dnt", 1)
|
.Add("dnt", 1)
|
||||||
.Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.Authority, "www.threads.net"))
|
.Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.Authority, "www.threads.com"))
|
||||||
.Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.Origin, "https://www.threads.net"))
|
.Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.Origin, "https://www.threads.com"))
|
||||||
.Add("Sec-Ch-Ua-Model", "")
|
.Add("Sec-Ch-Ua-Model", "")
|
||||||
.Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.SecChUaMobile, "?0"))
|
.Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.SecChUaMobile, "?0"))
|
||||||
.Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.SecChUaPlatform, """Windows"""))
|
.Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.SecChUaPlatform, """Windows"""))
|
||||||
@@ -294,9 +385,25 @@ Namespace API.ThreadsNet
|
|||||||
End With
|
End With
|
||||||
WaitTimer()
|
WaitTimer()
|
||||||
Dim r$ = Responser.GetResponse(URL,, EDP.ThrowException)
|
Dim r$ = Responser.GetResponse(URL,, EDP.ThrowException)
|
||||||
|
Dim newID$
|
||||||
|
Dim idStr$ = String.Empty
|
||||||
If Not r.IsEmptyString Then
|
If Not r.IsEmptyString Then
|
||||||
ParseTokens(r, 0)
|
ParseTokens(r, 0)
|
||||||
If ID.IsEmptyString Then ID = RegexReplace(r, RParams.DMS("""props"":\{""user_id"":""(\d+)""", 1, EDP.ReturnValue))
|
newID = RegexReplace(r, RParams.DMS("""props"":\{[^\{\}]*?""user_id"":""(\d+)""", 1, EDP.ReturnValue))
|
||||||
|
If ID.IsEmptyString OrElse ID = newID Then
|
||||||
|
_IdChanged = ID.IsEmptyString
|
||||||
|
ID = newID
|
||||||
|
Else
|
||||||
|
_IdChanged = True
|
||||||
|
idStr = $"user ID changed from {ID} to {newID}"
|
||||||
|
LogError(Nothing, idStr)
|
||||||
|
ID = newID
|
||||||
|
End If
|
||||||
|
If _IdChanged Then
|
||||||
|
If Not idStr.IsEmptyString Then UserDescriptionUpdate(idStr, True, True, True)
|
||||||
|
_ForceSaveUserInfo = True
|
||||||
|
_ForceSaveUserInfoOnException = True
|
||||||
|
End If
|
||||||
End If
|
End If
|
||||||
Return Valid
|
Return Valid
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
@@ -322,20 +429,22 @@ Namespace API.ThreadsNet
|
|||||||
#End Region
|
#End Region
|
||||||
#Region "ReparseMissing"
|
#Region "ReparseMissing"
|
||||||
Protected Overrides Sub ReparseMissing(ByVal Token As CancellationToken)
|
Protected Overrides Sub ReparseMissing(ByVal Token As CancellationToken)
|
||||||
Const varsPattern$ = """postID"":""{0}"",""userID"":""{1}"",""__relay_internal__pv__BarcelonaIsLoggedInrelayprovider"":true,""__relay_internal__pv__BarcelonaIsFeedbackHubEnabledrelayprovider"":false"
|
'Const varsPattern$ = """postID"":""{0}"",""userID"":""{1}"",""__relay_internal__pv__BarcelonaIsLoggedInrelayprovider"":true,""__relay_internal__pv__BarcelonaIsFeedbackHubEnabledrelayprovider"":false"
|
||||||
|
Const varsPattern$ = """postID"":""{0}"",""__relay_internal__pv__BarcelonaIsLoggedInrelayprovider"":true,""__relay_internal__pv__BarcelonaShouldShowFediverseM1Featuresrelayprovider"":true,""__relay_internal__pv__BarcelonaShareableListsrelayprovider"":true,""__relay_internal__pv__BarcelonaIsSearchDiscoveryEnabledrelayprovider"":false,""__relay_internal__pv__BarcelonaOptionalCookiesEnabledrelayprovider"":true,""__relay_internal__pv__BarcelonaQuotedPostUFIEnabledrelayprovider"":false,""__relay_internal__pv__BarcelonaIsCrawlerrelayprovider"":false,""__relay_internal__pv__BarcelonaHasDisplayNamesrelayprovider"":false,""__relay_internal__pv__BarcelonaCanSeeSponsoredContentrelayprovider"":false,""__relay_internal__pv__BarcelonaShouldShowFediverseM075Featuresrelayprovider"":true,""__relay_internal__pv__BarcelonaShouldShowTagRedesignrelayprovider"":false,""__relay_internal__pv__BarcelonaIsInternalUserrelayprovider"":false,""__relay_internal__pv__BarcelonaInlineComposerEnabledrelayprovider"":false"
|
||||||
'Const varsPattern$ = "{""postID"":""{0}"",""__relay_internal__pv__BarcelonaIsLoggedInrelayprovider"":true,""__relay_internal__pv__BarcelonaIsFeedbackHubEnabledrelayprovider"":false}"
|
'Const varsPattern$ = "{""postID"":""{0}"",""__relay_internal__pv__BarcelonaIsLoggedInrelayprovider"":true,""__relay_internal__pv__BarcelonaIsFeedbackHubEnabledrelayprovider"":false}"
|
||||||
Const urlPattern$ = "https://www.threads.net/api/graphql?lsd={0}&variables={1}&fb_api_req_friendly_name=BarcelonaPostPageQuery&server_timestamps=true&fb_dtsg={2}&doc_id=25460088156920903"
|
'Const urlPattern$ = "https://www.threads.com/api/graphql?lsd={0}&variables={1}&fb_api_req_friendly_name=BarcelonaPostPageQuery&server_timestamps=true&fb_dtsg={2}&doc_id=25460088156920903"
|
||||||
Dim rList As New List(Of Integer)
|
Dim rList As New List(Of Integer)
|
||||||
Dim URL$ = String.Empty
|
|
||||||
DefaultParser_ElemNode = Nothing
|
DefaultParser_ElemNode = Nothing
|
||||||
DefaultParser_IgnorePass = True
|
DefaultParser_IgnorePass = True
|
||||||
Try
|
Try
|
||||||
If ContentMissingExists Then
|
If ContentMissingExists Then
|
||||||
Responser.Method = "POST"
|
Responser.Method = "POST"
|
||||||
Responser.Referer = $"https://www.threads.net/@{NameTrue}"
|
Responser.ContentType = "application/x-www-form-urlencoded"
|
||||||
|
Responser.Referer = $"https://www.threads.com/@{NameTrue}"
|
||||||
If Not IsSingleObjectDownload AndAlso Not UpdateCredentials() Then Throw New Exception("Failed to update credentials")
|
If Not IsSingleObjectDownload AndAlso Not UpdateCredentials() Then Throw New Exception("Failed to update credentials")
|
||||||
Dim m As UserMedia
|
Dim m As UserMedia
|
||||||
Dim vars$
|
Dim vars$
|
||||||
|
Dim r As Byte
|
||||||
Dim j As EContainer
|
Dim j As EContainer
|
||||||
ProgressPre.ChangeMax(_ContentList.Count)
|
ProgressPre.ChangeMax(_ContentList.Count)
|
||||||
For i% = 0 To _ContentList.Count - 1
|
For i% = 0 To _ContentList.Count - 1
|
||||||
@@ -343,21 +452,39 @@ Namespace API.ThreadsNet
|
|||||||
m = _ContentList(i)
|
m = _ContentList(i)
|
||||||
If m.State = UserMedia.States.Missing And Not m.Post.ID.IsEmptyString Then
|
If m.State = UserMedia.States.Missing And Not m.Post.ID.IsEmptyString Then
|
||||||
ThrowAny(Token)
|
ThrowAny(Token)
|
||||||
vars = SymbolsConverter.ASCII.EncodeSymbolsOnly("{" & String.Format(varsPattern, m.Post.ID.Split("_").FirstOrDefault, ID) & "}")
|
'vars = SymbolsConverter.ASCII.EncodeSymbolsOnly("{" & String.Format(varsPattern, m.Post.ID.Split("_").FirstOrDefault, ID) & "}")
|
||||||
URL = String.Format(urlPattern, Token_lsd, vars, Token_dtsg_Var)
|
'URL = String.Format(urlPattern, Token_lsd, vars, Token_dtsg_Var)
|
||||||
|
|
||||||
j = GetDocument(URL, Token)
|
vars = String.Format(PayloadData, Token_lsd, Token_dtsg_Var, "9094233770675261", "BarcelonaPostPageDirectQuery",
|
||||||
If j.ListExists Then
|
SymbolsConverter.ASCII.EncodeSymbolsOnly("{" & String.Format(varsPattern, m.Post.ID) & "}"))
|
||||||
With j.ItemF({"data", "data", "edges", 0, "node", "thread_items", 0, "post"})
|
|
||||||
If .ListExists AndAlso DefaultParser({ .Self}, Sections.Timeline, Token) Then rList.Add(i)
|
For r = 0 To 1
|
||||||
End With
|
j = GetDocument(GQL_Q2, vars, Token)
|
||||||
j.Dispose()
|
If Not CheckErrors(j) Then
|
||||||
End If
|
If j.ListExists Then
|
||||||
|
With j.ItemF({"data", "data", "edges", 0, "node", "thread_items", 0, "post"})
|
||||||
|
If .ListExists AndAlso DefaultParser({ .Self}, Sections.Timeline, Token) Then rList.Add(i)
|
||||||
|
End With
|
||||||
|
j.Dispose()
|
||||||
|
End If
|
||||||
|
Else
|
||||||
|
j.DisposeIfReady(False)
|
||||||
|
If r > 0 Then
|
||||||
|
ProcessJsonErrorException(New JsonErrorException(JsonErrorMessage(j)))
|
||||||
|
ElseIf Not _IdChanged AndAlso UpdateCredentials() Then
|
||||||
|
Continue For
|
||||||
|
Else
|
||||||
|
ProcessJsonErrorException(New JsonErrorException(JsonErrorMessage(j)))
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
Next
|
||||||
End If
|
End If
|
||||||
Next
|
Next
|
||||||
End If
|
End If
|
||||||
|
Catch eex As ExitException
|
||||||
|
Throw eex
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
ProcessException(ex, Token, $"ReparseMissing error [{URL}]")
|
ProcessException(ex, Token, "reparseMissing error")
|
||||||
Finally
|
Finally
|
||||||
DefaultParser_ElemNode = DefaultParser_ElemNode_Default
|
DefaultParser_ElemNode = DefaultParser_ElemNode_Default
|
||||||
DefaultParser_IgnorePass = False
|
DefaultParser_IgnorePass = False
|
||||||
@@ -375,9 +502,9 @@ Namespace API.ThreadsNet
|
|||||||
If Not postCode.IsEmptyString Then
|
If Not postCode.IsEmptyString Then
|
||||||
Dim postId$ = CodeToID(postCode)
|
Dim postId$ = CodeToID(postCode)
|
||||||
If Not postId.IsEmptyString Then
|
If Not postId.IsEmptyString Then
|
||||||
_NameTrue = MySettings.IsMyUser(url).UserName
|
NameTrue = MySettings.IsMyUser(url).UserName
|
||||||
DefaultParser_PostUrlCreator = Function(post) url
|
DefaultParser_PostUrlCreator = Function(post) url
|
||||||
If Not _NameTrue.IsEmptyString AndAlso UpdateCredentials(EDP.ReturnValue) Then
|
If Not NameTrue(True).IsEmptyString AndAlso UpdateCredentials(EDP.ReturnValue) Then
|
||||||
_ContentList.Add(New UserMedia(url) With {.State = UserMedia.States.Missing, .Post = postId})
|
_ContentList.Add(New UserMedia(url) With {.State = UserMedia.States.Missing, .Post = postId})
|
||||||
ReparseMissing(Token)
|
ReparseMissing(Token)
|
||||||
End If
|
End If
|
||||||
|
|||||||
@@ -6,11 +6,14 @@
|
|||||||
'
|
'
|
||||||
' 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.Text.RegularExpressions
|
||||||
Imports PersonalUtilities.Functions.RegularExpressions
|
Imports PersonalUtilities.Functions.RegularExpressions
|
||||||
Namespace API.TikTok
|
Namespace API.TikTok
|
||||||
Friend Module Declarations
|
Friend Module Declarations
|
||||||
Friend ReadOnly SimpleDateConverter As New ADateTime("yyyyMMdd")
|
Friend ReadOnly SimpleDateConverter As New ADateTime("yyyyMMdd")
|
||||||
Friend ReadOnly RegexTagsReplacer As RParams = RParams.DM("#\w+\s?", -1, RegexReturn.Replace,
|
Friend ReadOnly RegexTagsReplacer As RParams = RParams.DM("#\w+\s?", -1, RegexReturn.Replace,
|
||||||
CType(Function(input$) String.Empty, Func(Of String, String)), EDP.ReturnValue)
|
CType(Function(input$) String.Empty, Func(Of String, String)), EDP.ReturnValue)
|
||||||
|
Friend ReadOnly RegexPhotoJson As RParams = RParams.DMS("UNIVERSAL_DATA_FOR_REHYDRATION__"" type=""application/json""\>([^\<]+)\<", 1,
|
||||||
|
RegexOptions.IgnoreCase, EDP.ReturnValue)
|
||||||
End Module
|
End Module
|
||||||
End Namespace
|
End Namespace
|
||||||
@@ -13,6 +13,15 @@ Imports PersonalUtilities.Functions.RegularExpressions
|
|||||||
Namespace API.TikTok
|
Namespace API.TikTok
|
||||||
<Manifest("AndyProgram_TikTok"), SpecialForm(False), SeparatedTasks(1)>
|
<Manifest("AndyProgram_TikTok"), SpecialForm(False), SeparatedTasks(1)>
|
||||||
Friend Class SiteSettings : Inherits SiteSettingsBase
|
Friend Class SiteSettings : Inherits SiteSettingsBase
|
||||||
|
#Region "Categories"
|
||||||
|
Private Const CAT_DOWN As String = "Download"
|
||||||
|
#End Region
|
||||||
|
#Region "Download"
|
||||||
|
<PropertyOption(ControlText:="Download videos", Category:=CAT_DOWN), PXML, PClonable>
|
||||||
|
Friend ReadOnly Property DownloadTTVideos As PropertyValue
|
||||||
|
<PropertyOption(ControlText:="Download photos", Category:=CAT_DOWN), PXML, PClonable>
|
||||||
|
Friend ReadOnly Property DownloadTTPhotos As PropertyValue
|
||||||
|
#End Region
|
||||||
<PropertyOption(ControlText:="Remove tags from title"), PXML, PClonable>
|
<PropertyOption(ControlText:="Remove tags from title"), PXML, PClonable>
|
||||||
Friend ReadOnly Property RemoveTagsFromTitle As PropertyValue
|
Friend ReadOnly Property RemoveTagsFromTitle As PropertyValue
|
||||||
<PropertyOption(ControlText:="Use native title", ControlToolTip:="Use a user-created video title for the filename instead of the video ID."), PXML, PClonable>
|
<PropertyOption(ControlText:="Use native title", ControlToolTip:="Use a user-created video title for the filename instead of the video ID."), PXML, PClonable>
|
||||||
@@ -34,8 +43,15 @@ Namespace API.TikTok
|
|||||||
<PropertyOption(ControlText:="Use video date as file date (standalone downloader)",
|
<PropertyOption(ControlText:="Use video date as file date (standalone downloader)",
|
||||||
ControlToolTip:="Set the file date to the date the video was added (website) (if available)."), PXML, PClonable>
|
ControlToolTip:="Set the file date to the date the video was added (website) (if available)."), PXML, PClonable>
|
||||||
Friend ReadOnly Property UseParsedVideoDateSTD As PropertyValue
|
Friend ReadOnly Property UseParsedVideoDateSTD As PropertyValue
|
||||||
|
<DoNotUse> Friend Overrides Property DownloadText As PropertyValue
|
||||||
|
<DoNotUse> Friend Overrides Property DownloadTextPosts As PropertyValue
|
||||||
|
<DoNotUse> Friend Overrides Property DownloadTextSpecialFolder As PropertyValue
|
||||||
Friend Sub New(ByVal AccName As String, ByVal Temp As Boolean)
|
Friend Sub New(ByVal AccName As String, ByVal Temp As Boolean)
|
||||||
MyBase.New("TikTok", "www.tiktok.com", AccName, Temp, My.Resources.SiteResources.TikTokIcon_32, My.Resources.SiteResources.TikTokPic_192)
|
MyBase.New("TikTok", "www.tiktok.com", AccName, Temp, My.Resources.SiteResources.TikTokIcon_32, My.Resources.SiteResources.TikTokPic_192)
|
||||||
|
|
||||||
|
DownloadTTVideos = New PropertyValue(True)
|
||||||
|
DownloadTTPhotos = New PropertyValue(True)
|
||||||
|
|
||||||
RemoveTagsFromTitle = New PropertyValue(False)
|
RemoveTagsFromTitle = New PropertyValue(False)
|
||||||
TitleUseNative = New PropertyValue(True)
|
TitleUseNative = New PropertyValue(True)
|
||||||
TitleUseNativeSTD = New PropertyValue(True)
|
TitleUseNativeSTD = New PropertyValue(True)
|
||||||
@@ -45,6 +61,7 @@ Namespace API.TikTok
|
|||||||
TitleUseRegexForTitle_Value = New PropertyValue(String.Empty, GetType(String))
|
TitleUseRegexForTitle_Value = New PropertyValue(String.Empty, GetType(String))
|
||||||
UseParsedVideoDate = New PropertyValue(True)
|
UseParsedVideoDate = New PropertyValue(True)
|
||||||
UseParsedVideoDateSTD = New PropertyValue(False)
|
UseParsedVideoDateSTD = New PropertyValue(False)
|
||||||
|
|
||||||
UseNetscapeCookies = True
|
UseNetscapeCookies = True
|
||||||
UrlPatternUser = "https://www.tiktok.com/@{0}/"
|
UrlPatternUser = "https://www.tiktok.com/@{0}/"
|
||||||
UserRegex = RParams.DMS(String.Format(UserRegexDefaultPattern, "tiktok.com/@"), 1)
|
UserRegex = RParams.DMS(String.Format(UserRegexDefaultPattern, "tiktok.com/@"), 1)
|
||||||
@@ -62,8 +79,5 @@ Namespace API.TikTok
|
|||||||
Using f As New InternalSettingsForm(Options, Me, False) : f.ShowDialog() : End Using
|
Using f As New InternalSettingsForm(Options, Me, False) : f.ShowDialog() : End Using
|
||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
Friend Overrides Function GetUserUrl(ByVal User As IPluginContentProvider) As String
|
|
||||||
Return String.Format(UrlPatternUser, DirectCast(User, UserData).TrueName)
|
|
||||||
End Function
|
|
||||||
End Class
|
End Class
|
||||||
End Namespace
|
End Namespace
|
||||||
@@ -13,6 +13,7 @@ Imports PersonalUtilities.Functions.XML
|
|||||||
Imports PersonalUtilities.Functions.RegularExpressions
|
Imports PersonalUtilities.Functions.RegularExpressions
|
||||||
Imports PersonalUtilities.Tools
|
Imports PersonalUtilities.Tools
|
||||||
Imports PersonalUtilities.Tools.Web.Documents.JSON
|
Imports PersonalUtilities.Tools.Web.Documents.JSON
|
||||||
|
Imports UTypes = SCrawler.API.Base.UserMedia.Types
|
||||||
Namespace API.TikTok
|
Namespace API.TikTok
|
||||||
Friend Class UserData : Inherits UserDataBase
|
Friend Class UserData : Inherits UserDataBase
|
||||||
#Region "XML names"
|
#Region "XML names"
|
||||||
@@ -23,6 +24,7 @@ Namespace API.TikTok
|
|||||||
Private Const Name_TitleUseRegexForTitle As String = "TitleUseRegexForTitle"
|
Private Const Name_TitleUseRegexForTitle As String = "TitleUseRegexForTitle"
|
||||||
Private Const Name_TitleUseRegexForTitle_Value As String = "TitleUseRegexForTitle_Value"
|
Private Const Name_TitleUseRegexForTitle_Value As String = "TitleUseRegexForTitle_Value"
|
||||||
Private Const Name_TitleUseGlobalRegexOptions As String = "TitleUseGlobalRegexOptions"
|
Private Const Name_TitleUseGlobalRegexOptions As String = "TitleUseGlobalRegexOptions"
|
||||||
|
Private Const Name_PhotosDownloaded As String = "PhotosDownloaded"
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Declarations"
|
#Region "Declarations"
|
||||||
Private ReadOnly Property MySettings As SiteSettings
|
Private ReadOnly Property MySettings As SiteSettings
|
||||||
@@ -62,15 +64,7 @@ Namespace API.TikTok
|
|||||||
Friend Property TitleUseRegexForTitle_Value As String = String.Empty
|
Friend Property TitleUseRegexForTitle_Value As String = String.Empty
|
||||||
Friend Property TitleUseGlobalRegexOptions As Boolean = True
|
Friend Property TitleUseGlobalRegexOptions As Boolean = True
|
||||||
Private Property LastDownloadDate As Date? = Nothing
|
Private Property LastDownloadDate As Date? = Nothing
|
||||||
Private _TrueName As String = String.Empty
|
Private Property PhotosDownloaded As Boolean = False
|
||||||
Friend Property TrueName As String
|
|
||||||
Get
|
|
||||||
Return _TrueName.IfNullOrEmpty(Name)
|
|
||||||
End Get
|
|
||||||
Set(ByVal NewName As String)
|
|
||||||
_TrueName = NewName
|
|
||||||
End Set
|
|
||||||
End Property
|
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Exchange"
|
#Region "Exchange"
|
||||||
Friend Overrides Function ExchangeOptionsGet() As Object
|
Friend Overrides Function ExchangeOptionsGet() As Object
|
||||||
@@ -98,19 +92,19 @@ Namespace API.TikTok
|
|||||||
TitleAddVideoID = .Value(Name_TitleAddVideoID).FromXML(Of Boolean)(True)
|
TitleAddVideoID = .Value(Name_TitleAddVideoID).FromXML(Of Boolean)(True)
|
||||||
LastDownloadDate = AConvert(Of Date)(.Value(Name_LastDownloadDate), ADateTime.Formats.BaseDateTime, Nothing)
|
LastDownloadDate = AConvert(Of Date)(.Value(Name_LastDownloadDate), ADateTime.Formats.BaseDateTime, Nothing)
|
||||||
If Not LastDownloadDate.HasValue Then LastDownloadDate = LastUpdated
|
If Not LastDownloadDate.HasValue Then LastDownloadDate = LastUpdated
|
||||||
_TrueName = .Value(Name_TrueName)
|
|
||||||
TitleUseRegexForTitle = .Value(Name_TitleUseRegexForTitle).FromXML(Of Boolean)(False)
|
TitleUseRegexForTitle = .Value(Name_TitleUseRegexForTitle).FromXML(Of Boolean)(False)
|
||||||
TitleUseRegexForTitle_Value = .Value(Name_TitleUseRegexForTitle_Value)
|
TitleUseRegexForTitle_Value = .Value(Name_TitleUseRegexForTitle_Value)
|
||||||
TitleUseGlobalRegexOptions = .Value(Name_TitleUseGlobalRegexOptions).FromXML(Of Boolean)(True)
|
TitleUseGlobalRegexOptions = .Value(Name_TitleUseGlobalRegexOptions).FromXML(Of Boolean)(True)
|
||||||
|
PhotosDownloaded = .Value(Name_PhotosDownloaded).FromXML(Of Boolean)(False)
|
||||||
Else
|
Else
|
||||||
.Add(Name_RemoveTagsFromTitle, RemoveTagsFromTitle.BoolToInteger)
|
.Add(Name_RemoveTagsFromTitle, RemoveTagsFromTitle.BoolToInteger)
|
||||||
.Add(Name_TitleUseNative, TitleUseNative.BoolToInteger)
|
.Add(Name_TitleUseNative, TitleUseNative.BoolToInteger)
|
||||||
.Add(Name_TitleAddVideoID, TitleAddVideoID.BoolToInteger)
|
.Add(Name_TitleAddVideoID, TitleAddVideoID.BoolToInteger)
|
||||||
.Add(Name_LastDownloadDate, AConvert(Of String)(LastDownloadDate, AModes.XML, ADateTime.Formats.BaseDateTime, String.Empty))
|
.Add(Name_LastDownloadDate, AConvert(Of String)(LastDownloadDate, AModes.XML, ADateTime.Formats.BaseDateTime, String.Empty))
|
||||||
.Add(Name_TrueName, _TrueName)
|
|
||||||
.Add(Name_TitleUseRegexForTitle, TitleUseRegexForTitle.BoolToInteger)
|
.Add(Name_TitleUseRegexForTitle, TitleUseRegexForTitle.BoolToInteger)
|
||||||
.Add(Name_TitleUseRegexForTitle_Value, TitleUseRegexForTitle_Value)
|
.Add(Name_TitleUseRegexForTitle_Value, TitleUseRegexForTitle_Value)
|
||||||
.Add(Name_TitleUseGlobalRegexOptions, TitleUseGlobalRegexOptions.BoolToInteger)
|
.Add(Name_TitleUseGlobalRegexOptions, TitleUseGlobalRegexOptions.BoolToInteger)
|
||||||
|
.Add(Name_PhotosDownloaded, PhotosDownloaded.BoolToInteger)
|
||||||
End If
|
End If
|
||||||
End With
|
End With
|
||||||
End Sub
|
End Sub
|
||||||
@@ -153,7 +147,7 @@ Namespace API.TikTok
|
|||||||
End Function
|
End Function
|
||||||
Private Function GetNewFileName(ByVal Title As String, ByVal Native As Boolean, ByVal RemoveTags As Boolean, ByVal AddVideoID As Boolean,
|
Private Function GetNewFileName(ByVal Title As String, ByVal Native As Boolean, ByVal RemoveTags As Boolean, ByVal AddVideoID As Boolean,
|
||||||
ByVal PostID As String, ByVal TitleRegex As RParams) As String
|
ByVal PostID As String, ByVal TitleRegex As RParams) As String
|
||||||
If Not Title.IsEmptyString Then Title = Left(Title, 150).StringTrim
|
If Not Title.IsEmptyString Then Title = TitleHtmlConverter(Left(Title, 150)).StringTrim
|
||||||
If Title.IsEmptyString Or Not Native Then
|
If Title.IsEmptyString Or Not Native Then
|
||||||
Title = PostID
|
Title = PostID
|
||||||
Else
|
Else
|
||||||
@@ -168,22 +162,33 @@ Namespace API.TikTok
|
|||||||
End If
|
End If
|
||||||
Return Title
|
Return Title
|
||||||
End Function
|
End Function
|
||||||
|
Private Function GetPhotoNode() As Object()
|
||||||
|
Return {"imageURL", "urlList", 0, 0}
|
||||||
|
End Function
|
||||||
Friend Overrides Sub DownloadData(ByVal Token As CancellationToken)
|
Friend Overrides Sub DownloadData(ByVal Token As CancellationToken)
|
||||||
MyBase.DownloadData(Token)
|
MyBase.DownloadData(Token)
|
||||||
UserCache.DisposeIfReady(False)
|
UserCache.DisposeIfReady(False)
|
||||||
UserCache = Nothing
|
UserCache = Nothing
|
||||||
End Sub
|
End Sub
|
||||||
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
|
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
|
||||||
Dim URL$ = $"https://www.tiktok.com/@{TrueName}"
|
Dim URL$ = $"https://www.tiktok.com/@{NameTrue}"
|
||||||
UserCache = CreateCache()
|
UserCache = CreateCache()
|
||||||
Try
|
Try
|
||||||
Dim postID$, title$, postUrl$, newName$
|
Const photoPrefix$ = "photo_"
|
||||||
|
Dim postID$, title$, postUrl$, newName$, t$, postID2$, imgUrl$
|
||||||
Dim postDate As Date?
|
Dim postDate As Date?
|
||||||
Dim dateAfterC As Date? = Nothing
|
Dim dateAfterC As Date? = Nothing
|
||||||
Dim dateBefore As Date? = DownloadDateTo
|
Dim dateBefore As Date? = DownloadDateTo
|
||||||
Dim dateAfter As Date? = DownloadDateFrom
|
Dim dateAfter As Date? = DownloadDateFrom
|
||||||
Dim baseDataObtained As Boolean = False
|
Dim baseDataObtained As Boolean = False
|
||||||
Dim titleRegex As RParams = GetTitleRegex()
|
Dim titleRegex As RParams = GetTitleRegex()
|
||||||
|
Dim vPath As SFile = Nothing, pPath As SFile = Nothing
|
||||||
|
Dim file As SFile
|
||||||
|
Dim j As EContainer, photo As EContainer
|
||||||
|
Dim photoNode As Object() = GetPhotoNode()
|
||||||
|
Dim c%, cc%, i%
|
||||||
|
Dim errDef As New ErrorsDescriber(EDP.ReturnValue)
|
||||||
|
Dim infoParsed As Boolean = False
|
||||||
|
|
||||||
If _ContentList.Count > 0 Then
|
If _ContentList.Count > 0 Then
|
||||||
With (From d In _ContentList Where d.Post.Date.HasValue Select d.Post.Date.Value)
|
With (From d In _ContentList Where d.Post.Date.HasValue Select d.Post.Date.Value)
|
||||||
@@ -209,60 +214,154 @@ Namespace API.TikTok
|
|||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
|
|
||||||
Using b As New YTDLP.YTDLPBatch(Token) With {.TempPostsList = _TempPostsList}
|
If DownloadVideos And Settings.YtdlpFile.Exists And CBool(MySettings.DownloadTTVideos.Value) Then
|
||||||
b.Commands.Clear()
|
With UserCache.NewInstance : .Validate() : vPath = .RootDirectory : End With
|
||||||
b.ChangeDirectory(UserCache)
|
Using b As New YTDLP.YTDLPBatch(Token) With {.TempPostsList = _TempPostsList}
|
||||||
b.Encoding = BatchExecutor.UnicodeEncoding
|
b.Commands.Clear()
|
||||||
b.Execute(CreateYTCommand(UserCache.RootDirectory, URL, False, dateBefore, dateAfter))
|
b.ChangeDirectory(vPath)
|
||||||
End Using
|
b.Encoding = BatchExecutor.UnicodeEncoding
|
||||||
|
b.Execute(CreateYTCommand(vPath, URL, False, dateBefore, dateAfter))
|
||||||
|
End Using
|
||||||
|
End If
|
||||||
|
|
||||||
|
If DownloadImages And Settings.GalleryDLFile.Exists And CBool(MySettings.DownloadTTPhotos.Value) Then
|
||||||
|
With UserCache.NewInstance : .Validate() : pPath = .RootDirectory : End With
|
||||||
|
Using b As New GDL.GDLBatch(Token)
|
||||||
|
With b
|
||||||
|
If PhotosDownloaded And _TempPostsList.Count > 0 Then
|
||||||
|
.TempPostsList = (From p As String In _TempPostsList
|
||||||
|
Where Not p.IsEmptyString AndAlso p.StartsWith(photoPrefix)
|
||||||
|
Select p.Replace(photoPrefix, String.Empty)).ListIfNothing
|
||||||
|
Else
|
||||||
|
.TempPostsList = New List(Of String)
|
||||||
|
End If
|
||||||
|
.ChangeDirectory(pPath)
|
||||||
|
.Encoding = BatchExecutor.UnicodeEncoding
|
||||||
|
.Execute(CreateGDLCommand(URL))
|
||||||
|
If Not PhotosDownloaded Then _ForceSaveUserInfo = True : _ForceSaveUserInfoOnException = True
|
||||||
|
PhotosDownloaded = True
|
||||||
|
End With
|
||||||
|
End Using
|
||||||
|
End If
|
||||||
|
|
||||||
ThrowAny(Token)
|
ThrowAny(Token)
|
||||||
|
|
||||||
Dim files As List(Of SFile) = SFile.GetFiles(UserCache, "*.json",, EDP.ReturnValue)
|
Dim files As List(Of SFile)
|
||||||
If files.ListExists Then
|
If Not vPath.IsEmptyString AndAlso vPath.Exists(SFO.Path, False) Then
|
||||||
Dim j As EContainer
|
files = SFile.GetFiles(vPath, "*.json",, errDef)
|
||||||
For Each file As SFile In files
|
If files.ListExists Then
|
||||||
j = JsonDocument.Parse(file.GetText, EDP.ReturnValue)
|
For Each file In files
|
||||||
If j.ListExists Then
|
j = JsonDocument.Parse(file.GetText, errDef)
|
||||||
If j.Value("_type").StringToLower = "video" Then
|
If j.ListExists Then
|
||||||
If Not baseDataObtained Then
|
If j.Value("_type").StringToLower = "video" Then
|
||||||
baseDataObtained = True
|
If Not baseDataObtained Then
|
||||||
If ID.IsEmptyString Then
|
baseDataObtained = True
|
||||||
ID = j.Value("uploader_id")
|
If ID.IsEmptyString Then
|
||||||
If Not ID.IsEmptyString Then _ForceSaveUserInfo = True
|
ID = j.Value("uploader_id")
|
||||||
|
If Not ID.IsEmptyString Then _ForceSaveUserInfo = True
|
||||||
|
End If
|
||||||
|
newName = j.Value("uploader")
|
||||||
|
If Not newName.IsEmptyString Then NameTrue = newName
|
||||||
|
newName = j.Value("creator")
|
||||||
|
If Not newName.IsEmptyString Then UserSiteName = newName
|
||||||
End If
|
End If
|
||||||
newName = j.Value("uploader")
|
postID = j.Value("id")
|
||||||
If Not newName.IsEmptyString Then
|
If Not _TempPostsList.Contains(postID) Then
|
||||||
If Not _TrueName = newName Then _ForceSaveUserInfo = True
|
_TempPostsList.ListAddValue(postID, LNC)
|
||||||
_TrueName = newName
|
Else
|
||||||
|
Exit For 'Exit Sub
|
||||||
End If
|
End If
|
||||||
newName = j.Value("creator")
|
title = GetNewFileName(j.Value("title").StringRemoveWinForbiddenSymbols,
|
||||||
If Not newName.IsEmptyString Then UserSiteName = newName
|
TitleUseNative, RemoveTagsFromTitle, TitleAddVideoID, postID, titleRegex)
|
||||||
End If
|
postDate = AConvert(Of Date)(j.Value("timestamp"), UnixDate32Provider, Nothing)
|
||||||
postID = j.Value("id")
|
If Not postDate.HasValue Then postDate = AConvert(Of Date)(j.Value("upload_date"), SimpleDateConverter, Nothing)
|
||||||
If Not _TempPostsList.Contains(postID) Then
|
Select Case CheckDatesLimit(postDate, SimpleDateConverter)
|
||||||
_TempPostsList.Add(postID)
|
Case DateResult.Skip : Continue For
|
||||||
Else
|
Case DateResult.Exit : Exit For 'Exit Sub
|
||||||
Exit Sub
|
End Select
|
||||||
End If
|
|
||||||
title = GetNewFileName(j.Value("title").StringRemoveWinForbiddenSymbols,
|
|
||||||
TitleUseNative, RemoveTagsFromTitle, TitleAddVideoID, postID, titleRegex)
|
|
||||||
postDate = AConvert(Of Date)(j.Value("timestamp"), UnixDate32Provider, Nothing)
|
|
||||||
If Not postDate.HasValue Then postDate = AConvert(Of Date)(j.Value("upload_date"), SimpleDateConverter, Nothing)
|
|
||||||
Select Case CheckDatesLimit(postDate, SimpleDateConverter)
|
|
||||||
Case DateResult.Skip : Continue For
|
|
||||||
Case DateResult.Exit : Exit Sub
|
|
||||||
End Select
|
|
||||||
|
|
||||||
postUrl = j.Value("webpage_url")
|
postUrl = j.Value("webpage_url")
|
||||||
If postUrl.IsEmptyString Then postUrl = $"https://www.tiktok.com/@{Name}/video/{postID}"
|
If postUrl.IsEmptyString Then postUrl = $"https://www.tiktok.com/@{Name}/video/{postID}"
|
||||||
_TempMediaList.Add(New UserMedia(postUrl, UserMedia.Types.Video) With {
|
_TempMediaList.Add(New UserMedia(postUrl, UTypes.Video) With {
|
||||||
.File = $"{title}.mp4", .Post = New UserPost(postID, postDate)})
|
.File = $"{title}.mp4", .Post = New UserPost(postID, postDate)})
|
||||||
|
End If
|
||||||
|
j.Dispose()
|
||||||
End If
|
End If
|
||||||
j.Dispose()
|
Next
|
||||||
End If
|
End If
|
||||||
Next
|
|
||||||
End If
|
End If
|
||||||
|
|
||||||
|
If Not pPath.IsEmptyString AndAlso pPath.Exists(SFO.Path, False) Then
|
||||||
|
files = SFile.GetFiles(pPath, "*.txt",, errDef)
|
||||||
|
If files.ListExists Then
|
||||||
|
For Each file In files
|
||||||
|
t = file.GetText(errDef)
|
||||||
|
If Not t.IsEmptyString Then t = RegexReplace(t, RegexPhotoJson)
|
||||||
|
If Not t.IsEmptyString Then
|
||||||
|
j = JsonDocument.Parse(t, errDef)
|
||||||
|
If j.ListExists Then
|
||||||
|
With j.ItemF({0, "webapp.video-detail", "itemInfo", "itemStruct"})
|
||||||
|
If .ListExists Then
|
||||||
|
postID = .Value("id")
|
||||||
|
postID2 = $"{photoPrefix}{postID}"
|
||||||
|
If Not _TempPostsList.Contains(postID2) Then _TempPostsList.ListAddValue(postID2, LNC) Else Exit For 'Exit Sub
|
||||||
|
postDate = AConvert(Of Date)(j.Value("createTime"), UnixDate32Provider, Nothing)
|
||||||
|
Select Case CheckDatesLimit(postDate, SimpleDateConverter)
|
||||||
|
Case DateResult.Skip : Continue For
|
||||||
|
Case DateResult.Exit : Exit For 'Exit Sub
|
||||||
|
End Select
|
||||||
|
|
||||||
|
If Not infoParsed Then
|
||||||
|
With .Item("author")
|
||||||
|
If .ListExists Then
|
||||||
|
infoParsed = True
|
||||||
|
SimpleDownloadAvatar(.Value("avatarLarger").IfNullOrEmpty(.Value("avatarMedium")).IfNullOrEmpty(.Value("avatarThumb")),
|
||||||
|
Function(ByVal ____url As String) As SFile
|
||||||
|
Dim ____f As SFile = CreateFileFromUrl(____url)
|
||||||
|
If Not ____f.Name.IsEmptyString Then ____f.Name = ____f.Name.Replace(":", "_").Replace("~", "-")
|
||||||
|
If Not ____f.Extension.IsEmptyString Then
|
||||||
|
If Not (____f.Extension = "jpg" Or ____f.Extension = "jpeg") Then
|
||||||
|
____f.Extension = RegexReplace(____f.Extension, RParams.DMS("(.+)\?", 1, EDP.ReturnValue))
|
||||||
|
If Not ____f.Extension.IsEmptyString AndAlso Not (____f.Extension = "jpg" Or ____f.Extension = "jpeg") Then ____f.Extension = String.Empty
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
Return ____f
|
||||||
|
End Function)
|
||||||
|
UserSiteNameUpdate(.Value("nickname"))
|
||||||
|
UserDescriptionUpdate(.Value("signature"))
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
End If
|
||||||
|
|
||||||
|
title = GetNewFileName(j.Value({"imagePost"}, "title").StringRemoveWinForbiddenSymbols,
|
||||||
|
TitleUseNative, RemoveTagsFromTitle, TitleAddVideoID, postID, titleRegex)
|
||||||
|
postUrl = $"https://www.tiktok.com/@{Name}/photo/{postID}"
|
||||||
|
With .Item({"imagePost", "images"})
|
||||||
|
If .ListExists Then
|
||||||
|
i = 0
|
||||||
|
c = .Count
|
||||||
|
cc = Math.Max(c.ToString.Length, 3)
|
||||||
|
For Each photo In .Self
|
||||||
|
i += 1
|
||||||
|
imgUrl = photo.ItemF(photoNode).XmlIfNothingValue
|
||||||
|
If Not imgUrl.IsEmptyString Then _
|
||||||
|
_TempMediaList.Add(New UserMedia(imgUrl, UTypes.Picture) With {
|
||||||
|
.URL_BASE = postUrl,
|
||||||
|
.SpecialFolder = "Photo",
|
||||||
|
.File = $"{title}{IIf(c > 1, $"_{i.NumToString(ANumbers.Formats.NumberGroup, cc)}", String.Empty)}.jpg",
|
||||||
|
.Post = New UserPost(postID, postDate)})
|
||||||
|
Next
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
j.Dispose()
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
Next
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
|
||||||
If _TempMediaList.Count > 0 Then LastDownloadDate = Now
|
If _TempMediaList.Count > 0 Then LastDownloadDate = Now
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
ProcessException(ex, Token, $"data downloading error [{URL}]")
|
ProcessException(ex, Token, $"data downloading error [{URL}]")
|
||||||
@@ -273,16 +372,41 @@ Namespace API.TikTok
|
|||||||
Protected Overrides Sub ReparseMissing(ByVal Token As CancellationToken)
|
Protected Overrides Sub ReparseMissing(ByVal Token As CancellationToken)
|
||||||
If ContentMissingExists Then
|
If ContentMissingExists Then
|
||||||
Dim m As UserMedia
|
Dim m As UserMedia
|
||||||
|
Dim d As IYouTubeMediaContainer = Nothing
|
||||||
Dim i%
|
Dim i%
|
||||||
Dim rList As New List(Of Integer)
|
Dim rList As New List(Of Integer)
|
||||||
|
Dim picIDs As New List(Of String)
|
||||||
|
Dim defDir As SFile = SFile.GetPath(DownloadContentDefault_GetRootDir())
|
||||||
|
Dim result As Boolean
|
||||||
For i = 0 To _ContentList.Count - 1
|
For i = 0 To _ContentList.Count - 1
|
||||||
If _ContentList(i).State = UserMedia.States.Missing Then
|
If _ContentList(i).State = UserMedia.States.Missing Then
|
||||||
m = _ContentList(i)
|
m = _ContentList(i)
|
||||||
m.URL = m.URL_BASE
|
result = False
|
||||||
_TempMediaList.Add(m)
|
Try
|
||||||
rList.Add(i)
|
If m.Type = UTypes.Video Then
|
||||||
|
d = MySettings.GetSingleMediaInstance(m.URL_BASE, defDir)
|
||||||
|
result = False
|
||||||
|
If If(UserCache?.Disposed, True) Then UserCache = CreateCache()
|
||||||
|
DownloadSingleObject_GetPosts(d, Token, UserCache, result)
|
||||||
|
ElseIf m.Type = UTypes.Picture Then
|
||||||
|
If picIDs.Contains(m.Post.ID) Then
|
||||||
|
rList.Add(i)
|
||||||
|
Else
|
||||||
|
d = MySettings.GetSingleMediaInstance(m.URL_BASE, defDir)
|
||||||
|
If If(UserCache?.Disposed, True) Then UserCache = CreateCache()
|
||||||
|
DownloadSingleObject_GetPosts(d, Token, UserCache, result)
|
||||||
|
picIDs.Add(m.Post.ID)
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
Catch ex As Exception
|
||||||
|
result = False
|
||||||
|
ProcessException(ex, Token, "ReparseMissing")
|
||||||
|
End Try
|
||||||
|
If result Then rList.Add(i)
|
||||||
|
d.DisposeIfReady(False)
|
||||||
End If
|
End If
|
||||||
Next
|
Next
|
||||||
|
picIDs.Clear()
|
||||||
If rList.Count > 0 Then
|
If rList.Count > 0 Then
|
||||||
For i% = rList.Count - 1 To 0 Step -1 : _ContentList.RemoveAt(rList(i)) : Next
|
For i% = rList.Count - 1 To 0 Step -1 : _ContentList.RemoveAt(rList(i)) : Next
|
||||||
End If
|
End If
|
||||||
@@ -317,10 +441,18 @@ Namespace API.TikTok
|
|||||||
Return command
|
Return command
|
||||||
End Function
|
End Function
|
||||||
#End Region
|
#End Region
|
||||||
|
#Region "GDL Support"
|
||||||
|
Private Function CreateGDLCommand(ByVal URL As String) As String
|
||||||
|
Return $"""{Settings.GalleryDLFile}"" --verbose --no-download --no-skip --write-pages {URL}"
|
||||||
|
End Function
|
||||||
|
#End Region
|
||||||
#Region "DownloadContent, DownloadFile"
|
#Region "DownloadContent, DownloadFile"
|
||||||
Protected Overrides Sub DownloadContent(ByVal Token As CancellationToken)
|
Protected Overrides Sub DownloadContent(ByVal Token As CancellationToken)
|
||||||
DownloadContentDefault(Token)
|
DownloadContentDefault(Token)
|
||||||
End Sub
|
End Sub
|
||||||
|
Protected Overrides Function ValidateDownloadFile(ByVal URL As String, ByVal Media As UserMedia, ByRef Interrupt As Boolean) As Boolean
|
||||||
|
Return Not Media.Type = UTypes.Picture
|
||||||
|
End Function
|
||||||
Protected Overrides Function DownloadFile(ByVal URL As String, ByVal Media As UserMedia, ByVal DestinationFile As SFile, ByVal Token As CancellationToken) As SFile
|
Protected Overrides Function DownloadFile(ByVal URL As String, ByVal Media As UserMedia, ByVal DestinationFile As SFile, ByVal Token As CancellationToken) As SFile
|
||||||
Using b As New TokenBatch(Token) With {.FileExchanger = RootCacheTikTok}
|
Using b As New TokenBatch(Token) With {.FileExchanger = RootCacheTikTok}
|
||||||
b.Encoding = BatchExecutor.UnicodeEncoding
|
b.Encoding = BatchExecutor.UnicodeEncoding
|
||||||
@@ -330,33 +462,94 @@ Namespace API.TikTok
|
|||||||
End Function
|
End Function
|
||||||
#End Region
|
#End Region
|
||||||
#Region "DownloadSingleObject"
|
#Region "DownloadSingleObject"
|
||||||
Protected Overrides Sub DownloadSingleObject_GetPosts(ByVal Data As IYouTubeMediaContainer, ByVal Token As CancellationToken)
|
Protected Overloads Overrides Sub DownloadSingleObject_GetPosts(ByVal Data As IYouTubeMediaContainer, ByVal Token As CancellationToken)
|
||||||
|
DownloadSingleObject_GetPosts(Data, Token, Nothing, Nothing)
|
||||||
|
End Sub
|
||||||
|
Private Overloads Sub DownloadSingleObject_GetPosts(ByVal Data As IYouTubeMediaContainer, ByVal Token As CancellationToken,
|
||||||
|
ByRef Cache As CacheKeeper, ByRef Result As Boolean)
|
||||||
Dim f$ = String.Empty
|
Dim f$ = String.Empty
|
||||||
If CBool(MySettings.TitleUseNativeSTD.Value) Then
|
Dim urlsList As New List(Of String)
|
||||||
Using b As New BatchExecutor(True) With {
|
Dim t As UTypes
|
||||||
.Encoding = BatchExecutor.UnicodeEncoding,
|
Dim defName$ = New SFile(Data.URL).Name
|
||||||
.CleanAutomaticallyViaRegEx = True,
|
If Data.URL.ToLower.Contains("/video/") Then
|
||||||
.CleanAutomaticallyViaRegExRemoveAllCommands = True
|
urlsList.Add(Data.URL)
|
||||||
}
|
t = UTypes.Video
|
||||||
b.Execute(CreateYTCommand(Nothing, Data.URL, True,,, True, False))
|
If CBool(MySettings.TitleUseNativeSTD.Value) Then
|
||||||
b.Clean()
|
Using b As New BatchExecutor(True) With {
|
||||||
With b.OutputData
|
.Encoding = BatchExecutor.UnicodeEncoding,
|
||||||
If .Count > 0 Then
|
.CleanAutomaticallyViaRegEx = True,
|
||||||
For Each vData$ In .Self
|
.CleanAutomaticallyViaRegExRemoveAllCommands = True
|
||||||
If Not vData.Contains($": {BatchExecutor.UnicodeEncoding}") Then f = vData : Exit For
|
}
|
||||||
Next
|
b.Execute(CreateYTCommand(Nothing, Data.URL, True,,, True, False))
|
||||||
End If
|
b.Clean()
|
||||||
End With
|
With b.OutputData
|
||||||
|
If .Count > 0 Then
|
||||||
|
For Each vData$ In .Self
|
||||||
|
If Not vData.Contains($": {BatchExecutor.UnicodeEncoding}") Then f = vData : Exit For
|
||||||
|
Next
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
End Using
|
||||||
|
End If
|
||||||
|
Else
|
||||||
|
t = UTypes.Picture
|
||||||
|
Data.ContentType = Plugin.UserMediaTypes.Picture
|
||||||
|
Data.Title = defName
|
||||||
|
Dim dir As SFile
|
||||||
|
With If(Cache, Settings.Cache).NewInstance() : .Validate() : dir = .RootDirectory : End With
|
||||||
|
Using b As New GDL.GDLBatch(Token)
|
||||||
|
b.ChangeDirectory(dir)
|
||||||
|
b.Encoding = BatchExecutor.UnicodeEncoding
|
||||||
|
b.Execute(CreateGDLCommand(Data.URL))
|
||||||
End Using
|
End Using
|
||||||
|
Dim file As SFile = SFile.GetFiles(dir, "*.txt",, EDP.ReturnValue).FirstOrDefault
|
||||||
|
If file.Exists Then
|
||||||
|
Dim r$ = file.GetText(EDP.ReturnValue)
|
||||||
|
If Not r.IsEmptyString Then r = RegexReplace(r, RegexPhotoJson)
|
||||||
|
If Not r.IsEmptyString Then
|
||||||
|
Using j As EContainer = JsonDocument.Parse(r, EDP.ReturnValue)
|
||||||
|
If j.ListExists Then
|
||||||
|
With j.ItemF({0, "webapp.video-detail", "itemInfo", "itemStruct"})
|
||||||
|
If CBool(MySettings.TitleUseNativeSTD.Value) Then f = j.Value({"imagePost"}, "title").StringRemoveWinForbiddenSymbols
|
||||||
|
With .Item({"imagePost", "images"})
|
||||||
|
If .ListExists Then
|
||||||
|
For Each photo As EContainer In .Self : urlsList.Add(photo.ItemF(GetPhotoNode()).XmlIfNothingValue) : Next
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
End With
|
||||||
|
End If
|
||||||
|
End Using
|
||||||
|
End If
|
||||||
|
End If
|
||||||
End If
|
End If
|
||||||
Dim m As New UserMedia(Data.URL, UserMedia.Types.Video)
|
|
||||||
If Not f.IsEmptyString Then f = TitleHtmlConverter(f)
|
Dim m As UserMedia
|
||||||
If Not f.IsEmptyString Then
|
Dim i% = 0, c%, cc%
|
||||||
f = GetNewFileName(f, MySettings.TitleUseNativeSTD.Value, MySettings.RemoveTagsFromTitle.Value, MySettings.TitleAddVideoIDSTD.Value,
|
Dim ff As Boolean = False
|
||||||
m.File.Name, GetTitleRegex)
|
If urlsList.Count > 0 Then
|
||||||
If Not f.IsEmptyString Then m.File.Name = f.StringTrim
|
c = urlsList.Count
|
||||||
|
cc = Math.Max(c.ToString.Length, 3)
|
||||||
|
For Each url$ In urlsList
|
||||||
|
i += 1
|
||||||
|
m = New UserMedia(url, t) With {.URL_BASE = Data.URL}
|
||||||
|
If Not f.IsEmptyString Then f = TitleHtmlConverter(f)
|
||||||
|
If Not f.IsEmptyString Or t = UTypes.Picture Then
|
||||||
|
If Not ff Then f = GetNewFileName(f, MySettings.TitleUseNativeSTD.Value, MySettings.RemoveTagsFromTitle.Value, MySettings.TitleAddVideoIDSTD.Value,
|
||||||
|
defName, GetTitleRegex)
|
||||||
|
ff = True
|
||||||
|
If Not f.IsEmptyString Then
|
||||||
|
m.File.Name = $"{f.StringTrim}{IIf(c > 1, $"_{i.NumToString(ANumbers.Formats.NumberGroup, cc)}", String.Empty)}"
|
||||||
|
If t = UTypes.Picture Then m.File.Extension = "jpg"
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
|
||||||
|
_TempMediaList.Add(m)
|
||||||
|
Result = True
|
||||||
|
Next
|
||||||
End If
|
End If
|
||||||
_TempMediaList.Add(m)
|
End Sub
|
||||||
|
Protected Overrides Sub DownloadSingleObject_PostProcessing(ByVal Data As IYouTubeMediaContainer, Optional ByVal ResetTitle As Boolean = True)
|
||||||
|
MyBase.DownloadSingleObject_PostProcessing(Data, Not Data.ContentType = Plugin.UserMediaTypes.Picture)
|
||||||
End Sub
|
End Sub
|
||||||
#End Region
|
#End Region
|
||||||
#Region "EraseData"
|
#Region "EraseData"
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
' This program is distributed in the hope that it will be useful,
|
' This program is distributed in the hope that it will be useful,
|
||||||
' but WITHOUT ANY WARRANTY
|
' but WITHOUT ANY WARRANTY
|
||||||
Imports System.Globalization
|
Imports System.Globalization
|
||||||
Imports PersonalUtilities.Functions.XML.Base
|
Imports System.Text.RegularExpressions
|
||||||
Imports PersonalUtilities.Functions.RegularExpressions
|
Imports PersonalUtilities.Functions.RegularExpressions
|
||||||
Namespace API.Twitter
|
Namespace API.Twitter
|
||||||
Friend Module Declarations
|
Friend Module Declarations
|
||||||
@@ -17,6 +17,8 @@ Namespace API.Twitter
|
|||||||
Friend ReadOnly VideoSizeRegEx As RParams = RParams.DMS("\d+x(\d+)", 1, EDP.ReturnValue)
|
Friend ReadOnly VideoSizeRegEx As RParams = RParams.DMS("\d+x(\d+)", 1, EDP.ReturnValue)
|
||||||
Friend ReadOnly StatusRegEx As RParams = RParams.DM(".*?(twitter|x)\.com/\S+/status/\d+", 0, EDP.ReturnValue)
|
Friend ReadOnly StatusRegEx As RParams = RParams.DM(".*?(twitter|x)\.com/\S+/status/\d+", 0, EDP.ReturnValue)
|
||||||
Friend ReadOnly BroadcastsUrls As Object() = {"entities", "urls", 0, "expanded_url"}
|
Friend ReadOnly BroadcastsUrls As Object() = {"entities", "urls", 0, "expanded_url"}
|
||||||
|
Friend ReadOnly GdlLimitRegEx As RParams = RParams.DM("Waiting until[\s\W\d\:]+\(rate limit\)", 0, RegexOptions.IgnoreCase, EDP.ReturnValue)
|
||||||
|
Friend ReadOnly GdlPostCoutNumberNodes As String() = {"data", "user", "result", "legacy", "statuses_count"}
|
||||||
Private Function GetDateProvider() As ADateTime
|
Private Function GetDateProvider() As ADateTime
|
||||||
Dim n As DateTimeFormatInfo = CultureInfo.GetCultureInfo("en-us").DateTimeFormat.Clone
|
Dim n As DateTimeFormatInfo = CultureInfo.GetCultureInfo("en-us").DateTimeFormat.Clone
|
||||||
n.FullDateTimePattern = "ddd MMM dd HH:mm:ss +ffff yyyy"
|
n.FullDateTimePattern = "ddd MMM dd HH:mm:ss +ffff yyyy"
|
||||||
|
|||||||
@@ -8,11 +8,10 @@
|
|||||||
' but WITHOUT ANY WARRANTY
|
' but WITHOUT ANY WARRANTY
|
||||||
Imports SCrawler.Plugin.Attributes
|
Imports SCrawler.Plugin.Attributes
|
||||||
Imports DModels = SCrawler.API.Twitter.UserData.DownloadModels
|
Imports DModels = SCrawler.API.Twitter.UserData.DownloadModels
|
||||||
Imports DN = SCrawler.API.Base.DeclaredNames
|
|
||||||
Namespace API.Twitter
|
Namespace API.Twitter
|
||||||
Friend Class EditorExchangeOptions
|
Friend Class EditorExchangeOptions : Inherits Base.EditorExchangeOptionsBase
|
||||||
Private Const DefaultOffset As Integer = 100
|
Private Const DefaultOffset As Integer = 100
|
||||||
Friend Property SiteKey As String = TwitterSiteKey
|
Friend Overrides Property SiteKey As String = TwitterSiteKey
|
||||||
<PSetting(NameOf(SiteSettings.GifsDownload), NameOf(MySettings), LeftOffset:=DefaultOffset)>
|
<PSetting(NameOf(SiteSettings.GifsDownload), NameOf(MySettings), LeftOffset:=DefaultOffset)>
|
||||||
Friend Property GifsDownload As Boolean
|
Friend Property GifsDownload As Boolean
|
||||||
<PSetting(NameOf(SiteSettings.GifsSpecialFolder), NameOf(MySettings), LeftOffset:=DefaultOffset)>
|
<PSetting(NameOf(SiteSettings.GifsSpecialFolder), NameOf(MySettings), LeftOffset:=DefaultOffset)>
|
||||||
@@ -51,10 +50,9 @@ Namespace API.Twitter
|
|||||||
Caption:="Force apply",
|
Caption:="Force apply",
|
||||||
ToolTip:="Force overrides the default parameters for the first download." & vbCr & "Applies to first download only.", LeftOffset:=DefaultOffset)>
|
ToolTip:="Force overrides the default parameters for the first download." & vbCr & "Applies to first download only.", LeftOffset:=DefaultOffset)>
|
||||||
Friend Overridable Property DownloadModelForceApply As Boolean = False
|
Friend Overridable Property DownloadModelForceApply As Boolean = False
|
||||||
<PSetting(Address:=SettingAddress.User, Caption:=DN.UserNameChangeCaption, ToolTip:=DN.UserNameChangeToolTip, LeftOffset:=DefaultOffset)>
|
|
||||||
Friend Overridable Property UserName As String = String.Empty
|
|
||||||
Private ReadOnly Property MySettings As Object
|
Private ReadOnly Property MySettings As Object
|
||||||
Friend Sub New(ByVal s As SiteSettings)
|
Friend Sub New(ByVal s As SiteSettings)
|
||||||
|
MyBase.New(s)
|
||||||
GifsDownload = s.GifsDownload.Value
|
GifsDownload = s.GifsDownload.Value
|
||||||
GifsSpecialFolder = s.GifsSpecialFolder.Value
|
GifsSpecialFolder = s.GifsSpecialFolder.Value
|
||||||
GifsPrefix = s.GifsPrefix.Value
|
GifsPrefix = s.GifsPrefix.Value
|
||||||
@@ -71,6 +69,7 @@ Namespace API.Twitter
|
|||||||
MySettings = s
|
MySettings = s
|
||||||
End Sub
|
End Sub
|
||||||
Friend Sub New(ByVal u As UserData)
|
Friend Sub New(ByVal u As UserData)
|
||||||
|
MyBase.New(u)
|
||||||
GifsDownload = u.GifsDownload
|
GifsDownload = u.GifsDownload
|
||||||
GifsSpecialFolder = u.GifsSpecialFolder
|
GifsSpecialFolder = u.GifsSpecialFolder
|
||||||
GifsPrefix = u.GifsPrefix
|
GifsPrefix = u.GifsPrefix
|
||||||
@@ -88,7 +87,6 @@ Namespace API.Twitter
|
|||||||
DownloadModelLikes = dm.Contains(DModels.Likes)
|
DownloadModelLikes = dm.Contains(DModels.Likes)
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
UserName = u.NameTrue(True)
|
|
||||||
MySettings = u.HOST.Source
|
MySettings = u.HOST.Source
|
||||||
End Sub
|
End Sub
|
||||||
End Class
|
End Class
|
||||||
|
|||||||
@@ -11,14 +11,50 @@ Imports SCrawler.Plugin
|
|||||||
Imports SCrawler.Plugin.Attributes
|
Imports SCrawler.Plugin.Attributes
|
||||||
Imports PersonalUtilities.Functions.RegularExpressions
|
Imports PersonalUtilities.Functions.RegularExpressions
|
||||||
Imports PersonalUtilities.Tools.Web.Clients
|
Imports PersonalUtilities.Tools.Web.Clients
|
||||||
|
Imports PersonalUtilities.Tools.Web.Cookies
|
||||||
Imports DN = SCrawler.API.Base.DeclaredNames
|
Imports DN = SCrawler.API.Base.DeclaredNames
|
||||||
|
Imports IG = SCrawler.API.Instagram.SiteSettings
|
||||||
Namespace API.Twitter
|
Namespace API.Twitter
|
||||||
<Manifest(TwitterSiteKey), SavedPosts, SeparatedTasks, SpecialForm(False)>
|
<Manifest(TwitterSiteKey), SavedPosts, SeparatedTasks, SpecialForm(False)>
|
||||||
Friend Class SiteSettings : Inherits SiteSettingsBase
|
Friend Class SiteSettings : Inherits SiteSettingsBase
|
||||||
#Region "Declarations"
|
#Region "Declarations"
|
||||||
|
#Region "Icon"
|
||||||
|
<PXML("UseNewIcon")> Private ReadOnly Property UseNewIconXML As PropertyValue
|
||||||
|
<PropertyOption(ControlText:="Use the new Twitter icon (X)", ControlToolTip:="Restart SCrawler to take effect")>
|
||||||
|
Private ReadOnly Property UseNewIcon As PropertyValue
|
||||||
|
Get
|
||||||
|
If Not DefaultInstance Is Nothing Then
|
||||||
|
Return DirectCast(DefaultInstance, SiteSettings).UseNewIconXML
|
||||||
|
Else
|
||||||
|
Return UseNewIconXML
|
||||||
|
End If
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
|
Private Sub UpdateIcon()
|
||||||
|
If CBool(UseNewIcon.Value) Then _Icon = My.Resources.SiteResources.TwitterIconNew_32 : _Image = _Icon.ToBitmap
|
||||||
|
End Sub
|
||||||
|
#End Region
|
||||||
#Region "Categories"
|
#Region "Categories"
|
||||||
Private Const CAT_DOWN As String = "Downloading"
|
Private Const CAT_DOWN As String = "Downloading"
|
||||||
#End Region
|
#End Region
|
||||||
|
#Region "Auth"
|
||||||
|
<PropertyOption(ControlText:="Update cookies", ControlToolTip:="Update cookies during requests", IsAuth:=True), PXML, PClonable, HiddenControl>
|
||||||
|
Friend ReadOnly Property CookiesUpdate As PropertyValue
|
||||||
|
<PropertyOption(ControlText:="Use UserAgent", ControlToolTip:="Use UserAgent in requests", IsAuth:=True), PXML, PClonable>
|
||||||
|
Friend ReadOnly Property UserAgentUse As PropertyValue
|
||||||
|
<PropertyOption(ControlText:="UserAgent", IsAuth:=True, AllowNull:=True, InheritanceName:=SettingsCLS.HEADER_DEF_UserAgent),
|
||||||
|
PXML("UserAgent", OnlyForChecked:=True), PClonable>
|
||||||
|
Private ReadOnly Property UserAgentXML As PropertyValue
|
||||||
|
Friend ReadOnly Property UserAgent As String
|
||||||
|
Get
|
||||||
|
If CBool(UserAgentUse.Value) AndAlso Not CStr(UserAgentXML.Value).IsEmptyString Then
|
||||||
|
Return UserAgentXML.Value
|
||||||
|
Else
|
||||||
|
Return String.Empty
|
||||||
|
End If
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
|
#End Region
|
||||||
#Region "Other properties"
|
#Region "Other properties"
|
||||||
<PropertyOption(ControlText:="Use the appropriate model",
|
<PropertyOption(ControlText:="Use the appropriate model",
|
||||||
ControlToolTip:="Use the appropriate model for new users." & vbCr &
|
ControlToolTip:="Use the appropriate model for new users." & vbCr &
|
||||||
@@ -35,10 +71,30 @@ Namespace API.Twitter
|
|||||||
Friend Property UseNewEndPointProfiles As PropertyValue
|
Friend Property UseNewEndPointProfiles As PropertyValue
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Limits"
|
#Region "Limits"
|
||||||
|
Friend Const TimerDisabled As Integer = -1
|
||||||
|
Friend Const TimerFirstUseTheSame As Integer = -2
|
||||||
<PropertyOption(ControlText:="Abort on limit", ControlToolTip:="Abort twitter downloading when limit is reached", Category:=CAT_DOWN), PXML, PClonable>
|
<PropertyOption(ControlText:="Abort on limit", ControlToolTip:="Abort twitter downloading when limit is reached", Category:=CAT_DOWN), PXML, PClonable>
|
||||||
Friend Property AbortOnLimit As PropertyValue
|
Friend Property AbortOnLimit As PropertyValue
|
||||||
<PropertyOption(ControlText:="Download already parsed", ControlToolTip:="Download already parsed content on abort", Category:=CAT_DOWN), PXML, PClonable>
|
<PropertyOption(ControlText:="Download already parsed", ControlToolTip:="Download already parsed content on abort", Category:=CAT_DOWN), PXML, PClonable>
|
||||||
Friend Property DownloadAlreadyParsed As PropertyValue
|
Friend Property DownloadAlreadyParsed As PropertyValue
|
||||||
|
#End Region
|
||||||
|
#Region "Timers"
|
||||||
|
<PropertyOption(ControlText:="Sleep timer",
|
||||||
|
ControlToolTip:="Use sleep timer in requests." & vbCr &
|
||||||
|
"You can set a timer value (in seconds) to wait before each subsequent request." & vbCr &
|
||||||
|
"-1 to disable and use the default algorithm." & vbCr &
|
||||||
|
"Default: 20", Category:=CAT_DOWN), PXML, PClonable>
|
||||||
|
Friend ReadOnly Property SleepTimer As PropertyValue
|
||||||
|
<Provider(NameOf(SleepTimer), FieldsChecker:=True)>
|
||||||
|
Private ReadOnly Property SleepTimerProvider As IFormatProvider
|
||||||
|
<PropertyOption(ControlText:="Sleep timer at start",
|
||||||
|
ControlToolTip:="Set a sleep timer (in seconds) before the first request." & vbCr &
|
||||||
|
"-1 to disable" & vbCr &
|
||||||
|
"-2 to use the 'Sleep timer' value" & vbCr &
|
||||||
|
"Default: -2", Category:=CAT_DOWN), PXML, PClonable>
|
||||||
|
Friend ReadOnly Property SleepTimerBeforeFirst As PropertyValue
|
||||||
|
<Provider(NameOf(SleepTimerBeforeFirst), FieldsChecker:=True)>
|
||||||
|
Private ReadOnly Property SleepTimerBeforeFirstProvider As IFormatProvider
|
||||||
#End Region
|
#End Region
|
||||||
<PropertyOption(ControlText:="Media Model: allow non-user tweets", ControlToolTip:="Allow downloading non-user tweets in the media-model.", Category:=DN.CAT_UserDefs), PXML, PClonable>
|
<PropertyOption(ControlText:="Media Model: allow non-user tweets", ControlToolTip:="Allow downloading non-user tweets in the media-model.", Category:=DN.CAT_UserDefs), PXML, PClonable>
|
||||||
Friend ReadOnly Property MediaModelAllowNonUserTweets As PropertyValue
|
Friend ReadOnly Property MediaModelAllowNonUserTweets As PropertyValue
|
||||||
@@ -76,7 +132,17 @@ Namespace API.Twitter
|
|||||||
<Provider(NameOf(ConcurrentDownloads), FieldsChecker:=True)>
|
<Provider(NameOf(ConcurrentDownloads), FieldsChecker:=True)>
|
||||||
Private ReadOnly Property MyConcurrentDownloadsProvider As IFormatProvider
|
Private ReadOnly Property MyConcurrentDownloadsProvider As IFormatProvider
|
||||||
#End Region
|
#End Region
|
||||||
|
Friend Overrides Property DefaultInstance As ISiteSettings
|
||||||
|
Get
|
||||||
|
Return MyBase.DefaultInstance
|
||||||
|
End Get
|
||||||
|
Set(ByVal Instance As ISiteSettings)
|
||||||
|
MyBase.DefaultInstance = Instance
|
||||||
|
If Not Instance Is Nothing Then UpdateIcon()
|
||||||
|
End Set
|
||||||
|
End Property
|
||||||
#End Region
|
#End Region
|
||||||
|
#Region "Initializer"
|
||||||
Friend Sub New(ByVal AccName As String, ByVal Temp As Boolean)
|
Friend Sub New(ByVal AccName As String, ByVal Temp As Boolean)
|
||||||
MyBase.New(TwitterSite, "x.com", AccName, Temp, My.Resources.SiteResources.TwitterIcon_32, My.Resources.SiteResources.TwitterIcon_32.ToBitmap)
|
MyBase.New(TwitterSite, "x.com", AccName, Temp, My.Resources.SiteResources.TwitterIcon_32, My.Resources.SiteResources.TwitterIcon_32.ToBitmap)
|
||||||
|
|
||||||
@@ -87,11 +153,28 @@ Namespace API.Twitter
|
|||||||
.Cookies.Changed = False
|
.Cookies.Changed = False
|
||||||
End With
|
End With
|
||||||
|
|
||||||
|
UseNewIconXML = New PropertyValue(False)
|
||||||
|
|
||||||
|
CookiesUpdate = New PropertyValue(False)
|
||||||
|
UserAgentUse = New PropertyValue(True)
|
||||||
|
UserAgentXML = New PropertyValue(If(Responser.UserAgentExists, Responser.UserAgent, String.Empty), GetType(String),
|
||||||
|
Sub(ByVal Value As Object)
|
||||||
|
Responser.UserAgent = CStr(Value)
|
||||||
|
Responser.SaveSettings(, EDP.ReturnValue)
|
||||||
|
End Sub)
|
||||||
|
|
||||||
UseAppropriateModel = New PropertyValue(True)
|
UseAppropriateModel = New PropertyValue(True)
|
||||||
|
|
||||||
UseNewEndPointSearch = New PropertyValue(True)
|
UseNewEndPointSearch = New PropertyValue(True)
|
||||||
UseNewEndPointProfiles = New PropertyValue(True)
|
UseNewEndPointProfiles = New PropertyValue(True)
|
||||||
|
|
||||||
AbortOnLimit = New PropertyValue(True)
|
AbortOnLimit = New PropertyValue(True)
|
||||||
DownloadAlreadyParsed = New PropertyValue(True)
|
DownloadAlreadyParsed = New PropertyValue(True)
|
||||||
|
SleepTimer = New PropertyValue(TimerDisabled)
|
||||||
|
SleepTimerProvider = New IG.TimersChecker(TimerDisabled)
|
||||||
|
SleepTimerBeforeFirst = New PropertyValue(TimerFirstUseTheSame)
|
||||||
|
SleepTimerBeforeFirstProvider = New IG.TimersChecker(TimerFirstUseTheSame)
|
||||||
|
|
||||||
MediaModelAllowNonUserTweets = New PropertyValue(False)
|
MediaModelAllowNonUserTweets = New PropertyValue(False)
|
||||||
GifsDownload = New PropertyValue(True)
|
GifsDownload = New PropertyValue(True)
|
||||||
GifsSpecialFolder = New PropertyValue(String.Empty, GetType(String))
|
GifsSpecialFolder = New PropertyValue(String.Empty, GetType(String))
|
||||||
@@ -101,28 +184,60 @@ Namespace API.Twitter
|
|||||||
ConcurrentDownloads = New PropertyValue(1)
|
ConcurrentDownloads = New PropertyValue(1)
|
||||||
MyConcurrentDownloadsProvider = New ConcurrentDownloadsProvider
|
MyConcurrentDownloadsProvider = New ConcurrentDownloadsProvider
|
||||||
|
|
||||||
|
_AllowUserAgentUpdate = False
|
||||||
UserRegex = RParams.DMS(String.Format(UserRegexDefaultPattern, $"/(twitter|x).com({CommunitiesUser}|)/"), 3)
|
UserRegex = RParams.DMS(String.Format(UserRegexDefaultPattern, $"/(twitter|x).com({CommunitiesUser}|)/"), 3)
|
||||||
UrlPatternUser = "https://x.com/{0}"
|
UrlPatternUser = "https://x.com/{0}"
|
||||||
ImageVideoContains = "twitter"
|
ImageVideoContains = "twitter"
|
||||||
CheckNetscapeCookiesOnEndInit = True
|
CheckNetscapeCookiesOnEndInit = True
|
||||||
UseNetscapeCookies = True
|
UseNetscapeCookies = True
|
||||||
End Sub
|
End Sub
|
||||||
|
Friend Overrides Sub EndInit()
|
||||||
|
UpdateIcon()
|
||||||
|
MyBase.EndInit()
|
||||||
|
End Sub
|
||||||
|
#End Region
|
||||||
|
#Region "GetInstance"
|
||||||
Friend Overrides Function GetInstance(ByVal What As ISiteSettings.Download) As IPluginContentProvider
|
Friend Overrides Function GetInstance(ByVal What As ISiteSettings.Download) As IPluginContentProvider
|
||||||
Return New UserData
|
Return New UserData
|
||||||
End Function
|
End Function
|
||||||
Friend Const SinglePostPattern As String = "https://x.com/i/web/status/{0}"
|
#End Region
|
||||||
Friend Overrides Function GetUserPostUrl(ByVal User As UserDataBase, ByVal Media As UserMedia) As String
|
#Region "BaseAuthExists, Available"
|
||||||
Return String.Format(SinglePostPattern, Media.Post.ID)
|
|
||||||
End Function
|
|
||||||
Friend Overrides Function BaseAuthExists() As Boolean
|
Friend Overrides Function BaseAuthExists() As Boolean
|
||||||
Return Responser.CookiesExists
|
Return Responser.CookiesExists
|
||||||
End Function
|
End Function
|
||||||
Friend Overrides Function Available(ByVal What As ISiteSettings.Download, ByVal Silent As Boolean) As Boolean
|
Friend Overrides Function Available(ByVal What As ISiteSettings.Download, ByVal Silent As Boolean) As Boolean
|
||||||
Return Settings.GalleryDLFile.Exists And BaseAuthExists()
|
Return Settings.GalleryDLFile.Exists And BaseAuthExists()
|
||||||
End Function
|
End Function
|
||||||
|
#End Region
|
||||||
|
#Region "Download"
|
||||||
Friend Property LIMIT_ABORT As Boolean = False
|
Friend Property LIMIT_ABORT As Boolean = False
|
||||||
Friend ReadOnly Property LimitSkippedUsers As List(Of UserDataBase)
|
Friend ReadOnly Property LimitSkippedUsers As List(Of UserDataBase)
|
||||||
|
Friend Property UserNumber As Integer = -1
|
||||||
|
Friend Overrides Sub DownloadStarted(ByVal What As ISiteSettings.Download)
|
||||||
|
UserNumber = 0
|
||||||
|
MyBase.DownloadStarted(What)
|
||||||
|
End Sub
|
||||||
|
Friend Overrides Sub AfterDownload(ByVal User As Object, ByVal What As ISiteSettings.Download)
|
||||||
|
If Not User Is Nothing AndAlso DirectCast(User, UserData).GDL_REQUESTS_COUNT > 0 Then UserNumber += 1
|
||||||
|
MyBase.AfterDownload(User, What)
|
||||||
|
End Sub
|
||||||
Friend Overrides Sub DownloadDone(ByVal What As ISiteSettings.Download)
|
Friend Overrides Sub DownloadDone(ByVal What As ISiteSettings.Download)
|
||||||
|
If UserNumber > 0 Then
|
||||||
|
If CBool(CookiesUpdate.Value) Then
|
||||||
|
With CookieKeeper.ParseNetscapeText(CookiesNetscapeFile.GetText(EDP.ReturnValue), EDP.ReturnValue)
|
||||||
|
If .ListExists Then
|
||||||
|
Responser.Cookies.Clear()
|
||||||
|
Responser.Cookies.AddRange(.Self,, EDP.ReturnValue)
|
||||||
|
Responser.SaveCookies(EDP.ReturnValue)
|
||||||
|
Else
|
||||||
|
Update_SaveCookiesNetscape(True)
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
Else
|
||||||
|
Update_SaveCookiesNetscape(True)
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
UserNumber = -1
|
||||||
If LimitSkippedUsers.Count > 0 Then
|
If LimitSkippedUsers.Count > 0 Then
|
||||||
With LimitSkippedUsers
|
With LimitSkippedUsers
|
||||||
If .Count = 1 Then
|
If .Count = 1 Then
|
||||||
@@ -137,6 +252,8 @@ Namespace API.Twitter
|
|||||||
LIMIT_ABORT = False
|
LIMIT_ABORT = False
|
||||||
MyBase.DownloadDone(What)
|
MyBase.DownloadDone(What)
|
||||||
End Sub
|
End Sub
|
||||||
|
#End Region
|
||||||
|
#Region "UserOptions, Update"
|
||||||
Friend Overrides Sub UserOptions(ByRef Options As Object, ByVal OpenForm As Boolean)
|
Friend Overrides Sub UserOptions(ByRef Options As Object, ByVal OpenForm As Boolean)
|
||||||
If Options Is Nothing OrElse (Not TypeOf Options Is EditorExchangeOptions OrElse
|
If Options Is Nothing OrElse (Not TypeOf Options Is EditorExchangeOptions OrElse
|
||||||
Not DirectCast(Options, EditorExchangeOptions).SiteKey = TwitterSiteKey) Then _
|
Not DirectCast(Options, EditorExchangeOptions).SiteKey = TwitterSiteKey) Then _
|
||||||
@@ -152,6 +269,8 @@ Namespace API.Twitter
|
|||||||
End If
|
End If
|
||||||
MyBase.Update()
|
MyBase.Update()
|
||||||
End Sub
|
End Sub
|
||||||
|
#End Region
|
||||||
|
#Region "IsMyUser, IsMyImageVideo, GetUserPostUrl, GetUserUrl"
|
||||||
Friend Const CommunitiesUser As String = "/i/communities"
|
Friend Const CommunitiesUser As String = "/i/communities"
|
||||||
Friend Overrides Function IsMyUser(ByVal UserURL As String) As ExchangeOptions
|
Friend Overrides Function IsMyUser(ByVal UserURL As String) As ExchangeOptions
|
||||||
Dim e As ExchangeOptions = MyBase.IsMyUser(UserURL)
|
Dim e As ExchangeOptions = MyBase.IsMyUser(UserURL)
|
||||||
@@ -169,8 +288,13 @@ Namespace API.Twitter
|
|||||||
Return Nothing
|
Return Nothing
|
||||||
End If
|
End If
|
||||||
End Function
|
End Function
|
||||||
|
Friend Const SinglePostPattern As String = "https://x.com/i/web/status/{0}"
|
||||||
|
Friend Overrides Function GetUserPostUrl(ByVal User As UserDataBase, ByVal Media As UserMedia) As String
|
||||||
|
Return String.Format(SinglePostPattern, Media.Post.ID)
|
||||||
|
End Function
|
||||||
Friend Overrides Function GetUserUrl(ByVal User As IPluginContentProvider) As String
|
Friend Overrides Function GetUserUrl(ByVal User As IPluginContentProvider) As String
|
||||||
Return DirectCast(User, UserData).GetUserUrl
|
Return DirectCast(User, UserData).GetUserUrl
|
||||||
End Function
|
End Function
|
||||||
|
#End Region
|
||||||
End Class
|
End Class
|
||||||
End Namespace
|
End Namespace
|
||||||
@@ -35,15 +35,6 @@ Namespace API.Twitter
|
|||||||
#Region "Declarations"
|
#Region "Declarations"
|
||||||
Private Const BroadCastPartUrl As String = "i/broadcasts"
|
Private Const BroadCastPartUrl As String = "i/broadcasts"
|
||||||
Private Const Label_Community As String = "Community"
|
Private Const Label_Community As String = "Community"
|
||||||
Private _NameTrue As String = String.Empty
|
|
||||||
Friend Property NameTrue(Optional ByVal Exact As Boolean = False) As String
|
|
||||||
Get
|
|
||||||
Return If(Exact, _NameTrue, _NameTrue.IfNullOrEmpty(Name))
|
|
||||||
End Get
|
|
||||||
Set(ByVal NewName As String)
|
|
||||||
_NameTrue = NewName
|
|
||||||
End Set
|
|
||||||
End Property
|
|
||||||
Friend Overrides ReadOnly Property SpecialLabels As IEnumerable(Of String)
|
Friend Overrides ReadOnly Property SpecialLabels As IEnumerable(Of String)
|
||||||
Get
|
Get
|
||||||
Return {Label_Community}
|
Return {Label_Community}
|
||||||
@@ -98,6 +89,7 @@ Namespace API.Twitter
|
|||||||
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)
|
||||||
|
.ApplyBase(Me)
|
||||||
GifsDownload = .GifsDownload
|
GifsDownload = .GifsDownload
|
||||||
GifsSpecialFolder = .GifsSpecialFolder
|
GifsSpecialFolder = .GifsSpecialFolder
|
||||||
GifsPrefix = .GifsPrefix
|
GifsPrefix = .GifsPrefix
|
||||||
@@ -114,7 +106,6 @@ Namespace API.Twitter
|
|||||||
If .DownloadModelSearch Then DownloadModel += DownloadModels.Search
|
If .DownloadModelSearch Then DownloadModel += DownloadModels.Search
|
||||||
If .DownloadModelLikes Then DownloadModel += DownloadModels.Likes
|
If .DownloadModelLikes Then DownloadModel += DownloadModels.Likes
|
||||||
If Not dModel = DownloadModel Then DownloadModelChanged = True
|
If Not dModel = DownloadModel Then DownloadModelChanged = True
|
||||||
_NameTrue = .UserName
|
|
||||||
End With
|
End With
|
||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
@@ -164,12 +155,11 @@ Namespace API.Twitter
|
|||||||
StartMD5Checked = .Value(Name_StartMD5Checked).FromXML(Of Boolean)(False)
|
StartMD5Checked = .Value(Name_StartMD5Checked).FromXML(Of Boolean)(False)
|
||||||
MediaModelAllowNonUserTweets = .Value(Name_MediaModelAllowNonUserTweets).FromXML(Of Boolean)(False)
|
MediaModelAllowNonUserTweets = .Value(Name_MediaModelAllowNonUserTweets).FromXML(Of Boolean)(False)
|
||||||
IsCommunity = .Value(Name_IsCommunity).FromXML(Of Boolean)(False)
|
IsCommunity = .Value(Name_IsCommunity).FromXML(Of Boolean)(False)
|
||||||
_NameTrue = .Value(Name_TrueName)
|
|
||||||
Else
|
Else
|
||||||
If Name.Contains("@") And Not IsCommunity Then
|
If Name.Contains("@") And Not IsCommunity Then
|
||||||
IsCommunity = True
|
IsCommunity = True
|
||||||
_NameTrue = Name.Split("@")(0)
|
NameTrue = Name.Split("@")(0)
|
||||||
ID = _NameTrue
|
ID = NameTrue
|
||||||
ParseUserMediaOnly = False
|
ParseUserMediaOnly = False
|
||||||
Labels.ListAddValue(Label_Community, LNC)
|
Labels.ListAddValue(Label_Community, LNC)
|
||||||
Labels.Sort()
|
Labels.Sort()
|
||||||
@@ -190,7 +180,7 @@ Namespace API.Twitter
|
|||||||
.Add(Name_StartMD5Checked, StartMD5Checked.BoolToInteger)
|
.Add(Name_StartMD5Checked, StartMD5Checked.BoolToInteger)
|
||||||
.Add(Name_MediaModelAllowNonUserTweets, MediaModelAllowNonUserTweets.BoolToInteger)
|
.Add(Name_MediaModelAllowNonUserTweets, MediaModelAllowNonUserTweets.BoolToInteger)
|
||||||
.Add(Name_IsCommunity, IsCommunity.BoolToInteger)
|
.Add(Name_IsCommunity, IsCommunity.BoolToInteger)
|
||||||
.Add(Name_TrueName, _NameTrue)
|
.Add(Name_TrueName, NameTrue(True))
|
||||||
End If
|
End If
|
||||||
End With
|
End With
|
||||||
End Sub
|
End Sub
|
||||||
@@ -266,8 +256,14 @@ Namespace API.Twitter
|
|||||||
End If
|
End If
|
||||||
Return result
|
Return result
|
||||||
End Function
|
End Function
|
||||||
|
Friend Property GDL_REQUESTS_COUNT As Integer = 0
|
||||||
|
Private Const DEBUG_PROFILE As Boolean = False
|
||||||
|
Private Const DEBUG_LEAVE_CACHE As Boolean = False
|
||||||
|
Private JsonNullErr As Boolean = False
|
||||||
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
|
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
|
||||||
Try
|
Try
|
||||||
|
GDL_REQUESTS_COUNT = 0
|
||||||
|
JsonNullErr = False
|
||||||
If MySettings.LIMIT_ABORT Then
|
If MySettings.LIMIT_ABORT Then
|
||||||
Throw New TwitterLimitException(Me)
|
Throw New TwitterLimitException(Me)
|
||||||
Else
|
Else
|
||||||
@@ -285,6 +281,7 @@ Namespace API.Twitter
|
|||||||
LikesPosts.Clear()
|
LikesPosts.Clear()
|
||||||
If _ContentList.Count > 0 Then _DataNames.ListAddList(_ContentList.Select(Function(c) c.File.File), LAP.ClearBeforeAdd, LAP.NotContainsOnly)
|
If _ContentList.Count > 0 Then _DataNames.ListAddList(_ContentList.Select(Function(c) c.File.File), LAP.ClearBeforeAdd, LAP.NotContainsOnly)
|
||||||
DownloadData_Timeline(Token)
|
DownloadData_Timeline(Token)
|
||||||
|
If _TempMediaList.Count = 0 And LikesPosts.Count = 0 And JsonNullErr Then Throw New Plugin.ExitException("No deserialized data found")
|
||||||
LoadSavePostsKV(False)
|
LoadSavePostsKV(False)
|
||||||
If LikesPosts.Count > 0 Then
|
If LikesPosts.Count > 0 Then
|
||||||
_ReparseLikes = True
|
_ReparseLikes = True
|
||||||
@@ -297,10 +294,20 @@ Namespace API.Twitter
|
|||||||
_ReparseLikes = False
|
_ReparseLikes = False
|
||||||
End Try
|
End Try
|
||||||
End Sub
|
End Sub
|
||||||
|
Private Class WebDocumentEventArgsT : Inherits WebDocumentEventArgs
|
||||||
|
Public Overloads Overrides Sub Reset()
|
||||||
|
State = States.None
|
||||||
|
End Sub
|
||||||
|
Public Overloads Sub Reset(ByVal Token As CancellationToken)
|
||||||
|
Reset()
|
||||||
|
Me.Token = Token
|
||||||
|
End Sub
|
||||||
|
End Class
|
||||||
Private Sub DownloadData_Timeline(ByVal Token As CancellationToken)
|
Private Sub DownloadData_Timeline(ByVal Token As CancellationToken)
|
||||||
Dim URL$ = String.Empty
|
Dim URL$ = String.Empty
|
||||||
Dim tCache As CacheKeeper = Nothing
|
Dim tCache As CacheKeeper = Nothing
|
||||||
Dim likesDetected As Boolean = False
|
Dim likesDetected As Boolean = False
|
||||||
|
Dim jsonArgs As New WebDocumentEventArgsT With {.DeclaredError = New ErrorsDescriber(EDP.ReturnValue)}
|
||||||
Try
|
Try
|
||||||
Const entry$ = "entry"
|
Const entry$ = "entry"
|
||||||
Dim PostID$ = String.Empty
|
Dim PostID$ = String.Empty
|
||||||
@@ -348,6 +355,8 @@ Namespace API.Twitter
|
|||||||
ElseIf dirIndx = 3 Then
|
ElseIf dirIndx = 3 Then
|
||||||
ElseIf isPins Then
|
ElseIf isPins Then
|
||||||
Return False
|
Return False
|
||||||
|
ElseIf Not FirstDownloadComplete Then
|
||||||
|
Return True
|
||||||
Else
|
Else
|
||||||
ExistsDetected = Not multiMode
|
ExistsDetected = Not multiMode
|
||||||
Return multiMode
|
Return multiMode
|
||||||
@@ -387,13 +396,24 @@ Namespace API.Twitter
|
|||||||
Return True
|
Return True
|
||||||
End Function
|
End Function
|
||||||
|
|
||||||
tCache = CreateCache()
|
If Not DEBUG_PROFILE Then tCache = CreateCache()
|
||||||
|
|
||||||
'0 - media
|
'0 - media
|
||||||
'1 - profile
|
'1 - profile
|
||||||
'2 - search
|
'2 - search
|
||||||
'3 - likes
|
'3 - likes
|
||||||
Dim dirs As List(Of SFile) = GetTimelineFromGalleryDL(tCache, Token)
|
Dim dirs As List(Of SFile)
|
||||||
|
If Not DEBUG_PROFILE Then
|
||||||
|
dirs = GetTimelineFromGalleryDL(tCache, Token)
|
||||||
|
Else
|
||||||
|
dirs = SFile.GetDirectories($"{DownloadContentDefault_GetRootDir()}\_tCache\".CSFileP)
|
||||||
|
If dirs.ListExists(2) Then
|
||||||
|
dirs = SFile.GetDirectories(dirs(1))
|
||||||
|
Else
|
||||||
|
dirs = New List(Of SFile)
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
|
||||||
If dirs.ListExists Then
|
If dirs.ListExists Then
|
||||||
For Each dir As SFile In dirs
|
For Each dir As SFile In dirs
|
||||||
dirIndx += 1
|
dirIndx += 1
|
||||||
@@ -416,27 +436,23 @@ Namespace API.Twitter
|
|||||||
If timelineFiles.ListExists Then
|
If timelineFiles.ListExists Then
|
||||||
ResetFileNameProvider(Math.Max(timelineFiles.Count.ToString.Length, 2))
|
ResetFileNameProvider(Math.Max(timelineFiles.Count.ToString.Length, 2))
|
||||||
'rename files
|
'rename files
|
||||||
For i = 0 To timelineFiles.Count - 1 : timelineFiles(i) = RenameGdlFile(timelineFiles(i), i) : Next
|
If Not DEBUG_PROFILE Then
|
||||||
|
For i = 0 To timelineFiles.Count - 1 : timelineFiles(i) = RenameGdlFile(timelineFiles(i), i) : Next
|
||||||
|
End If
|
||||||
'parse files
|
'parse files
|
||||||
For i = 0 To timelineFiles.Count - 1
|
For i = 0 To timelineFiles.Count - 1
|
||||||
j = JsonDocument.Parse(timelineFiles(i).GetText)
|
j = JsonDocument.Parse(timelineFiles(i).GetText, jsonArgs)
|
||||||
|
If jsonArgs.State = WebDocumentEventArgs.States.Error Then
|
||||||
|
jsonArgs.Reset(Token)
|
||||||
|
Continue For
|
||||||
|
End If
|
||||||
If Not j Is Nothing Then
|
If Not j Is Nothing Then
|
||||||
If i = 0 And Not indxChanged Then
|
If Not userInfoParsed Or (i = 0 And Not indxChanged) Then
|
||||||
If Not userInfoParsed Then
|
If Not userInfoParsed Then
|
||||||
userInfoParsed = True
|
userInfoParsed = True
|
||||||
Dim resValue$ = j.Value({"data", IIf(IsCommunity, "communityResults", "user"), "result"}, "__typename").StringTrim.StringToLower
|
Dim resValue$ = j.Value({"data", IIf(IsCommunity, "communityResults", "user"), "result"}, "__typename").StringTrim.StringToLower
|
||||||
Dim icon$
|
Dim icon$
|
||||||
Dim __getImage As Action(Of String) = Sub(ByVal img As String)
|
Dim fileCrFunc As Func(Of String, SFile) = Function(img) UrlFile(img, True)
|
||||||
If Not img.IsEmptyString Then
|
|
||||||
Dim __imgFile As SFile = UrlFile(img, True)
|
|
||||||
If Not __imgFile.Name.IsEmptyString Then
|
|
||||||
If __imgFile.Extension.IsEmptyString Then __imgFile.Extension = "jpg"
|
|
||||||
__imgFile.Path = MyFile.CutPath.Path
|
|
||||||
If Not __imgFile.Exists Then GetWebFile(img, __imgFile, EDP.None)
|
|
||||||
If __imgFile.Exists Then IconBannerDownloaded = True
|
|
||||||
End If
|
|
||||||
End If
|
|
||||||
End Sub
|
|
||||||
If resValue.IsEmptyString Then
|
If resValue.IsEmptyString Then
|
||||||
UserExists = False
|
UserExists = False
|
||||||
j.Dispose()
|
j.Dispose()
|
||||||
@@ -458,7 +474,7 @@ Namespace API.Twitter
|
|||||||
|
|
||||||
icon = .Value({"custom_banner_media", "media_info"}, "original_img_url").
|
icon = .Value({"custom_banner_media", "media_info"}, "original_img_url").
|
||||||
IfNullOrEmpty(.Value({"default_banner_media", "media_info"}, "original_img_url"))
|
IfNullOrEmpty(.Value({"default_banner_media", "media_info"}, "original_img_url"))
|
||||||
If Not icon.IsEmptyString And DownloadIconBanner Then __getImage.Invoke(icon)
|
If Not icon.IsEmptyString And DownloadIconBanner Then SimpleDownloadAvatar(icon, fileCrFunc)
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
End With
|
End With
|
||||||
@@ -484,8 +500,8 @@ Namespace API.Twitter
|
|||||||
icon = .Value("profile_image_url_https")
|
icon = .Value("profile_image_url_https")
|
||||||
If Not icon.IsEmptyString Then icon = icon.Replace("_normal", String.Empty)
|
If Not icon.IsEmptyString Then icon = icon.Replace("_normal", String.Empty)
|
||||||
If DownloadIconBanner Then
|
If DownloadIconBanner Then
|
||||||
__getImage.Invoke(.Value("profile_banner_url"))
|
SimpleDownloadAvatar(.Value("profile_banner_url"), fileCrFunc)
|
||||||
__getImage.Invoke(icon)
|
SimpleDownloadAvatar(icon, fileCrFunc)
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
@@ -516,6 +532,8 @@ Namespace API.Twitter
|
|||||||
Select Case dirIndx
|
Select Case dirIndx
|
||||||
Case 0, 1, 3
|
Case 0, 1, 3
|
||||||
rootNode = j({"data", "user", "result", "timeline_v2", "timeline", "instructions"})
|
rootNode = j({"data", "user", "result", "timeline_v2", "timeline", "instructions"})
|
||||||
|
If Not rootNode.ListExists Then rootNode = j({"data", "user", "result", "timeline", "timeline", "instructions"})
|
||||||
|
If Not rootNode.ListExists Then rootNode = j({"data", "search_by_raw_query", "search_timeline", "timeline", "instructions"})
|
||||||
If rootNode.ListExists Then
|
If rootNode.ListExists Then
|
||||||
If dirIndx = 3 Then
|
If dirIndx = 3 Then
|
||||||
p = entriesNode
|
p = entriesNode
|
||||||
@@ -607,8 +625,9 @@ nextpIndx:
|
|||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
ProcessException(ex, Token, $"data downloading error [{URL}]")
|
ProcessException(ex, Token, $"data downloading error [{URL}]")
|
||||||
Finally
|
Finally
|
||||||
If Not tCache Is Nothing Then tCache.Dispose()
|
If Not tCache Is Nothing And Not DEBUG_PROFILE And Not DEBUG_LEAVE_CACHE Then tCache.Dispose()
|
||||||
If _TempPostsList.Count > 0 And Not likesDetected Then _TempPostsList.Sort()
|
If _TempPostsList.Count > 0 And Not likesDetected Then _TempPostsList.Sort()
|
||||||
|
jsonArgs.DisposeIfReady(False)
|
||||||
End Try
|
End Try
|
||||||
End Sub
|
End Sub
|
||||||
Private Sub DownloadData_SavedPosts(ByVal Token As CancellationToken)
|
Private Sub DownloadData_SavedPosts(ByVal Token As CancellationToken)
|
||||||
@@ -660,30 +679,42 @@ nextpIndx:
|
|||||||
Dim s As EContainer = e({"extended_entities", "media"})
|
Dim s As EContainer = e({"extended_entities", "media"})
|
||||||
If If(s?.Count, 0) = 0 Then s = e({"retweeted_status", "extended_entities", "media"})
|
If If(s?.Count, 0) = 0 Then s = e({"retweeted_status", "extended_entities", "media"})
|
||||||
If If(s?.Count, 0) = 0 Then s = e({"retweeted_status_result", "result", "legacy", "extended_entities", "media"})
|
If If(s?.Count, 0) = 0 Then s = e({"retweeted_status_result", "result", "legacy", "extended_entities", "media"})
|
||||||
|
Dim txt$ = If(DownloadText, e.Value("full_text"), String.Empty)
|
||||||
|
|
||||||
|
Dim mUrl$
|
||||||
|
Dim media As UserMedia
|
||||||
|
Dim setMediaDef As Action = Sub()
|
||||||
|
If Not SpecialFolder.IsEmptyString Then media.SpecialFolder = SpecialFolder
|
||||||
|
media.PostText = txt
|
||||||
|
media.PostTextFileSpecialFolder = DownloadTextSpecialFolder
|
||||||
|
End Sub
|
||||||
If If(s?.Count, 0) > 0 Then
|
If If(s?.Count, 0) > 0 Then
|
||||||
Dim mUrl$
|
|
||||||
Dim media As UserMedia
|
|
||||||
For Each m As EContainer In s
|
For Each m As EContainer In s
|
||||||
If Not CheckVideoNode(m, PostID, PostDate, State, SpecialFolder) Then
|
If Not CheckVideoNode(m, PostID, PostDate, State, SpecialFolder, txt) Then
|
||||||
mUrl = m.Value("media_url").IfNullOrEmpty(m.Value("media_url_https"))
|
mUrl = m.Value("media_url").IfNullOrEmpty(m.Value("media_url_https"))
|
||||||
If Not mUrl.IsEmptyString Then
|
If Not mUrl.IsEmptyString Then
|
||||||
Dim dName$ = UrlFile(mUrl)
|
Dim dName$ = UrlFile(mUrl)
|
||||||
If Not dName.IsEmptyString AndAlso Not _DataNames.Contains(dName) Then
|
If Not dName.IsEmptyString AndAlso Not _DataNames.Contains(dName) Then
|
||||||
_DataNames.Add(dName)
|
_DataNames.Add(dName)
|
||||||
media = MediaFromData(mUrl, PostID, PostDate, GetPictureOption(m), State, UTypes.Picture, Attempts)
|
media = MediaFromData(mUrl, PostID, PostDate, GetPictureOption(m), State, UTypes.Picture, Attempts)
|
||||||
If Not SpecialFolder.IsEmptyString Then media.SpecialFolder = SpecialFolder
|
setMediaDef()
|
||||||
_TempMediaList.ListAddValue(media, LNC)
|
_TempMediaList.ListAddValue(media, LNC)
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
Next
|
Next
|
||||||
|
ElseIf Not txt.IsEmptyString And DownloadTextPosts Then
|
||||||
|
media = MediaFromData(PostID, PostID, PostDate, String.Empty, State, UTypes.Text, Attempts)
|
||||||
|
setMediaDef()
|
||||||
|
media.PostTextFile = $"{PostID}.txt"
|
||||||
|
_TempMediaList.ListAddValue(media, LNC)
|
||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
Private Function CheckVideoNode(ByVal w As EContainer, ByVal PostID As String, ByVal PostDate As String,
|
Private Function CheckVideoNode(ByVal w As EContainer, ByVal PostID As String, ByVal PostDate As String,
|
||||||
Optional ByVal State As UStates = UStates.Unknown, Optional ByVal SpecialFolder As String = Nothing) As Boolean
|
Optional ByVal State As UStates = UStates.Unknown, Optional ByVal SpecialFolder As String = Nothing,
|
||||||
|
Optional ByVal PostText As String = Nothing) As Boolean
|
||||||
Try
|
Try
|
||||||
If CheckForGif(w, PostID, PostDate, State, SpecialFolder) Then Return True
|
If CheckForGif(w, PostID, PostDate, State, SpecialFolder, PostText) Then Return True
|
||||||
Dim URL$ = GetVideoNodeURL(w)
|
Dim URL$ = GetVideoNodeURL(w)
|
||||||
If Not URL.IsEmptyString Then
|
If Not URL.IsEmptyString Then
|
||||||
Dim f$ = UrlFile(URL)
|
Dim f$ = UrlFile(URL)
|
||||||
@@ -691,6 +722,7 @@ nextpIndx:
|
|||||||
_DataNames.Add(f)
|
_DataNames.Add(f)
|
||||||
Dim m As UserMedia = MediaFromData(URL, PostID, PostDate,, State, UTypes.Video)
|
Dim m As UserMedia = MediaFromData(URL, PostID, PostDate,, State, UTypes.Video)
|
||||||
If Not SpecialFolder.IsEmptyString Then m.SpecialFolder = SpecialFolder
|
If Not SpecialFolder.IsEmptyString Then m.SpecialFolder = SpecialFolder
|
||||||
|
m.PostText = PostText
|
||||||
_TempMediaList.ListAddValue(m, LNC)
|
_TempMediaList.ListAddValue(m, LNC)
|
||||||
End If
|
End If
|
||||||
Return True
|
Return True
|
||||||
@@ -702,7 +734,8 @@ nextpIndx:
|
|||||||
End Try
|
End Try
|
||||||
End Function
|
End Function
|
||||||
Private Function CheckForGif(ByVal w As EContainer, ByVal PostID As String, ByVal PostDate As String,
|
Private Function CheckForGif(ByVal w As EContainer, ByVal PostID As String, ByVal PostDate As String,
|
||||||
Optional ByVal State As UStates = UStates.Unknown, Optional ByVal SpecialFolder As String = Nothing) As Boolean
|
Optional ByVal State As UStates = UStates.Unknown, Optional ByVal SpecialFolder As String = Nothing,
|
||||||
|
Optional ByVal PostText As String = Nothing) As Boolean
|
||||||
Try
|
Try
|
||||||
Dim gifUrl As Predicate(Of EContainer) = Function(e) Not e.Value("content_type").IsEmptyString AndAlso
|
Dim gifUrl As Predicate(Of EContainer) = Function(e) Not e.Value("content_type").IsEmptyString AndAlso
|
||||||
e.Value("content_type").Contains("mp4") AndAlso
|
e.Value("content_type").Contains("mp4") AndAlso
|
||||||
@@ -728,6 +761,7 @@ nextpIndx:
|
|||||||
If Not m.SpecialFolder.IsEmptyString Then m.SpecialFolder &= "\"
|
If Not m.SpecialFolder.IsEmptyString Then m.SpecialFolder &= "\"
|
||||||
m.SpecialFolder &= $"{GifsSpecialFolder}*"
|
m.SpecialFolder &= $"{GifsSpecialFolder}*"
|
||||||
End If
|
End If
|
||||||
|
m.PostText = PostText
|
||||||
_TempMediaList.ListAddValue(m, LNC)
|
_TempMediaList.ListAddValue(m, LNC)
|
||||||
End If
|
End If
|
||||||
Return True
|
Return True
|
||||||
@@ -799,19 +833,87 @@ nextpIndx:
|
|||||||
End Sub
|
End Sub
|
||||||
Private Sub CheckForLimit(ByVal Value As String)
|
Private Sub CheckForLimit(ByVal Value As String)
|
||||||
If Token.IsCancellationRequested Or (KillOnLimit AndAlso Not ProcessKilled AndAlso
|
If Token.IsCancellationRequested Or (KillOnLimit AndAlso Not ProcessKilled AndAlso
|
||||||
Not Value.IsEmptyString AndAlso Value.ToLower.Contains("for rate limit reset")) Then
|
Not Value.IsEmptyString AndAlso (Value.ToLower.Contains("for rate limit reset") OrElse
|
||||||
|
Not CStr(RegexReplace(Value, GdlLimitRegEx)).IsEmptyString)) Then
|
||||||
LimitReached = True
|
LimitReached = True
|
||||||
Kill()
|
Kill()
|
||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
End Class
|
End Class
|
||||||
|
Private ReadOnly Property SleepTimerValue(ByVal First As Boolean) As Integer
|
||||||
|
Get
|
||||||
|
Dim fTimer% = If(First, MySettings.SleepTimerBeforeFirst, MySettings.SleepTimer).Value
|
||||||
|
If First And fTimer = SiteSettings.TimerFirstUseTheSame Then fTimer = MySettings.SleepTimer.Value
|
||||||
|
Return fTimer
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
|
Private ReadOnly Property SleepRequest As String
|
||||||
|
Get
|
||||||
|
Dim s% = SleepTimerValue(False)
|
||||||
|
Return If(s = SiteSettings.TimerDisabled, String.Empty, $" --sleep-request {s}")
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
|
Private Sub GdlWaitFirstTimer(ByVal fTimer As Integer)
|
||||||
|
If GDL_REQUESTS_COUNT = 0 And Not fTimer = SiteSettings.TimerDisabled And MySettings.UserNumber > 0 Then Thread.Sleep(fTimer * 1000)
|
||||||
|
GDL_REQUESTS_COUNT += 1
|
||||||
|
End Sub
|
||||||
|
Private _GdlPreProgressPerformEnabled As Boolean = False
|
||||||
|
Private Sub GdlPreProgressPerform(ByVal Path As SFile, ByVal UpDir As SFile)
|
||||||
|
Dim f As SFile = Nothing
|
||||||
|
Try
|
||||||
|
Dim c% = -1, lb% = -1, cc%
|
||||||
|
Dim e As New ErrorsDescriber(EDP.ReturnValue)
|
||||||
|
While _GdlPreProgressPerformEnabled
|
||||||
|
Thread.Sleep(100)
|
||||||
|
If c > 0 Then
|
||||||
|
cc = If(SFile.GetFiles(Path,,, e)?.Count, 0)
|
||||||
|
If cc > c Then
|
||||||
|
Exit Sub
|
||||||
|
ElseIf cc > 0 And (lb = -1 Or cc > lb) Then
|
||||||
|
ProgressPre.Perform(cc - IIf(lb = -1, 0, lb))
|
||||||
|
lb = cc
|
||||||
|
End If
|
||||||
|
ElseIf Path.Exists(SFO.Path, False) Then
|
||||||
|
Dim files As List(Of SFile) = SFile.GetFiles(Path,,, e)
|
||||||
|
If files.ListExists Then
|
||||||
|
f = files.FirstOrDefault(Function(ff) Not ff.Name.IsEmptyString AndAlso ff.Name.StartsWith("01_"))
|
||||||
|
If UpDir.Exists(SFO.Path, False) Then
|
||||||
|
Dim fNew As SFile = $"{UpDir.PathWithSeparator}00.txt"
|
||||||
|
If f.Copy(fNew,, True, SFODelete.DeletePermanently,, e) Then
|
||||||
|
f = fNew
|
||||||
|
Using j As EContainer = JsonDocument.Parse(f.GetText(e), e)
|
||||||
|
If j.ListExists Then
|
||||||
|
c = j(GdlPostCoutNumberNodes).XmlIfNothingValue.FromXML(Of Integer)(-1)
|
||||||
|
If c > 0 Then c /= 30 : ProgressPre.ChangeMax(c) : Continue While
|
||||||
|
End If
|
||||||
|
End Using
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
Exit Sub
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
End While
|
||||||
|
Catch ex As Exception
|
||||||
|
ErrorsDescriber.Execute(EDP.SendToLog, ex, $"{ToStringForLog()}:{vbCr}Path: '{Path.Path}'{vbCr}Path 2: '{UpDir.Path}'")
|
||||||
|
Finally
|
||||||
|
If f.Exists Then f.Delete(SFO.File, SFODelete.DeletePermanently, EDP.ReturnValue)
|
||||||
|
End Try
|
||||||
|
End Sub
|
||||||
|
Private Sub GdlPreProgressPerformWait(ByVal t As Task)
|
||||||
|
_GdlPreProgressPerformEnabled = False
|
||||||
|
Try
|
||||||
|
While t.Status = TaskStatus.Running Or t.Status = TaskStatus.WaitingToRun : Thread.Sleep(100) : End While
|
||||||
|
Catch
|
||||||
|
End Try
|
||||||
|
End Sub
|
||||||
Private Function GetDataFromGalleryDL(ByVal URL As String, ByVal Cache As CacheKeeper, ByVal UseTempPostList As Boolean,
|
Private Function GetDataFromGalleryDL(ByVal URL As String, ByVal Cache As CacheKeeper, ByVal UseTempPostList As Boolean,
|
||||||
Optional ByVal Token As CancellationToken = Nothing) As SFile
|
Optional ByVal Token As CancellationToken = Nothing) As SFile
|
||||||
Dim command$ = String.Empty
|
Dim command$ = String.Empty
|
||||||
Try
|
Try
|
||||||
Dim conf As SFile = GdlCreateConf(Cache.NewPath)
|
Dim conf As SFile = GdlCreateConf(Cache.NewPath)
|
||||||
command = $"""{Settings.GalleryDLFile}"" --verbose --no-download --no-skip --config ""{conf}"" --write-pages "
|
Dim fTimer% = SleepTimerValue(True)
|
||||||
command &= GdlGetIdFilterString()
|
command = $"""{Settings.GalleryDLFile}"" --verbose --no-download --no-skip{SleepRequest} --config ""{conf}"" --write-pages "
|
||||||
|
'command &= GdlGetIdFilterString()
|
||||||
Dim dir As SFile = Cache.NewPath
|
Dim dir As SFile = Cache.NewPath
|
||||||
If dir.Exists(SFO.Path,, EDP.ThrowException) Then
|
If dir.Exists(SFO.Path,, EDP.ThrowException) Then
|
||||||
Using batch As New TwitterGDL(dir, Token, MySettings.AbortOnLimit.Value)
|
Using batch As New TwitterGDL(dir, Token, MySettings.AbortOnLimit.Value)
|
||||||
@@ -823,6 +925,7 @@ nextpIndx:
|
|||||||
'#If DEBUG Then
|
'#If DEBUG Then
|
||||||
'Debug.WriteLine(command)
|
'Debug.WriteLine(command)
|
||||||
'#End If
|
'#End If
|
||||||
|
GdlWaitFirstTimer(fTimer)
|
||||||
batch.Execute(command)
|
batch.Execute(command)
|
||||||
If batch.LimitReached Then
|
If batch.LimitReached Then
|
||||||
If CBool(MySettings.DownloadAlreadyParsed.Value) And
|
If CBool(MySettings.DownloadAlreadyParsed.Value) And
|
||||||
@@ -867,6 +970,8 @@ nextpIndx:
|
|||||||
Dim process As Boolean, multiMode As Boolean
|
Dim process As Boolean, multiMode As Boolean
|
||||||
Dim currentModel As DownloadModels
|
Dim currentModel As DownloadModels
|
||||||
Dim urlPrePattern$ = $"https://x.com{IIf(IsCommunity, SiteSettings.CommunitiesUser, String.Empty)}/"
|
Dim urlPrePattern$ = $"https://x.com{IIf(IsCommunity, SiteSettings.CommunitiesUser, String.Empty)}/"
|
||||||
|
Dim fTimer% = SleepTimerValue(True)
|
||||||
|
Dim t As Task
|
||||||
|
|
||||||
If DownloadBroadcasts AndAlso Not dm.Contains(DownloadModels.Profile) Then dm.Add(DownloadModels.Profile)
|
If DownloadBroadcasts AndAlso Not dm.Contains(DownloadModels.Profile) Then dm.Add(DownloadModels.Profile)
|
||||||
|
|
||||||
@@ -885,7 +990,7 @@ nextpIndx:
|
|||||||
dir.Exists(SFO.Path, True, EDP.ThrowException)
|
dir.Exists(SFO.Path, True, EDP.ThrowException)
|
||||||
outList.Add(dir)
|
outList.Add(dir)
|
||||||
tgdl.ChangeDirectory(dir)
|
tgdl.ChangeDirectory(dir)
|
||||||
command = $"""{Settings.GalleryDLFile}"" --verbose --no-download --no-skip --config ""{conf}"" --write-pages "
|
command = $"""{Settings.GalleryDLFile}"" --verbose --no-download --no-skip{SleepRequest} --config ""{conf}"" --write-pages "
|
||||||
If multiMode Then
|
If multiMode Then
|
||||||
command &= "{0}"
|
command &= "{0}"
|
||||||
Else
|
Else
|
||||||
@@ -913,7 +1018,18 @@ nextpIndx:
|
|||||||
Else
|
Else
|
||||||
tgdl.TempPostsList = _TempPostsList
|
tgdl.TempPostsList = _TempPostsList
|
||||||
End If
|
End If
|
||||||
|
|
||||||
|
GdlWaitFirstTimer(fTimer)
|
||||||
|
|
||||||
|
_GdlPreProgressPerformEnabled = True
|
||||||
|
t = New Task(Sub() GdlPreProgressPerform(dir, conf))
|
||||||
|
t.Start()
|
||||||
|
|
||||||
tgdl.Execute(command)
|
tgdl.Execute(command)
|
||||||
|
|
||||||
|
_GdlPreProgressPerformEnabled = False
|
||||||
|
GdlPreProgressPerformWait(t)
|
||||||
|
|
||||||
If tgdl.LimitReached Then
|
If tgdl.LimitReached Then
|
||||||
If CBool(MySettings.DownloadAlreadyParsed.Value) And
|
If CBool(MySettings.DownloadAlreadyParsed.Value) And
|
||||||
SFile.GetFiles(rootDir, "*.txt", IO.SearchOption.AllDirectories, EDP.ReturnValue).Count > 0 Then
|
SFile.GetFiles(rootDir, "*.txt", IO.SearchOption.AllDirectories, EDP.ReturnValue).Count > 0 Then
|
||||||
@@ -936,6 +1052,8 @@ nextpIndx:
|
|||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
ProcessException(ex, Token, $"{ToStringForLog()}: GetTimelineFromGalleryDL({command})")
|
ProcessException(ex, Token, $"{ToStringForLog()}: GetTimelineFromGalleryDL({command})")
|
||||||
Return Nothing
|
Return Nothing
|
||||||
|
Finally
|
||||||
|
_GdlPreProgressPerformEnabled = False
|
||||||
End Try
|
End Try
|
||||||
End Function
|
End Function
|
||||||
Private Function GdlGetIdFilterString(Optional ByVal TL As List(Of String) = Nothing) As String
|
Private Function GdlGetIdFilterString(Optional ByVal TL As List(Of String) = Nothing) As String
|
||||||
@@ -945,8 +1063,11 @@ nextpIndx:
|
|||||||
Private Function GdlCreateConf(ByVal Path As SFile) As SFile
|
Private Function GdlCreateConf(ByVal Path As SFile) As SFile
|
||||||
Try
|
Try
|
||||||
Dim conf As SFile = $"{Path.PathWithSeparator}TwitterGdlConfig.conf"
|
Dim conf As SFile = $"{Path.PathWithSeparator}TwitterGdlConfig.conf"
|
||||||
|
Dim __userAgent$ = MySettings.UserAgent
|
||||||
|
If Not __userAgent.IsEmptyString Then __userAgent = $"""user-agent"": ""{__userAgent}"","
|
||||||
Dim confText$ = "{""extractor"":{""cookies"": """ & MySettings.CookiesNetscapeFile.ToString.Replace("\", "/") &
|
Dim confText$ = "{""extractor"":{""cookies"": """ & MySettings.CookiesNetscapeFile.ToString.Replace("\", "/") &
|
||||||
""",""cookies-update"": false,""twitter"":{""tweet-endpoint"": ""detail"",""cards"": false,""conversations"": true,""pinned"": false,""quoted"": false,""replies"": true,""retweets"": true,""strategy"": null,""text-tweets"": false,""twitpic"": false,""unique"": true,""users"": ""timeline"",""videos"": true}}}"
|
$""",""cookies-update"": {IIf(CBool(MySettings.CookiesUpdate.Value), "true", "false")}," & __userAgent &
|
||||||
|
"""twitter"":{""tweet-endpoint"": ""detail"",""cards"": false,""conversations"": true,""pinned"": false,""quoted"": false,""replies"": true,""retweets"": true,""strategy"": null,""text-tweets"": false,""twitpic"": false,""unique"": true,""users"": ""timeline"",""videos"": true}}}"
|
||||||
If conf.Exists(SFO.Path, True, EDP.ThrowException) Then TextSaver.SaveTextToFile(confText, conf)
|
If conf.Exists(SFO.Path, True, EDP.ThrowException) Then TextSaver.SaveTextToFile(confText, conf)
|
||||||
If Not conf.Exists Then Throw New IO.FileNotFoundException("Can't find Twitter GDL config file", conf)
|
If Not conf.Exists Then Throw New IO.FileNotFoundException("Can't find Twitter GDL config file", conf)
|
||||||
Return conf
|
Return conf
|
||||||
@@ -1050,6 +1171,7 @@ nextpIndx:
|
|||||||
#End Region
|
#End Region
|
||||||
#Region "DownloadSingleObject"
|
#Region "DownloadSingleObject"
|
||||||
Protected Overrides Sub DownloadSingleObject_GetPosts(ByVal Data As IYouTubeMediaContainer, ByVal Token As CancellationToken)
|
Protected Overrides Sub DownloadSingleObject_GetPosts(ByVal Data As IYouTubeMediaContainer, ByVal Token As CancellationToken)
|
||||||
|
GDL_REQUESTS_COUNT = 0
|
||||||
Dim um As New UserMedia(Data.URL) With {.State = UStates.Missing}
|
Dim um As New UserMedia(Data.URL) With {.State = UStates.Missing}
|
||||||
If Not Data.URL.IsEmptyString AndAlso Data.URL.Contains(BroadCastPartUrl) Then um.Type = UTypes.m3u8
|
If Not Data.URL.IsEmptyString AndAlso Data.URL.Contains(BroadCastPartUrl) Then um.Type = UTypes.m3u8
|
||||||
_ContentList.Add(um)
|
_ContentList.Add(um)
|
||||||
|
|||||||
@@ -35,6 +35,9 @@ Namespace API.XVIDEOS
|
|||||||
"This playlist must be entered by pattern: https://www.xvideos.com/favorite/01234567/playlistname.",
|
"This playlist must be entered by pattern: https://www.xvideos.com/favorite/01234567/playlistname.",
|
||||||
LeftOffset:=130), PXML, PClonable(Clone:=False)>
|
LeftOffset:=130), PXML, PClonable(Clone:=False)>
|
||||||
Friend ReadOnly Property SavedVideosPlaylist As PropertyValue
|
Friend ReadOnly Property SavedVideosPlaylist As PropertyValue
|
||||||
|
<DoNotUse> Friend Overrides Property DownloadText As PropertyValue
|
||||||
|
<DoNotUse> Friend Overrides Property DownloadTextPosts As PropertyValue
|
||||||
|
<DoNotUse> Friend Overrides Property DownloadTextSpecialFolder As PropertyValue
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Initializer"
|
#Region "Initializer"
|
||||||
Friend Sub New(ByVal AccName As String, ByVal Temp As Boolean)
|
Friend Sub New(ByVal AccName As String, ByVal Temp As Boolean)
|
||||||
|
|||||||
@@ -45,7 +45,6 @@ Namespace API.XVIDEOS
|
|||||||
End Get
|
End Get
|
||||||
End Property
|
End Property
|
||||||
Private Property SiteMode As SiteModes = SiteModes.User
|
Private Property SiteMode As SiteModes = SiteModes.User
|
||||||
Private Property TrueName As String = String.Empty
|
|
||||||
Private Property Arguments As String = String.Empty
|
Private Property Arguments As String = String.Empty
|
||||||
Private Property PersonType As String = String.Empty
|
Private Property PersonType As String = String.Empty
|
||||||
Friend Overrides ReadOnly Property IsUser As Boolean
|
Friend Overrides ReadOnly Property IsUser As Boolean
|
||||||
@@ -92,14 +91,14 @@ Namespace API.XVIDEOS
|
|||||||
If Not Force OrElse (Not SiteMode = SiteModes.User AndAlso Not NewUrl.IsEmptyString AndAlso MyFileSettings.Exists) Then
|
If Not Force OrElse (Not SiteMode = SiteModes.User AndAlso Not NewUrl.IsEmptyString AndAlso MyFileSettings.Exists) Then
|
||||||
Dim eObj As Plugin.ExchangeOptions = Nothing
|
Dim eObj As Plugin.ExchangeOptions = Nothing
|
||||||
If Force Then eObj = MySettings.IsMyUser(NewUrl)
|
If Force Then eObj = MySettings.IsMyUser(NewUrl)
|
||||||
If (Force And Not eObj.UserName.IsEmptyString) Or (Not Force And TrueName.IsEmptyString) Then
|
If (Force And Not eObj.UserName.IsEmptyString) Or (Not Force And NameTrue(True).IsEmptyString) Then
|
||||||
Dim n$() = If(Force, eObj.UserName, Name).Split("@")
|
Dim n$() = If(Force, eObj.UserName, Name).Split("@")
|
||||||
If n.ListExists(2) Then
|
If n.ListExists(2) Then
|
||||||
Dim opt$ = If(Force, eObj.Options, Options)
|
Dim opt$ = If(Force, eObj.Options, Options)
|
||||||
If opt.IsEmptyString AndAlso Not IsNumeric(n(0)) Then
|
If opt.IsEmptyString AndAlso Not IsNumeric(n(0)) Then
|
||||||
If Not Force Then
|
If Not Force Then
|
||||||
PersonType = n(0)
|
PersonType = n(0)
|
||||||
TrueName = If(Force, eObj.UserName, Name).Replace($"{PersonType}@", String.Empty)
|
NameTrue = If(Force, eObj.UserName, Name).Replace($"{PersonType}@", String.Empty)
|
||||||
End If
|
End If
|
||||||
ElseIf Not opt.IsEmptyString Then
|
ElseIf Not opt.IsEmptyString Then
|
||||||
Dim n2$() = opt.Split("@")
|
Dim n2$() = opt.Split("@")
|
||||||
@@ -108,8 +107,8 @@ Namespace API.XVIDEOS
|
|||||||
Dim __Arguments$ = opt.Replace($"{__TrueName}@", String.Empty)
|
Dim __Arguments$ = opt.Replace($"{__TrueName}@", String.Empty)
|
||||||
Dim __ForceApply As Boolean = False
|
Dim __ForceApply As Boolean = False
|
||||||
|
|
||||||
If Force AndAlso (Not TrueName = __TrueName Or Not SiteMode = __SiteMode) Then
|
If Force AndAlso (Not NameTrue(True) = __TrueName Or Not SiteMode = __SiteMode) Then
|
||||||
If ValidateChangeSearchOptions(ToStringForLog, $"{__SiteMode}: {__TrueName}", $"{SiteMode}: {TrueName}") Then
|
If ValidateChangeSearchOptions(ToStringForLog, $"{__SiteMode}: {__TrueName}", $"{SiteMode}: {NameTrue(True)}") Then
|
||||||
__ForceApply = True
|
__ForceApply = True
|
||||||
Else
|
Else
|
||||||
Return False
|
Return False
|
||||||
@@ -120,15 +119,15 @@ Namespace API.XVIDEOS
|
|||||||
Options = opt
|
Options = opt
|
||||||
If Not Force Then
|
If Not Force Then
|
||||||
SiteMode = __SiteMode
|
SiteMode = __SiteMode
|
||||||
TrueName = __TrueName
|
NameTrue = __TrueName
|
||||||
UserSiteName = $"{SiteMode}: {TrueName}"
|
UserSiteName = $"{SiteMode}: {NameTrue}"
|
||||||
If FriendlyName.IsEmptyString Then FriendlyName = UserSiteName
|
If FriendlyName.IsEmptyString Then FriendlyName = UserSiteName
|
||||||
Settings.Labels.Add(SearchRequestLabelName)
|
Settings.Labels.Add(SearchRequestLabelName)
|
||||||
Labels.ListAddValue(SearchRequestLabelName, LNC)
|
Labels.ListAddValue(SearchRequestLabelName, LNC)
|
||||||
Labels.Sort()
|
Labels.Sort()
|
||||||
ElseIf Force And __ForceApply Then
|
ElseIf Force And __ForceApply Then
|
||||||
SiteMode = __SiteMode
|
SiteMode = __SiteMode
|
||||||
TrueName = __TrueName
|
NameTrue = __TrueName
|
||||||
End If
|
End If
|
||||||
|
|
||||||
Return True
|
Return True
|
||||||
@@ -142,14 +141,13 @@ Namespace API.XVIDEOS
|
|||||||
With Container
|
With Container
|
||||||
If Loading Then
|
If Loading Then
|
||||||
SiteMode = .Value(Name_SiteMode).FromXML(Of Integer)(SiteModes.User)
|
SiteMode = .Value(Name_SiteMode).FromXML(Of Integer)(SiteModes.User)
|
||||||
TrueName = .Value(Name_TrueName)
|
|
||||||
Arguments = .Value(Name_Arguments)
|
Arguments = .Value(Name_Arguments)
|
||||||
PersonType = .Value(Name_PersonType)
|
PersonType = .Value(Name_PersonType)
|
||||||
If PersonType.IsEmptyString And TrueName.IsEmptyString And Not Name.IsEmptyString Then
|
If PersonType.IsEmptyString And NameTrue(True).IsEmptyString And Not Name.IsEmptyString Then
|
||||||
If Not Name.Contains("@") Then
|
If Not Name.Contains("@") Then
|
||||||
Dim n$() = Name.Split("_")
|
Dim n$() = Name.Split("_")
|
||||||
PersonType = n(0)
|
PersonType = n(0)
|
||||||
TrueName = Name.Replace($"{PersonType}_", String.Empty)
|
NameTrue = Name.Replace($"{PersonType}_", String.Empty)
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
UpdateUserOptions()
|
UpdateUserOptions()
|
||||||
@@ -160,7 +158,7 @@ Namespace API.XVIDEOS
|
|||||||
.Value(Name_FriendlyName) = FriendlyName
|
.Value(Name_FriendlyName) = FriendlyName
|
||||||
End If
|
End If
|
||||||
.Add(Name_SiteMode, CInt(SiteMode))
|
.Add(Name_SiteMode, CInt(SiteMode))
|
||||||
.Add(Name_TrueName, TrueName)
|
.Add(Name_TrueName, NameTrue(True))
|
||||||
.Add(Name_Arguments, Arguments)
|
.Add(Name_Arguments, Arguments)
|
||||||
.Add(Name_PersonType, PersonType)
|
.Add(Name_PersonType, PersonType)
|
||||||
|
|
||||||
@@ -181,19 +179,19 @@ Namespace API.XVIDEOS
|
|||||||
Friend Function GetUserUrl(ByVal Page As Integer) As String
|
Friend Function GetUserUrl(ByVal Page As Integer) As String
|
||||||
Dim url$ = String.Empty
|
Dim url$ = String.Empty
|
||||||
If SiteMode = SiteModes.User Then
|
If SiteMode = SiteModes.User Then
|
||||||
url = $"https://xvideos.com/{PersonType}/{TrueName}"
|
url = $"https://xvideos.com/{PersonType}/{NameTrue}"
|
||||||
ElseIf SiteMode = SiteModes.Categories Then
|
ElseIf SiteMode = SiteModes.Categories Then
|
||||||
url = "https://xvideos.com/c/"
|
url = "https://xvideos.com/c/"
|
||||||
If Not Arguments.IsEmptyString Then url &= $"{Arguments}/"
|
If Not Arguments.IsEmptyString Then url &= $"{Arguments}/"
|
||||||
url &= TrueName
|
url &= NameTrue
|
||||||
If Page > 1 Then url &= $"/{Page - 1}"
|
If Page > 1 Then url &= $"/{Page - 1}"
|
||||||
ElseIf SiteMode = SiteModes.Tags Then
|
ElseIf SiteMode = SiteModes.Tags Then
|
||||||
url = "https://www.xvideos.com/tags/"
|
url = "https://www.xvideos.com/tags/"
|
||||||
If Not Arguments.IsEmptyString Then url &= $"{Arguments}/"
|
If Not Arguments.IsEmptyString Then url &= $"{Arguments}/"
|
||||||
url &= $"{TrueName}/"
|
url &= $"{NameTrue}/"
|
||||||
If Page > 1 Then url &= Page - 1
|
If Page > 1 Then url &= Page - 1
|
||||||
ElseIf SiteMode = SiteModes.Search Then
|
ElseIf SiteMode = SiteModes.Search Then
|
||||||
url = $"https://www.xvideos.com/?k={TrueName}"
|
url = $"https://www.xvideos.com/?k={NameTrue}"
|
||||||
If Not Arguments.IsEmptyString Then url &= $"&{Arguments}"
|
If Not Arguments.IsEmptyString Then url &= $"&{Arguments}"
|
||||||
If Page > 1 Then url &= $"&p={Page - 1}"
|
If Page > 1 Then url &= $"&p={Page - 1}"
|
||||||
End If
|
End If
|
||||||
|
|||||||
@@ -33,6 +33,9 @@ Namespace API.Xhamster
|
|||||||
ControlToolTip:="If enabled and the video is downloaded in a non-native format, the video will be re-encoded." & vbCr &
|
ControlToolTip:="If enabled and the video is downloaded in a non-native format, the video will be re-encoded." & vbCr &
|
||||||
"Attention! Enabling this setting results in maximum CPU usage."), PXML, PClonable>
|
"Attention! Enabling this setting results in maximum CPU usage."), PXML, PClonable>
|
||||||
Friend ReadOnly Property ReencodeVideos As PropertyValue
|
Friend ReadOnly Property ReencodeVideos As PropertyValue
|
||||||
|
<DoNotUse> Friend Overrides Property DownloadText As PropertyValue
|
||||||
|
<DoNotUse> Friend Overrides Property DownloadTextPosts As PropertyValue
|
||||||
|
<DoNotUse> Friend Overrides Property DownloadTextSpecialFolder As PropertyValue
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Initializer"
|
#Region "Initializer"
|
||||||
Friend Sub New(ByVal AccName As String, ByVal Temp As Boolean)
|
Friend Sub New(ByVal AccName As String, ByVal Temp As Boolean)
|
||||||
@@ -86,7 +89,7 @@ Namespace API.Xhamster
|
|||||||
If Not .SiteMode = SiteModes.User Then
|
If Not .SiteMode = SiteModes.User Then
|
||||||
Return .GetNonUserUrl(0)
|
Return .GetNonUserUrl(0)
|
||||||
Else
|
Else
|
||||||
Return String.Format(UrlPatternUser, IIf(.IsChannel, ChannelOption, UserOption), .TrueName)
|
Return String.Format(UrlPatternUser, IIf(.IsChannel, ChannelOption, UserOption), .NameTrue)
|
||||||
End If
|
End If
|
||||||
End With
|
End With
|
||||||
End Function
|
End Function
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ Namespace API.Xhamster
|
|||||||
End Property
|
End Property
|
||||||
Friend Property IsChannel As Boolean = False
|
Friend Property IsChannel As Boolean = False
|
||||||
Friend Property IsCreator As Boolean = False
|
Friend Property IsCreator As Boolean = False
|
||||||
Friend Property TrueName As String = String.Empty
|
|
||||||
Friend Property Gender As String = String.Empty
|
Friend Property Gender As String = String.Empty
|
||||||
Friend Property SiteMode As SiteModes = SiteModes.User
|
Friend Property SiteMode As SiteModes = SiteModes.User
|
||||||
Friend Property Arguments As String = String.Empty
|
Friend Property Arguments As String = String.Empty
|
||||||
@@ -73,17 +72,17 @@ Namespace API.Xhamster
|
|||||||
If Not Force OrElse (Not SiteMode = SiteModes.User AndAlso Not NewUrl.IsEmptyString AndAlso MyFileSettings.Exists) Then
|
If Not Force OrElse (Not SiteMode = SiteModes.User AndAlso Not NewUrl.IsEmptyString AndAlso MyFileSettings.Exists) Then
|
||||||
Dim eObj As Plugin.ExchangeOptions = Nothing
|
Dim eObj As Plugin.ExchangeOptions = Nothing
|
||||||
If Force Then eObj = MySettings.IsMyUser(NewUrl)
|
If Force Then eObj = MySettings.IsMyUser(NewUrl)
|
||||||
If (Force And Not eObj.UserName.IsEmptyString) Or (Not Force And TrueName.IsEmptyString) Then
|
If (Force And Not eObj.UserName.IsEmptyString) Or (Not Force And NameTrue(True).IsEmptyString) Then
|
||||||
Dim n$() = If(Force, eObj.UserName, Name).Split("@")
|
Dim n$() = If(Force, eObj.UserName, Name).Split("@")
|
||||||
If n.ListExists Then
|
If n.ListExists Then
|
||||||
If n.Length = 2 And If(Force, eObj.Options, Options).IsEmptyString Then
|
If n.Length = 2 And If(Force, eObj.Options, Options).IsEmptyString Then
|
||||||
If Force Then Return False
|
If Force Then Return False
|
||||||
TrueName = n(0)
|
NameTrue = n(0)
|
||||||
IsChannel = n(1) = SiteSettings.ChannelOption
|
IsChannel = n(1) = SiteSettings.ChannelOption
|
||||||
IsCreator = n(1) = SiteSettings.P_Creators
|
IsCreator = n(1) = SiteSettings.P_Creators
|
||||||
ElseIf IsChannel Then
|
ElseIf IsChannel Then
|
||||||
If Force Then Return False
|
If Force Then Return False
|
||||||
TrueName = Name
|
NameTrue = Name
|
||||||
ElseIf Not If(Force, eObj.Options, Options).IsEmptyString Then
|
ElseIf Not If(Force, eObj.Options, Options).IsEmptyString Then
|
||||||
Dim __TrueName$, __Arguments$, __Gender$
|
Dim __TrueName$, __Arguments$, __Gender$
|
||||||
Dim __Mode As SiteModes
|
Dim __Mode As SiteModes
|
||||||
@@ -97,10 +96,10 @@ Namespace API.Xhamster
|
|||||||
__Arguments = n2(3)
|
__Arguments = n2(3)
|
||||||
__TrueName = n2.ListTake(3, 100, EDP.ReturnValue).ListToString(String.Empty)
|
__TrueName = n2.ListTake(3, 100, EDP.ReturnValue).ListToString(String.Empty)
|
||||||
|
|
||||||
If Force AndAlso (Not TrueName = __TrueName Or Not SiteMode = __Mode Or Not Gender = __Gender) Then
|
If Force AndAlso (Not NameTrue(True) = __TrueName Or Not SiteMode = __Mode Or Not Gender = __Gender) Then
|
||||||
If ValidateChangeSearchOptions(ToStringForLog,
|
If ValidateChangeSearchOptions(ToStringForLog,
|
||||||
$"{__Mode}{IIf(__Gender.IsEmptyString, String.Empty, $" ({__Gender})")}: {__TrueName}",
|
$"{__Mode}{IIf(__Gender.IsEmptyString, String.Empty, $" ({__Gender})")}: {__TrueName}",
|
||||||
$"{SiteMode}{IIf(Gender.IsEmptyString, String.Empty, $" ({Gender})")}: {TrueName}") Then
|
$"{SiteMode}{IIf(Gender.IsEmptyString, String.Empty, $" ({Gender})")}: {NameTrue(True)}") Then
|
||||||
__ForceApply = True
|
__ForceApply = True
|
||||||
Else
|
Else
|
||||||
Return False
|
Return False
|
||||||
@@ -110,17 +109,17 @@ Namespace API.Xhamster
|
|||||||
Arguments = __Arguments
|
Arguments = __Arguments
|
||||||
Options = If(Force, eObj.Options, Options)
|
Options = If(Force, eObj.Options, Options)
|
||||||
If Not Force Then
|
If Not Force Then
|
||||||
TrueName = __TrueName
|
NameTrue = __TrueName
|
||||||
SiteMode = __Mode
|
SiteMode = __Mode
|
||||||
Gender = __Gender
|
Gender = __Gender
|
||||||
|
|
||||||
UserSiteName = $"{SiteMode}: {TrueName}"
|
UserSiteName = $"{SiteMode}: {NameTrue}"
|
||||||
If FriendlyName.IsEmptyString Then FriendlyName = UserSiteName
|
If FriendlyName.IsEmptyString Then FriendlyName = UserSiteName
|
||||||
Settings.Labels.Add(SearchRequestLabelName)
|
Settings.Labels.Add(SearchRequestLabelName)
|
||||||
Labels.ListAddValue(SearchRequestLabelName, LNC)
|
Labels.ListAddValue(SearchRequestLabelName, LNC)
|
||||||
Labels.Sort()
|
Labels.Sort()
|
||||||
ElseIf Force And __ForceApply Then
|
ElseIf Force And __ForceApply Then
|
||||||
TrueName = __TrueName
|
NameTrue = __TrueName
|
||||||
SiteMode = __Mode
|
SiteMode = __Mode
|
||||||
Gender = __Gender
|
Gender = __Gender
|
||||||
End If
|
End If
|
||||||
@@ -132,7 +131,7 @@ Namespace API.Xhamster
|
|||||||
End If
|
End If
|
||||||
Else
|
Else
|
||||||
If Force Then Return False
|
If Force Then Return False
|
||||||
TrueName = n(0)
|
NameTrue = n(0)
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
@@ -144,7 +143,6 @@ Namespace API.Xhamster
|
|||||||
If Loading Then
|
If Loading Then
|
||||||
IsChannel = .Value(Name_IsChannel).FromXML(Of Boolean)(False)
|
IsChannel = .Value(Name_IsChannel).FromXML(Of Boolean)(False)
|
||||||
IsCreator = .Value(Name_IsCreator).FromXML(Of Boolean)(False)
|
IsCreator = .Value(Name_IsCreator).FromXML(Of Boolean)(False)
|
||||||
TrueName = .Value(Name_TrueName)
|
|
||||||
Gender = .Value(Name_Gender)
|
Gender = .Value(Name_Gender)
|
||||||
SiteMode = .Value(Name_SiteMode).FromXML(Of Integer)(SiteModes.User)
|
SiteMode = .Value(Name_SiteMode).FromXML(Of Integer)(SiteModes.User)
|
||||||
Arguments = .Value(Name_Arguments)
|
Arguments = .Value(Name_Arguments)
|
||||||
@@ -157,7 +155,7 @@ Namespace API.Xhamster
|
|||||||
End If
|
End If
|
||||||
.Add(Name_IsChannel, IsChannel.BoolToInteger)
|
.Add(Name_IsChannel, IsChannel.BoolToInteger)
|
||||||
.Add(Name_IsCreator, IsCreator.BoolToInteger)
|
.Add(Name_IsCreator, IsCreator.BoolToInteger)
|
||||||
.Add(Name_TrueName, TrueName)
|
.Add(Name_TrueName, NameTrue(True))
|
||||||
.Add(Name_Gender, Gender)
|
.Add(Name_Gender, Gender)
|
||||||
.Add(Name_SiteMode, CInt(SiteMode))
|
.Add(Name_SiteMode, CInt(SiteMode))
|
||||||
.Add(Name_Arguments, Arguments)
|
.Add(Name_Arguments, Arguments)
|
||||||
@@ -198,7 +196,7 @@ Namespace API.Xhamster
|
|||||||
Case SiteModes.User : url &= SiteSettings.P_Creators
|
Case SiteModes.User : url &= SiteSettings.P_Creators
|
||||||
Case Else : Return String.Empty
|
Case Else : Return String.Empty
|
||||||
End Select
|
End Select
|
||||||
url &= $"/{TrueName}"
|
url &= $"/{NameTrue}"
|
||||||
|
|
||||||
Dim args$ = Arguments
|
Dim args$ = Arguments
|
||||||
If (args.IsEmptyString OrElse Not args.Contains(newest)) And Not SiteMode = SiteModes.Search Then url &= newest
|
If (args.IsEmptyString OrElse Not args.Contains(newest)) And Not SiteMode = SiteModes.Search Then url &= newest
|
||||||
@@ -289,14 +287,14 @@ Namespace API.Xhamster
|
|||||||
URL = $"https://xhamster.com/my/favorites/{IIf(IsVideo, "videos", "photos-and-galleries")}{IIf(Page = 1, String.Empty, $"/{Page}")}"
|
URL = $"https://xhamster.com/my/favorites/{IIf(IsVideo, "videos", "photos-and-galleries")}{IIf(Page = 1, String.Empty, $"/{Page}")}"
|
||||||
containerNodes.Add(If(IsVideo, {"favoriteVideoListComponent", "models"}, {"favoritesGalleriesAndPhotosCollection"}))
|
containerNodes.Add(If(IsVideo, {"favoriteVideoListComponent", "models"}, {"favoritesGalleriesAndPhotosCollection"}))
|
||||||
ElseIf IsChannel Then
|
ElseIf IsChannel Then
|
||||||
URL = $"https://xhamster.com/channels/{TrueName}/newest{IIf(Page = 1, String.Empty, $"/{Page}")}"
|
URL = $"https://xhamster.com/channels/{NameTrue}/newest{IIf(Page = 1, String.Empty, $"/{Page}")}"
|
||||||
ElseIf SiteMode = SiteModes.Search Then
|
ElseIf SiteMode = SiteModes.Search Then
|
||||||
URL = GetNonUserUrl(Page)
|
URL = GetNonUserUrl(Page)
|
||||||
containerNodes.Add({"searchResult", "models"})
|
containerNodes.Add({"searchResult", "models"})
|
||||||
ElseIf IsCreator Or SiteMode = SiteModes.Tags Or SiteMode = SiteModes.Categories Or SiteMode = SiteModes.Pornstars Then
|
ElseIf IsCreator Or SiteMode = SiteModes.Tags Or SiteMode = SiteModes.Categories Or SiteMode = SiteModes.Pornstars Then
|
||||||
URL = GetNonUserUrl(Page)
|
URL = GetNonUserUrl(Page)
|
||||||
Else
|
Else
|
||||||
URL = $"https://xhamster.com/users/{TrueName}/{IIf(IsVideo, "videos", "photos")}{IIf(Page = 1, String.Empty, $"/{Page}")}"
|
URL = $"https://xhamster.com/users/{NameTrue}/{IIf(IsVideo, "videos", "photos")}{IIf(Page = 1, String.Empty, $"/{Page}")}"
|
||||||
End If
|
End If
|
||||||
ThrowAny(Token)
|
ThrowAny(Token)
|
||||||
|
|
||||||
@@ -617,7 +615,7 @@ Namespace API.Xhamster
|
|||||||
If m.Post.ID.IsEmptyString Then m.Post.ID = m.URL.Split("/").LastOrDefault
|
If m.Post.ID.IsEmptyString Then m.Post.ID = m.URL.Split("/").LastOrDefault
|
||||||
If m.PictureOption.IsEmptyString Then m.PictureOption = TitleHtmlConverter(j.Value("titleLocalized"))
|
If m.PictureOption.IsEmptyString Then m.PictureOption = TitleHtmlConverter(j.Value("titleLocalized"))
|
||||||
If m.PictureOption.IsEmptyString Then m.PictureOption = m.Post.ID
|
If m.PictureOption.IsEmptyString Then m.PictureOption = m.Post.ID
|
||||||
If setSpecialFolder Then m.SpecialFolder = m.PictureOption
|
If setSpecialFolder Then m.SpecialFolder = IIf(t = UTypes.Picture, "Photo\", String.Empty) & m.PictureOption
|
||||||
|
|
||||||
If processFile Then
|
If processFile Then
|
||||||
If Not m.PictureOption.IsEmptyString Then
|
If Not m.PictureOption.IsEmptyString Then
|
||||||
|
|||||||