Compare commits
16 Commits
2024.9.2.0
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d0d8e5470e | ||
|
|
164b999de7 | ||
|
|
e6d5fc2b95 | ||
|
|
6d4380ccac | ||
|
|
8dfd4e8bd1 | ||
|
|
1404afdfa3 | ||
|
|
5857fcfae3 | ||
|
|
e09752a2d5 | ||
|
|
05772a9fc4 | ||
|
|
24ad338c60 | ||
|
|
ff0c4587eb | ||
|
|
fff63d0a9f | ||
|
|
2f838929cc | ||
|
|
4d74f5204b | ||
|
|
b42832719f | ||
|
|
aedcebc781 |
515
Changelog.md
16
FAQ.md
@@ -26,22 +26,23 @@ I strongly recommend you to **regularly** create backup copies of the settings f
|
|||||||
|
|
||||||
# Most frequently questions about SCrawler
|
# Most frequently questions about SCrawler
|
||||||
|
|
||||||
**Is something doesn't download, always check the [SITE'S REQUIREMENTS](https://github.com/AAndyProgram/SCrawler/wiki/Settings#sites-requirements) before asking questions!**
|
**If something doesn't download, always check the [SITE'S REQUIREMENTS](https://github.com/AAndyProgram/SCrawler/wiki/Settings#sites-requirements) before asking questions!**
|
||||||
|
|
||||||
*How to use: find your problem in the list and read the answer.*
|
*How to use: find your problem in the list and read the answer.*
|
||||||
|
|
||||||
## General questions
|
## General questions
|
||||||
- **PROFILES**
|
- **PROFILES**
|
||||||
- I added a profile but **nothing downloaded** :arrow_forward: check your cookies and [site requirements](https://github.com/AAndyProgram/SCrawler/wiki/Settings#sites-requirements). If there are any optional fields that you don't fill in, do so. Still nothing works - [report it](#how-to-report-a-problem)!
|
- I added a profile but **nothing downloaded** :arrow_forward: check your cookies and [site requirements](https://github.com/AAndyProgram/SCrawler/wiki/Settings#sites-requirements). If there are any optional fields that you don't fill in, do so. Still nothing works - [report it](#how-to-report-a-problem)!
|
||||||
- User downloading failed :arrow_forward: check your credentials and **[SITES REQUIREMENTS](https://github.com/AAndyProgram/SCrawler/wiki/Settings#sites-requirements)**. If all settings are set and nothing works, [report it](#how-to-report-a-problem). <u>Don't forget to attach the LOG.</u>
|
- :exclamation: **Try to avoid Chinese/Japanese symbols in the paths.**
|
||||||
|
- User downloading failed :arrow_forward: check your credentials and **[SITES REQUIREMENTS](https://github.com/AAndyProgram/SCrawler/wiki/Settings#sites-requirements)**. If all settings are set and nothing works, [report it](#how-to-report-a-problem). **Don't forget to attach the LOG.**
|
||||||
- [How to redownload user](https://github.com/AAndyProgram/SCrawler/wiki#redownload-user)
|
- [How to redownload user](https://github.com/AAndyProgram/SCrawler/wiki#redownload-user)
|
||||||
- How to **add profile** to download :arrow_forward: copy the **[profile URL](https://github.com/AAndyProgram/SCrawler/wiki#add-user)** and press `Insert` or `Ctrl+Insert`. **ALWAYS PASTE THE USER PROFILE URL**. After that select this user and press `F5` or click the `Download selected` button.
|
- How to **add profile** to download :arrow_forward: copy the **[profile URL](https://github.com/AAndyProgram/SCrawler/wiki#add-user)** and press `Insert` or `Ctrl+Insert`. **ALWAYS PASTE THE USER PROFILE URL**. After that select this user and press `F5` or click the `Download selected` button.
|
||||||
- How to download **[saved posts](https://github.com/AAndyProgram/SCrawler/wiki#saved-posts)**
|
- How to download **[saved posts](https://github.com/AAndyProgram/SCrawler/wiki#saved-posts)**
|
||||||
- **[HOW TO ADD COOKIES](https://github.com/AAndyProgram/SCrawler/wiki/Settings#how-to-set-up-cookies)**
|
- **[HOW TO ADD COOKIES](https://github.com/AAndyProgram/SCrawler/wiki/Settings#how-to-set-up-cookies)**
|
||||||
- [How to report a problem](#how-to-report-a-problem)
|
- [How to report a problem](#how-to-report-a-problem)
|
||||||
- I want you to **add the site** to SCrawler :arrow_forward: **I'm not currently accepting requests to add new sites**, but you can [create a plugin](https://github.com/AAndyProgram/SCrawler/wiki/Plugins) (for your site) for SCrawler.
|
- I want you to **add the site** to SCrawler :arrow_forward: **I'm not currently accepting requests to add new sites**, but you can [create a plugin](https://github.com/AAndyProgram/SCrawler/wiki/Plugins) (for your site) for SCrawler.
|
||||||
- What language is SCrawler written in :arrow_forward: vb.net
|
- What language is SCrawler written in :arrow_forward: `vb.net`
|
||||||
- I don't know vb.net and I can't write a plugin :arrow_forward: you can write a plugin in `C#`
|
- I don't know `vb.net` and I can't write a plugin :arrow_forward: you can write a plugin in `C#`
|
||||||
- I have a suggestion, will it be added :arrow_forward: maybe if it interested me.
|
- I have a suggestion, will it be added :arrow_forward: maybe if it interested me.
|
||||||
- How to name files using a pattern (e.g. `Site_PostID_Name.jpg`) :arrow_forward: **there is no such functionality and there are no such plans**.
|
- How to name files using a pattern (e.g. `Site_PostID_Name.jpg`) :arrow_forward: **there is no such functionality and there are no such plans**.
|
||||||
- **DON'T CHANGE THE DEFAULT SITE SETTINGS UNLESS YOU KNOW EXACTLY WHAT YOU'RE DOING!** SCrawler already has all the default settings to work. You only need to add credentials (where [required](https://github.com/AAndyProgram/SCrawler/wiki/Settings#sites-requirements)).
|
- **DON'T CHANGE THE DEFAULT SITE SETTINGS UNLESS YOU KNOW EXACTLY WHAT YOU'RE DOING!** SCrawler already has all the default settings to work. You only need to add credentials (where [required](https://github.com/AAndyProgram/SCrawler/wiki/Settings#sites-requirements)).
|
||||||
@@ -55,19 +56,20 @@ I strongly recommend you to **regularly** create backup copies of the settings f
|
|||||||
- [Video how to configure](#video-how-to-configure)
|
- [Video how to configure](#video-how-to-configure)
|
||||||
- **Antivirus**
|
- **Antivirus**
|
||||||
- **Antivirus detects SCrawler as a virus** :arrow_forward: SCrawler doesn't contain any viruses at all. All code is posted on GitHub. You can review it. I have nothing to hide. SCrawler just downloads pictures and videos. That's all. If you trust SCrawler, you should just add it to the antivirus exceptions, as I did. Sometimes antiviruses identify SCawler as a virus. This is usually related to the number of files being edited (users' settings files) and the number of files being downloaded. In this case, the antivirus can also remove these files, which will damage users' settings. **If you don't trust SCrawler, just delete it.**
|
- **Antivirus detects SCrawler as a virus** :arrow_forward: SCrawler doesn't contain any viruses at all. All code is posted on GitHub. You can review it. I have nothing to hide. SCrawler just downloads pictures and videos. That's all. If you trust SCrawler, you should just add it to the antivirus exceptions, as I did. Sometimes antiviruses identify SCawler as a virus. This is usually related to the number of files being edited (users' settings files) and the number of files being downloaded. In this case, the antivirus can also remove these files, which will damage users' settings. **If you don't trust SCrawler, just delete it.**
|
||||||
- **Antivirus detects gallery-dl as a virus** :arrow_forward: it's a trustworthy program that is trusted by thousands of people around the world. Antiviruses identify some builds as containing viruses, but this is not true. **If you don't trust gallery-dl, you can simply delete it**. **But if you delete it, you won't be able to download [Twitter & Pinterest](https://github.com/AAndyProgram/SCrawler/wiki/Settings#gallery-dl).** You should decide for yourself.
|
- **Antivirus detects gallery-dl as a virus** :arrow_forward: it's a trustworthy program that is trusted by thousands of people around the world. Antiviruses identify some builds as containing viruses, but this is not true. **If you don't trust gallery-dl, you can simply delete it. But if you delete it, you won't be able to download [Twitter & Pinterest](https://github.com/AAndyProgram/SCrawler/wiki/Settings#gallery-dl).** You should decide for yourself.
|
||||||
|
|
||||||
## Sites questions
|
## Sites questions
|
||||||
|
|
||||||
*How to use: find the site you need in the list and read the answer.*
|
*How to use: find the site you need in the list and read the answer.*
|
||||||
|
|
||||||
- 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!**
|
- 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**!
|
||||||
- ThisVid: https://github.com/AAndyProgram/SCrawler/wiki/Settings#thisvid-faq
|
- ThisVid: https://github.com/AAndyProgram/SCrawler/wiki/Settings#thisvid-faq
|
||||||
- **OnlyFans**: cookies + **all fields** + [OF-Scraper (download the correct version that I pointed)](https://github.com/AAndyProgram/SCrawler/wiki/Settings#of-scraper) & [mp4decrypt](https://www.bento4.com/downloads/) to download DRM protected videos. [OF-Scraper support](https://github.com/AAndyProgram/SCrawler/wiki/Settings#of-scraper-support). Also read [this](https://github.com/AAndyProgram/SCrawler/wiki/Settings#onlyfans-faq)
|
- **OnlyFans**: cookies + **all fields** + [OF-Scraper (download the correct version that I pointed)](https://github.com/AAndyProgram/SCrawler/wiki/Settings#of-scraper) & [mp4decrypt](https://www.bento4.com/downloads/) & **DRM keys** to download DRM protected videos. [OF-Scraper support](https://github.com/AAndyProgram/SCrawler/wiki/Settings#of-scraper-support). Also read [this](https://github.com/AAndyProgram/SCrawler/wiki/Settings#onlyfans-faq)
|
||||||
- **JustForFans**: **THE VIDEO ISN'T DOWNLOADING AT THE MOMENT** ([Issue](https://discord.com/channels/1124032649682493462/1205547615199039551/1231349555132366870))
|
- **JustForFans**: **THE VIDEO ISN'T DOWNLOADING AT THE MOMENT** ([Issue](https://discord.com/channels/1124032649682493462/1205547615199039551/1231349555132366870))
|
||||||
|
|
||||||
## Other questions
|
## Other questions
|
||||||
|
|||||||
@@ -7,4 +7,5 @@ If you've created a plugin, you can create a [new issue](https://github.com/AAnd
|
|||||||
List of available plugins:
|
List of available plugins:
|
||||||
|
|
||||||
Tools:
|
Tools:
|
||||||
- [image2post](https://github.com/unknown81311/SCrawler-image2post) by @unknown81311: **get reddit post URL from file.**
|
- [image2post](https://github.com/unknown81311/SCrawler-image2post) by @unknown81311: **get reddit post URL from file.**
|
||||||
|
- [Update-SCrawler-Tools](https://github.com/cjb900/Update-SCrawler-Tools) by @cjb900: **a tool for updating third-party programs such as yt-dlp and gallery-dl**
|
||||||
|
Before Width: | Height: | Size: 101 KiB After Width: | Height: | Size: 121 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 38 KiB |
|
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: 28 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 24 KiB |
30
README.md
@@ -1,5 +1,6 @@
|
|||||||
|
<!--
|
||||||
# 🏳️🌈 Happy LGBT Pride Month 🎉
|
# 🏳️🌈 Happy LGBT Pride Month 🎉
|
||||||
|
-->
|
||||||
# 🏳️🌈 Social networks crawler 🏳️🌈
|
# 🏳️🌈 Social networks crawler 🏳️🌈
|
||||||
|
|
||||||
[](https://github.com/AAndyProgram/SCrawler/releases/latest)
|
[](https://github.com/AAndyProgram/SCrawler/releases/latest)
|
||||||
@@ -35,16 +36,17 @@ A program to download photo and video from [any site](#supported-sites) (e.g. Yo
|
|||||||
# What can program do:
|
# What can program do:
|
||||||
- Download pictures and videos from user profiles:
|
- Download pictures and videos from user profiles:
|
||||||
- YouTube videos, shorts, community feeds, users, artists, playlists, music, tracks;
|
- YouTube videos, shorts, community feeds, users, artists, playlists, music, tracks;
|
||||||
- Reddit images, galleries of images, videos, saved posts;
|
- Reddit images, galleries of images, videos, text, 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, text, saved (bookmarked) posts, likes, communities;
|
||||||
- OnlyFans images and videos, saved (bookmarked) posts, stories;
|
- Bluesky images and videos, text;
|
||||||
|
- OnlyFans images and videos, text, 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, text, tagged posts, stories, saved posts;
|
||||||
- Threads images and videos, saved posts;
|
- Threads images and videos, text, 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 +80,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 +134,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 +219,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>
|
||||||
@@ -136,4 +136,34 @@ Namespace API.YouTube.Base
|
|||||||
End If
|
End If
|
||||||
End Function
|
End Function
|
||||||
End Structure
|
End Structure
|
||||||
|
Public Structure TrimOption : Implements IComparable(Of TrimOption)
|
||||||
|
Public Name As String
|
||||||
|
Public Start As Integer
|
||||||
|
Public ReadOnly Property StartTime As TimeSpan
|
||||||
|
Get
|
||||||
|
Return TimeSpan.FromSeconds(Start)
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
|
Public [End] As Integer
|
||||||
|
Public ReadOnly Property EndTime As TimeSpan
|
||||||
|
Get
|
||||||
|
Return TimeSpan.FromSeconds([End])
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
|
Public Shared Widening Operator CType(ByVal t As TrimOption) As String
|
||||||
|
Return t.ToString
|
||||||
|
End Operator
|
||||||
|
Public Overrides Function ToString() As String
|
||||||
|
Dim v$ = $"{Start} - {[End]}"
|
||||||
|
If Not Name.IsEmptyString Then v = $"[{v}] - {Name}"
|
||||||
|
Return v
|
||||||
|
End Function
|
||||||
|
Public Overrides Function Equals(ByVal Obj As Object) As Boolean
|
||||||
|
Try : With DirectCast(Obj, TrimOption) : Return Start = .Start And [End] = .End : End With : Catch : End Try
|
||||||
|
Return False
|
||||||
|
End Function
|
||||||
|
Private Function CompareTo(ByVal Other As TrimOption) As Integer Implements IComparable(Of TrimOption).CompareTo
|
||||||
|
Return Start.CompareTo(Other.Start)
|
||||||
|
End Function
|
||||||
|
End Structure
|
||||||
End Namespace
|
End Namespace
|
||||||
@@ -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)
|
||||||
@@ -191,7 +189,7 @@ Namespace API.YouTube.Base
|
|||||||
<Browsable(True), GridVisible, XMLVN({"Defaults"}), Category("Defaults"), DisplayName("Use cookies"),
|
<Browsable(True), GridVisible, XMLVN({"Defaults"}), Category("Defaults"), DisplayName("Use cookies"),
|
||||||
Description("By default, use cookies when downloading from YouTube.")>
|
Description("By default, use cookies when downloading from YouTube.")>
|
||||||
Public ReadOnly Property DefaultUseCookies As XMLValue(Of Boolean)
|
Public ReadOnly Property DefaultUseCookies As XMLValue(Of Boolean)
|
||||||
<Browsable(True), GridVisible, XMLVN({"Defaults"}, Protocols.Any), Category("Defaults"), DisplayName("Protocol"),
|
<Browsable(True), GridVisible, XMLVN({"Defaults"}, Protocols.https), Category("Defaults"), DisplayName("Protocol"),
|
||||||
Description("Priority download protocol. Default: 'Any'")>
|
Description("Priority download protocol. Default: 'Any'")>
|
||||||
Public ReadOnly Property DefaultProtocol As XMLValue(Of Protocols)
|
Public ReadOnly Property DefaultProtocol As XMLValue(Of Protocols)
|
||||||
<Browsable(True), GridVisible(False), XMLVN({"Defaults"}), Category("Defaults"),
|
<Browsable(True), GridVisible(False), XMLVN({"Defaults"}), Category("Defaults"),
|
||||||
@@ -267,6 +265,12 @@ Namespace API.YouTube.Base
|
|||||||
<Browsable(True), GridVisible, XMLVN({"Defaults"}), Category("Defaults"), DisplayName("Add date to title: video list"),
|
<Browsable(True), GridVisible, XMLVN({"Defaults"}), Category("Defaults"), DisplayName("Add date to title: video list"),
|
||||||
Description("Add video upload date before video title (visual only) in the video list")>
|
Description("Add video upload date before video title (visual only) in the video list")>
|
||||||
Public ReadOnly Property FileAddDateToFileName_VideoList As XMLValue(Of Boolean)
|
Public ReadOnly Property FileAddDateToFileName_VideoList As XMLValue(Of Boolean)
|
||||||
|
<Browsable(True), GridVisible, XMLVN({"Defaults"}, FileDateMode.None), Category("Defaults"), DisplayName("Add channel to file name"),
|
||||||
|
Description("Add channel name before/after the file name")>
|
||||||
|
Public ReadOnly Property FileAddChannelToFileName As XMLValue(Of FileDateMode)
|
||||||
|
<Browsable(True), GridVisible, XMLVN({"Defaults"}, True), Category("Defaults"), DisplayName("Parse long user titles"),
|
||||||
|
Description("Suitable for multiple artists")>
|
||||||
|
Public ReadOnly Property ParseLongUserTitle As XMLValue(Of Boolean)
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Defaults ChannelsDownload"
|
#Region "Defaults ChannelsDownload"
|
||||||
<Browsable(True), GridVisible, XMLVN({"Defaults", "Channels"}), Category("Defaults"), DisplayName("Default download tabs for channels"),
|
<Browsable(True), GridVisible, XMLVN({"Defaults", "Channels"}), Category("Defaults"), DisplayName("Default download tabs for channels"),
|
||||||
@@ -311,12 +315,18 @@ Namespace API.YouTube.Base
|
|||||||
<Browsable(True), GridVisible, XMLVN({"DefaultsVideo"}, 1080), Category("Defaults Video"), DisplayName("Default definition"),
|
<Browsable(True), GridVisible, XMLVN({"DefaultsVideo"}, 1080), Category("Defaults Video"), DisplayName("Default definition"),
|
||||||
Description("The default maximum video resolution. -1 for max definition")>
|
Description("The default maximum video resolution. -1 for max definition")>
|
||||||
Public ReadOnly Property DefaultVideoDefinition As XMLValue(Of Integer)
|
Public ReadOnly Property DefaultVideoDefinition As XMLValue(Of Integer)
|
||||||
|
<Browsable(True), GridVisible, XMLVN({"DefaultsVideo"}, True), Category("Defaults Video"), DisplayName("Allow webm formats"),
|
||||||
|
Description("Allow webm formats over http if mp4 formats are not available. Default: true.")>
|
||||||
|
Public ReadOnly Property DefaultVideoAllowWebm As XMLValue(Of Boolean)
|
||||||
<Browsable(True), GridVisible, XMLVN({"DefaultsVideo"}), Category("Defaults Video"), DisplayName("Convert non-AVC codecs to AVC"),
|
<Browsable(True), GridVisible, XMLVN({"DefaultsVideo"}), Category("Defaults Video"), DisplayName("Convert non-AVC codecs to AVC"),
|
||||||
Description("Convert non-AVC codecs (eg 'VP9') to AVC. Not recommended due to high CPU usage!")>
|
Description("Convert non-AVC codecs (eg 'VP9') to AVC. Not recommended due to high CPU usage!")>
|
||||||
Public ReadOnly Property DefaultVideoConvertNonAVC As XMLValue(Of Boolean)
|
Public ReadOnly Property DefaultVideoConvertNonAVC As XMLValue(Of Boolean)
|
||||||
<Browsable(True), GridVisible, XMLVN({"DefaultsVideo"}, False), Category("Defaults Video"), DisplayName("Embed thumbnail (video)"),
|
<Browsable(True), GridVisible, XMLVN({"DefaultsVideo"}, False), Category("Defaults Video"), DisplayName("Embed thumbnail (video)"),
|
||||||
Description("Embed thumbnail in the video as cover art. Default: true.")>
|
Description("Embed thumbnail in the video as cover art. Default: false.")>
|
||||||
Public ReadOnly Property DefaultVideoEmbedThumbnail As XMLValue(Of Boolean)
|
Public ReadOnly Property DefaultVideoEmbedThumbnail As XMLValue(Of Boolean)
|
||||||
|
<Browsable(True), GridVisible, XMLVN({"DefaultsVideo"}, True), Category("Defaults Video"), DisplayName("Embed chapters"),
|
||||||
|
Description("Embed chapters in the video. Default: true.")>
|
||||||
|
Public ReadOnly Property DefaultVideoEmbedChapters As XMLValue(Of Boolean)
|
||||||
<Browsable(True), GridVisible, XMLVN({"DefaultsVideo"}), Category("Defaults Video"), DisplayName("Include zero size formats"),
|
<Browsable(True), GridVisible, XMLVN({"DefaultsVideo"}), Category("Defaults Video"), DisplayName("Include zero size formats"),
|
||||||
Description("Include formats with zero size (or undefined size).")>
|
Description("Include formats with zero size (or undefined size).")>
|
||||||
Public ReadOnly Property DefaultVideoIncludeNullSize As XMLValue(Of Boolean)
|
Public ReadOnly Property DefaultVideoIncludeNullSize As XMLValue(Of Boolean)
|
||||||
@@ -416,6 +426,9 @@ Namespace API.YouTube.Base
|
|||||||
<Browsable(True), GridVisible, XMLVN({"DefaultsAudio"}, True), Category("Defaults Audio"), DisplayName("Embed thumbnail"),
|
<Browsable(True), GridVisible, XMLVN({"DefaultsAudio"}, True), Category("Defaults Audio"), DisplayName("Embed thumbnail"),
|
||||||
Description("Embed thumbnail in the audio as cover art. Default: true.")>
|
Description("Embed thumbnail in the audio as cover art. Default: true.")>
|
||||||
Public ReadOnly Property DefaultAudioEmbedThumbnail As XMLValue(Of Boolean)
|
Public ReadOnly Property DefaultAudioEmbedThumbnail As XMLValue(Of Boolean)
|
||||||
|
<Browsable(True), GridVisible, XMLVN({"DefaultsAudio"}, True), Category("Defaults Audio"), DisplayName("Embed thumbnail (cover)"),
|
||||||
|
Description("Try embedding the playlist cover (if it exists) as cover art. Default: true.")>
|
||||||
|
Public ReadOnly Property DefaultAudioEmbedThumbnail_Cover As XMLValue(Of Boolean)
|
||||||
<Browsable(True), GridVisible, XMLVN({"DefaultsAudio"}, True), Category("Defaults Audio"), DisplayName("Embed thumbnail (extracted files)"),
|
<Browsable(True), GridVisible, XMLVN({"DefaultsAudio"}, True), Category("Defaults Audio"), DisplayName("Embed thumbnail (extracted files)"),
|
||||||
Description("Embed thumbnail in the extracted (additional file ('mp3' only)) audio as cover art. Default: true.")>
|
Description("Embed thumbnail in the extracted (additional file ('mp3' only)) audio as cover art. Default: true.")>
|
||||||
Public ReadOnly Property DefaultAudioEmbedThumbnail_ExtractedFiles As XMLValue(Of Boolean)
|
Public ReadOnly Property DefaultAudioEmbedThumbnail_ExtractedFiles As XMLValue(Of Boolean)
|
||||||
@@ -488,6 +501,29 @@ Namespace API.YouTube.Base
|
|||||||
TypeConverter(GetType(ValueCollectionConverter)),
|
TypeConverter(GetType(ValueCollectionConverter)),
|
||||||
Description("Additional format for downloading subtitles. This means that all subtitles will be converted to the formats you choose and saved as separate files.")>
|
Description("Additional format for downloading subtitles. This means that all subtitles will be converted to the formats you choose and saved as separate files.")>
|
||||||
Public ReadOnly Property DefaultSubtitlesFormatAddit As XMLValuesCollection(Of String)
|
Public ReadOnly Property DefaultSubtitlesFormatAddit As XMLValuesCollection(Of String)
|
||||||
|
<Browsable(True), GridVisible, XMLVN({"DefaultsSubtitles"}), Category("Defaults Subtitles"), DisplayName("Embed subtitles"),
|
||||||
|
Description("Embed subtitles in the video (only for mp4, webm and mkv videos)")>
|
||||||
|
Public ReadOnly Property DefaultSubtitlesEmbed As XMLValue(Of Boolean)
|
||||||
|
#End Region
|
||||||
|
#Region "Trim"
|
||||||
|
<Browsable(True), GridVisible, XMLVN({"DefaultsTrim"}, False), Category("Defaults Trimming"), DisplayName("Delete original file"),
|
||||||
|
Description("If true, the original file will be deleted after trimming")>
|
||||||
|
Public ReadOnly Property TrimDeleteOriginalFile As XMLValue(Of Boolean)
|
||||||
|
<Browsable(True), GridVisible, XMLVN({"DefaultsTrim"}, False), Category("Defaults Trimming"), DisplayName("Add to M3U8"),
|
||||||
|
Description("If true, the trimmed files will be added to the M3U8 playlist (if selected)")>
|
||||||
|
Public ReadOnly Property TrimAddTrimmedFilesToM3U8 As XMLValue(Of Boolean)
|
||||||
|
<Browsable(True), GridVisible, XMLVN({"DefaultsTrim"}, False), Category("Defaults Trimming"), DisplayName("Separate folder"),
|
||||||
|
Description("Place the trimmed files in a separate folder")>
|
||||||
|
Public ReadOnly Property TrimSeparateFolder As XMLValue(Of Boolean)
|
||||||
|
Friend Const TrimSeparateFolderNameDefault As String = "Trim"
|
||||||
|
<Browsable(True), GridVisible, XMLVN({"DefaultsTrim"}, TrimSeparateFolderNameDefault), Category("Defaults Trimming"), DisplayName("Separate folder name"),
|
||||||
|
Description("Name of a separate folder")>
|
||||||
|
Public ReadOnly Property TrimSeparateFolderName As XMLValue(Of String)
|
||||||
|
#End Region
|
||||||
|
#Region "Errors"
|
||||||
|
<Browsable(True), GridVisible, XMLVN({"Errors"}, True), Category("ERRORS"), DisplayName("Ignore downloading errors"),
|
||||||
|
Description("Ignore download errors if some files are missing (e.g. subtitles) and continue downloading")>
|
||||||
|
Public ReadOnly Property ErrorsIgnore As XMLValue(Of Boolean)
|
||||||
#End Region
|
#End Region
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Initializer"
|
#Region "Initializer"
|
||||||
@@ -508,6 +544,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
|
||||||
|
|||||||
158
SCrawler.YouTube/Controls/ChaptersForm.Designer.vb
generated
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
' 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 ChaptersForm : 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_BUTTONS As System.Windows.Forms.TableLayoutPanel
|
||||||
|
Me.BTT_ALL = New System.Windows.Forms.Button()
|
||||||
|
Me.BTT_NONE = New System.Windows.Forms.Button()
|
||||||
|
Me.BTT_INVERT = New System.Windows.Forms.Button()
|
||||||
|
Me.LIST_CHAPTERS = New System.Windows.Forms.CheckedListBox()
|
||||||
|
CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer()
|
||||||
|
TP_MAIN = New System.Windows.Forms.TableLayoutPanel()
|
||||||
|
TP_BUTTONS = New System.Windows.Forms.TableLayoutPanel()
|
||||||
|
CONTAINER_MAIN.ContentPanel.SuspendLayout()
|
||||||
|
CONTAINER_MAIN.SuspendLayout()
|
||||||
|
TP_MAIN.SuspendLayout()
|
||||||
|
TP_BUTTONS.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.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20.0!))
|
||||||
|
TP_MAIN.Controls.Add(TP_BUTTONS, 0, 1)
|
||||||
|
TP_MAIN.Controls.Add(Me.LIST_CHAPTERS, 0, 0)
|
||||||
|
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 = 2
|
||||||
|
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, 30.0!))
|
||||||
|
TP_MAIN.Size = New System.Drawing.Size(384, 361)
|
||||||
|
TP_MAIN.TabIndex = 0
|
||||||
|
'
|
||||||
|
'TP_BUTTONS
|
||||||
|
'
|
||||||
|
TP_BUTTONS.ColumnCount = 3
|
||||||
|
TP_BUTTONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333!))
|
||||||
|
TP_BUTTONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333!))
|
||||||
|
TP_BUTTONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333!))
|
||||||
|
TP_BUTTONS.Controls.Add(Me.BTT_ALL, 0, 0)
|
||||||
|
TP_BUTTONS.Controls.Add(Me.BTT_NONE, 1, 0)
|
||||||
|
TP_BUTTONS.Controls.Add(Me.BTT_INVERT, 2, 0)
|
||||||
|
TP_BUTTONS.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
TP_BUTTONS.Location = New System.Drawing.Point(0, 331)
|
||||||
|
TP_BUTTONS.Margin = New System.Windows.Forms.Padding(0)
|
||||||
|
TP_BUTTONS.Name = "TP_BUTTONS"
|
||||||
|
TP_BUTTONS.RowCount = 1
|
||||||
|
TP_BUTTONS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
|
TP_BUTTONS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20.0!))
|
||||||
|
TP_BUTTONS.Size = New System.Drawing.Size(384, 30)
|
||||||
|
TP_BUTTONS.TabIndex = 1
|
||||||
|
'
|
||||||
|
'BTT_ALL
|
||||||
|
'
|
||||||
|
Me.BTT_ALL.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.BTT_ALL.Location = New System.Drawing.Point(3, 3)
|
||||||
|
Me.BTT_ALL.Name = "BTT_ALL"
|
||||||
|
Me.BTT_ALL.Size = New System.Drawing.Size(122, 24)
|
||||||
|
Me.BTT_ALL.TabIndex = 0
|
||||||
|
Me.BTT_ALL.Text = "All"
|
||||||
|
Me.BTT_ALL.UseVisualStyleBackColor = True
|
||||||
|
'
|
||||||
|
'BTT_NONE
|
||||||
|
'
|
||||||
|
Me.BTT_NONE.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.BTT_NONE.Location = New System.Drawing.Point(131, 3)
|
||||||
|
Me.BTT_NONE.Name = "BTT_NONE"
|
||||||
|
Me.BTT_NONE.Size = New System.Drawing.Size(122, 24)
|
||||||
|
Me.BTT_NONE.TabIndex = 1
|
||||||
|
Me.BTT_NONE.Text = "None"
|
||||||
|
Me.BTT_NONE.UseVisualStyleBackColor = True
|
||||||
|
'
|
||||||
|
'BTT_INVERT
|
||||||
|
'
|
||||||
|
Me.BTT_INVERT.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.BTT_INVERT.Location = New System.Drawing.Point(259, 3)
|
||||||
|
Me.BTT_INVERT.Name = "BTT_INVERT"
|
||||||
|
Me.BTT_INVERT.Size = New System.Drawing.Size(122, 24)
|
||||||
|
Me.BTT_INVERT.TabIndex = 2
|
||||||
|
Me.BTT_INVERT.Text = "Invert"
|
||||||
|
Me.BTT_INVERT.UseVisualStyleBackColor = True
|
||||||
|
'
|
||||||
|
'LIST_CHAPTERS
|
||||||
|
'
|
||||||
|
Me.LIST_CHAPTERS.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.LIST_CHAPTERS.FormattingEnabled = True
|
||||||
|
Me.LIST_CHAPTERS.Location = New System.Drawing.Point(3, 3)
|
||||||
|
Me.LIST_CHAPTERS.Name = "LIST_CHAPTERS"
|
||||||
|
Me.LIST_CHAPTERS.Size = New System.Drawing.Size(378, 325)
|
||||||
|
Me.LIST_CHAPTERS.TabIndex = 0
|
||||||
|
'
|
||||||
|
'ChaptersForm
|
||||||
|
'
|
||||||
|
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.KeyPreview = True
|
||||||
|
Me.MinimizeBox = False
|
||||||
|
Me.MinimumSize = New System.Drawing.Size(400, 400)
|
||||||
|
Me.Name = "ChaptersForm"
|
||||||
|
Me.ShowIcon = False
|
||||||
|
Me.ShowInTaskbar = False
|
||||||
|
Me.Text = "Chapters"
|
||||||
|
CONTAINER_MAIN.ContentPanel.ResumeLayout(False)
|
||||||
|
CONTAINER_MAIN.ResumeLayout(False)
|
||||||
|
CONTAINER_MAIN.PerformLayout()
|
||||||
|
TP_MAIN.ResumeLayout(False)
|
||||||
|
TP_BUTTONS.ResumeLayout(False)
|
||||||
|
Me.ResumeLayout(False)
|
||||||
|
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Private WithEvents BTT_ALL As Button
|
||||||
|
Private WithEvents BTT_NONE As Button
|
||||||
|
Private WithEvents BTT_INVERT As Button
|
||||||
|
Private WithEvents LIST_CHAPTERS As CheckedListBox
|
||||||
|
End Class
|
||||||
|
End Namespace
|
||||||
129
SCrawler.YouTube/Controls/ChaptersForm.resx
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
<?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_BUTTONS.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</metadata>
|
||||||
|
</root>
|
||||||
66
SCrawler.YouTube/Controls/ChaptersForm.vb
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
' Copyright (C) Andy https://github.com/AAndyProgram
|
||||||
|
' This program is free software: you can redistribute it and/or modify
|
||||||
|
' it under the terms of the GNU General Public License as published by
|
||||||
|
' the Free Software Foundation, either version 3 of the License, or
|
||||||
|
' (at your option) any later version.
|
||||||
|
'
|
||||||
|
' This program is distributed in the hope that it will be useful,
|
||||||
|
' but WITHOUT ANY WARRANTY
|
||||||
|
Imports PersonalUtilities.Forms
|
||||||
|
Imports PersonalUtilities.Forms.Toolbars
|
||||||
|
Imports SCrawler.API.YouTube.Base
|
||||||
|
Imports SCrawler.API.YouTube.Objects
|
||||||
|
Namespace API.YouTube.Controls
|
||||||
|
Friend Class ChaptersForm
|
||||||
|
Private WithEvents MyDefs As DefaultFormOptions
|
||||||
|
Private ReadOnly Property MyData As YouTubeMediaContainerBase
|
||||||
|
Private ReadOnly Property MyDataSelected As List(Of TrimOption)
|
||||||
|
Friend ReadOnly Property MyResult As List(Of TrimOption)
|
||||||
|
Friend Sub New(ByRef data As YouTubeMediaContainerBase, ByVal selected As IEnumerable(Of TrimOption))
|
||||||
|
InitializeComponent()
|
||||||
|
MyDefs = New DefaultFormOptions(Me, MyYouTubeSettings.DesignXml)
|
||||||
|
MyData = data
|
||||||
|
MyDataSelected = New List(Of TrimOption)
|
||||||
|
MyDataSelected.ListAddList(selected)
|
||||||
|
MyResult = New List(Of TrimOption)
|
||||||
|
End Sub
|
||||||
|
Private Sub ChaptersForm_Load(sender As Object, e As EventArgs) Handles Me.Load
|
||||||
|
With MyDefs
|
||||||
|
.MyViewInitialize()
|
||||||
|
.AddOkCancelToolbar()
|
||||||
|
|
||||||
|
With LIST_CHAPTERS
|
||||||
|
.BeginUpdate()
|
||||||
|
.Items.AddRange(MyData.Chapters.Cast(Of Object).ToArray)
|
||||||
|
If MyDataSelected.Count > 0 Then
|
||||||
|
For i% = 0 To .Items.Count - 1 : .SetItemChecked(i, MyDataSelected.Contains(MyData.Chapters(i))) : Next
|
||||||
|
End If
|
||||||
|
.EndUpdate()
|
||||||
|
End With
|
||||||
|
|
||||||
|
.EndLoaderOperations()
|
||||||
|
End With
|
||||||
|
End Sub
|
||||||
|
Private Sub ChaptersForm_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed
|
||||||
|
MyResult.Clear()
|
||||||
|
MyDataSelected.Clear()
|
||||||
|
End Sub
|
||||||
|
Private Sub MyDefs_ButtonOkClick(ByVal Sender As Object, ByVal e As KeyHandleEventArgs) Handles MyDefs.ButtonOkClick
|
||||||
|
With LIST_CHAPTERS
|
||||||
|
For i% = 0 To .Items.Count - 1
|
||||||
|
If .GetItemChecked(i) Then MyResult.Add(MyData.Chapters(i))
|
||||||
|
Next
|
||||||
|
End With
|
||||||
|
MyDefs.CloseForm()
|
||||||
|
End Sub
|
||||||
|
Private Sub BTT_ALL_NONE_INVERT_Click(sender As Object, e As EventArgs) Handles BTT_ALL.Click, BTT_NONE.Click, BTT_INVERT.Click
|
||||||
|
Dim v As Boolean = sender Is BTT_ALL
|
||||||
|
Dim isInvert As Boolean = sender Is BTT_INVERT
|
||||||
|
With LIST_CHAPTERS
|
||||||
|
.BeginUpdate()
|
||||||
|
For i% = 0 To .Items.Count - 1 : .SetItemChecked(i, If(isInvert, Not .GetItemChecked(i), v)) : Next
|
||||||
|
.EndUpdate()
|
||||||
|
End With
|
||||||
|
End Sub
|
||||||
|
End Class
|
||||||
|
End Namespace
|
||||||
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
|
||||||
'
|
'
|
||||||
|
|||||||
274
SCrawler.YouTube/Controls/TrimOptionForm.Designer.vb
generated
Normal file
@@ -0,0 +1,274 @@
|
|||||||
|
' 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 TrimOptionForm : 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 ActionButton1 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||||
|
Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(TrimOptionForm))
|
||||||
|
Dim TP_OPTIONS As System.Windows.Forms.TableLayoutPanel
|
||||||
|
Me.TXT_NAME = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
||||||
|
Me.TP_TIME_TIME = New System.Windows.Forms.TableLayoutPanel()
|
||||||
|
Me.TXT_FROM_DATE = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
||||||
|
Me.TXT_TO_DATE = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
||||||
|
Me.OPT_INT = New System.Windows.Forms.RadioButton()
|
||||||
|
Me.OPT_TIME = New System.Windows.Forms.RadioButton()
|
||||||
|
Me.TP_TIME_INT = New System.Windows.Forms.TableLayoutPanel()
|
||||||
|
Me.TXT_FROM_INT = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
||||||
|
Me.TXT_TO_INT = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
||||||
|
CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer()
|
||||||
|
TP_MAIN = New System.Windows.Forms.TableLayoutPanel()
|
||||||
|
TP_OPTIONS = New System.Windows.Forms.TableLayoutPanel()
|
||||||
|
CONTAINER_MAIN.ContentPanel.SuspendLayout()
|
||||||
|
CONTAINER_MAIN.SuspendLayout()
|
||||||
|
TP_MAIN.SuspendLayout()
|
||||||
|
CType(Me.TXT_NAME, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||||
|
TP_OPTIONS.SuspendLayout()
|
||||||
|
Me.TP_TIME_TIME.SuspendLayout()
|
||||||
|
CType(Me.TXT_FROM_DATE, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||||
|
CType(Me.TXT_TO_DATE, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||||
|
Me.TP_TIME_INT.SuspendLayout()
|
||||||
|
CType(Me.TXT_FROM_INT, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||||
|
CType(Me.TXT_TO_INT, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||||
|
Me.SuspendLayout()
|
||||||
|
'
|
||||||
|
'CONTAINER_MAIN
|
||||||
|
'
|
||||||
|
'
|
||||||
|
'CONTAINER_MAIN.ContentPanel
|
||||||
|
'
|
||||||
|
CONTAINER_MAIN.ContentPanel.Controls.Add(TP_MAIN)
|
||||||
|
CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(334, 112)
|
||||||
|
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(334, 112)
|
||||||
|
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.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20.0!))
|
||||||
|
TP_MAIN.Controls.Add(Me.TXT_NAME, 0, 0)
|
||||||
|
TP_MAIN.Controls.Add(TP_OPTIONS, 0, 1)
|
||||||
|
TP_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
TP_MAIN.Location = New System.Drawing.Point(0, 0)
|
||||||
|
TP_MAIN.Name = "TP_MAIN"
|
||||||
|
TP_MAIN.RowCount = 2
|
||||||
|
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
|
||||||
|
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
|
TP_MAIN.Size = New System.Drawing.Size(334, 112)
|
||||||
|
TP_MAIN.TabIndex = 0
|
||||||
|
'
|
||||||
|
'TXT_NAME
|
||||||
|
'
|
||||||
|
ActionButton1.BackgroundImage = CType(resources.GetObject("ActionButton1.BackgroundImage"), System.Drawing.Image)
|
||||||
|
ActionButton1.Name = "Clear"
|
||||||
|
ActionButton1.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
|
||||||
|
Me.TXT_NAME.Buttons.Add(ActionButton1)
|
||||||
|
Me.TXT_NAME.CaptionText = "Name"
|
||||||
|
Me.TXT_NAME.CaptionToolTipText = "Section name"
|
||||||
|
Me.TXT_NAME.CaptionWidth = 50.0R
|
||||||
|
Me.TXT_NAME.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.TXT_NAME.Location = New System.Drawing.Point(3, 3)
|
||||||
|
Me.TXT_NAME.Name = "TXT_NAME"
|
||||||
|
Me.TXT_NAME.Size = New System.Drawing.Size(328, 22)
|
||||||
|
Me.TXT_NAME.TabIndex = 0
|
||||||
|
'
|
||||||
|
'TP_OPTIONS
|
||||||
|
'
|
||||||
|
TP_OPTIONS.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single]
|
||||||
|
TP_OPTIONS.ColumnCount = 2
|
||||||
|
TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 30.0!))
|
||||||
|
TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
|
TP_OPTIONS.Controls.Add(Me.TP_TIME_TIME, 1, 1)
|
||||||
|
TP_OPTIONS.Controls.Add(Me.OPT_INT, 0, 0)
|
||||||
|
TP_OPTIONS.Controls.Add(Me.OPT_TIME, 0, 1)
|
||||||
|
TP_OPTIONS.Controls.Add(Me.TP_TIME_INT, 1, 0)
|
||||||
|
TP_OPTIONS.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
TP_OPTIONS.Location = New System.Drawing.Point(3, 31)
|
||||||
|
TP_OPTIONS.Name = "TP_OPTIONS"
|
||||||
|
TP_OPTIONS.RowCount = 3
|
||||||
|
TP_OPTIONS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
|
||||||
|
TP_OPTIONS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
|
||||||
|
TP_OPTIONS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
|
TP_OPTIONS.Size = New System.Drawing.Size(328, 78)
|
||||||
|
TP_OPTIONS.TabIndex = 1
|
||||||
|
'
|
||||||
|
'TP_TIME_TIME
|
||||||
|
'
|
||||||
|
Me.TP_TIME_TIME.ColumnCount = 2
|
||||||
|
Me.TP_TIME_TIME.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
|
||||||
|
Me.TP_TIME_TIME.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
|
||||||
|
Me.TP_TIME_TIME.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20.0!))
|
||||||
|
Me.TP_TIME_TIME.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20.0!))
|
||||||
|
Me.TP_TIME_TIME.Controls.Add(Me.TXT_FROM_DATE, 0, 0)
|
||||||
|
Me.TP_TIME_TIME.Controls.Add(Me.TXT_TO_DATE, 1, 0)
|
||||||
|
Me.TP_TIME_TIME.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.TP_TIME_TIME.Location = New System.Drawing.Point(32, 27)
|
||||||
|
Me.TP_TIME_TIME.Margin = New System.Windows.Forms.Padding(0)
|
||||||
|
Me.TP_TIME_TIME.Name = "TP_TIME_TIME"
|
||||||
|
Me.TP_TIME_TIME.RowCount = 1
|
||||||
|
Me.TP_TIME_TIME.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
|
Me.TP_TIME_TIME.Size = New System.Drawing.Size(295, 25)
|
||||||
|
Me.TP_TIME_TIME.TabIndex = 3
|
||||||
|
'
|
||||||
|
'TXT_FROM_DATE
|
||||||
|
'
|
||||||
|
Me.TXT_FROM_DATE.CaptionPadding = New System.Windows.Forms.Padding(0, 0, 6, 0)
|
||||||
|
Me.TXT_FROM_DATE.CaptionText = "From"
|
||||||
|
Me.TXT_FROM_DATE.CaptionWidth = 40.0R
|
||||||
|
Me.TXT_FROM_DATE.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.TXT_FROM_DATE.Location = New System.Drawing.Point(3, 3)
|
||||||
|
Me.TXT_FROM_DATE.Name = "TXT_FROM_DATE"
|
||||||
|
Me.TXT_FROM_DATE.PlaceholderEnabled = True
|
||||||
|
Me.TXT_FROM_DATE.PlaceholderText = "h:mm:ss"
|
||||||
|
Me.TXT_FROM_DATE.Size = New System.Drawing.Size(141, 22)
|
||||||
|
Me.TXT_FROM_DATE.TabIndex = 0
|
||||||
|
'
|
||||||
|
'TXT_TO_DATE
|
||||||
|
'
|
||||||
|
Me.TXT_TO_DATE.CaptionPadding = New System.Windows.Forms.Padding(0, 0, 6, 0)
|
||||||
|
Me.TXT_TO_DATE.CaptionText = "To"
|
||||||
|
Me.TXT_TO_DATE.CaptionWidth = 40.0R
|
||||||
|
Me.TXT_TO_DATE.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.TXT_TO_DATE.Location = New System.Drawing.Point(150, 3)
|
||||||
|
Me.TXT_TO_DATE.Name = "TXT_TO_DATE"
|
||||||
|
Me.TXT_TO_DATE.PlaceholderEnabled = True
|
||||||
|
Me.TXT_TO_DATE.PlaceholderText = "h:mm:ss"
|
||||||
|
Me.TXT_TO_DATE.Size = New System.Drawing.Size(142, 22)
|
||||||
|
Me.TXT_TO_DATE.TabIndex = 1
|
||||||
|
'
|
||||||
|
'OPT_INT
|
||||||
|
'
|
||||||
|
Me.OPT_INT.AutoSize = True
|
||||||
|
Me.OPT_INT.CheckAlign = System.Drawing.ContentAlignment.MiddleCenter
|
||||||
|
Me.OPT_INT.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.OPT_INT.Location = New System.Drawing.Point(4, 4)
|
||||||
|
Me.OPT_INT.Name = "OPT_INT"
|
||||||
|
Me.OPT_INT.Size = New System.Drawing.Size(24, 19)
|
||||||
|
Me.OPT_INT.TabIndex = 0
|
||||||
|
Me.OPT_INT.TabStop = True
|
||||||
|
Me.OPT_INT.UseVisualStyleBackColor = True
|
||||||
|
'
|
||||||
|
'OPT_TIME
|
||||||
|
'
|
||||||
|
Me.OPT_TIME.AutoSize = True
|
||||||
|
Me.OPT_TIME.CheckAlign = System.Drawing.ContentAlignment.MiddleCenter
|
||||||
|
Me.OPT_TIME.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.OPT_TIME.Location = New System.Drawing.Point(4, 30)
|
||||||
|
Me.OPT_TIME.Name = "OPT_TIME"
|
||||||
|
Me.OPT_TIME.Size = New System.Drawing.Size(24, 19)
|
||||||
|
Me.OPT_TIME.TabIndex = 1
|
||||||
|
Me.OPT_TIME.TabStop = True
|
||||||
|
Me.OPT_TIME.UseVisualStyleBackColor = True
|
||||||
|
'
|
||||||
|
'TP_TIME_INT
|
||||||
|
'
|
||||||
|
Me.TP_TIME_INT.ColumnCount = 2
|
||||||
|
Me.TP_TIME_INT.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
|
||||||
|
Me.TP_TIME_INT.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
|
||||||
|
Me.TP_TIME_INT.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20.0!))
|
||||||
|
Me.TP_TIME_INT.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20.0!))
|
||||||
|
Me.TP_TIME_INT.Controls.Add(Me.TXT_FROM_INT, 0, 0)
|
||||||
|
Me.TP_TIME_INT.Controls.Add(Me.TXT_TO_INT, 1, 0)
|
||||||
|
Me.TP_TIME_INT.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.TP_TIME_INT.Location = New System.Drawing.Point(32, 1)
|
||||||
|
Me.TP_TIME_INT.Margin = New System.Windows.Forms.Padding(0)
|
||||||
|
Me.TP_TIME_INT.Name = "TP_TIME_INT"
|
||||||
|
Me.TP_TIME_INT.RowCount = 1
|
||||||
|
Me.TP_TIME_INT.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
|
Me.TP_TIME_INT.Size = New System.Drawing.Size(295, 25)
|
||||||
|
Me.TP_TIME_INT.TabIndex = 2
|
||||||
|
'
|
||||||
|
'TXT_FROM_INT
|
||||||
|
'
|
||||||
|
Me.TXT_FROM_INT.CaptionPadding = New System.Windows.Forms.Padding(0, 0, 6, 0)
|
||||||
|
Me.TXT_FROM_INT.CaptionText = "From"
|
||||||
|
Me.TXT_FROM_INT.CaptionWidth = 40.0R
|
||||||
|
Me.TXT_FROM_INT.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.TXT_FROM_INT.Location = New System.Drawing.Point(3, 3)
|
||||||
|
Me.TXT_FROM_INT.Name = "TXT_FROM_INT"
|
||||||
|
Me.TXT_FROM_INT.Size = New System.Drawing.Size(141, 22)
|
||||||
|
Me.TXT_FROM_INT.TabIndex = 0
|
||||||
|
'
|
||||||
|
'TXT_TO_INT
|
||||||
|
'
|
||||||
|
Me.TXT_TO_INT.CaptionPadding = New System.Windows.Forms.Padding(0, 0, 6, 0)
|
||||||
|
Me.TXT_TO_INT.CaptionText = "To"
|
||||||
|
Me.TXT_TO_INT.CaptionWidth = 40.0R
|
||||||
|
Me.TXT_TO_INT.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.TXT_TO_INT.Location = New System.Drawing.Point(150, 3)
|
||||||
|
Me.TXT_TO_INT.Name = "TXT_TO_INT"
|
||||||
|
Me.TXT_TO_INT.Size = New System.Drawing.Size(142, 22)
|
||||||
|
Me.TXT_TO_INT.TabIndex = 1
|
||||||
|
'
|
||||||
|
'TrimOptionForm
|
||||||
|
'
|
||||||
|
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
|
||||||
|
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
|
||||||
|
Me.ClientSize = New System.Drawing.Size(334, 112)
|
||||||
|
Me.Controls.Add(CONTAINER_MAIN)
|
||||||
|
Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle
|
||||||
|
Me.KeyPreview = True
|
||||||
|
Me.MaximizeBox = False
|
||||||
|
Me.MaximumSize = New System.Drawing.Size(350, 151)
|
||||||
|
Me.MinimizeBox = False
|
||||||
|
Me.MinimumSize = New System.Drawing.Size(350, 151)
|
||||||
|
Me.Name = "TrimOptionForm"
|
||||||
|
Me.ShowIcon = False
|
||||||
|
Me.ShowInTaskbar = False
|
||||||
|
Me.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide
|
||||||
|
Me.Text = "Trim option"
|
||||||
|
CONTAINER_MAIN.ContentPanel.ResumeLayout(False)
|
||||||
|
CONTAINER_MAIN.ResumeLayout(False)
|
||||||
|
CONTAINER_MAIN.PerformLayout()
|
||||||
|
TP_MAIN.ResumeLayout(False)
|
||||||
|
CType(Me.TXT_NAME, System.ComponentModel.ISupportInitialize).EndInit()
|
||||||
|
TP_OPTIONS.ResumeLayout(False)
|
||||||
|
TP_OPTIONS.PerformLayout()
|
||||||
|
Me.TP_TIME_TIME.ResumeLayout(False)
|
||||||
|
CType(Me.TXT_FROM_DATE, System.ComponentModel.ISupportInitialize).EndInit()
|
||||||
|
CType(Me.TXT_TO_DATE, System.ComponentModel.ISupportInitialize).EndInit()
|
||||||
|
Me.TP_TIME_INT.ResumeLayout(False)
|
||||||
|
CType(Me.TXT_FROM_INT, System.ComponentModel.ISupportInitialize).EndInit()
|
||||||
|
CType(Me.TXT_TO_INT, System.ComponentModel.ISupportInitialize).EndInit()
|
||||||
|
Me.ResumeLayout(False)
|
||||||
|
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Private WithEvents TXT_NAME As PersonalUtilities.Forms.Controls.TextBoxExtended
|
||||||
|
Private WithEvents OPT_INT As RadioButton
|
||||||
|
Private WithEvents OPT_TIME As RadioButton
|
||||||
|
Private WithEvents TP_TIME_INT As TableLayoutPanel
|
||||||
|
Private WithEvents TP_TIME_TIME As TableLayoutPanel
|
||||||
|
Private WithEvents TXT_FROM_DATE As PersonalUtilities.Forms.Controls.TextBoxExtended
|
||||||
|
Private WithEvents TXT_TO_DATE As PersonalUtilities.Forms.Controls.TextBoxExtended
|
||||||
|
Private WithEvents TXT_FROM_INT As PersonalUtilities.Forms.Controls.TextBoxExtended
|
||||||
|
Private WithEvents TXT_TO_INT As PersonalUtilities.Forms.Controls.TextBoxExtended
|
||||||
|
End Class
|
||||||
|
End Namespace
|
||||||
138
SCrawler.YouTube/Controls/TrimOptionForm.resx
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
<?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>
|
||||||
|
<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">
|
||||||
|
<value>
|
||||||
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
|
vgAADr4B6kKxwAAAAHpJREFUOE+1kVEKgDAMQ3e2/e+MXqpn6W/HxM7SpkIVB4HxSMKiTUTaFwVQ1X25
|
||||||
|
DjMfSxskHBYsAxHJkjUjHgrUNMY4peaMPxb03rcZMVhgn2oDKAwn+L0aROH/Cny4NAGFSx8x+10ZDwV2
|
||||||
|
gt+LOCxQsw1nPBS8VQBVTTzyhrdZSUm7AAAAAElFTkSuQmCC
|
||||||
|
</value>
|
||||||
|
</data>
|
||||||
|
<metadata name="TP_OPTIONS.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</metadata>
|
||||||
|
</root>
|
||||||
79
SCrawler.YouTube/Controls/TrimOptionForm.vb
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
' Copyright (C) Andy https://github.com/AAndyProgram
|
||||||
|
' This program is free software: you can redistribute it and/or modify
|
||||||
|
' it under the terms of the GNU General Public License as published by
|
||||||
|
' the Free Software Foundation, either version 3 of the License, or
|
||||||
|
' (at your option) any later version.
|
||||||
|
'
|
||||||
|
' This program is distributed in the hope that it will be useful,
|
||||||
|
' but WITHOUT ANY WARRANTY
|
||||||
|
Imports PersonalUtilities.Forms
|
||||||
|
Imports PersonalUtilities.Forms.Toolbars
|
||||||
|
Imports SCrawler.API.YouTube.Base
|
||||||
|
Namespace API.YouTube.Controls
|
||||||
|
Friend Class TrimOptionForm
|
||||||
|
Private WithEvents MyDefs As DefaultFormOptions
|
||||||
|
Friend Property MyTrimOption As TrimOption
|
||||||
|
Private ReadOnly FieldsDateProvider As New CustomProvider(Function(v) AConvert(Of TimeSpan)(v, Nothing, EDP.ReturnValue))
|
||||||
|
Private ReadOnly TCE As New ErrorsDescriber(False, False, False, New TimeSpan)
|
||||||
|
Friend Sub New(Optional ByVal Opt As TrimOption = Nothing)
|
||||||
|
InitializeComponent()
|
||||||
|
MyDefs = New DefaultFormOptions(Me, MyYouTubeSettings.DesignXml)
|
||||||
|
MyTrimOption = Opt
|
||||||
|
End Sub
|
||||||
|
Private Sub TrimOptionForm_Load(sender As Object, e As EventArgs) Handles Me.Load
|
||||||
|
Try
|
||||||
|
With MyDefs
|
||||||
|
.MyViewInitialize()
|
||||||
|
.AddOkCancelToolbar()
|
||||||
|
|
||||||
|
TXT_NAME.Text = MyTrimOption.Name
|
||||||
|
TXT_FROM_INT.Text = MyTrimOption.Start
|
||||||
|
TXT_TO_INT.Text = MyTrimOption.End
|
||||||
|
|
||||||
|
OPT_INT.Checked = True
|
||||||
|
|
||||||
|
.MyFieldsCheckerE = New FieldsChecker
|
||||||
|
With .MyFieldsCheckerE
|
||||||
|
.AddControl(Of Integer)(TXT_FROM_INT, "From")
|
||||||
|
.AddControl(Of Integer)(TXT_TO_INT, "To")
|
||||||
|
.AddControl(Of String)(TXT_FROM_DATE, "From (time)",, FieldsDateProvider)
|
||||||
|
.AddControl(Of String)(TXT_TO_DATE, "To (time)",, FieldsDateProvider)
|
||||||
|
.EndLoaderOperations()
|
||||||
|
End With
|
||||||
|
|
||||||
|
.EndLoaderOperations()
|
||||||
|
End With
|
||||||
|
Catch ex As Exception
|
||||||
|
MyDefs.InvokeLoaderError(ex)
|
||||||
|
End Try
|
||||||
|
End Sub
|
||||||
|
Private Sub MyDefs_ButtonOkClick(ByVal Sender As Object, ByVal e As KeyHandleEventArgs) Handles MyDefs.ButtonOkClick
|
||||||
|
If MyDefs.MyFieldsChecker.AllParamsOK Then
|
||||||
|
MyTrimOption = New TrimOption With {
|
||||||
|
.Name = TXT_NAME.Text,
|
||||||
|
.Start = AConvert(Of Integer)(TXT_FROM_INT.Text, 0),
|
||||||
|
.[End] = AConvert(Of Integer)(TXT_TO_INT.Text, 0)
|
||||||
|
}
|
||||||
|
MyDefs.CloseForm()
|
||||||
|
End If
|
||||||
|
End Sub
|
||||||
|
Private Sub OPT_INT_TIME_CheckedChanged(sender As Object, e As EventArgs) Handles OPT_INT.CheckedChanged, OPT_TIME.CheckedChanged
|
||||||
|
TP_TIME_INT.Enabled = OPT_INT.Checked
|
||||||
|
TP_TIME_TIME.Enabled = OPT_TIME.Checked
|
||||||
|
End Sub
|
||||||
|
Private _TextHandlersEnabled As Boolean = True
|
||||||
|
Private Sub TXT_FROM_TO_TextChanged(sender As Object, e As EventArgs) Handles TXT_FROM_INT.ActionOnTextChanged, TXT_TO_INT.ActionOnTextChanged,
|
||||||
|
TXT_FROM_DATE.ActionOnTextChanged, TXT_TO_DATE.ActionOnTextChanged
|
||||||
|
If _TextHandlersEnabled Then
|
||||||
|
_TextHandlersEnabled = False
|
||||||
|
Select Case DirectCast(sender, Control).Name
|
||||||
|
Case TXT_FROM_INT.Name : TXT_FROM_DATE.Value = AConvert(Of String)(TimeSpan.FromSeconds(AConvert(Of Integer)(TXT_FROM_INT.Text, 0)), TimeToStringProviderH)
|
||||||
|
Case TXT_TO_INT.Name : TXT_TO_DATE.Value = AConvert(Of String)(TimeSpan.FromSeconds(AConvert(Of Integer)(TXT_TO_INT.Text, 0)), TimeToStringProviderH)
|
||||||
|
Case TXT_FROM_DATE.Name : TXT_FROM_INT.Text = CInt(CType(AConvert(Of TimeSpan)(TXT_FROM_DATE.Text, TCE), TimeSpan).TotalSeconds)
|
||||||
|
Case TXT_TO_DATE.Name : TXT_TO_INT.Text = CInt(CType(AConvert(Of TimeSpan)(TXT_TO_DATE.Text, TCE), TimeSpan).TotalSeconds)
|
||||||
|
End Select
|
||||||
|
_TextHandlersEnabled = True
|
||||||
|
End If
|
||||||
|
End Sub
|
||||||
|
End Class
|
||||||
|
End Namespace
|
||||||
@@ -73,6 +73,7 @@ Namespace API.YouTube.Controls
|
|||||||
Me.OPT_VIDEO = New System.Windows.Forms.RadioButton()
|
Me.OPT_VIDEO = New System.Windows.Forms.RadioButton()
|
||||||
Me.OPT_AUDIO = New System.Windows.Forms.RadioButton()
|
Me.OPT_AUDIO = New System.Windows.Forms.RadioButton()
|
||||||
Me.LBL_AUDIO_CODEC = New System.Windows.Forms.Label()
|
Me.LBL_AUDIO_CODEC = New System.Windows.Forms.Label()
|
||||||
|
Me.BTT_TRIM = New System.Windows.Forms.Button()
|
||||||
Me.TXT_FPS = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
Me.TXT_FPS = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
||||||
Me.TXT_AUDIO_BITRATE = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
Me.TXT_AUDIO_BITRATE = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
||||||
Me.TP_HEADER_BASE = New System.Windows.Forms.TableLayoutPanel()
|
Me.TP_HEADER_BASE = New System.Windows.Forms.TableLayoutPanel()
|
||||||
@@ -545,20 +546,32 @@ Namespace API.YouTube.Controls
|
|||||||
Me.LBL_AUDIO_CODEC.TextAlign = System.Drawing.ContentAlignment.MiddleRight
|
Me.LBL_AUDIO_CODEC.TextAlign = System.Drawing.ContentAlignment.MiddleRight
|
||||||
TT_MAIN.SetToolTip(Me.LBL_AUDIO_CODEC, "Output Audio Codec")
|
TT_MAIN.SetToolTip(Me.LBL_AUDIO_CODEC, "Output Audio Codec")
|
||||||
'
|
'
|
||||||
|
'BTT_TRIM
|
||||||
|
'
|
||||||
|
Me.BTT_TRIM.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.BTT_TRIM.Location = New System.Drawing.Point(541, 3)
|
||||||
|
Me.BTT_TRIM.Name = "BTT_TRIM"
|
||||||
|
Me.BTT_TRIM.Size = New System.Drawing.Size(45, 22)
|
||||||
|
Me.BTT_TRIM.TabIndex = 2
|
||||||
|
Me.BTT_TRIM.Text = "Trim"
|
||||||
|
TT_MAIN.SetToolTip(Me.BTT_TRIM, "Trim the file by setting trimming options and/or selecting chapters")
|
||||||
|
Me.BTT_TRIM.UseVisualStyleBackColor = True
|
||||||
|
'
|
||||||
'TP_FPS_BITRATE
|
'TP_FPS_BITRATE
|
||||||
'
|
'
|
||||||
TP_FPS_BITRATE.ColumnCount = 2
|
TP_FPS_BITRATE.ColumnCount = 3
|
||||||
TP_FPS_BITRATE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
|
TP_FPS_BITRATE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
|
||||||
TP_FPS_BITRATE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
|
TP_FPS_BITRATE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
|
||||||
|
TP_FPS_BITRATE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 51.0!))
|
||||||
TP_FPS_BITRATE.Controls.Add(Me.TXT_FPS, 0, 0)
|
TP_FPS_BITRATE.Controls.Add(Me.TXT_FPS, 0, 0)
|
||||||
TP_FPS_BITRATE.Controls.Add(Me.TXT_AUDIO_BITRATE, 1, 0)
|
TP_FPS_BITRATE.Controls.Add(Me.TXT_AUDIO_BITRATE, 1, 0)
|
||||||
|
TP_FPS_BITRATE.Controls.Add(Me.BTT_TRIM, 2, 0)
|
||||||
TP_FPS_BITRATE.Dock = System.Windows.Forms.DockStyle.Fill
|
TP_FPS_BITRATE.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
TP_FPS_BITRATE.Location = New System.Drawing.Point(6, 93)
|
TP_FPS_BITRATE.Location = New System.Drawing.Point(6, 93)
|
||||||
TP_FPS_BITRATE.Margin = New System.Windows.Forms.Padding(6, 0, 6, 0)
|
TP_FPS_BITRATE.Margin = New System.Windows.Forms.Padding(6, 0, 6, 0)
|
||||||
TP_FPS_BITRATE.Name = "TP_FPS_BITRATE"
|
TP_FPS_BITRATE.Name = "TP_FPS_BITRATE"
|
||||||
TP_FPS_BITRATE.RowCount = 1
|
TP_FPS_BITRATE.RowCount = 1
|
||||||
TP_FPS_BITRATE.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
TP_FPS_BITRATE.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
TP_FPS_BITRATE.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
|
|
||||||
TP_FPS_BITRATE.Size = New System.Drawing.Size(589, 28)
|
TP_FPS_BITRATE.Size = New System.Drawing.Size(589, 28)
|
||||||
TP_FPS_BITRATE.TabIndex = 6
|
TP_FPS_BITRATE.TabIndex = 6
|
||||||
'
|
'
|
||||||
@@ -577,7 +590,7 @@ Namespace API.YouTube.Controls
|
|||||||
Me.TXT_FPS.Location = New System.Drawing.Point(3, 2)
|
Me.TXT_FPS.Location = New System.Drawing.Point(3, 2)
|
||||||
Me.TXT_FPS.Margin = New System.Windows.Forms.Padding(3, 2, 3, 3)
|
Me.TXT_FPS.Margin = New System.Windows.Forms.Padding(3, 2, 3, 3)
|
||||||
Me.TXT_FPS.Name = "TXT_FPS"
|
Me.TXT_FPS.Name = "TXT_FPS"
|
||||||
Me.TXT_FPS.Size = New System.Drawing.Size(288, 22)
|
Me.TXT_FPS.Size = New System.Drawing.Size(263, 22)
|
||||||
Me.TXT_FPS.TabIndex = 0
|
Me.TXT_FPS.TabIndex = 0
|
||||||
Me.TXT_FPS.TextBoxWidthMinimal = 30
|
Me.TXT_FPS.TextBoxWidthMinimal = 30
|
||||||
'
|
'
|
||||||
@@ -593,9 +606,9 @@ Namespace API.YouTube.Controls
|
|||||||
" to change."
|
" to change."
|
||||||
Me.TXT_AUDIO_BITRATE.CaptionWidth = 75.0R
|
Me.TXT_AUDIO_BITRATE.CaptionWidth = 75.0R
|
||||||
Me.TXT_AUDIO_BITRATE.Dock = System.Windows.Forms.DockStyle.Fill
|
Me.TXT_AUDIO_BITRATE.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
Me.TXT_AUDIO_BITRATE.Location = New System.Drawing.Point(297, 3)
|
Me.TXT_AUDIO_BITRATE.Location = New System.Drawing.Point(272, 3)
|
||||||
Me.TXT_AUDIO_BITRATE.Name = "TXT_AUDIO_BITRATE"
|
Me.TXT_AUDIO_BITRATE.Name = "TXT_AUDIO_BITRATE"
|
||||||
Me.TXT_AUDIO_BITRATE.Size = New System.Drawing.Size(289, 22)
|
Me.TXT_AUDIO_BITRATE.Size = New System.Drawing.Size(263, 22)
|
||||||
Me.TXT_AUDIO_BITRATE.TabIndex = 1
|
Me.TXT_AUDIO_BITRATE.TabIndex = 1
|
||||||
'
|
'
|
||||||
'TP_HEADER_BASE
|
'TP_HEADER_BASE
|
||||||
@@ -920,5 +933,6 @@ Namespace API.YouTube.Controls
|
|||||||
Private WithEvents CMB_PLS As PersonalUtilities.Forms.Controls.ComboBoxExtended
|
Private WithEvents CMB_PLS As PersonalUtilities.Forms.Controls.ComboBoxExtended
|
||||||
Private WithEvents BTT_PLS_BROWSE As SCrawler.API.YouTube.Controls.ButtonRC
|
Private WithEvents BTT_PLS_BROWSE As SCrawler.API.YouTube.Controls.ButtonRC
|
||||||
Private WithEvents TXT_AUDIO_BITRATE As PersonalUtilities.Forms.Controls.TextBoxExtended
|
Private WithEvents TXT_AUDIO_BITRATE As PersonalUtilities.Forms.Controls.TextBoxExtended
|
||||||
|
Private WithEvents BTT_TRIM As Button
|
||||||
End Class
|
End Class
|
||||||
End Namespace
|
End Namespace
|
||||||
@@ -139,98 +139,96 @@
|
|||||||
<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
|
||||||
wwAADsMBx2+oZAAAAFFJREFUOE9joAr49u3bf1Lw169f50O1QgBI0MnJCY4/vP8Ix8hiILqtrQ3TEFIM
|
vAAADrwBlbxySQAAAEhJREFUOE9jYKAG+Pbt239S8NevX+djGODk5ATHH95/hGNkMRDd1taGaQgpBiAb
|
||||||
AGGYIVDtpBsAwkQbgIyR1dDWAGLwqAGD0gByMFQ7JYCBAQChNviRiQ8ETwAAAABJRU5ErkJggg==
|
QrYBIEy0AdgMo70BxOBRAwalAeRguAGUAAChNviRcuLCdwAAAABJRU5ErkJggg==
|
||||||
</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>
|
||||||
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
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMK3O3r79wVUIz65jfGNVxI/VIX69CvGO9M//a9P+e8o3B/8v
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwJQ6e/v2BzQpPSNHvLap4sM5xVeaFLflFP/XpfvfTYqvHfx3
|
||||||
vKn9s+3fyX8dAJgmaWd+fl3E96Wd/E9XdvZHkfbvXNa+Rn45AGCS3bvjj/E/h3box5OrmxjPyy8PAEyS
|
6XXdf9t9Tfl9AIApkFM6P1fxrpzixysv9seQ7msu7b5H+X0BgAl04IU/4j97XtSPN1e1EeeVPwcAmAC7
|
||||||
XXO7zqhCeH/HDnwUOdCE+J6zdux4eH47YIrEGE8uy/Ls9Bnx/LooL0oH9b9Th/I1TVG+rCqKC+q6Xsh/
|
5ned0aT07p4X8HFkf5viHWft2PGQ8ucCky8iTq7r+uwmpefkqr6ojfitnOpXtlX94qaqLsg5L5ZfA0yB
|
||||||
FJgmO8vy6WknfdPQTnsjckMdwlPy2wITLO3wF6si/lGas1ekuXvX0Fzuyg9S3psOCl6qDwimQB3ji9Ok
|
nXX9lJzihp4X7nHnupzSE8ufD0yeuq6Xmir+IKd0eU5xZ896LvO9nOKdbVW/SA8IpkCOeEFOsadnMW9U
|
||||||
3btmEm907kpnEa/Mbw9Mlq1pB/6cdHZ/ZcfcPZrcXoXyrVVVFfl1gUmSdsS/libqPUMTd5NSvjktwrbB
|
7mxSelm5HcBE2NZW9TNzqq/oWbvHkluaVL+xaZqq/AHABGhS+pWc4u6exbsJqV8/Nzd3QrlNwNZoFpsn
|
||||||
kgDjVi1UT26K+Nnu+XrMuaud60uPWHpIfhtg3JqyfEaanHcPTdZNTRPCPy4uLj40LxIwBudt2fKAtOP/
|
tFV8cnStrit3dmt9+aHLDyx/HrBF2rp+ak5xV8+C3bS0Kf3j0tLSg8ptAzbPeXNz922r+OMN/ctAFdd3
|
||||||
0zQnN+5koIg3tpca81sC49J+LZcm5a3rJulYEq6LSV40YBOFEB6V5uFV6+flRiTsSwf9r81vDYzBCSO4
|
lxrLnw1ssu5tuZzippFFuiVJn4+IKLcR2HgppYfnFFeOrsuNSNrbpvSqchuAzXOfMVzfG3e+l6vqSeWG
|
||||||
vjfq/KAuiqfm5QM2QRPjuWnubUbz71DCn6W33zpYCmDT1EX5m92Tcuy5q47xFXkxgQ3UduqnOXfn0Bzc
|
AhunjTh3k8q/RdKfdl2DcnuADZar+tdHF+RE5M4c8dJye4Hx65r6OcXtPetwk1K/ptwmYAN1H83JKb4/
|
||||||
xJSvz4sCbIb2pzlp8v1w/WScnKSzkjekRT1hsMTAKC0vL5/Ydud3zb1NT1FelBcL2GiDm3d0TMTJy0ea
|
uhgnJ23En3TvUpTbDqzf7t27T+za+eW625JU9UXl9gEb5ODNO3oW4uTlg23bnlpuP3D8upt95RSX9ay3
|
||||||
pjk1LzYwAu3NvtLc+uTQXBtn7tYYCJtja/vQno5JOJFpQrzWb4hhNJoQnpjm1Q3D82wCcnNRFKfnxQQ2
|
rcpdioGwObZ1D+3pWYQTmTbFNT5DDOPRpvS4gzfiGl1rW5xvV1V1erm9wBh1JbuexTfhSTf6GwKsz6Gb
|
||||||
Qttk1zH5JjzhFmcIcHzyzb6O5aFem5J0sP/OvKjARmg7b7sm3xRkT3vDorwawJHb1t6Ep2NOTVoOtDch
|
fR3PQ702JW2Kt5TbDIxR17wtF96U5I7uhkXl/gD36oTuJjw9a2rSsr+7CVG58cCY5FR/umfhTU8i3qAc
|
||||||
yssMjFr6IPh8x8SbnsT4lrQamgPhCMzPzz+sifHjnXNpMnN5XnRglJaWlk5KE2z/0ISbxnzQQ0bgvlXz
|
CEdnYWHhwW3ER0bW0eTmA+U+AGOwvLx8Uk6xr2fRTVve6yEj8JM1C82jc4qv9qyfiU5bVY8s9wVYp50p
|
||||||
1ePSXPnG0NyZ+DRF8Zi8CsCo7Azh0V0TbkrzRc2B0G3wIJ9429CcmZLce4MgYJTyff87JtzU5uayLM/J
|
PaJcbFOczyoHQr+DD/KJm3vWzRTkwA2CgHE6dN//ngU3tfl2XdfnlPsJA9bd4fM13fX0nvUyLbmu3Clg
|
||||||
qwcM7vD5+jQ3DgzNlWnKDXldgFFJZwW/2jHZpj1727uZ5VWE3mofqJXmw4eG5sdUpqqqXXm1gFGoQnhJ
|
ndqq/uWexTbt2dPdzazcVxia7oFaOcX7etbI1KVpml3l/gHr0KT0wnKhzUj2txF/6L7iDFVEnJVTfLFn
|
||||||
12SbgRxoYvzjtIruK04vxRjPSvPgK0PzYmqTPqtemVcNGIU6xgu7JtusJH1ovH9ubu6UvLrQC2ncPyuN
|
bUxlmpReVu4jsA454sJyoc1SmpTePT8/f0q53zDLmpSenlP8qFwP05369eV+AutQL9ZPHl1os5b0qaXF
|
||||||
/58Mz4fpTvnmvHrAKJQL5dO6J9ssJXxucWFhLq8yzLKtaUf5h2ncb9zz+8eUKsYP53UERmHX/PyOrsk2
|
xfly32EGbcup/v2c4u7RdTDdaSLeX+4ssA67FhZ2lAttRnODG4owy5YfuvzANtXv6Tn3ZyMRHy/3GVif
|
||||||
g7nJDUWYZUuPWHpIE8oPdIz92UiMn86rCoxIOmOYta8KD5uftk2Peb1hZtTzdVOHcF3HmJ+ZVCF+Ia8u
|
bbP3VuE95sdd6bEcAEy7vJDbnNLne875mUmT4jPlfgPr1N1pq1xsM5yuHNg9Vlg5kJnQRjwtp/hhz7k+
|
||||||
MCppcl0+PNlmOG1zYPtYYc2BzIQ0np+ZxvWPh8b5LObqvMrAqEzRo4BHmctijCfnEsBUqkP5u2ksz8Kd
|
a7mq3HdgnaboUcDjzKURcXI5C5gmOdW/PSN38jyK1B8t9x9Yp64gN4uloaPI1e2OdqGcB0y67pfXHPG2
|
||||||
PI8g5SfyagOj0jbIpQk2c01DR5Brmh3NfC4DTI324LWO8V0dY3pm48mAsEGm7OEgo0sRb9wZ4+NzGWDi
|
nnN6ZuPJgLBBpuzhIONLFdfvjHhMOQ+YVHVdp+6X15FzedZTxe+UswDGYAZvCXzUaVLcllN6djkTmDSH
|
||||||
lWUZ0ti9Zt1YnvUU8fdyCYBRmsFbAh9xqhDvqEN4Xi4FTKz8s93vD4/hPiSdpJyXywCMWPtrgKuGJ12P
|
Prb73fIcHkLaiPPKeQDj0X0a4Mpy0Q0od7cRv1cOBSZFrurfyCnt7Tl3h5DbdXZgAzWLzeMH2gVYk/T2
|
||||||
ck/6gPmDXAuYOHVR/lY6UN3XMXb7kDv17MAGqhaqJ6WJ1sdegDUJ726a5oG5JDB2917vL+Kl3eO1N/lQ
|
tm3vV84GtsqB6/1VvHX0XB1U3lfOBRiznNLrehbf0HJVXdfby9nAZusKuk2KT/Sco8NKxIXlbIAx2717
|
||||||
LgewUdIO8E0dk69vubosy+25JDA2bYNuFeJnOsZovxLjhbkkwEZZXl4+0QfOvfl2Ogg4O5cFNl1dFE9N
|
94n+wDmQb9R1fXY5H9gsuaqelFN8p+fcHFqu6/5cKucDbIC2bR+aq/hyz0IcWNKt/ubBVshVfVFOcefo
|
||||||
4/B7Q+Oyj7mh/VzKZQE2UtM0j6iL+LWOidizhN3OPBiHuigvSmPwrvVjsn9pQnh1LguwGQa3Fo3fHp6M
|
OTm8tCm9opwPsIEO3lo0vlEuxgHm7u5mK+V8YCMsLy+flKv4y57zcJBpU3xBJwe2wMEHBc32/cWPOlW8
|
||||||
Pcw97c1WcllgQy0tLZ2UDr7/qmMc9jJNiF/WkwNjMHhQ0GzfX/yIU8RLfRCxkdq+kzTfrugcf/3MgZ1l
|
1R9EbKSud5JTunzk3Btu9u+s66eUcwI2SfeEsRzxDz2Lc4i5UjmQjdCm9FjvuJWp/6icE7D5TmhS/Nno
|
||||||
+fRcHmCztU8Yq2P8h47J2cdcpTmQjdCE8IQ0vnzjdkjKP8nlAcZoWxXin3dP0n4l1eGb9UL92FwXOG51
|
Ah1emhRfy4v5UeWA4Hjlqn5JTnFHea4NOd2dSbs/d8pZAVukTenXFJO6pFvbxfpZ5XzgGJ3QPZly9Pwa
|
||||||
Ub48ja09w2Otz2nvTJpKs21QIWDs0lnKb6TJqTEphN3NQvncXBY4VtvSju4N3WOs17l6cXHxoblGwKRo
|
fK5aWlp6UDksYIt11+RySjf2LNqhZV+b0qvK+cDR2DW/64yc4rKe82rouSwiTivnBUyIXVXV5BT/1bN4
|
||||||
r8mlHeAtHZO2b9mfDohem8sCR2XX3K4z0hj65NCYklSTGONpuUzApNlVFFWaqP81NHF7mvD2tnM7lwbu
|
B5j0pq65Xc4I7kn38Kmc4uuj59Kw06T6zT7vD1NAOXBt6ityzmeWM4JSjnj+wYdPlefQkJP2NlVcXM4K
|
||||||
V/vwqTR2vrV+LPU7VSjf4ff+MAU0B65NeWVd12fm0sBhpTnzosHDp7rGUV8T9lVFvDiXCJgSrmEezDea
|
mGyuYR7OV9uqemQ5IDhkWxvx6u6jbT3nzoDTXU5MP1MOC5gSyoGruaWpml8s58OwtW17qnfLRtOk+ExE
|
||||||
onhMrgsM25rmyuvSODkwNG56nvZyYvi5XCNg2mgOXM3tVVH9ci4L3KtpmlN9W7Y+VYhfiEkuEzCt8n3L
|
RDkvYMocum/598pFPsDs83YmK+q6XuruZtdzngw975yfnz+lnBcwpZQD1yb9lULTsHXvBuUU/zt6bgw6
|
||||||
fzA8yXuY/b7OZEVZlovt3ew6xknf8965ublTcpmAaac5cG3C2zQ09Vv7bVAaC/+7fmz0Og6QYVZpDlyT
|
fkGGWaUcuCYRH+8erFTOiJm3rXuRO/gciZ7zYqBpU/ygruqfK4cFzBblwMP5ys6UHlEOiNnU3cAmp/j7
|
||||||
GD/dPlgpl4b+2Nru5NIYuGfdmOhxmhB/VBblL+QaATNKc+DBfH1nCI/OdWHGtTewSdv874fGgIT4xfYb
|
nvNg6Pls9w5hOS9gRikHrubmJqVnlPNhthx6gqZLYGUi/u7s7dsfUM4LmHHKgavZl6v4zXI+zIYc8fM5
|
||||||
wlwmYNZpDlzNbVUIz85lYUblJ2i6BDacGP/u7O3bH5zLBPSF5sDV7K+L+Nu5LMyYtJP7xbSNfzy0zfue
|
xQ97jvuQs797J7C7JFLOCxgI5cA1ibhEOXCmrFzv3zdyrIedm9uIXyqHBQyQcuDhdE86c7/z6de9rd29
|
||||||
A+03gak8WwdVAnpHc+CaxHiJ5sCZsnK9f/+6bd3v3JZ2/r+SawT0mebAg0kfjB93v/Pp136t3X693bWN
|
vV0eX4kv6b0AJeXA1aRrI+KsckBMh5zzYk71p0eP69BT/1PTND9VzgvgAOXAg+k+FuU2qNPn4BMx9VqK
|
||||||
e56v6nsBhmkOXE24Ph0EnJXrwpSp63qhDuXnu7dtn1P+U1VVP5PLBHAozYGDtD+LchvU6TN4Iqa+lqGs
|
rFzvv085L4AjKAeuJO3NqX5lOR8mU67qi3KKu0aP45CTbm1Sek45K4B7pBy4JhGXnDc3d99yRkyGiDg5
|
||||||
XO8/YVAlgMPQHLiSsC+dNb0ml4UJVxflRWm73b1+O/Y5YXcVwvNziQDun+bANYnxkvO2bHlALg0TJsZ4
|
V/HWkeM2+KRr26paLucFcK+UAw+nqeLDyoGTZ9fCwo62ik+Wx0viQ1VVnV7OC+BYKAeupIovdw+QKQfE
|
||||||
cl3ESzu3Xa8Trm+KYimXCeDIaQ48mKqIH9McOHl2zc/vaIr42a5t1vN8tCiK03OZAI6J5sCVFPFr7QNk
|
1jh0qeo7I8dp2Fm53n9COS+A46IceDCHyoHnl/Nhcx263j/483FtmhS3tVX9vHJWAOumHLiStLdN6RXl
|
||||||
cl0Ys3yp6nvrtlO/s3K9f9ugSgDHSXPgILk58PxcFsYkX+93J8s1qUK8oynKF+YSAYyO5sCVhH3pgOjV
|
fNh4bdveL6f0ptFjMvBUcX2uqt3lvADGRjlwTSLe4K3WzbO0uDifU/zHyHGQf885n1nOC2DslAOPyIfc
|
||||||
uSxsoqZpHpjq//bu7dLjFPHGND+Xc5kARk9z4JrE+JZUEl+1bpLFhYW5VPf/WLcd5N/ruj4zlwlg42gO
|
XGXjtSk9Lqe4rmf+w47bVwNbQDlwNenzSynV5YAYj7aqX5RT3D4690Hnjhzx0nJWAJtGOXA1N7URP13O
|
||||||
PCQfdXOVjdeE8MRU6xuGai9uXw2MgebA1YTrFkMoc10YsaYoX5rqfOf6uvc6e9LO/xW5RACbT3Pgam5N
|
h+PX3XvBL5l9Sd9sFpsnlPMC2HTKgau509/KxmPX/K4zcorLemY88KTL67reXs4LYMsoB67JwXKg+64f
|
||||||
B0Q/m8vCCLT3XnCQ2ZXwnWqhenIuE8D4aA5czV3OykZj19yuM1I9PzlUXwnhirIst+cyAYyf5sA1GTQH
|
p50Rj8kpvj4y16HH9X5gUikHHpEPtm17ajkjfrIc8YKc4sc98xxy9nSX2spZAUwa5cCVRHwuIqIcEL2c
|
||||||
uu/6MdoZ4+NTHb+1rq59j+v9wKTSHHhIPtI0zam5NByhNH5enGr306Fa9j1720ttuUQAE0tz4Epi/FJM
|
N/25oY04txwWwMRSDlxJurF7RG05Hw5bWFh4cBvxkdHZDT5XppQeXs4LYOIpB65mT67ql5TzYW6uWWge
|
||||||
cl24b8ZNd25KdTk31whg8mkOXEm4pX1EbS4LHebn5x+WdnIf765fr3NVCOFRuUwA00Nz4Gr21kX58lwW
|
nVN8tWdmw07EJcvLyyeV8wKYGsqBa6IceIS2qp+ZU9w8MqdBJ+1tqri4nBXAVFIOPCLvPXv79geUMxqY
|
||||||
1qjmq8el+nxjqF4S4yVLS0sn5TIBTB/NgWuiOfAQTVE+J9XltnV16nXCvqqIF+cSAUw3zYGH5INnb9/+
|
bd2LXE5xd898hpzvtxHnlcMCmHZKXofz2aZpqnJAQ7C0tPSgnOJ9PTMZeq6u6zqV8wKYGcqBq/l2Xdfn
|
||||||
4Fyavtra7uRSLe4Zqk3f88MmxvNyjQBmhiavg/liVVVFrkuvLC4uPjSt/4eG6iEhXlOWZchlApg9mgNX
|
lPOZZc1CszOn+J+eWQw6bar/ZmFh4f7lvABmjnLgavZ097kv5zOLmpSenlP8qGcGA47r/cAAKQeuZn93
|
||||||
c3P6wD8nl6UXqvlqZ1rv/xmqQ+/ThPJv5ufnH5TLBDC7NAeuZm97n/tclplWhfCstL4/GVr/nsf1fqCH
|
aWSGy4Gu9/fnpqaqLiiHBTAIyoGH06T07vn5+VPKGU2z7vi2qX5Pua9DT5viGk+PBFAOXE2T4jOzUg5s
|
||||||
NAeu5kB7aSSVZFabA13v786tVVFckGsE0C+aAw8mnSG/f25u7pRcmpnQbt8mlB/oWt8+pwnxWk+PBNAc
|
Fxdz95jkch8l3jlrv+gBrIty4GpumPZHvbYRT8spftizb0POvkPX+7eV8wIYPOXA1dzRpPTCcj7TIFf1
|
||||||
uJoqxC/MSnNgs7BQ1yFc17WePc97Z+1AD+C4aA5czU3T/qjXdED3zLQePx5ar75nf77ev3VQJQBWaQ5c
|
RV25rWefBps2xQ/aun5qOSsA1lAOXM1KOXAq/sYYESfniLf17MewE/G57pwu5wVAD+XANYn420m/Ztzu
|
||||||
zZ4qhJfkskyVuigvapvbOtapt2lC/FFTls/IJQKgi+bA1aw0B07FGWOM8eQ6xnd1rEe/E+OX2jGdywTA
|
aBdySp8a2faBp4l4v0dCAxw75cDDubp7kS0HNAnqxfrJOcV3e7Z5yJn1j3YCbDzlwNV8K1fV7nI+W+ng
|
||||||
fdEcuCYx/u2kXzNudjTz6az/c53L3+NUMX7YI6EBjp7mwIO5pt3J5rpMlHKhfFpavu8PLW/fM+s/7QTY
|
9f64q2dbh5xbcsSF5awAOA7KgQfTpLgtp/Tscj6brW3b+7Up3lJun8SXdqb0iHJeAKyDcuBqureXX71V
|
||||||
eJoDV/PduiiWc1kmwuB6f7x7aDn7ntvrGC/MJQLgeGgOHKQK8Y46hOflsoxN0zQPbEJ8Z9cy9jxf3RnC
|
5cClxcX5JsUnerZr6PlARJxWzguAMVAOXJMq3rXZD5DJKT2xe4jRyLYMO673A2wS5cDDuaqu6+3lgDbC
|
||||||
o3OZABgFzYGrab9efl0qyViaAxcXFubSgchnOpar77k8xnhaLhMAo6Q5cE2K+L7NfoBMHcJT0nvfvG5Z
|
oev9uhhHJN3apPTcclYAbCDlwJWkb7YpPa6cz7icNzd3X79w9SVdmxfzo8p5AbAJlANXkm7diOb5rvld
|
||||||
+h3X+wE2iebAg7m6LMvtuS4bKl/v14txSMLuKoQX5BIBsBk0B64kfCfV4om5LCN33pYtD3DA1ZVwfb1Q
|
Z+QU/zb68wafD1VVdXo5LwA2kXLgalbKgWPRpvTYnOIbPT9nyFm53n9COS8AtoBy4BG5tLstbzmjY9E9
|
||||||
PzaXCYDNpDlwJWH3RnSe75rbdUZ6/X9b/369z0eLojg9lwmAcdAcuJqV5sCRaEJ4QnrNbw+9R9+zcr1/
|
hyCnuL3new85d7RV/eJyVgBsPeXAw7nyOMuBZtiXKq6ftJswAVBoUnqZcmCXA+XAx5bzuSdn7djxkJzS
|
||||||
26BKAIyV5sBDcll7W95cmmPSPocgvc6dQ6/b9+xpivJluUQATBDNgQdz1TE2B6phV4p446TdhAmAIens
|
v4x+n2GnqeJjOeczy3kBMIGUA1eSbm0X62eV8ynVdX12k+Jro18/8ERcsnv37hPLeQEwwZQDV7OvqeLi
|
||||||
9ZXpQ1tz4KA58Am5LPfrrB07Hp7+zr90v1Z/UxXxU3Vdn5nLBMAk0xy4krC7WSifm8tyWGVZnl2F+M3u
|
cj4rcsTzD95ieOTrhpw7csRLy1kBMCWUAw+nSfWbl5eXT1oznm3dpwa6Znv53w4836rr+pw1cwJgSim2
|
||||||
1+hxYrxkeXn5xFwmAKaB5sDV7E9nsRfnsqyTdnIvGtxiuPPv9jV7Ul1ekUsEwLTRHHgwVSjfsbS0dFIu
|
raa+orue3T2j3i9GfUmXR8TDyhMIgCnmzoGr+cqBu9iN/v+DTpPqN7reDzCjlAOlJ3vaVL+8PFcAmDHK
|
||||||
TWtr+6uB9P8ODP/Znue7ZVmek2sEwBTT2Laa8sr2enb7jHoHRl0JV8QYH5nHDQCzwJ0DV/P1tKO7vuO/
|
gbImN7QR55bnCAAzSjlQupslpZQeXp4bAMw+5cDBJr19vbdLBmDKuXPgkJL2/qR7IgAwMMqBQ0i6Mad0
|
||||||
9zpVKN/qej/AjNIcKB3Z24TyVXmIADCrNAfKmtzUxHhuHhoAzDrNgZJyVQjhUXlIANAjmgN7m/Du471d
|
fnnsARg45cCZztV1XafymAPAAcqBs5c2xTsWFhbuXx5rACgpB85EXO8H4DgoB051bmqq6oLymALAUVEO
|
||||||
MgBTzp0D+5Sw777uiQBAz2gO7EPCLSnn500OAAOaA2c615RlGfKmBoBDaQ6cvTQhvmd+fv5BeRMDwGFp
|
nL60Ka5ZSqkujyUAHBPlwClKFe+an58/pTyGAHBclAMnPvsOXe/fVh47AFgv5cAJTJviB21dP7U8WAAw
|
||||||
DpyJuN4PwDHQHDjVubUqigvypgSAo6M5cPrShHjtYghl3oQAcGw0B05Rivi+ubm5U/KmA4Djozlw4rM/
|
VsqBE5UvRsRZ5TECgA2hHLj1aSLe37btqeWxAYANpRy4ZdnfXYqZm5u7T3lMAGBTKAduem7JEReWxwEA
|
||||||
X+/fOthiADA6mgMnME2IP2rK8hl5GwHAxtAcOFH5SozxrLxpAGBjaQ4cf6oYP9w0zal5kwDA5tAcOLYc
|
toJy4Gakii+3VfXIcvgAsKWUAzc0H4iI08qZA8BEUA4ce1zvB2A6KAeOK+nWJqXnlvMFgImlHLjepGvz
|
||||||
aC/FpE1wwmBLAMAm0xy46bk91fvCXH4AGCvNgZuRIn6tKYrH5JoDwGTQHLihuTzGeFouNQBMFs2BI4/r
|
Yn5UOVcAmAbKgceTKv65qqrTy2ECwFRRDjyGRLyh+8WpnCEATCXlwHvNHbmqX1LODQCmnnLgPaSK65vF
|
||||||
/QBMB82Bo0rYXYXwglxWAJh8mgOPN+H6eqF+bC4nAEwVzYHHkiL+c1EUp+caAsB00hx4FInxLalk2waV
|
5vHlvABgZigHHpmmio/lnM8s5wQAs0g5sEvEJbt37z6xHA4AzLQBlwP3NBG/Ws4DAAZjgOXAb9V1fU45
|
||||||
A4AppznwfrOnLsqX53IBwOzQHHiYFPHGaqF6Ui4TAMwezYGHpirip+q6PjOXBwBmmubANjFesry8fGKu
|
BwAYnOGUA+srIuJh5f4DwGDNfDkw4pLl5eWTyv0GAGazHLinTfXLyx0FAAozVA68oY04t9w/AOAeTH85
|
||||||
CQD0Q4+bA/dWMf56LgMA9E8PmwO/W5blOXn1AaC/+tMcWF4ZY3xkXm0AYOabA2O8ZGlp6aS8ugDAGrPY
|
sP500zRVuV8AwL2Y1nJgk9JfLyws3L/cHwDgKE1XOTDtbaq4uNwHAOD4TEE5MN2YUzq/3HAAYJ0muBx4
|
||||||
HLi3CeWr8voBAIczQ82BN6UDmnPzagEA92f6mwPLz1dVVeTVAQCO1LQ2B1Yh/PX8/PyD8moAAEdrupoD
|
dV3XqdxeAGBMJrAceOn8/Pwp5XYCAGM2IeXAfa73A8Am2+Jy4E1N1fxsuU0AwOY4IUe8NqfY3/MivSFp
|
||||||
w76qiBfnRQcAjtMUNAeGW1LOz8sLAIzKBDcHXlOWZciLCQCM2gQ2B142Nzd3Sl48AGCjTEhz4H7X+wFg
|
U1wTEVFuCACwydqqfmZO8Z3yxXrc6T7f73o/AEyQiDgtp/QXG/EpgTbFF3JKv1D+TABgQnQfx2ur+POc
|
||||||
k425OfDWqqh+Pi8KALDJtqWDgDemHfKBoR30hqUJ8dqY5PcHAMalKcrnpJ3z94Z31qNO+/t+1/sBYIKk
|
4kflC/kx5u6c4l+blF7YXWoofw4AMIG6W/G2i/Wzckp/lVP896EX9PJFvkh3M5/6o03E7+acF8vvCQBM
|
||||||
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="TT_MAIN.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
<metadata name="TT_MAIN.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
@@ -248,115 +246,113 @@
|
|||||||
<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
|
||||||
wwAADsMBx2+oZAAAAFFJREFUOE9joAr49u3bf1Lw169f50O1QgBI0MnJCY4/vP8Ix8hiILqtrQ3TEFIM
|
vAAADrwBlbxySQAAAEhJREFUOE9jYKAG+Pbt239S8NevX+djGODk5ATHH95/hGNkMRDd1taGaQgpBiAb
|
||||||
AGGYIVDtpBsAwkQbgIyR1dDWAGLwqAGD0gByMFQ7JYCBAQChNviRiQ8ETwAAAABJRU5ErkJggg==
|
QrYBIEy0AdgMo70BxOBRAwalAeRguAGUAAChNviRcuLCdwAAAABJRU5ErkJggg==
|
||||||
</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/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
|
||||||
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAeElE
|
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsMAAALDAE/QCLIAAAAd0lE
|
||||||
QVQ4T2P4//8/RRhMFHQfKgDi/yAaXQEhDCZAmkNbnvyXta4CciESLEws//FhmDqYAQUgzUBMngsowVgF
|
QVQ4T2P4//8/AyUYTBR0Hyoo6D70H0SjKyCEYQb8D2158l/Wuuo/TIKFieU/PoxuQAFIs6x1FXkuoARj
|
||||||
ScFgYjQQsUsQi8FEYsXyAiD+D6LRFRDCYAKk2bPo6H9J40wgFyKBLeCQMUwdzIACkGYgHnKB+J8BAD5Q
|
CJCKwcRoIGIKkoLBRGLF8oLEiuX/QTS6AkIYZsB/z6Kj/yWNM8kLRJDNIM2SxpnkuYASjCFAKgYAPlC2
|
||||||
tqhi4tzWAAAAAElFTkSuQmCC
|
qCS4LQgAAAAASUVORK5CYII=
|
||||||
</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
|
vAAADrwBlbxySQAAAHpJREFUOE+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>
|
||||||
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="LB_SEP_1.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
<metadata name="LB_SEP_1.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
@@ -383,122 +379,122 @@
|
|||||||
<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
|
vAAADrwBlbxySQAAAHpJREFUOE+1kVEKgDAMQ3e2/e+MXqpn6W/HxM7SpkIVB4HxSMKiTUTaFwVQ1X25
|
||||||
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
|
DjMfSxskHBYsAxHJkjUjHgrUNMY4peaMPxb03rcZMVhgn2oDKAwn+L0aROH/Cny4NAGFSx8x+10ZDwV2
|
||||||
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
|
gt+LOCxQsw1nPBS8VQBVTTzyhrdZSUm7AAAAAElFTkSuQmCC
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<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>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
|
vAAADrwBlbxySQAAAHpJREFUOE+1kVEKgDAMQ3e2/e+MXqpn6W/HxM7SpkIVB4HxSMKiTUTaFwVQ1X25
|
||||||
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
|
DjMfSxskHBYsAxHJkjUjHgrUNMY4peaMPxb03rcZMVhgn2oDKAwn+L0aROH/Cny4NAGFSx8x+10ZDwV2
|
||||||
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
|
gt+LOCxQsw1nPBS8VQBVTTzyhrdZSUm7AAAAAElFTkSuQmCC
|
||||||
</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
|
||||||
wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP
|
vAAADrwBlbxySQAAARlJREFUOE+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="ActionButton10.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ActionButton10.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
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
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ActionButton11.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ActionButton11.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
|
vAAADrwBlbxySQAAAHpJREFUOE+1kVEKgDAMQ3e2/e+MXqpn6W/HxM7SpkIVB4HxSMKiTUTaFwVQ1X25
|
||||||
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
|
DjMfSxskHBYsAxHJkjUjHgrUNMY4peaMPxb03rcZMVhgn2oDKAwn+L0aROH/Cny4NAGFSx8x+10ZDwV2
|
||||||
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
|
gt+LOCxQsw1nPBS8VQBVTTzyhrdZSUm7AAAAAElFTkSuQmCC
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ActionButton12.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ActionButton12.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP
|
vAAADrwBlbxySQAAARlJREFUOE+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="ActionButton13.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ActionButton13.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
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
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ActionButton14.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ActionButton14.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
|
vAAADrwBlbxySQAAAHpJREFUOE+1kVEKgDAMQ3e2/e+MXqpn6W/HxM7SpkIVB4HxSMKiTUTaFwVQ1X25
|
||||||
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
|
DjMfSxskHBYsAxHJkjUjHgrUNMY4peaMPxb03rcZMVhgn2oDKAwn+L0aROH/Cny4NAGFSx8x+10ZDwV2
|
||||||
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
|
gt+LOCxQsw1nPBS8VQBVTTzyhrdZSUm7AAAAAElFTkSuQmCC
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ActionButton15.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ActionButton15.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP
|
vAAADrwBlbxySQAAARlJREFUOE+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="ActionButton16.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ActionButton16.BackgroundImage" 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="ActionButton17.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ActionButton17.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
|
vAAADrwBlbxySQAAAHpJREFUOE+1kVEKgDAMQ3e2/e+MXqpn6W/HxM7SpkIVB4HxSMKiTUTaFwVQ1X25
|
||||||
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
|
DjMfSxskHBYsAxHJkjUjHgrUNMY4peaMPxb03rcZMVhgn2oDKAwn+L0aROH/Cny4NAGFSx8x+10ZDwV2
|
||||||
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
|
gt+LOCxQsw1nPBS8VQBVTTzyhrdZSUm7AAAAAElFTkSuQmCC
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
</root>
|
</root>
|
||||||
@@ -465,6 +465,9 @@ Namespace API.YouTube.Controls
|
|||||||
TXT_FILE.Text = f
|
TXT_FILE.Text = f
|
||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
|
Private Sub BTT_TRIM_Click(sender As Object, e As EventArgs) Handles BTT_TRIM.Click
|
||||||
|
Using f As New VideoOptionsTrimForm(MyContainer) : f.ShowDialog() : End Using
|
||||||
|
End Sub
|
||||||
Private Sub TXT_SUBS_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As ActionButtonEventArgs) Handles TXT_SUBS.ActionOnButtonClick
|
Private Sub TXT_SUBS_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As ActionButtonEventArgs) Handles TXT_SUBS.ActionOnButtonClick
|
||||||
Select Case Sender.DefaultButton
|
Select Case Sender.DefaultButton
|
||||||
Case ADB.Open
|
Case ADB.Open
|
||||||
|
|||||||
166
SCrawler.YouTube/Controls/VideoOptionsTrimForm.Designer.vb
generated
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
' 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 VideoOptionsTrimForm : 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()
|
||||||
|
Me.components = New System.ComponentModel.Container()
|
||||||
|
Dim CONTAINER_MAIN As System.Windows.Forms.ToolStripContainer
|
||||||
|
Dim TP_MAIN As System.Windows.Forms.TableLayoutPanel
|
||||||
|
Dim TP_OPTIONS As System.Windows.Forms.TableLayoutPanel
|
||||||
|
Dim TT_MAIN As System.Windows.Forms.ToolTip
|
||||||
|
Me.LIST_TRIM = New System.Windows.Forms.ListBox()
|
||||||
|
Me.CH_DEL_ORIG = New System.Windows.Forms.CheckBox()
|
||||||
|
Me.CH_ADD_M3U8 = New System.Windows.Forms.CheckBox()
|
||||||
|
Me.CH_SEP_FOLDER = New System.Windows.Forms.CheckBox()
|
||||||
|
CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer()
|
||||||
|
TP_MAIN = New System.Windows.Forms.TableLayoutPanel()
|
||||||
|
TP_OPTIONS = New System.Windows.Forms.TableLayoutPanel()
|
||||||
|
TT_MAIN = New System.Windows.Forms.ToolTip(Me.components)
|
||||||
|
CONTAINER_MAIN.ContentPanel.SuspendLayout()
|
||||||
|
CONTAINER_MAIN.SuspendLayout()
|
||||||
|
TP_MAIN.SuspendLayout()
|
||||||
|
TP_OPTIONS.SuspendLayout()
|
||||||
|
Me.SuspendLayout()
|
||||||
|
'
|
||||||
|
'CONTAINER_MAIN
|
||||||
|
'
|
||||||
|
'
|
||||||
|
'CONTAINER_MAIN.ContentPanel
|
||||||
|
'
|
||||||
|
CONTAINER_MAIN.ContentPanel.Controls.Add(TP_MAIN)
|
||||||
|
CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(434, 236)
|
||||||
|
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(434, 261)
|
||||||
|
CONTAINER_MAIN.TabIndex = 0
|
||||||
|
'
|
||||||
|
'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(Me.LIST_TRIM, 0, 1)
|
||||||
|
TP_MAIN.Controls.Add(TP_OPTIONS, 0, 0)
|
||||||
|
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 = 2
|
||||||
|
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 30.0!))
|
||||||
|
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
|
TP_MAIN.Size = New System.Drawing.Size(434, 236)
|
||||||
|
TP_MAIN.TabIndex = 0
|
||||||
|
'
|
||||||
|
'LIST_TRIM
|
||||||
|
'
|
||||||
|
Me.LIST_TRIM.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.LIST_TRIM.FormattingEnabled = True
|
||||||
|
Me.LIST_TRIM.Location = New System.Drawing.Point(3, 33)
|
||||||
|
Me.LIST_TRIM.Name = "LIST_TRIM"
|
||||||
|
Me.LIST_TRIM.Size = New System.Drawing.Size(428, 200)
|
||||||
|
Me.LIST_TRIM.TabIndex = 0
|
||||||
|
'
|
||||||
|
'TP_OPTIONS
|
||||||
|
'
|
||||||
|
TP_OPTIONS.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single]
|
||||||
|
TP_OPTIONS.ColumnCount = 3
|
||||||
|
TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333!))
|
||||||
|
TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33334!))
|
||||||
|
TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33334!))
|
||||||
|
TP_OPTIONS.Controls.Add(Me.CH_DEL_ORIG, 0, 0)
|
||||||
|
TP_OPTIONS.Controls.Add(Me.CH_ADD_M3U8, 1, 0)
|
||||||
|
TP_OPTIONS.Controls.Add(Me.CH_SEP_FOLDER, 2, 0)
|
||||||
|
TP_OPTIONS.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
TP_OPTIONS.Location = New System.Drawing.Point(3, 3)
|
||||||
|
TP_OPTIONS.Name = "TP_OPTIONS"
|
||||||
|
TP_OPTIONS.RowCount = 1
|
||||||
|
TP_OPTIONS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
|
TP_OPTIONS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 23.0!))
|
||||||
|
TP_OPTIONS.Size = New System.Drawing.Size(428, 24)
|
||||||
|
TP_OPTIONS.TabIndex = 1
|
||||||
|
'
|
||||||
|
'CH_DEL_ORIG
|
||||||
|
'
|
||||||
|
Me.CH_DEL_ORIG.AutoSize = True
|
||||||
|
Me.CH_DEL_ORIG.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.CH_DEL_ORIG.Location = New System.Drawing.Point(4, 4)
|
||||||
|
Me.CH_DEL_ORIG.Name = "CH_DEL_ORIG"
|
||||||
|
Me.CH_DEL_ORIG.Size = New System.Drawing.Size(135, 16)
|
||||||
|
Me.CH_DEL_ORIG.TabIndex = 0
|
||||||
|
Me.CH_DEL_ORIG.Text = "Delete original file"
|
||||||
|
TT_MAIN.SetToolTip(Me.CH_DEL_ORIG, "If checked, the original file will be deleted after trimming")
|
||||||
|
Me.CH_DEL_ORIG.UseVisualStyleBackColor = True
|
||||||
|
'
|
||||||
|
'CH_ADD_M3U8
|
||||||
|
'
|
||||||
|
Me.CH_ADD_M3U8.AutoSize = True
|
||||||
|
Me.CH_ADD_M3U8.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.CH_ADD_M3U8.Location = New System.Drawing.Point(146, 4)
|
||||||
|
Me.CH_ADD_M3U8.Name = "CH_ADD_M3U8"
|
||||||
|
Me.CH_ADD_M3U8.Size = New System.Drawing.Size(135, 16)
|
||||||
|
Me.CH_ADD_M3U8.TabIndex = 1
|
||||||
|
Me.CH_ADD_M3U8.Text = "Add to M3U8"
|
||||||
|
TT_MAIN.SetToolTip(Me.CH_ADD_M3U8, "If checked, the trimmed files will be added to the M3U8 playlist (if selected)")
|
||||||
|
Me.CH_ADD_M3U8.UseVisualStyleBackColor = True
|
||||||
|
'
|
||||||
|
'CH_SEP_FOLDER
|
||||||
|
'
|
||||||
|
Me.CH_SEP_FOLDER.AutoSize = True
|
||||||
|
Me.CH_SEP_FOLDER.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.CH_SEP_FOLDER.Location = New System.Drawing.Point(288, 4)
|
||||||
|
Me.CH_SEP_FOLDER.Name = "CH_SEP_FOLDER"
|
||||||
|
Me.CH_SEP_FOLDER.Size = New System.Drawing.Size(136, 16)
|
||||||
|
Me.CH_SEP_FOLDER.TabIndex = 2
|
||||||
|
Me.CH_SEP_FOLDER.Text = "Separate folder"
|
||||||
|
TT_MAIN.SetToolTip(Me.CH_SEP_FOLDER, "Place the trimmed files in a separate folder")
|
||||||
|
Me.CH_SEP_FOLDER.UseVisualStyleBackColor = True
|
||||||
|
'
|
||||||
|
'VideoOptionsTrimForm
|
||||||
|
'
|
||||||
|
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
|
||||||
|
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
|
||||||
|
Me.ClientSize = New System.Drawing.Size(434, 261)
|
||||||
|
Me.Controls.Add(CONTAINER_MAIN)
|
||||||
|
Me.KeyPreview = True
|
||||||
|
Me.MinimizeBox = False
|
||||||
|
Me.MinimumSize = New System.Drawing.Size(450, 300)
|
||||||
|
Me.Name = "VideoOptionsTrimForm"
|
||||||
|
Me.ShowIcon = False
|
||||||
|
Me.ShowInTaskbar = False
|
||||||
|
Me.Text = "Trimming options"
|
||||||
|
CONTAINER_MAIN.ContentPanel.ResumeLayout(False)
|
||||||
|
CONTAINER_MAIN.ResumeLayout(False)
|
||||||
|
CONTAINER_MAIN.PerformLayout()
|
||||||
|
TP_MAIN.ResumeLayout(False)
|
||||||
|
TP_OPTIONS.ResumeLayout(False)
|
||||||
|
TP_OPTIONS.PerformLayout()
|
||||||
|
Me.ResumeLayout(False)
|
||||||
|
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Private WithEvents LIST_TRIM As ListBox
|
||||||
|
Private WithEvents CH_DEL_ORIG As CheckBox
|
||||||
|
Private WithEvents CH_ADD_M3U8 As CheckBox
|
||||||
|
Private WithEvents CH_SEP_FOLDER As CheckBox
|
||||||
|
End Class
|
||||||
|
End Namespace
|
||||||
135
SCrawler.YouTube/Controls/VideoOptionsTrimForm.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_OPTIONS.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</metadata>
|
||||||
|
<metadata name="TT_MAIN.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>
|
||||||
|
</root>
|
||||||
167
SCrawler.YouTube/Controls/VideoOptionsTrimForm.vb
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
' Copyright (C) Andy https://github.com/AAndyProgram
|
||||||
|
' This program is free software: you can redistribute it and/or modify
|
||||||
|
' it under the terms of the GNU General Public License as published by
|
||||||
|
' the Free Software Foundation, either version 3 of the License, or
|
||||||
|
' (at your option) any later version.
|
||||||
|
'
|
||||||
|
' This program is distributed in the hope that it will be useful,
|
||||||
|
' but WITHOUT ANY WARRANTY
|
||||||
|
Imports PersonalUtilities.Forms
|
||||||
|
Imports PersonalUtilities.Forms.Toolbars
|
||||||
|
Imports SCrawler.API.YouTube.Objects
|
||||||
|
Imports SCrawler.API.YouTube.Base
|
||||||
|
Imports ETC = PersonalUtilities.Forms.Toolbars.EditToolbar.ControlItem
|
||||||
|
Namespace API.YouTube.Controls
|
||||||
|
Friend Class VideoOptionsTrimForm
|
||||||
|
#Region "Declarations"
|
||||||
|
Private WithEvents MyDefs As DefaultFormOptions
|
||||||
|
Private ReadOnly Property MyMedia As YouTubeMediaContainerBase
|
||||||
|
Private ReadOnly Property TrimData As List(Of TrimOption)
|
||||||
|
Private WithEvents BTT_CLEAR_ALL As ToolStripButton
|
||||||
|
Private WithEvents BTT_CHAPTERS As ToolStripButton
|
||||||
|
#End Region
|
||||||
|
#Region "Initializer"
|
||||||
|
Friend Sub New(ByRef Media As YouTubeMediaContainerBase)
|
||||||
|
InitializeComponent()
|
||||||
|
MyDefs = New DefaultFormOptions(Me, MyYouTubeSettings.DesignXml)
|
||||||
|
MyMedia = Media
|
||||||
|
TrimData = New List(Of TrimOption)
|
||||||
|
TrimData.ListAddList(Media.TrimOptions)
|
||||||
|
BTT_CLEAR_ALL = New ToolStripButton("Clear", PersonalUtilities.My.Resources.DeletePic_Red_24) With {
|
||||||
|
.DisplayStyle = ToolStripItemDisplayStyle.ImageAndText,
|
||||||
|
.BackColor = MyColor.DeleteBack,
|
||||||
|
.ForeColor = MyColor.DeleteFore
|
||||||
|
}
|
||||||
|
BTT_CHAPTERS = New ToolStripButton("Chapters") With {.DisplayStyle = ToolStripItemDisplayStyle.Text, .Enabled = Media.Chapters.Count > 0}
|
||||||
|
End Sub
|
||||||
|
#End Region
|
||||||
|
#Region "Form handlers"
|
||||||
|
Private Sub VideoOptionsTrimForm_Load(sender As Object, e As EventArgs) Handles Me.Load
|
||||||
|
With MyDefs
|
||||||
|
.MyViewInitialize()
|
||||||
|
.AddOkCancelToolbar()
|
||||||
|
.AddEditToolbar({ETC.Add, ETC.Edit, ETC.Delete, BTT_CLEAR_ALL, ETC.Separator, BTT_CHAPTERS})
|
||||||
|
|
||||||
|
Refill()
|
||||||
|
|
||||||
|
With MyMedia
|
||||||
|
If Not .TrimOptionsSet Then
|
||||||
|
With MyYouTubeSettings
|
||||||
|
CH_DEL_ORIG.Checked = .TrimDeleteOriginalFile
|
||||||
|
CH_ADD_M3U8.Checked = .TrimAddTrimmedFilesToM3U8
|
||||||
|
CH_SEP_FOLDER.Checked = .TrimSeparateFolder
|
||||||
|
End With
|
||||||
|
Else
|
||||||
|
CH_DEL_ORIG.Checked = .TrimDeleteOriginalFile
|
||||||
|
CH_ADD_M3U8.Checked = .TrimAddTrimmedFilesToM3U8
|
||||||
|
CH_SEP_FOLDER.Checked = .TrimSeparateFolder
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
|
||||||
|
.EndLoaderOperations()
|
||||||
|
End With
|
||||||
|
End Sub
|
||||||
|
Private Sub VideoOptionsTrimForm_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed
|
||||||
|
TrimData.Clear()
|
||||||
|
End Sub
|
||||||
|
#End Region
|
||||||
|
#Region "Refill"
|
||||||
|
Private Sub Refill(Optional ByVal DEL As Boolean = False)
|
||||||
|
Dim indx% = _CurrentIndex
|
||||||
|
With LIST_TRIM
|
||||||
|
.BeginUpdate()
|
||||||
|
.Items.Clear()
|
||||||
|
If TrimData.Count > 0 Then
|
||||||
|
TrimData.Sort()
|
||||||
|
.Items.AddRange(TrimData.Cast(Of Object).ToArray)
|
||||||
|
If DEL Then indx -= IIf(indx - 1 < 0, 0, 1)
|
||||||
|
If indx.ValueBetween(0, TrimData.Count - 1) Then
|
||||||
|
.SelectedIndex = indx
|
||||||
|
ElseIf (indx - 1).ValueBetween(0, TrimData.Count - 1) Then
|
||||||
|
.SelectedIndex = indx - 1
|
||||||
|
ElseIf (indx + 1).ValueBetween(0, TrimData.Count - 1) Then
|
||||||
|
.SelectedIndex = indx + 1
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
.EndUpdate()
|
||||||
|
End With
|
||||||
|
End Sub
|
||||||
|
#End Region
|
||||||
|
#Region "Ok"
|
||||||
|
Private Sub MyDefs_ButtonOkClick(ByVal Sender As Object, ByVal e As KeyHandleEventArgs) Handles MyDefs.ButtonOkClick
|
||||||
|
With MyMedia
|
||||||
|
.TrimOptions.Clear()
|
||||||
|
.TrimDeleteOriginalFile = CH_DEL_ORIG.Checked
|
||||||
|
.TrimAddTrimmedFilesToM3U8 = CH_ADD_M3U8.Checked
|
||||||
|
.TrimSeparateFolder = CH_SEP_FOLDER.Checked
|
||||||
|
.TrimOptionsSet = True
|
||||||
|
End With
|
||||||
|
|
||||||
|
If TrimData.Count > 0 Then
|
||||||
|
TrimData.Sort()
|
||||||
|
Dim indx% = 0
|
||||||
|
Dim c%
|
||||||
|
Dim opt As TrimOption
|
||||||
|
Dim dic As New Dictionary(Of String, Integer)
|
||||||
|
For i% = 0 To TrimData.Count - 1
|
||||||
|
opt = TrimData(i)
|
||||||
|
If opt.Name.IsEmptyString Then
|
||||||
|
indx += 1
|
||||||
|
opt.Name = indx
|
||||||
|
Else
|
||||||
|
c = TrimData.LongCount(Function(d) Not d.Name.IsEmptyString AndAlso d.Name = opt.Name)
|
||||||
|
If c > 1 Then
|
||||||
|
If Not dic.ContainsKey(opt.Name) Then dic.Add(opt.Name, 0)
|
||||||
|
dic(opt.Name) += 1
|
||||||
|
opt.Name &= $"_{dic(opt.Name)}"
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
TrimData(i) = opt
|
||||||
|
Next
|
||||||
|
dic.Clear()
|
||||||
|
MyMedia.TrimOptions.AddRange(TrimData)
|
||||||
|
End If
|
||||||
|
|
||||||
|
MyDefs.CloseForm()
|
||||||
|
End Sub
|
||||||
|
#End Region
|
||||||
|
#Region "Edit"
|
||||||
|
Private Sub MyDefs_ButtonAddClick(ByVal Sender As Object, ByVal e As EditToolbarEventArgs) Handles MyDefs.ButtonAddClick
|
||||||
|
Using f As New TrimOptionForm
|
||||||
|
f.ShowDialog()
|
||||||
|
If f.DialogResult = DialogResult.OK AndAlso
|
||||||
|
(TrimData.Count = 0 OrElse Not TrimData.Any(Function(t) t.End = f.MyTrimOption.End And t.Start = f.MyTrimOption.Start)) Then _
|
||||||
|
TrimData.Add(f.MyTrimOption) : Refill()
|
||||||
|
End Using
|
||||||
|
End Sub
|
||||||
|
Private Sub MyDefs_ButtonEditClick(ByVal Sender As Object, ByVal e As EditToolbarEventArgs) Handles MyDefs.ButtonEditClick
|
||||||
|
If _CurrentIndex.ValueBetween(0, TrimData.Count - 1) Then
|
||||||
|
Using f As New TrimOptionForm(TrimData(_CurrentIndex))
|
||||||
|
f.ShowDialog()
|
||||||
|
If f.DialogResult = DialogResult.OK Then TrimData(_CurrentIndex) = f.MyTrimOption : Refill()
|
||||||
|
End Using
|
||||||
|
End If
|
||||||
|
End Sub
|
||||||
|
Private Sub MyDefs_ButtonDeleteClickE(ByVal Sender As Object, ByVal e As EditToolbarEventArgs) Handles MyDefs.ButtonDeleteClickE
|
||||||
|
If _CurrentIndex.ValueBetween(0, TrimData.Count - 1) AndAlso
|
||||||
|
MsgBoxE({$"Are you sure you want to remove the following trim option?{vbCr}{vbCr}{TrimData(_CurrentIndex)}", "Remove trim option"}, vbYesNo + vbExclamation) = vbYes Then _
|
||||||
|
TrimData.RemoveAt(_CurrentIndex) : Refill(True)
|
||||||
|
End Sub
|
||||||
|
Private Sub BTT_CLEAR_ALL_Click(sender As Object, e As EventArgs) Handles BTT_CLEAR_ALL.Click
|
||||||
|
If MsgBoxE({$"Are you sure you want to remove ALL trim options?", "Remove trim option"}, vbYesNo + vbCritical) = vbYes Then TrimData.Clear() : Refill()
|
||||||
|
End Sub
|
||||||
|
Private Sub BTT_CHAPTERS_Click(sender As Object, e As EventArgs) Handles BTT_CHAPTERS.Click
|
||||||
|
Using f As New ChaptersForm(MyMedia, TrimData)
|
||||||
|
f.ShowDialog()
|
||||||
|
If f.DialogResult = DialogResult.OK AndAlso f.MyResult.Count > 0 Then TrimData.ListAddList(f.MyResult, LAP.NotContainsOnly) : Refill()
|
||||||
|
End Using
|
||||||
|
End Sub
|
||||||
|
#End Region
|
||||||
|
#Region "List"
|
||||||
|
Private _CurrentIndex As Integer = -1
|
||||||
|
Private Sub LIST_TRIM_SelectedIndexChanged(sender As Object, e As EventArgs) Handles LIST_TRIM.SelectedIndexChanged
|
||||||
|
_CurrentIndex = LIST_TRIM.SelectedIndex
|
||||||
|
End Sub
|
||||||
|
#End Region
|
||||||
|
End Class
|
||||||
|
End Namespace
|
||||||
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
|
||||||
@@ -54,11 +54,13 @@ Namespace API.YouTube
|
|||||||
Friend ReadOnly DateBaseProvider As New ADateTime(ADateTime.Formats.BaseDateTime)
|
Friend ReadOnly DateBaseProvider As New ADateTime(ADateTime.Formats.BaseDateTime)
|
||||||
Friend ReadOnly DateAddedProvider As New ADateTime(ADateTime.Formats.yyyymmdd) With {.DateSeparator = String.Empty}
|
Friend ReadOnly DateAddedProvider As New ADateTime(ADateTime.Formats.yyyymmdd) With {.DateSeparator = String.Empty}
|
||||||
Friend ReadOnly TimeToStringProvider As IFormatProvider = New TimeToStringConverter
|
Friend ReadOnly TimeToStringProvider As IFormatProvider = New TimeToStringConverter
|
||||||
|
Friend ReadOnly TimeToStringProviderH As IFormatProvider = New TimeToStringConverter(True)
|
||||||
Friend ReadOnly TitleHtmlConverter As Func(Of String, String) = Function(Input) Input.StringRemoveWinForbiddenSymbols().StringTrim()
|
Friend ReadOnly TitleHtmlConverter As Func(Of String, String) = Function(Input) Input.StringRemoveWinForbiddenSymbols().StringTrim()
|
||||||
Friend ReadOnly ProgressProvider As IMyProgressNumberProvider = MyProgressNumberProvider.Percentage
|
Friend ReadOnly ProgressProvider As IMyProgressNumberProvider = MyProgressNumberProvider.Percentage
|
||||||
Public ReadOnly TrueUrlRegEx As RParams = RParams.DM(Base.YouTubeFunctions.TrueUrlPattern, 0, EDP.ReturnValue)
|
Public ReadOnly TrueUrlRegEx As RParams = RParams.DM(Base.YouTubeFunctions.TrueUrlPattern, 0, EDP.ReturnValue)
|
||||||
Friend ReadOnly MusicUrlApply As RParams = RParams.DMS("https://([w\.]*)youtube.com.+", 1, RegexReturn.Replace, EDP.ReturnValue,
|
Friend ReadOnly MusicUrlApply As RParams = RParams.DMS("https://([w\.]*)youtube.com.+", 1, RegexReturn.Replace, EDP.ReturnValue,
|
||||||
CType(Function(input$) "music.", Func(Of String, String)), String.Empty)
|
CType(Function(input$) "music.", Func(Of String, String)), String.Empty)
|
||||||
|
Friend ReadOnly M3U8ExcludedSymbols As String() = {".", ",", ":", "/", "\", "(", ")", "[", "]"}
|
||||||
<Extension> Friend Function ToMusicUrl(ByVal URL As String, ByVal IsMusic As Boolean) As String
|
<Extension> Friend Function ToMusicUrl(ByVal URL As String, ByVal IsMusic As Boolean) As String
|
||||||
Try : Return If(IsMusic And Not URL.IsEmptyString, CStr(RegexReplace(URL, MusicUrlApply)).IfNullOrEmpty(URL), URL) : Catch : Return URL : End Try
|
Try : Return If(IsMusic And Not URL.IsEmptyString, CStr(RegexReplace(URL, MusicUrlApply)).IfNullOrEmpty(URL), URL) : Catch : Return URL : End Try
|
||||||
End Function
|
End Function
|
||||||
@@ -79,11 +81,15 @@ Namespace API.YouTube
|
|||||||
Private Class TimeToStringConverter : Implements ICustomProvider
|
Private Class TimeToStringConverter : Implements ICustomProvider
|
||||||
Private ReadOnly _Provider As New ADateTime("mm\:ss") With {.TimeParseMode = ADateTime.TimeModes.TimeSpan}
|
Private ReadOnly _Provider As New ADateTime("mm\:ss") With {.TimeParseMode = ADateTime.TimeModes.TimeSpan}
|
||||||
Private ReadOnly _ProviderWithHours As New ADateTime("h\:mm\:ss") With {.TimeParseMode = ADateTime.TimeModes.TimeSpan}
|
Private ReadOnly _ProviderWithHours As New ADateTime("h\:mm\:ss") With {.TimeParseMode = ADateTime.TimeModes.TimeSpan}
|
||||||
|
Private ReadOnly ForceHours As Boolean
|
||||||
Private ReadOnly Property Provider(ByVal t As TimeSpan) As IFormatProvider
|
Private ReadOnly Property Provider(ByVal t As TimeSpan) As IFormatProvider
|
||||||
Get
|
Get
|
||||||
Return If(t.Hours > 0, _ProviderWithHours, _Provider)
|
Return If(t.Hours > 0 Or ForceHours, _ProviderWithHours, _Provider)
|
||||||
End Get
|
End Get
|
||||||
End Property
|
End Property
|
||||||
|
Friend Sub New(Optional ByVal ForceHours As Boolean = False)
|
||||||
|
Me.ForceHours = ForceHours
|
||||||
|
End Sub
|
||||||
Private Function Convert(ByVal Value As Object, ByVal DestinationType As Type, ByVal Provider As IFormatProvider,
|
Private Function Convert(ByVal Value As Object, ByVal DestinationType As Type, ByVal Provider As IFormatProvider,
|
||||||
Optional ByVal NothingArg As Object = Nothing, Optional ByVal e As ErrorsDescriber = Nothing) As Object Implements ICustomProvider.Convert
|
Optional ByVal NothingArg As Object = Nothing, Optional ByVal e As ErrorsDescriber = Nothing) As Object Implements ICustomProvider.Convert
|
||||||
If Not IsNothing(Value) Then
|
If Not IsNothing(Value) Then
|
||||||
|
|||||||
@@ -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>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
|
iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
|
||||||
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAVDSURBVEhLjZVtTFNXGMcLQmdHO6AdarLSOcTxXqC3lls3
|
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAV6SURBVEhLjZVrTFNnGMcfT4Wto2dcOtRkyBzigALlcmo5
|
||||||
FeVFihZsqaBjRM2ouILiC0oUozGaaBSTJfuwfdg+bJnJnFuiyzKZMOp8ATJl4IYLAjqspfS9cNlLskjP
|
dVNwXKRowRYEGSNiRi3jXiwQqYEQTVxQkyX7sH3YPmyZicYt0WUXBEaJjkumDNxwQUCHWErpFQ5zSxbo
|
||||||
/qe0OmPZeJJfbu85z/k//z7n3Ht5NPqLimLMSUkfXV20aPiKTPbhOqn0FQxHBSb/J4ZUKvY3mez6yMKF
|
s7xd200Fxz95c9qcc37//3me9wIAAKOZmQGGiIiP+7ZsmewKD/9of1jYywCwkdz7P01Ipexv4eE3pjZv
|
||||||
fReTkw0YigERgUkaAyaT8FZR0ZdDzc1k9OxZ0tHU5L/Csp15ItFSTEfPZIWPQYZ507Z580Pu9Gky1dpK
|
HrkSGVkAAAEAsMH3wFhlpeBmZuYXE83NOH3+PHbpdK4ulu1NoekdAOD3GO0JjTPMG6bi4gdcRwcunTuH
|
||||||
hisrPe+nptbLYmPjMT1TpHPJkg/u7d1LHhw7RkaPHiVWJFsOHCBtLHtdLhK9jpSwRUbU6jUQt3BnzhAO
|
k4WF9g+io6vCAwODfSa927d/eLehAe+3t+N0WxsaOzpwpqkJO1n2hpimX1vLZEome9NUXDzDnT2LXHs7
|
||||||
a7mWFjJ15Ai5p9V6v5ZK30OKGETxrkokVir+oKmJPDx0iFiRNH7yJLnW3Oy/olLdyBKJUpD4TBG0pdhW
|
cno9LrW24l2FwvFVWNj7ABDirkKfUGgk8Ps6HT5oaUFjayvOnTmDfc3Nri6p9Id4mo560mRCKs0yFRUZ
|
||||||
VWWlzqn4FMS5/fvJFIz5amqIOSHhLtJYIOJ1JCaeG66tJaMoYAHWgweJDQscJ06QG2hXB8t2ZwqFqUgO
|
SXICX9LrkWtsxKWmJnSWlqIhNPQOALAAQEPP1q0XJsvLcVqnwxmdDo0nTqBJr8f506fxuk7n6mHZwTiB
|
||||||
FBlSKIrHKyutk6dOEQ5mpmCKw7qpPXvIxI4dpE2lcm2RSC4gtRSIefrFi19tUyqvt2/b5n+EpDEwDjcO
|
INprMpGcnDVXWGhcfO895FpbcamlBTmdDpe0WlyoqMBOqdR6RCi8DAA57q9Qbdv2SqdEcuPa0aOuh1ot
|
||||||
7IkbLXPu20euokiuUJj2E8MUjRkMtsnjxwMt4eCYQ3u5xkYyCXFzbq4nRSD4FMJGIAd0w3nRjESSiiLd
|
zmq1ONfYiPPNzWhra0PL8ePYx7KDSQJBzE8MkzlbUGBaPHXKXRKuqQm5hgbk6upwsaICDUlJ9ig+/zMA
|
||||||
li1biG3nTmJvaCCO3buJC8W8EOpuaPD3qNV37peXW7nDhwOOOcxxyOXq65+IpwkE56BXCzKC4pEgEPxc
|
UAOA2NNw8GOEwuhOiWRw5sgRNNXUoLm6Gufr69Gq1aJDr8f+6mrXkEx2+15enpE7edKdmNNqkaupQa6q
|
||||||
sTjtO4Wi64fqar+9ro44gdtkIh4I+FDMt2sXmYTbSSqMew73AXG0t0up9MqFQipOnaeD+eDpUQ0GXyUW
|
ygeP4fMvAEA5AMR64JS3rP5JISEx15KTBwwlJS6zRoMWjQZtlZVor6pCZ309OmtrcbGhARcJuL4eudra
|
||||||
p3dkZ3fbNm4kzq1biRt4jUbig8MJFJzABk6UlxPf6tXEp1YTD+jKy/PliETnsX47oM4F4DnxUPCXxcdn
|
f+Dl5TggkTjEAgGBk+QiAHj+sanqNZGGhIh6EhIGTYcOoaWsDG1lZehQq9FZUYELGg0ulJbiQl4eOvfu
|
||||||
dMjl3QMZGY89mzYRt0ZD3AxDXFIpcYlExBUdTVzz5pFuodDfnpTkZePi6IbWgUzwIphVPBSBdt2Sy/vH
|
RadMhnaZDAdSUpyJNH0JAI55kvNXg3vlvzM4OLZHLB4cE4mW7YcPo00uRxvDoDUsDK00jVY/P7TyeNgv
|
||||||
IWiHmAM4ARUOEBVF+rKz/zKkpn6L/HdBFpiTeCBsNTUmm1ptsQsEz4sDOjaQnPzYrNXeT0tMLMeSWDA3
|
ELi6IyIcbFAQaagGAOIA4IVnwb1yl+umWDw6R9No5vFwnsdDC4/nBrvHxo04kpDwZ0F09LcA8C4AxK8X
|
||||||
cZ/RuM9VUOCyw/1s4mPgIbBkZJA+ne7uW8uX52Dpf75WAuE2Gluca9e67TExz4k70XvaLio+CoYjI8kA
|
7paptLTSJJPNmPn8p+Eew7HIyGWDQnEvZuvWPAAIXDfcqVYft6anW800vSZ8lsfDBzwezsTG4ohSeeet
|
||||||
uJyT4++vqPjVwLK0TbMX8W7ffshRUuIJ59wpkZBHJSV/30hJ8VPxoaB4L+gCZoaZ7qf/ZLYiOIot9oIC
|
XbsSn1yMq8qmVust+/bZzAEBT8Etfn7uchH4NI+HkxSFYxSF3yQmukbz838tYFlSprVNHMeOtcxnZ9tX
|
||||||
r10oDAg/05YFC8hgaenvx1eu7Oldv37ckpZGfoHobXATXKMFKMuWTf9oMNwpkMvpC/Lpq95TW9tMxR3h
|
S24RCvFhdvZf16OiXAQ+4YEPUxQOUBQaGGZllHzJWiYOtVpvTk93mAUCN/ixsmzahOM5Ob+f2rNnaPjA
|
||||||
xBMSyOCqVX/UM0wHUhtKMjPfvltWdn8QvQ+Jd4J20EaLqFTTPRUVvZ9otXTj+SCC59mwweqIiwvvHOJ1
|
gbmZmBj8haLwFkVhP0XhdWJAxs6dKz8WFNxOF4vJBvnvVm8vL28m8PnV4KGhOJ6a+qiKYXoAoDo7Lu7t
|
||||||
CkU7Ek2AbqR4d37+G316/cidrKwn4pfBN+AS6E9Pf3xbr7+H3MWAz7PrdIMemSyscxPDfI+k+qB46EvF
|
O7m598ZjY33wXorCborCTmIila4M5ecPf6pQkMb7uxtvP3jQOB8U9DScJE9NfaRJTu4GgEoAII0MqU9L
|
||||||
31NYyPZVVIxcyMry/1v8q4gIchsFzBrNGPKKQDyvp7p687hG43ZDNOR8oLj4z53hxUPBb8zPz8PGDt/K
|
e31EpZq6HR/vg39HUfg1ReFVisJRkWj5lkp1FwC2uU3MSuW4PTx81eSVDPM9AFR54N6Tyl+bkcGO5OdP
|
||||||
ziYXg+LmvLzpzzWaR6VLl36MnJkCiPntlZWHrWVl3h6W9VPnjUplJ8ZnEw8F37hihYK24wusM6vV0xfg
|
XYqPd/0X/uWGDXhLJFo2yOWzAJAJAMEwVFJSPCeX22yhob7kY1lZf9SsDvfKvy4tLWVUqZy8mZCAVzxw
|
||||||
/CWBoBVzOjDTIkQEk5QU26vXf/agrMx5vrAQpy+yEeMMENJ5mjRL8C9VVb3zs043dlOrdZWkpNBvgR5I
|
Q0rKykW5/GHOjh2f+AzIxtRdWHjSmJvrGGBZF0leJ5H0PgPulb969+5kUo6LLOsyyGQrl+Xy2Rf5/HMA
|
||||||
AT2uT9bSH3FACdYFr3N9/F8A9GjSk7MevAbCPnDzAHVMP9b0Su/nEtQEff+/HIQWDBrj8f4B7zPYbtFn
|
oPSViLzMREQEDqtUn9/PzbVcysgYpiiqDgAYABCsAffK/2pR0Ts/K5Wz/QqFNTsqipwFKgAI80xX37vk
|
||||||
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>
|
||||||
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
|
||||||
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>
|
||||||
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
|
||||||
|
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()
|
||||||
@@ -332,6 +336,7 @@ Namespace DownloadObjects.STDownloader
|
|||||||
pForm.Dispose()
|
pForm.Dispose()
|
||||||
End If
|
End If
|
||||||
If Not c Is Nothing Then
|
If Not c Is Nothing Then
|
||||||
|
If Not c.HasElements Then DirectCast(c, YouTubeMediaContainerBase).FileForceArtist()
|
||||||
Dim f As Form
|
Dim f As Form
|
||||||
Select Case c.ObjectType
|
Select Case c.ObjectType
|
||||||
Case YouTubeMediaType.Single : f = New VideoOptionsForm(c) With {.UseCookies = useCookies}
|
Case YouTubeMediaType.Single : f = New VideoOptionsForm(c) With {.UseCookies = useCookies}
|
||||||
@@ -415,6 +420,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 +505,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 +521,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>
|
||||||
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
|
||||||
</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>
|
||||||
@@ -10,6 +10,7 @@ Imports System.Threading
|
|||||||
Imports PersonalUtilities.Tools
|
Imports PersonalUtilities.Tools
|
||||||
Imports PersonalUtilities.Tools.Web
|
Imports PersonalUtilities.Tools.Web
|
||||||
Imports PersonalUtilities.Functions.Messaging
|
Imports PersonalUtilities.Functions.Messaging
|
||||||
|
Imports PersonalUtilities.Functions.RegularExpressions
|
||||||
Imports SCrawler.DownloadObjects.STDownloader
|
Imports SCrawler.DownloadObjects.STDownloader
|
||||||
Public Module MainModShared
|
Public Module MainModShared
|
||||||
Public Property BATCH As BatchExecutor
|
Public Property BATCH As BatchExecutor
|
||||||
@@ -135,9 +136,11 @@ Namespace Editors
|
|||||||
Public Shared Function GetProgramEnvirText(ByVal EnvirData As IDownloaderSettings, ByVal IsYouTube As Boolean) As String
|
Public Shared Function GetProgramEnvirText(ByVal EnvirData As IDownloaderSettings, ByVal IsYouTube As Boolean) As String
|
||||||
Try
|
Try
|
||||||
Dim output$ = String.Empty
|
Dim output$ = String.Empty
|
||||||
|
Dim verAfter As RParams = RParams.DM("\A\w\:\\.*", 0, EDP.ReturnValue)
|
||||||
Using b As New BatchExecutor(True)
|
Using b As New BatchExecutor(True)
|
||||||
Dim f As SFile
|
Dim f As SFile
|
||||||
Dim cmd$, ff$, vText$
|
Dim cmd$, ff$, vText$
|
||||||
|
Dim ii%
|
||||||
|
|
||||||
For i% = 0 To IIf(IsYouTube, 1, 3)
|
For i% = 0 To IIf(IsYouTube, 1, 3)
|
||||||
cmd = "--version"
|
cmd = "--version"
|
||||||
@@ -154,7 +157,17 @@ Namespace Editors
|
|||||||
Else
|
Else
|
||||||
b.Reset()
|
b.Reset()
|
||||||
b.Execute($"""{f}"" {cmd}", EDP.None)
|
b.Execute($"""{f}"" {cmd}", EDP.None)
|
||||||
If b.OutputData.Count > 3 Then vText = b.OutputData(3) Else vText = "undefined"
|
'If b.OutputData.Count > 3 Then vText = b.OutputData(3) Else vText = "undefined"
|
||||||
|
|
||||||
|
vText = String.Empty
|
||||||
|
With b.OutputData
|
||||||
|
If .Count > 0 Then
|
||||||
|
ii = .FindIndex(Function(bb) Not CStr(RegexReplace(bb, verAfter)).IsEmptyString)
|
||||||
|
If ii >= 0 And ii + 1 <= .Count - 1 Then vText = .Item(ii + 1)
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
If vText.IsEmptyString Then vText = "undefined"
|
||||||
|
|
||||||
output.StringAppendLine($"{ff} version: {vText}")
|
output.StringAppendLine($"{ff} version: {vText}")
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ Imports System.Runtime.InteropServices
|
|||||||
<Assembly: AssemblyDescription("YouTube plugin environment")>
|
<Assembly: AssemblyDescription("YouTube plugin environment")>
|
||||||
<Assembly: AssemblyCompany("AndyProgram")>
|
<Assembly: AssemblyCompany("AndyProgram")>
|
||||||
<Assembly: AssemblyProduct("SCrawler.YouTube")>
|
<Assembly: AssemblyProduct("SCrawler.YouTube")>
|
||||||
<Assembly: AssemblyCopyright("Copyright © 2024")>
|
<Assembly: AssemblyCopyright("Copyright © 2026")>
|
||||||
<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.8.10.0")>
|
<Assembly: AssemblyVersion("2025.11.25.0")>
|
||||||
<Assembly: AssemblyFileVersion("2024.8.10.0")>
|
<Assembly: AssemblyFileVersion("2025.11.25.0")>
|
||||||
<Assembly: NeutralResourcesLanguage("en")>
|
<Assembly: NeutralResourcesLanguage("en")>
|
||||||
|
|||||||
@@ -30,6 +30,11 @@ Namespace API.YouTube.Objects
|
|||||||
_File = CleanFileName(_File)
|
_File = CleanFileName(_File)
|
||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
|
Protected Friend Overrides Sub FileForceArtist()
|
||||||
|
Dim __artistName$ = UserTitle.IfNullOrEmpty(AccountName)
|
||||||
|
If Not _File.Name.IsEmptyString AndAlso Not _File.Name.ToLower.Contains(__artistName.ToLower) Then _
|
||||||
|
_File.Name = $"{__artistName} - {_File.Name}"
|
||||||
|
End Sub
|
||||||
Public Overrides Function ToString(ByVal ForMediaItem As Boolean) As String
|
Public Overrides Function ToString(ByVal ForMediaItem As Boolean) As String
|
||||||
Dim s$ = SizeStr
|
Dim s$ = SizeStr
|
||||||
If Not s.IsEmptyString Then s = $" [{s}]"
|
If Not s.IsEmptyString Then s = $" [{s}]"
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -175,7 +177,9 @@ Namespace API.YouTube.Objects
|
|||||||
Protected _ThumbnailUrl As String = String.Empty
|
Protected _ThumbnailUrl As String = String.Empty
|
||||||
<XMLEC> Public Overridable Property ThumbnailUrl As String Implements IDownloadableMedia.ThumbnailUrl
|
<XMLEC> Public Overridable Property ThumbnailUrl As String Implements IDownloadableMedia.ThumbnailUrl
|
||||||
Get
|
Get
|
||||||
If _ThumbnailUrl.IsEmptyString And Thumbnails.Count > 0 Then
|
If Not CoverURL.IsEmptyString Then
|
||||||
|
Return CoverURL
|
||||||
|
ElseIf _ThumbnailUrl.IsEmptyString And Thumbnails.Count > 0 Then
|
||||||
Return Thumbnails.FirstOrDefault.URL
|
Return Thumbnails.FirstOrDefault.URL
|
||||||
Else
|
Else
|
||||||
Return _ThumbnailUrl
|
Return _ThumbnailUrl
|
||||||
@@ -352,6 +356,14 @@ Namespace API.YouTube.Objects
|
|||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
#End Region
|
#End Region
|
||||||
|
#Region "Chapters, Trimming"
|
||||||
|
Friend ReadOnly Property Chapters As List(Of TrimOption)
|
||||||
|
Friend ReadOnly Property TrimOptions As List(Of TrimOption)
|
||||||
|
Friend Property TrimDeleteOriginalFile As Boolean = False
|
||||||
|
Friend Property TrimAddTrimmedFilesToM3U8 As Boolean = False
|
||||||
|
Friend Property TrimSeparateFolder As Boolean = False
|
||||||
|
Friend Property TrimOptionsSet As Boolean = False
|
||||||
|
#End Region
|
||||||
#Region "IUserMedia Support"
|
#Region "IUserMedia Support"
|
||||||
<XMLEC> Private Property Attempts As Integer Implements IUserMedia.Attempts
|
<XMLEC> Private Property Attempts As Integer Implements IUserMedia.Attempts
|
||||||
Private _Object As Object = Nothing
|
Private _Object As Object = Nothing
|
||||||
@@ -680,13 +692,22 @@ Namespace API.YouTube.Objects
|
|||||||
End If
|
End If
|
||||||
End Set
|
End Set
|
||||||
End Property
|
End Property
|
||||||
|
Protected Friend Overridable Sub FileForceArtist()
|
||||||
|
End Sub
|
||||||
Friend Sub FileDateUpdate()
|
Friend Sub FileDateUpdate()
|
||||||
Dim n$ = _File.Name.StringTrim
|
Dim n$ = _File.Name.StringTrim
|
||||||
Dim s$ = IIf(n.IsEmptyString, String.Empty, " ")
|
Dim s$ = IIf(n.IsEmptyString, String.Empty, " ")
|
||||||
|
Dim c$ = AccountName.IfNullOrEmpty(UserID)
|
||||||
Select Case MyYouTubeSettings.FileAddDateToFileName.Value
|
Select Case MyYouTubeSettings.FileAddDateToFileName.Value
|
||||||
Case FileDateMode.Before : n = $"[{DateAdded:yyyy-MM-dd}]{s}{n}"
|
Case FileDateMode.Before : n = $"[{DateAdded:yyyy-MM-dd}]{s}{n}"
|
||||||
Case FileDateMode.After : n = $"{n}{s}[{DateAdded:yyyy-MM-dd}]"
|
Case FileDateMode.After : n = $"{n}{s}[{DateAdded:yyyy-MM-dd}]"
|
||||||
End Select
|
End Select
|
||||||
|
If Not c.IsEmptyString Then
|
||||||
|
Select Case MyYouTubeSettings.FileAddChannelToFileName.Value
|
||||||
|
Case FileDateMode.Before : n = $"[{c}] {n}"
|
||||||
|
Case FileDateMode.After : n = $"{n} [{c}]"
|
||||||
|
End Select
|
||||||
|
End If
|
||||||
_File.Name = n
|
_File.Name = n
|
||||||
End Sub
|
End Sub
|
||||||
Public Property FileSettings As SFile
|
Public Property FileSettings As SFile
|
||||||
@@ -727,6 +748,7 @@ Namespace API.YouTube.Objects
|
|||||||
#Region "Command"
|
#Region "Command"
|
||||||
<XMLEC> Public Property UseCookies As Boolean = MyYouTubeSettings.DefaultUseCookies Implements IYouTubeMediaContainer.UseCookies
|
<XMLEC> Public Property UseCookies As Boolean = MyYouTubeSettings.DefaultUseCookies Implements IYouTubeMediaContainer.UseCookies
|
||||||
Protected Const mp3 As String = "mp3"
|
Protected Const mp3 As String = "mp3"
|
||||||
|
Private Const mp4 As String = "mp4"
|
||||||
Private Const aac As String = "aac"
|
Private Const aac As String = "aac"
|
||||||
Private Const ac3 As String = "ac3"
|
Private Const ac3 As String = "ac3"
|
||||||
Protected PostProcessing_AudioAC3 As Boolean = False
|
Protected PostProcessing_AudioAC3 As Boolean = False
|
||||||
@@ -762,7 +784,12 @@ Namespace API.YouTube.Objects
|
|||||||
'2023.3.4 -> 2023.7.6
|
'2023.3.4 -> 2023.7.6
|
||||||
'cmd.StringAppend($"ba*[format_id={SelectedAudio.ID}]", "+")
|
'cmd.StringAppend($"ba*[format_id={SelectedAudio.ID}]", "+")
|
||||||
cmd.StringAppend(SelectedAudio.ID, "+")
|
cmd.StringAppend(SelectedAudio.ID, "+")
|
||||||
If OutputAudioCodec.StringToLower = ac3 Then
|
If SelectedVideoIndex >= 0 And SelectedAudio.ProtocolType = Protocols.m3u8 And
|
||||||
|
(SelectedAudio.Codec.StringToLower = mp4 Or OutputAudioCodec.StringToLower = mp4) Then
|
||||||
|
PostProcessing_AudioAC3 = True
|
||||||
|
formats.StringAppend($"--merge-output-format ""{mp4}{IIf(OutputVideoExtension.IsEmptyString, String.Empty, $"/{OutputVideoExtension.StringToLower}")}""", " ")
|
||||||
|
atCodec = aac
|
||||||
|
ElseIf OutputAudioCodec.StringToLower = ac3 Then
|
||||||
PostProcessing_AudioAC3 = True
|
PostProcessing_AudioAC3 = True
|
||||||
formats.StringAppend($"--audio-format {aac}", " ")
|
formats.StringAppend($"--audio-format {aac}", " ")
|
||||||
atCodec = aac
|
atCodec = aac
|
||||||
@@ -800,15 +827,20 @@ Namespace API.YouTube.Objects
|
|||||||
subs = ListAddList(Nothing, Subtitles.Select(Function(s, i) If(SubtitlesSelectedIndexes.Contains(i), s.FullID, String.Empty)),
|
subs = ListAddList(Nothing, Subtitles.Select(Function(s, i) If(SubtitlesSelectedIndexes.Contains(i), s.FullID, String.Empty)),
|
||||||
LAP.NotContainsOnly, EDP.ReturnValue).ListToString(",")
|
LAP.NotContainsOnly, EDP.ReturnValue).ListToString(",")
|
||||||
subs = $"--write-subs --write-auto-subs --sub-format {OutputSubtitlesFormat.StringToLower} --sub-langs ""{subs}"" --convert-subs {OutputSubtitlesFormat.StringToLower}"
|
subs = $"--write-subs --write-auto-subs --sub-format {OutputSubtitlesFormat.StringToLower} --sub-langs ""{subs}"" --convert-subs {OutputSubtitlesFormat.StringToLower}"
|
||||||
|
If MyYouTubeSettings.DefaultSubtitlesEmbed Then subs = $"--write-auto-sub --embed-subs {subs}"
|
||||||
End If
|
End If
|
||||||
If Not cmd.IsEmptyString Then
|
If Not cmd.IsEmptyString Then
|
||||||
'2023.3.4 -> 2023.7.6
|
'2023.3.4 -> 2023.7.6
|
||||||
'cmd = $"yt-dlp -f ""{cmd}"""
|
'cmd = $"yt-dlp -f ""{cmd}"""
|
||||||
'cmd = $"yt-dlp -f {cmd}"
|
'cmd = $"yt-dlp -f {cmd}"
|
||||||
cmd = $"{YTDLP_NAME} -f {cmd}"
|
cmd = $"{YTDLP_NAME} -f {cmd}"
|
||||||
If Not MyYouTubeSettings.ReplaceModificationDate Then cmd &= " --no-mtime"
|
'yt-dlp 2025.07.21
|
||||||
|
'If Not MyYouTubeSettings.ReplaceModificationDate Then cmd &= " --no-mtime"
|
||||||
|
cmd &= $" --{IIf(MyYouTubeSettings.ReplaceModificationDate.Value, String.Empty, "no-")}mtime"
|
||||||
|
If MyYouTubeSettings.DefaultVideoEmbedChapters Then cmd &= " --embed-chapters --add-chapters"
|
||||||
cmd.StringAppend(formats, " ")
|
cmd.StringAppend(formats, " ")
|
||||||
cmd.StringAppend(subs, " ")
|
cmd.StringAppend(subs, " ")
|
||||||
|
If MyYouTubeSettings.ErrorsIgnore Then cmd &= " --no-abort-on-error --ignore-errors"
|
||||||
cmd.StringAppend(YouTubeFunctions.GetCookiesCommand(WithCookies, YouTubeCookieNetscapeFile), " ")
|
cmd.StringAppend(YouTubeFunctions.GetCookiesCommand(WithCookies, YouTubeCookieNetscapeFile), " ")
|
||||||
cmd &= $" {URL} -o ""{File.PathWithSeparator}{File.Name}"""
|
cmd &= $" {URL} -o ""{File.PathWithSeparator}{File.Name}"""
|
||||||
File.Exists(SFO.Path, True)
|
File.Exists(SFO.Path, True)
|
||||||
@@ -826,6 +858,8 @@ Namespace API.YouTube.Objects
|
|||||||
_Subtitles = New List(Of Subtitles)
|
_Subtitles = New List(Of Subtitles)
|
||||||
_SubtitlesDelegated = New List(Of Subtitles)
|
_SubtitlesDelegated = New List(Of Subtitles)
|
||||||
SubtitlesSelectedIndexes = New List(Of Integer)
|
SubtitlesSelectedIndexes = New List(Of Integer)
|
||||||
|
Chapters = New List(Of TrimOption)
|
||||||
|
TrimOptions = New List(Of TrimOption)
|
||||||
MediaObjects = New List(Of MediaObject)
|
MediaObjects = New List(Of MediaObject)
|
||||||
_Files = New List(Of SFile)
|
_Files = New List(Of SFile)
|
||||||
|
|
||||||
@@ -904,7 +938,8 @@ Namespace API.YouTube.Objects
|
|||||||
Const m3u8DataRow$ = "#EXTINF:{0},{1}" & vbCrLf & "{2}"
|
Const m3u8DataRow$ = "#EXTINF:{0},{1}" & vbCrLf & "{2}"
|
||||||
With Element
|
With Element
|
||||||
Dim f As SFile = __file.IfNullOrEmpty(.File)
|
Dim f As SFile = __file.IfNullOrEmpty(.File)
|
||||||
Dim __f$ = SymbolsConverter.ASCII.EncodeSymbolsOnly(If(Mode = M3U8CreationMode.Absolute, f.ToString, f.File))
|
Dim fStr$ = f.ToString.StringReplaceSymbols({"\"}, "/", EDP.ReturnValue)
|
||||||
|
Dim __f$ = SymbolsConverter.ASCII.Extended.EncodeSymbolsOnly(If(Mode = M3U8CreationMode.Absolute, fStr, f.File), M3U8ExcludedSymbols)
|
||||||
If Mode = M3U8CreationMode.Absolute Then __f = $"file:///{__f}"
|
If Mode = M3U8CreationMode.Absolute Then __f = $"file:///{__f}"
|
||||||
Dim fName$ = .Title.IfNullOrEmpty(f.Name)
|
Dim fName$ = .Title.IfNullOrEmpty(f.Name)
|
||||||
If MyYouTubeSettings.MusicPlaylistCreate_M3U8_AppendNumber And .PlaylistIndex > 0 Then fName = $"{ .PlaylistIndex}. {fName}"
|
If MyYouTubeSettings.MusicPlaylistCreate_M3U8_AppendNumber And .PlaylistIndex > 0 Then fName = $"{ .PlaylistIndex}. {fName}"
|
||||||
@@ -1022,12 +1057,19 @@ Namespace API.YouTube.Objects
|
|||||||
End If
|
End If
|
||||||
|
|
||||||
Dim cDown As Boolean = False
|
Dim cDown As Boolean = False
|
||||||
|
Dim fCover As SFile = Nothing
|
||||||
|
Dim cUrl$ = String.Empty
|
||||||
For Each elem In Elements
|
For Each elem In Elements
|
||||||
With DirectCast(elem, YouTubeMediaContainerBase)
|
With DirectCast(elem, YouTubeMediaContainerBase)
|
||||||
If Not .CoverDownloaded Then .CoverDownloaded = cDown
|
'If Not .CoverDownloaded Then .CoverDownloaded = cDown
|
||||||
|
.CoverDownloaded = cDown
|
||||||
|
.CoverFile = fCover
|
||||||
|
.CoverURL = cUrl
|
||||||
AddHandler .FileDownloadStarted, fDown
|
AddHandler .FileDownloadStarted, fDown
|
||||||
.Download(UseCookies, Token)
|
.Download(UseCookies, Token)
|
||||||
cDown = .CoverDownloaded
|
cDown = .CoverDownloaded
|
||||||
|
fCover = .CoverFile
|
||||||
|
cUrl = .CoverURL
|
||||||
RemoveHandler .FileDownloadStarted, fDown
|
RemoveHandler .FileDownloadStarted, fDown
|
||||||
End With
|
End With
|
||||||
If Token.IsCancellationRequested Or disposedValue Then Exit For
|
If Token.IsCancellationRequested Or disposedValue Then Exit For
|
||||||
@@ -1054,6 +1096,8 @@ Namespace API.YouTube.Objects
|
|||||||
End Try
|
End Try
|
||||||
End Sub
|
End Sub
|
||||||
Protected CoverDownloaded As Boolean = False
|
Protected CoverDownloaded As Boolean = False
|
||||||
|
Protected CoverFile As SFile = Nothing
|
||||||
|
Protected CoverURL As String = String.Empty
|
||||||
Private Sub DownloadPlaylistCover(ByVal PlsId As String, ByVal f As SFile, ByVal UseCookies As Boolean)
|
Private Sub DownloadPlaylistCover(ByVal PlsId As String, ByVal f As SFile, ByVal UseCookies As Boolean)
|
||||||
Try
|
Try
|
||||||
Dim url$ = $"https://{IIf(IsMusic, "music", "www")}.youtube.com/playlist?list={PlsId}"
|
Dim url$ = $"https://{IIf(IsMusic, "music", "www")}.youtube.com/playlist?list={PlsId}"
|
||||||
@@ -1089,7 +1133,8 @@ Namespace API.YouTube.Objects
|
|||||||
url = LinkFormatterSecure(u)
|
url = LinkFormatterSecure(u)
|
||||||
f.Name = "cover"
|
f.Name = "cover"
|
||||||
f.Extension = "jpg"
|
f.Extension = "jpg"
|
||||||
If resp.DownloadFile(url, f, EDP.ReturnValue) And f.Exists Then CoverDownloaded = True : AddFile(f)
|
If resp.DownloadFile(url, f, EDP.ReturnValue) And f.Exists Then _
|
||||||
|
CoverFile = f : CoverURL = url : CoverDownloaded = True : AddFile(f)
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
End Using
|
End Using
|
||||||
@@ -1195,12 +1240,15 @@ 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($"Channel name: {AccountName}")
|
||||||
|
fileDesrText.AppendLine($"Channel ID: {UserID}")
|
||||||
If Not Description.IsEmptyString Then
|
If Not Description.IsEmptyString Then
|
||||||
If Not fileDesrText.IsEmptyString Then fileDesrText.AppendLine.AppendLine()
|
If Not fileDesrText.IsEmptyString Then fileDesrText.AppendLine.AppendLine()
|
||||||
fileDesrText.Append(Description)
|
fileDesrText.Append(Description)
|
||||||
@@ -1234,6 +1282,7 @@ Namespace API.YouTube.Objects
|
|||||||
Dim fPatternFiles$ = $"{File.Name}*." & "{0}"
|
Dim fPatternFiles$ = $"{File.Name}*." & "{0}"
|
||||||
Dim fAacAudio As New TempFileConversion(New SFile(String.Format(fPattern, aac)), Me)
|
Dim fAacAudio As New TempFileConversion(New SFile(String.Format(fPattern, aac)), Me)
|
||||||
Dim mp3ThumbEmbedded As Boolean = False
|
Dim mp3ThumbEmbedded As Boolean = False
|
||||||
|
Dim audioFiles As New List(Of SFile)
|
||||||
|
|
||||||
Dim tempFilesList As New List(Of TempFileConversion)
|
Dim tempFilesList As New List(Of TempFileConversion)
|
||||||
Dim ttFile As TempFileConversion
|
Dim ttFile As TempFileConversion
|
||||||
@@ -1270,10 +1319,10 @@ Namespace API.YouTube.Objects
|
|||||||
End Sub
|
End Sub
|
||||||
Dim embedThumbTo As Action(Of SFile) =
|
Dim embedThumbTo As Action(Of SFile) =
|
||||||
Sub(ByVal dFile As SFile)
|
Sub(ByVal dFile As SFile)
|
||||||
If dFile.Exists And ThumbnailFile.Exists Then
|
If dFile.Exists And CoverFile.IfNullOrEmpty(ThumbnailFile).Exists Then
|
||||||
Dim dFileNew As SFile = dFile
|
Dim dFileNew As SFile = dFile
|
||||||
dFileNew.Name &= "_NEW"
|
dFileNew.Name &= "_NEW"
|
||||||
.Execute($"ffmpeg -i ""{dFile}"" -i ""{ThumbnailFile}"" -map 0:0 -map 1:0 -c copy -id3v2_version 3 -metadata:s:v title=""Cover"" -metadata:s:v comment=""Cover"" ""{dFileNew}""")
|
.Execute($"ffmpeg -i ""{dFile}"" -i ""{CoverFile.IfNullOrEmpty(ThumbnailFile)}"" -map 0:0 -map 1:0 -c copy -id3v2_version 3 -metadata:s:v title=""Cover"" -metadata:s:v comment=""Cover"" ""{dFileNew}""")
|
||||||
If dFileNew.Exists AndAlso dFile.Delete(,, EDP.ReturnValue) Then SFile.Rename(dFileNew, dFile)
|
If dFileNew.Exists AndAlso dFile.Delete(,, EDP.ReturnValue) Then SFile.Rename(dFileNew, dFile)
|
||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
@@ -1341,18 +1390,26 @@ Namespace API.YouTube.Objects
|
|||||||
format = format.StringToLower
|
format = format.StringToLower
|
||||||
f = String.Format(fPattern, format)
|
f = String.Format(fPattern, format)
|
||||||
AddFile(f)
|
AddFile(f)
|
||||||
|
audioFiles.Add(f)
|
||||||
If Not f.Exists Then
|
If Not f.Exists Then
|
||||||
tryToConvert.Invoke(format, f)
|
tryToConvert.Invoke(format, f)
|
||||||
updateBitrate(f)
|
updateBitrate(f)
|
||||||
If format = mp3 And Not mp3ThumbEmbedded And MyYouTubeSettings.DefaultAudioEmbedThumbnail_ExtractedFiles Then _
|
If f.Exists Then
|
||||||
embedThumbTo.Invoke(f) : mp3ThumbEmbedded = True
|
If format = mp3 And Not mp3ThumbEmbedded And MyYouTubeSettings.DefaultAudioEmbedThumbnail_ExtractedFiles Then _
|
||||||
If Not M3U8_PlaylistFiles.ListExists AndAlso f.Exists Then M3U8_Append(f)
|
embedThumbTo.Invoke(f) : mp3ThumbEmbedded = True
|
||||||
If format = mp3 AndAlso f.Exists AndAlso MyYouTubeSettings.VideoPlaylist_AddExtractedMP3.Value Then M3U8_Append(f)
|
If M3U8_PlaylistFiles.ListExists OrElse
|
||||||
|
(format = mp3 AndAlso MyYouTubeSettings.VideoPlaylist_AddExtractedMP3.Value) Then _
|
||||||
|
M3U8_Append(f)
|
||||||
|
End If
|
||||||
End If
|
End If
|
||||||
Next
|
Next
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
|
|
||||||
|
'mp3
|
||||||
|
If IsMusic And ObjectType = YouTubeMediaType.Single And File.Extension = mp3 And
|
||||||
|
Not mp3ThumbEmbedded And CoverFile.Exists And MyYouTubeSettings.DefaultAudioEmbedThumbnail_Cover Then embedThumbTo.Invoke(File)
|
||||||
|
|
||||||
'Update video
|
'Update video
|
||||||
ThrowAny(Token)
|
ThrowAny(Token)
|
||||||
If SelectedVideoIndex >= 0 AndAlso tempFilesList.Count > 0 AndAlso tempFilesList.Exists(Function(tf) tf.ToReplace) Then
|
If SelectedVideoIndex >= 0 AndAlso tempFilesList.Count > 0 AndAlso tempFilesList.Exists(Function(tf) tf.ToReplace) Then
|
||||||
@@ -1396,6 +1453,69 @@ Namespace API.YouTube.Objects
|
|||||||
If OutputVideoFPS > 0 AndAlso SelectedVideo.Bitrate <> OutputVideoFPS Then _
|
If OutputVideoFPS > 0 AndAlso SelectedVideo.Bitrate <> OutputVideoFPS Then _
|
||||||
reencodeFile("ffmpeg -i ""{0}"" -filter:v fps=" & OutputVideoFPS.ToString.Replace(", ", ".") & " -c:a copy ""{1}""")
|
reencodeFile("ffmpeg -i ""{0}"" -filter:v fps=" & OutputVideoFPS.ToString.Replace(", ", ".") & " -c:a copy ""{1}""")
|
||||||
End If
|
End If
|
||||||
|
|
||||||
|
'Trimming
|
||||||
|
If TrimOptions.Count > 0 AndAlso File.Exists Then
|
||||||
|
Const trimCommand$ = "ffmpeg -i ""{0}"" -ss {1} -to {2} -c:v copy -c:a copy ""{3}"""
|
||||||
|
Dim trimFirstFile As SFile = Nothing
|
||||||
|
Dim trimFirstAdded As Boolean = False
|
||||||
|
Dim trimSingleReplace As Boolean = TrimOptions.Count = 1 And TrimDeleteOriginalFile
|
||||||
|
Dim audioReplace As New Dictionary(Of SFile, SFile)
|
||||||
|
Dim processTrim As Action(Of TrimOption, SFile, Boolean) =
|
||||||
|
Sub(ByVal opt As TrimOption, ByVal pFile As SFile, ByVal isAudio As Boolean)
|
||||||
|
Dim fNew As SFile = pFile
|
||||||
|
fNew.Name &= $"_{opt.Name}"
|
||||||
|
If TrimSeparateFolder Then fNew = $"{fNew.PathNoSeparator}\{MyYouTubeSettings.TrimSeparateFolderName.Value.IfNullOrEmpty(YouTubeSettings.TrimSeparateFolderNameDefault)}\{fNew.File}" : fNew.Exists(SFO.Path)
|
||||||
|
format = fNew.Extension.StringToLower
|
||||||
|
.Execute(String.Format(trimCommand,
|
||||||
|
pFile,
|
||||||
|
AConvert(Of String)(opt.StartTime, TimeToStringProvider),
|
||||||
|
AConvert(Of String)(opt.EndTime, TimeToStringProvider),
|
||||||
|
fNew))
|
||||||
|
If fNew.Exists Then
|
||||||
|
If trimFirstFile.IsEmptyString Then trimFirstFile = fNew
|
||||||
|
If Not trimSingleReplace Then AddFile(fNew)
|
||||||
|
If isAudio And trimSingleReplace And Not audioReplace.ContainsKey(pFile) Then audioReplace.Add(pFile, fNew)
|
||||||
|
If format = mp3 And MyYouTubeSettings.DefaultAudioEmbedThumbnail_ExtractedFiles Then _
|
||||||
|
embedThumbTo.Invoke(fNew) : mp3ThumbEmbedded = True
|
||||||
|
If Not trimSingleReplace AndAlso
|
||||||
|
(TrimAddTrimmedFilesToM3U8 Or (TrimDeleteOriginalFile And Not trimFirstAdded)) AndAlso
|
||||||
|
(M3U8_PlaylistFiles.ListExists OrElse
|
||||||
|
(format = mp3 AndAlso MyYouTubeSettings.VideoPlaylist_AddExtractedMP3.Value)) Then _
|
||||||
|
M3U8_Append(fNew) : trimFirstAdded = True
|
||||||
|
End If
|
||||||
|
End Sub
|
||||||
|
For Each tr As TrimOption In TrimOptions
|
||||||
|
processTrim(tr, File, False)
|
||||||
|
If audioFiles.Count > 0 Then
|
||||||
|
For Each f In audioFiles : processTrim(tr, f, True) : Next
|
||||||
|
End If
|
||||||
|
Next
|
||||||
|
If TrimDeleteOriginalFile Then
|
||||||
|
Dim silentEDP As New ErrorsDescriber(EDP.ReturnValue)
|
||||||
|
File.Delete(,, silentEDP)
|
||||||
|
If trimSingleReplace Then
|
||||||
|
File = SFile.Rename(trimFirstFile, File,, New ErrorsDescriber(False, False, False, trimFirstFile))
|
||||||
|
If audioReplace.Count > 0 Then
|
||||||
|
For Each kvf As KeyValuePair(Of SFile, SFile) In audioReplace
|
||||||
|
If kvf.Key.Exists And kvf.Value.Exists Then
|
||||||
|
kvf.Key.Delete(,, silentEDP)
|
||||||
|
SFile.Rename(kvf.Value, kvf.Key,, silentEDP)
|
||||||
|
End If
|
||||||
|
Next
|
||||||
|
audioReplace.Clear()
|
||||||
|
End If
|
||||||
|
Else
|
||||||
|
File = trimFirstFile
|
||||||
|
If audioFiles.Count > 0 Then
|
||||||
|
For Each f In audioFiles
|
||||||
|
If Not f = File Then f.Delete(,, silentEDP)
|
||||||
|
Next
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
|
||||||
|
End If
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
End With
|
End With
|
||||||
@@ -1623,12 +1743,20 @@ Namespace API.YouTube.Objects
|
|||||||
If Not tmpPls.IsEmptyString Then PlaylistTitle = tmpPls
|
If Not tmpPls.IsEmptyString Then PlaylistTitle = tmpPls
|
||||||
End If
|
End If
|
||||||
|
|
||||||
|
Dim tmpTitle$
|
||||||
UserID = .Value("uploader_id")
|
UserID = .Value("uploader_id")
|
||||||
UserTitle = TitleHtmlConverter.Invoke(.Value("uploader"))
|
UserTitle = TitleHtmlConverter.Invoke(.Value("uploader"))
|
||||||
If Not UserTitle.IsEmptyString Then
|
If Not UserTitle.IsEmptyString Then
|
||||||
Dim tmpTitle$ = UserTitle.Replace("Topic", String.Empty).StringTrimEnd(" ", "-")
|
tmpTitle = UserTitle.Replace("Topic", String.Empty).StringTrimEnd(" ", "-")
|
||||||
If Not tmpTitle.IsEmptyString Then UserTitle = tmpTitle
|
If Not tmpTitle.IsEmptyString Then UserTitle = tmpTitle
|
||||||
End If
|
End If
|
||||||
|
If MyYouTubeSettings.ParseLongUserTitle Or UserTitle.IsEmptyString Then
|
||||||
|
tmpTitle = TitleHtmlConverter.Invoke(.Value("artist"))
|
||||||
|
If Not tmpTitle.IsEmptyString Then
|
||||||
|
If Not UserTitle.IsEmptyString AndAlso Not tmpTitle.Contains(UserTitle) Then tmpTitle = $"{UserTitle}, {tmpTitle}"
|
||||||
|
UserTitle = ListAddList(Nothing, tmpTitle.Split(","), CType(Function(v$) v.StringTrim, Func(Of Object, Object)), EDP.ReturnValue).ListToString(" & ").IfNullOrEmpty(UserTitle)
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
|
||||||
Dim ext$ = IIf(IsMusic,
|
Dim ext$ = IIf(IsMusic,
|
||||||
MyYouTubeSettings.DefaultAudioCodecMusic.Value.StringToLower,
|
MyYouTubeSettings.DefaultAudioCodecMusic.Value.StringToLower,
|
||||||
@@ -1655,6 +1783,8 @@ Namespace API.YouTube.Objects
|
|||||||
ParseThumbnails(.Self)
|
ParseThumbnails(.Self)
|
||||||
|
|
||||||
ParseSubtitles(.Self)
|
ParseSubtitles(.Self)
|
||||||
|
|
||||||
|
ParseChapters(.Self)
|
||||||
End With
|
End With
|
||||||
Return True
|
Return True
|
||||||
End If
|
End If
|
||||||
@@ -1724,8 +1854,12 @@ Namespace API.YouTube.Objects
|
|||||||
If If(e({"formats"})?.Count, 0) > 0 Then
|
If If(e({"formats"})?.Count, 0) > 0 Then
|
||||||
Dim obj As MediaObject
|
Dim obj As MediaObject
|
||||||
Dim nValue#
|
Dim nValue#
|
||||||
Dim sValue$
|
Dim sValue$ = String.Empty
|
||||||
Dim validCodecValue As Func(Of String, Boolean) = Function(codec) Not codec.IsEmptyString AndAlso Not codec = "none"
|
Dim allowWebm As Boolean = MyYouTubeSettings.DefaultVideoAllowWebm
|
||||||
|
Dim validCodecValue As Func(Of String, Boolean) = Function(ByVal codec As String) As Boolean
|
||||||
|
sValue = codec
|
||||||
|
Return Not codec.IsEmptyString AndAlso Not codec = "none"
|
||||||
|
End Function
|
||||||
|
|
||||||
For Each ee In e({"formats"})
|
For Each ee In e({"formats"})
|
||||||
obj = New MediaObject With {
|
obj = New MediaObject With {
|
||||||
@@ -1749,19 +1883,30 @@ Namespace API.YouTube.Objects
|
|||||||
If obj.Size <= 0 And obj.Bitrate > 0 And Duration.TotalSeconds > 0 Then _
|
If obj.Size <= 0 And obj.Bitrate > 0 And Duration.TotalSeconds > 0 Then _
|
||||||
obj.Size = (obj.Bitrate / 8 * Duration.TotalSeconds).RoundVal(2)
|
obj.Size = (obj.Bitrate / 8 * Duration.TotalSeconds).RoundVal(2)
|
||||||
|
|
||||||
sValue = ee.Value("vcodec")
|
'sValue = ee.Value("vcodec")
|
||||||
If validCodecValue(sValue) Then
|
If validCodecValue(ee.Value("vcodec")) Then
|
||||||
obj.Type = UMTypes.Video
|
obj.Type = UMTypes.Video
|
||||||
obj.Codec = sValue.Split(".").First
|
obj.Codec = sValue.Split(".").First
|
||||||
If validCodecValue(ee.Value("acodec")) Then obj.Type = av
|
If validCodecValue(ee.Value("acodec")) Then obj.Type = av
|
||||||
|
ElseIf validCodecValue(ee.Value("acodec")) Then
|
||||||
|
obj.Type = UMTypes.Audio
|
||||||
|
obj.Codec = sValue.Split(".").First
|
||||||
Else
|
Else
|
||||||
sValue = ee.Value("acodec")
|
Dim fd As Boolean = False
|
||||||
If validCodecValue(sValue) Then
|
sValue = ee.Value("format_note")
|
||||||
obj.Type = UMTypes.Audio
|
If Not sValue.IsEmptyString Then
|
||||||
obj.Codec = sValue.Split(".").First
|
With ListAddList(Nothing, sValue.Split(","), CType(Function(v) CStr(v).StringToLower.StringTrim, Func(Of Object, Object)), EDP.ReturnValue)
|
||||||
Else
|
If .ListContains({"high", "low"}) Then
|
||||||
Continue For
|
obj.Type = UMTypes.Audio
|
||||||
|
obj.Codec = ee.Value("ext")
|
||||||
|
If obj.Protocol.StringToLower.StartsWith("m3u8") Then obj.Protocol = "m3u8"
|
||||||
|
If obj.Bitrate <= 0 Then obj.Bitrate = IIf(.Contains("high"), 129, 53)
|
||||||
|
If obj.Size <= 0 Then obj.Size = 1
|
||||||
|
fd = True
|
||||||
|
End If
|
||||||
|
End With
|
||||||
End If
|
End If
|
||||||
|
If Not fd Then Continue For
|
||||||
End If
|
End If
|
||||||
MediaObjects.Add(obj)
|
MediaObjects.Add(obj)
|
||||||
Next
|
Next
|
||||||
@@ -1773,14 +1918,18 @@ Namespace API.YouTube.Objects
|
|||||||
Dim data As New List(Of MediaObject)(MediaObjects.Where(Function(mo) mo.Type = t And mo.Extension = webm))
|
Dim data As New List(Of MediaObject)(MediaObjects.Where(Function(mo) mo.Type = t And mo.Extension = webm))
|
||||||
If data.Count > 0 Then
|
If data.Count > 0 Then
|
||||||
Dim d As MediaObject = Nothing
|
Dim d As MediaObject = Nothing
|
||||||
Dim expWebm As Predicate(Of MediaObject) = Function(mo) mo.Extension = webm
|
Dim allWebm As Boolean = False, allAVC As Boolean = False
|
||||||
Dim expAVC As Predicate(Of MediaObject) = Function(mo) mo.Codec.IfNullOrEmpty("/").ToLower.StartsWith(avc)
|
Dim expWebm As Predicate(Of MediaObject) = Function(mo) Not allWebm And mo.Extension = webm
|
||||||
Dim comp As Func(Of MediaObject, Predicate(Of MediaObject), Boolean, Boolean) =
|
Dim expAVC As Predicate(Of MediaObject) = Function(mo) Not allAVC And mo.Codec.IfNullOrEmpty("/").ToLower.StartsWith(avc)
|
||||||
Function(mo, exp, isTrue) mo.Type = t And exp.Invoke(mo) = isTrue And mo.Width = d.Width
|
Dim comp As Func(Of MediaObject, Predicate(Of MediaObject), Boolean, Boolean, Boolean) =
|
||||||
Dim CountWebm As Func(Of MediaObject, Boolean) = Function(mo) comp.Invoke(mo, expWebm, False)
|
Function(mo, exp, isTrue, checkHttp) mo.Type = t And exp.Invoke(mo) = isTrue And mo.Width = d.Width And
|
||||||
Dim RemoveWebm As Predicate(Of MediaObject) = Function(mo) comp.Invoke(mo, expWebm, True)
|
(Not checkHttp OrElse mo.ProtocolType = Protocols.https)
|
||||||
Dim CountAVC As Func(Of MediaObject, Boolean) = Function(mo) comp.Invoke(mo, expAVC, True)
|
Dim CountWebm As Func(Of MediaObject, Boolean) = Function(mo) comp.Invoke(mo, expWebm, False, allowWebm)
|
||||||
Dim RemoveAVC As Predicate(Of MediaObject) = Function(mo) comp.Invoke(mo, expAVC, False)
|
Dim RemoveWebm As Predicate(Of MediaObject) = Function(mo) comp.Invoke(mo, expWebm, True, allowWebm)
|
||||||
|
Dim CountAVC As Func(Of MediaObject, Boolean) = Function(mo) comp.Invoke(mo, expAVC, True, False)
|
||||||
|
Dim RemoveAVC As Predicate(Of MediaObject) = Function(mo) comp.Invoke(mo, expAVC, False, False)
|
||||||
|
allWebm = data.All(FPredicate(Of MediaObject).ToFunc(expWebm))
|
||||||
|
allAVC = data.All(FPredicate(Of MediaObject).ToFunc(expAVC))
|
||||||
For Each d In data
|
For Each d In data
|
||||||
If MediaObjects.Count = 0 Then Exit For
|
If MediaObjects.Count = 0 Then Exit For
|
||||||
If MediaObjects.LongCount(CountWebm) > 0 Then MediaObjects.RemoveAll(RemoveWebm)
|
If MediaObjects.LongCount(CountWebm) > 0 Then MediaObjects.RemoveAll(RemoveWebm)
|
||||||
@@ -1901,6 +2050,15 @@ Namespace API.YouTube.Objects
|
|||||||
End With
|
End With
|
||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
|
Protected Sub ParseChapters(ByVal e As EContainer)
|
||||||
|
With e({"chapters"})
|
||||||
|
If .ListExists Then Chapters.AddRange(.Select(Function(ee) New TrimOption With {
|
||||||
|
.Start = CInt(AConvert(Of Double)(ee.Value("start_time"), 0, EDP.ReturnValue)),
|
||||||
|
.[End] = CInt(AConvert(Of Double)(ee.Value("end_time"), 0, EDP.ReturnValue)),
|
||||||
|
.Name = CleanFileName(New SFile With {.Name = ee.Value("title")}).Name
|
||||||
|
}))
|
||||||
|
End With
|
||||||
|
End Sub
|
||||||
#End Region
|
#End Region
|
||||||
#Region "IEContainerProvider Support"
|
#Region "IEContainerProvider Support"
|
||||||
Private Function GetElementsChecked() As IEnumerable(Of EContainer)
|
Private Function GetElementsChecked() As IEnumerable(Of EContainer)
|
||||||
@@ -1975,6 +2133,8 @@ Namespace API.YouTube.Objects
|
|||||||
_Subtitles.Clear()
|
_Subtitles.Clear()
|
||||||
_SubtitlesDelegated.Clear()
|
_SubtitlesDelegated.Clear()
|
||||||
SubtitlesSelectedIndexes.Clear()
|
SubtitlesSelectedIndexes.Clear()
|
||||||
|
Chapters.Clear()
|
||||||
|
TrimOptions.Clear()
|
||||||
MediaObjects.Clear()
|
MediaObjects.Clear()
|
||||||
_Files.Clear()
|
_Files.Clear()
|
||||||
PostProcessing_OutputAudioFormats.Clear()
|
PostProcessing_OutputAudioFormats.Clear()
|
||||||
|
|||||||
@@ -124,12 +124,37 @@
|
|||||||
<Compile Include="Controls\ChannelTabsChooserForm.vb">
|
<Compile Include="Controls\ChannelTabsChooserForm.vb">
|
||||||
<SubType>Form</SubType>
|
<SubType>Form</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="Controls\ChaptersForm.Designer.vb">
|
||||||
|
<DependentUpon>ChaptersForm.vb</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Controls\ChaptersForm.vb">
|
||||||
|
<SubType>Form</SubType>
|
||||||
|
</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\TrimOptionForm.Designer.vb">
|
||||||
|
<DependentUpon>TrimOptionForm.vb</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Controls\TrimOptionForm.vb">
|
||||||
|
<SubType>Form</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Controls\VideoOptionsTrimForm.Designer.vb">
|
||||||
|
<DependentUpon>VideoOptionsTrimForm.vb</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Controls\VideoOptionsTrimForm.vb">
|
||||||
|
<SubType>Form</SubType>
|
||||||
|
</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,9 +245,21 @@
|
|||||||
<EmbeddedResource Include="Controls\ChannelTabsChooserForm.resx">
|
<EmbeddedResource Include="Controls\ChannelTabsChooserForm.resx">
|
||||||
<DependentUpon>ChannelTabsChooserForm.vb</DependentUpon>
|
<DependentUpon>ChannelTabsChooserForm.vb</DependentUpon>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
|
<EmbeddedResource Include="Controls\ChaptersForm.resx">
|
||||||
|
<DependentUpon>ChaptersForm.vb</DependentUpon>
|
||||||
|
</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>
|
||||||
|
<EmbeddedResource Include="Controls\TrimOptionForm.resx">
|
||||||
|
<DependentUpon>TrimOptionForm.vb</DependentUpon>
|
||||||
|
</EmbeddedResource>
|
||||||
|
<EmbeddedResource Include="Controls\VideoOptionsTrimForm.resx">
|
||||||
|
<DependentUpon>VideoOptionsTrimForm.vb</DependentUpon>
|
||||||
|
</EmbeddedResource>
|
||||||
<EmbeddedResource Include="Downloader\MediaItem.resx">
|
<EmbeddedResource Include="Downloader\MediaItem.resx">
|
||||||
<DependentUpon>MediaItem.vb</DependentUpon>
|
<DependentUpon>MediaItem.vb</DependentUpon>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ Imports System.Runtime.InteropServices
|
|||||||
<Assembly: AssemblyDescription("SCrawler YouTube downloader")>
|
<Assembly: AssemblyDescription("SCrawler YouTube downloader")>
|
||||||
<Assembly: AssemblyCompany("AndyProgram")>
|
<Assembly: AssemblyCompany("AndyProgram")>
|
||||||
<Assembly: AssemblyProduct("SCrawler.YouTubeDownloader")>
|
<Assembly: AssemblyProduct("SCrawler.YouTubeDownloader")>
|
||||||
<Assembly: AssemblyCopyright("Copyright © 2024")>
|
<Assembly: AssemblyCopyright("Copyright © 2026")>
|
||||||
<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.8.10.0")>
|
<Assembly: AssemblyVersion("2025.11.25.0")>
|
||||||
<Assembly: AssemblyFileVersion("2024.8.10.0")>
|
<Assembly: AssemblyFileVersion("2025.11.25.0")>
|
||||||
<Assembly: NeutralResourcesLanguage("en")>
|
<Assembly: NeutralResourcesLanguage("en")>
|
||||||
|
|||||||
14
SCrawler.sln
@@ -29,6 +29,8 @@ Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "SCrawler.Updater", "SCrawle
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "SCrawler.Shared", "SCrawler.Shared\SCrawler.Shared.vbproj", "{DC634700-24C7-42DD-BF8F-87E6CC54E625}"
|
Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "SCrawler.Shared", "SCrawler.Shared\SCrawler.Shared.vbproj", "{DC634700-24C7-42DD-BF8F-87E6CC54E625}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "PersonalUtilities.Images", "..\..\MyUtilities\PersonalUtilities.Images\PersonalUtilities.Images.vbproj", "{B7EF76A9-96F3-4C53-B252-0AB5F79B67B3}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@@ -135,6 +137,18 @@ Global
|
|||||||
{DC634700-24C7-42DD-BF8F-87E6CC54E625}.Release|x64.Build.0 = Release|x64
|
{DC634700-24C7-42DD-BF8F-87E6CC54E625}.Release|x64.Build.0 = Release|x64
|
||||||
{DC634700-24C7-42DD-BF8F-87E6CC54E625}.Release|x86.ActiveCfg = Release|x86
|
{DC634700-24C7-42DD-BF8F-87E6CC54E625}.Release|x86.ActiveCfg = Release|x86
|
||||||
{DC634700-24C7-42DD-BF8F-87E6CC54E625}.Release|x86.Build.0 = Release|x86
|
{DC634700-24C7-42DD-BF8F-87E6CC54E625}.Release|x86.Build.0 = Release|x86
|
||||||
|
{B7EF76A9-96F3-4C53-B252-0AB5F79B67B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{B7EF76A9-96F3-4C53-B252-0AB5F79B67B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{B7EF76A9-96F3-4C53-B252-0AB5F79B67B3}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{B7EF76A9-96F3-4C53-B252-0AB5F79B67B3}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{B7EF76A9-96F3-4C53-B252-0AB5F79B67B3}.Debug|x86.ActiveCfg = Debug|x86
|
||||||
|
{B7EF76A9-96F3-4C53-B252-0AB5F79B67B3}.Debug|x86.Build.0 = Debug|x86
|
||||||
|
{B7EF76A9-96F3-4C53-B252-0AB5F79B67B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{B7EF76A9-96F3-4C53-B252-0AB5F79B67B3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{B7EF76A9-96F3-4C53-B252-0AB5F79B67B3}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{B7EF76A9-96F3-4C53-B252-0AB5F79B67B3}.Release|x64.Build.0 = Release|x64
|
||||||
|
{B7EF76A9-96F3-4C53-B252-0AB5F79B67B3}.Release|x86.ActiveCfg = Release|x86
|
||||||
|
{B7EF76A9-96F3-4C53-B252-0AB5F79B67B3}.Release|x86.Build.0 = Release|x86
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|||||||
@@ -28,6 +28,15 @@ Namespace API.Base
|
|||||||
Friend Const GifsDownloadCaption As String = "Download GIFs"
|
Friend Const GifsDownloadCaption As String = "Download GIFs"
|
||||||
Friend Const UseMD5ComparisonCaption As String = "Use MD5 comparison"
|
Friend Const UseMD5ComparisonCaption As String = "Use MD5 comparison"
|
||||||
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 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
|
||||||
|
|||||||
@@ -6,8 +6,9 @@
|
|||||||
'
|
'
|
||||||
' 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.Net
|
Imports SCrawler.Plugin
|
||||||
Imports PersonalUtilities.Functions.RegularExpressions
|
Imports PersonalUtilities.Functions.RegularExpressions
|
||||||
|
Imports Download = SCrawler.Plugin.ISiteSettings.Download
|
||||||
Namespace API.Base
|
Namespace API.Base
|
||||||
Friend NotInheritable Class DownDetector
|
Friend NotInheritable Class DownDetector
|
||||||
Private Shared ReadOnly Property Params As New RParams("x:.'([\S]+?)',.y:.(\d+)", -1, Nothing, RegexReturn.List)
|
Private Shared ReadOnly Property Params As New RParams("x:.'([\S]+?)',.y:.(\d+)", -1, Nothing, RegexReturn.List)
|
||||||
@@ -34,34 +35,106 @@ Namespace API.Base
|
|||||||
Try
|
Try
|
||||||
Dim l As List(Of Data) = Nothing
|
Dim l As List(Of Data) = Nothing
|
||||||
Dim l2 As List(Of Data) = Nothing
|
Dim l2 As List(Of Data) = Nothing
|
||||||
Using w As New WebClient
|
Dim r$ = GetWebString($"https://downdetector.co.uk/status/{Site}/",, EDP.ThrowException)
|
||||||
Dim r$ = w.DownloadString($"https://downdetector.co.uk/status/{Site}/")
|
If Not r.IsEmptyString Then
|
||||||
If Not r.IsEmptyString Then
|
l = RegexFields(Of Data)(r, {Params}, {1, 2})
|
||||||
l = RegexFields(Of Data)(r, {Params}, {1, 2})
|
If l.ListExists(2) Then
|
||||||
If l.ListExists(2) Then
|
l.Sort()
|
||||||
l.Sort()
|
l2 = New List(Of Data)
|
||||||
l2 = New List(Of Data)
|
Dim d As Data
|
||||||
Dim d As Data
|
Dim eDates As New List(Of Date)
|
||||||
Dim eDates As New List(Of Date)
|
Dim MaxValue As Func(Of Date, Integer) = Function(dd) (From ddd As Data In l Where ddd.Date = dd Select ddd.Value).DefaultIfEmpty(0).Max
|
||||||
Dim MaxValue As Func(Of Date, Integer) = Function(dd) (From ddd In l Where ddd.Date = dd Select ddd.Value).DefaultIfEmpty(0).Max
|
For i% = 0 To l.Count - 1
|
||||||
For i% = 0 To l.Count - 1
|
If Not eDates.Contains(l(i).Date) Then
|
||||||
If Not eDates.Contains(l(i).Date) Then
|
d = l(i)
|
||||||
d = l(i)
|
d.Value = MaxValue(d.Date)
|
||||||
d.Value = MaxValue(d.Date)
|
l2.Add(d)
|
||||||
l2.Add(d)
|
eDates.Add(d.Date)
|
||||||
eDates.Add(d.Date)
|
End If
|
||||||
End If
|
Next
|
||||||
Next
|
eDates.Clear()
|
||||||
eDates.Clear()
|
l.Clear()
|
||||||
l.Clear()
|
l2.Sort()
|
||||||
l2.Sort()
|
|
||||||
End If
|
|
||||||
End If
|
End If
|
||||||
End Using
|
End If
|
||||||
Return l2
|
Return l2
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
Return ErrorsDescriber.Execute(EDP.SendToLog + EDP.ReturnValue, ex, $"[DownDetector.GetData({Site})]")
|
Return ErrorsDescriber.Execute(EDP.SendToLog + EDP.ReturnValue, ex, $"[DownDetector.GetData({Site})]")
|
||||||
End Try
|
End Try
|
||||||
End Function
|
End Function
|
||||||
|
Friend Interface IDownDetector
|
||||||
|
ReadOnly Property Value As Integer
|
||||||
|
ReadOnly Property AddToLog As Boolean
|
||||||
|
ReadOnly Property CheckSite As String
|
||||||
|
Function Available(ByVal What As Download, ByVal Silent As Boolean) As Boolean
|
||||||
|
End Interface
|
||||||
|
Friend Class Checker(Of T As {ISiteSettings, IDownDetector})
|
||||||
|
Protected ReadOnly Property Source As T
|
||||||
|
Private ReadOnly NP As New ANumbers With {.FormatOptions = ANumbers.Options.GroupIntegral}
|
||||||
|
Friend Sub New(ByRef _Source As T)
|
||||||
|
Source = _Source
|
||||||
|
End Sub
|
||||||
|
Private ____AvailableChecked As Boolean = False
|
||||||
|
Private ____AvailableResult As Boolean = False
|
||||||
|
Friend Overridable Function Available(ByVal What As Download, ByVal Silent As Boolean) As Boolean
|
||||||
|
If Settings.DownDetectorEnabled And Source.Value >= 0 Then
|
||||||
|
If Not ____AvailableChecked Then
|
||||||
|
____AvailableResult = AvailableImpl(What, Silent)
|
||||||
|
____AvailableChecked = True
|
||||||
|
End If
|
||||||
|
Return ____AvailableResult
|
||||||
|
Else
|
||||||
|
Return True
|
||||||
|
End If
|
||||||
|
End Function
|
||||||
|
Protected Overridable Function AvailableImpl(ByVal What As Download, ByVal Silent As Boolean) As Boolean
|
||||||
|
Try
|
||||||
|
Source.AvailableText = String.Empty
|
||||||
|
If Source.Value < 0 Then
|
||||||
|
Return True
|
||||||
|
Else
|
||||||
|
Dim dl As List(Of Data) = GetData(Source.CheckSite)
|
||||||
|
If dl.ListExists Then
|
||||||
|
dl = dl.Take(4).ToList
|
||||||
|
Dim avg% = dl.Average(Function(d) d.Value)
|
||||||
|
If avg > Source.Value Then
|
||||||
|
Source.AvailableText = $"Over the past hour, {Source.Site} has received an average of {avg.NumToString(NP)} outage reports:{vbCr}{dl.ListToString(vbCr)}"
|
||||||
|
If Source.AddToLog Then MyMainLOG = Source.AvailableText
|
||||||
|
If Silent Then
|
||||||
|
Return AvailableImpl_FALSE_SILENT()
|
||||||
|
Else
|
||||||
|
If MsgBoxE({$"{Source.AvailableText}{vbCr}{vbCr}Do you want to continue parsing {Source.Site} data?",
|
||||||
|
$"There are outage reports on {Source.Site}"}, vbYesNo) = vbYes Then
|
||||||
|
Return AvailableImpl_FALSE_SILENT_NOT_MSG_YES()
|
||||||
|
Else
|
||||||
|
Return AvailableImpl_FALSE_SILENT_NOT_MSG_NO()
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
Return AvailableImpl_TRUE()
|
||||||
|
End If
|
||||||
|
Catch ex As Exception
|
||||||
|
Return ErrorsDescriber.Execute(EDP.SendToLog + EDP.ReturnValue, ex, $"[API.{Source.Site}.SiteSettings.Available([DownDetector])]", True)
|
||||||
|
End Try
|
||||||
|
End Function
|
||||||
|
Protected Overridable Function AvailableImpl_TRUE() As Boolean
|
||||||
|
Return True
|
||||||
|
End Function
|
||||||
|
Protected Overridable Function AvailableImpl_FALSE_SILENT() As Boolean
|
||||||
|
Return False
|
||||||
|
End Function
|
||||||
|
Protected Overridable Function AvailableImpl_FALSE_SILENT_NOT_MSG_YES() As Boolean
|
||||||
|
Return True
|
||||||
|
End Function
|
||||||
|
Protected Overridable Function AvailableImpl_FALSE_SILENT_NOT_MSG_NO() As Boolean
|
||||||
|
Return False
|
||||||
|
End Function
|
||||||
|
Friend Overridable Sub Reset()
|
||||||
|
____AvailableChecked = False
|
||||||
|
____AvailableResult = False
|
||||||
|
Source.AvailableText = String.Empty
|
||||||
|
End Sub
|
||||||
|
End Class
|
||||||
End Class
|
End Class
|
||||||
End Namespace
|
End Namespace
|
||||||
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
|
||||||
43
SCrawler/API/Base/EditorExchangeOptionsBase_P.vb
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
' 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.Base
|
||||||
|
Friend Interface IPSite
|
||||||
|
Property QueryString As String
|
||||||
|
End Interface
|
||||||
|
Friend Class EditorExchangeOptionsBase_P : Inherits EditorExchangeOptionsBase : Implements IPSite
|
||||||
|
<PSetting(Address:=SettingAddress.None)> Friend Overrides Property UserName As String
|
||||||
|
<PSetting(Address:=SettingAddress.None)> Friend Overrides Property DownloadText As Boolean
|
||||||
|
<PSetting(Address:=SettingAddress.None)> Friend Overrides Property DownloadTextPosts As Boolean
|
||||||
|
<PSetting(Address:=SettingAddress.None)> Friend Overrides Property DownloadTextSpecialFolder As Boolean
|
||||||
|
<PSetting(Address:=SettingAddress.User, Caption:="Query",
|
||||||
|
ToolTip:="Query string. Don't change this field when creating a user! Change it only for the same request.")>
|
||||||
|
Friend Property QueryString As String Implements IPSite.QueryString
|
||||||
|
Friend Sub New()
|
||||||
|
DisableBase()
|
||||||
|
End Sub
|
||||||
|
Friend Sub New(ByVal u As UserDataBase)
|
||||||
|
MyBase.New(u)
|
||||||
|
DisableBase()
|
||||||
|
If TypeOf u Is IPSite Then QueryString = DirectCast(u, IPSite).QueryString
|
||||||
|
End Sub
|
||||||
|
Friend Sub New(ByVal s As SiteSettingsBase)
|
||||||
|
MyBase.New(s)
|
||||||
|
DisableBase()
|
||||||
|
End Sub
|
||||||
|
Friend Overridable Sub Apply(ByRef u As IPSite)
|
||||||
|
ApplyBase(u)
|
||||||
|
u.QueryString = QueryString
|
||||||
|
End Sub
|
||||||
|
Protected Overridable Sub DisableBase()
|
||||||
|
_ApplyBase_Name = False
|
||||||
|
_ApplyBase_Text = False
|
||||||
|
End Sub
|
||||||
|
End Class
|
||||||
|
End Namespace
|
||||||
@@ -6,73 +6,12 @@
|
|||||||
'
|
'
|
||||||
' This program is distributed in the hope that it will be useful,
|
' This program is distributed in the hope that it will be useful,
|
||||||
' but WITHOUT ANY WARRANTY
|
' but WITHOUT ANY WARRANTY
|
||||||
Imports 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"
|
||||||
Friend Sub New(ByVal _Token As Threading.CancellationToken)
|
Friend Sub New(ByVal _Token As Threading.CancellationToken, Optional ByVal __MainProcessName As String = Nothing, Optional ByVal WorkingDir As SFile = Nothing)
|
||||||
MyBase.New(_Token)
|
MyBase.New(_Token, __MainProcessName.IfNullOrEmpty(Settings.GalleryDLFile.File.Name), WorkingDir.IfNullOrEmpty(Settings.GalleryDLFile.File))
|
||||||
MainProcessName = "gallery-dl"
|
|
||||||
ChangeDirectory(Settings.GalleryDLFile.File)
|
|
||||||
End Sub
|
End Sub
|
||||||
Protected Overrides Async Sub OutputDataReceiver(ByVal Sender As Object, ByVal e As DataReceivedEventArgs)
|
Protected Overrides Async Sub OutputDataReceiver(ByVal Sender As Object, ByVal e As DataReceivedEventArgs)
|
||||||
If Not ProcessKilled Then
|
If Not ProcessKilled Then
|
||||||
|
|||||||
@@ -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,30 @@ 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 ReadOnly Property IsPhotoType As Boolean
|
||||||
|
Get
|
||||||
|
Return Type = Types.Picture Or Type = Types.GIF
|
||||||
|
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 +145,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 +215,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 +227,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 +243,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 +289,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))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,10 +13,21 @@ Namespace API.Base
|
|||||||
Friend Property TempPostsList As List(Of String)
|
Friend Property TempPostsList As List(Of String)
|
||||||
Protected ReadOnly Token As CancellationToken
|
Protected ReadOnly Token As CancellationToken
|
||||||
Friend Property DebugMode As Boolean = False
|
Friend Property DebugMode As Boolean = False
|
||||||
Friend Sub New(ByVal _Token As CancellationToken)
|
Friend Overridable Property MyWorkingDirectory As SFile = Nothing
|
||||||
|
Friend Sub New(ByVal _Token As CancellationToken, Optional ByVal _MainProcessName As String = Nothing, Optional ByVal WorkingDir As SFile = Nothing)
|
||||||
MyBase.New(True)
|
MyBase.New(True)
|
||||||
Token = _Token
|
Token = _Token
|
||||||
|
MainProcessName = _MainProcessName
|
||||||
|
If Not WorkingDir.IsEmptyString Then ChangeDirectory(WorkingDir)
|
||||||
End Sub
|
End Sub
|
||||||
|
Public Overrides Sub ChangeDirectory(ByVal Directory As SFile)
|
||||||
|
MyBase.ChangeDirectory(Directory)
|
||||||
|
If Not Directory.IsEmptyString Then MyWorkingDirectory = Directory
|
||||||
|
End Sub
|
||||||
|
Protected Overrides Function Internal_Execute(ByVal Commands As IEnumerable(Of String), ByVal e As ErrorsDescriber) As Boolean
|
||||||
|
If Not Encoding.HasValue Then Encoding = UnicodeEncoding
|
||||||
|
Return MyBase.Internal_Execute(Commands, e)
|
||||||
|
End Function
|
||||||
Public Overrides Sub Create()
|
Public Overrides Sub Create()
|
||||||
If TempPostsList Is Nothing Then TempPostsList = New List(Of String)
|
If TempPostsList Is Nothing Then TempPostsList = New List(Of String)
|
||||||
MyBase.Create()
|
MyBase.Create()
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -80,6 +81,8 @@ Namespace API.Base
|
|||||||
Private _CollectionButtonsExists As Boolean = False
|
Private _CollectionButtonsExists As Boolean = False
|
||||||
Private _CollectionButtonsColorsSet As Boolean = False
|
Private _CollectionButtonsColorsSet As Boolean = False
|
||||||
Friend WithEvents BTT_CONTEXT_DOWN As ToolStripKeyMenuItem
|
Friend WithEvents BTT_CONTEXT_DOWN As ToolStripKeyMenuItem
|
||||||
|
Friend WithEvents BTT_CONTEXT_DOWN_LIMIT As ToolStripKeyMenuItem
|
||||||
|
Friend WithEvents BTT_CONTEXT_DOWN_DATE As ToolStripKeyMenuItem
|
||||||
Friend WithEvents BTT_CONTEXT_EDIT As ToolStripMenuItem
|
Friend WithEvents BTT_CONTEXT_EDIT As ToolStripMenuItem
|
||||||
Friend WithEvents BTT_CONTEXT_DELETE As ToolStripMenuItem
|
Friend WithEvents BTT_CONTEXT_DELETE As ToolStripMenuItem
|
||||||
Friend WithEvents BTT_CONTEXT_ERASE As ToolStripMenuItem
|
Friend WithEvents BTT_CONTEXT_ERASE As ToolStripMenuItem
|
||||||
@@ -98,6 +101,8 @@ Namespace API.Base
|
|||||||
End If
|
End If
|
||||||
End With
|
End With
|
||||||
BTT_CONTEXT_DOWN = New ToolStripKeyMenuItem(tn, i) With {.Name = tnn("DOWN"), .Tag = Me}
|
BTT_CONTEXT_DOWN = New ToolStripKeyMenuItem(tn, i) With {.Name = tnn("DOWN"), .Tag = Me}
|
||||||
|
BTT_CONTEXT_DOWN_LIMIT = New ToolStripKeyMenuItem(tn, i) With {.Name = tnn("DOWN_LIMIT"), .Tag = Me}
|
||||||
|
BTT_CONTEXT_DOWN_DATE = New ToolStripKeyMenuItem(tn, i) With {.Name = tnn("DOWN_DATE"), .Tag = Me}
|
||||||
BTT_CONTEXT_EDIT = New ToolStripMenuItem(tn, i) With {.Name = tnn("EDIT"), .Tag = Me}
|
BTT_CONTEXT_EDIT = New ToolStripMenuItem(tn, i) With {.Name = tnn("EDIT"), .Tag = Me}
|
||||||
BTT_CONTEXT_DELETE = New ToolStripMenuItem(tn, i) With {.Name = tnn("DELETE"), .Tag = Me}
|
BTT_CONTEXT_DELETE = New ToolStripMenuItem(tn, i) With {.Name = tnn("DELETE"), .Tag = Me}
|
||||||
BTT_CONTEXT_ERASE = New ToolStripMenuItem(tn, i) With {.Name = tnn("ERASE"), .Tag = Me}
|
BTT_CONTEXT_ERASE = New ToolStripMenuItem(tn, i) With {.Name = tnn("ERASE"), .Tag = Me}
|
||||||
@@ -117,7 +122,8 @@ Namespace API.Base
|
|||||||
cb = MyColor.EditBack
|
cb = MyColor.EditBack
|
||||||
cf = MyColor.EditFore
|
cf = MyColor.EditFore
|
||||||
End If
|
End If
|
||||||
For Each b As ToolStripMenuItem In {BTT_CONTEXT_DOWN, BTT_CONTEXT_EDIT, BTT_CONTEXT_DELETE, BTT_CONTEXT_ERASE,
|
For Each b As ToolStripMenuItem In {BTT_CONTEXT_DOWN, BTT_CONTEXT_DOWN_LIMIT, BTT_CONTEXT_DOWN_DATE,
|
||||||
|
BTT_CONTEXT_EDIT, BTT_CONTEXT_DELETE, BTT_CONTEXT_ERASE,
|
||||||
BTT_CONTEXT_OPEN_PATH, BTT_CONTEXT_OPEN_SITE}
|
BTT_CONTEXT_OPEN_PATH, BTT_CONTEXT_OPEN_SITE}
|
||||||
If Not b Is Nothing Then b.BackColor = cb : b.ForeColor = cf
|
If Not b Is Nothing Then b.BackColor = cb : b.ForeColor = cf
|
||||||
Next
|
Next
|
||||||
@@ -147,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"
|
||||||
@@ -162,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"
|
||||||
@@ -173,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
|
||||||
@@ -240,7 +252,20 @@ Namespace API.Base
|
|||||||
#End Region
|
#End Region
|
||||||
#Region "User name, ID, exist, suspend, options"
|
#Region "User name, ID, exist, suspend, options"
|
||||||
Friend User As UserInfo
|
Friend User As UserInfo
|
||||||
|
Private _IsSavedPosts As Boolean = False
|
||||||
Friend Property IsSavedPosts As Boolean Implements IPluginContentProvider.IsSavedPosts
|
Friend Property IsSavedPosts As Boolean Implements IPluginContentProvider.IsSavedPosts
|
||||||
|
Get
|
||||||
|
Return _IsSavedPosts
|
||||||
|
End Get
|
||||||
|
Set(ByVal __IsSavedPosts As Boolean)
|
||||||
|
_IsSavedPosts = __IsSavedPosts
|
||||||
|
If _IsSavedPosts Then
|
||||||
|
DownloadText = True
|
||||||
|
DownloadTextPosts = True
|
||||||
|
DownloadTextSpecialFolder = True
|
||||||
|
End If
|
||||||
|
End Set
|
||||||
|
End Property
|
||||||
Private _UserExists As Boolean = True
|
Private _UserExists As Boolean = True
|
||||||
Friend Overridable Property UserExists As Boolean Implements IUserData.Exists, IPluginContentProvider.UserExists
|
Friend Overridable Property UserExists As Boolean Implements IUserData.Exists, IPluginContentProvider.UserExists
|
||||||
Get
|
Get
|
||||||
@@ -273,7 +298,31 @@ Namespace API.Base
|
|||||||
Return User.Name
|
Return User.Name
|
||||||
End Get
|
End Get
|
||||||
End Property
|
End Property
|
||||||
Friend Overridable Property ID As String = String.Empty Implements IUserData.ID, IPluginContentProvider.ID
|
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
|
||||||
|
Private _ID As String = String.Empty
|
||||||
|
Friend Property ID As String Implements IUserData.ID, IPluginContentProvider.ID
|
||||||
|
Get
|
||||||
|
Return _ID
|
||||||
|
End Get
|
||||||
|
Set(ByVal NewId As String)
|
||||||
|
If Not _ID = NewId Then EnvirChanged(NewId)
|
||||||
|
_ID = NewId
|
||||||
|
End Set
|
||||||
|
End Property
|
||||||
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
|
||||||
Get
|
Get
|
||||||
@@ -343,12 +392,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
|
||||||
@@ -609,6 +666,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
|
||||||
@@ -720,9 +780,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
|
||||||
@@ -902,6 +976,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)
|
||||||
@@ -929,9 +1007,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)(IsSavedPosts)
|
||||||
|
DownloadTextPosts = x.Value(Name_DownloadTextPosts).FromXML(Of Boolean)(IsSavedPosts)
|
||||||
|
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)
|
||||||
@@ -947,6 +1029,9 @@ BlockNullPicture:
|
|||||||
LogError(ex, "user information loading error")
|
LogError(ex, "user information loading error")
|
||||||
End Try
|
End Try
|
||||||
End Sub
|
End Sub
|
||||||
|
Private Sub UpdateUserInformation_Ex()
|
||||||
|
If _ForceSaveUserInfoOnException Then UpdateUserInformation()
|
||||||
|
End Sub
|
||||||
Friend Overridable Overloads Sub UpdateUserInformation() Implements IUserData.UpdateUserInformation
|
Friend Overridable Overloads Sub UpdateUserInformation() Implements IUserData.UpdateUserInformation
|
||||||
UpdateUserInformation(False)
|
UpdateUserInformation(False)
|
||||||
End Sub
|
End Sub
|
||||||
@@ -959,6 +1044,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)
|
||||||
@@ -987,9 +1073,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)
|
||||||
@@ -1117,6 +1207,7 @@ BlockNullPicture:
|
|||||||
Protected UseClientTokens As Boolean = False
|
Protected UseClientTokens As Boolean = False
|
||||||
Protected _ForceSaveUserData As Boolean = False
|
Protected _ForceSaveUserData As Boolean = False
|
||||||
Protected _ForceSaveUserInfo As Boolean = False
|
Protected _ForceSaveUserInfo As Boolean = False
|
||||||
|
Protected _ForceSaveUserInfoOnException As Boolean = False
|
||||||
Private _DownloadInProgress As Boolean = False
|
Private _DownloadInProgress As Boolean = False
|
||||||
Private _EnvirUserExists As Boolean
|
Private _EnvirUserExists As Boolean
|
||||||
Private _EnvirUserSuspended As Boolean
|
Private _EnvirUserSuspended As Boolean
|
||||||
@@ -1136,6 +1227,7 @@ BlockNullPicture:
|
|||||||
_DescriptionEveryTime = Settings.UpdateUserDescriptionEveryTime
|
_DescriptionEveryTime = Settings.UpdateUserDescriptionEveryTime
|
||||||
_ForceSaveUserData = False
|
_ForceSaveUserData = False
|
||||||
_ForceSaveUserInfo = False
|
_ForceSaveUserInfo = False
|
||||||
|
_ForceSaveUserInfoOnException = False
|
||||||
_EnvirUserExists = UserExists
|
_EnvirUserExists = UserExists
|
||||||
_EnvirUserSuspended = UserSuspended
|
_EnvirUserSuspended = UserSuspended
|
||||||
_EnvirCreatedByChannel = CreatedByChannel
|
_EnvirCreatedByChannel = CreatedByChannel
|
||||||
@@ -1152,6 +1244,8 @@ 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 : _ForceSaveUserInfo = True : _ForceSaveUserInfoOnException = True
|
||||||
|
Case NameOf(ID) : _EnvirChanged = True : _ForceSaveUserInfo = True : _ForceSaveUserInfoOnException = True
|
||||||
Case Else : _EnvirChanged = True
|
Case Else : _EnvirChanged = True
|
||||||
End Select
|
End Select
|
||||||
End If
|
End If
|
||||||
@@ -1205,6 +1299,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
|
||||||
|
|
||||||
@@ -1265,21 +1360,26 @@ BlockNullPicture:
|
|||||||
ThrowIfDisposed()
|
ThrowIfDisposed()
|
||||||
If Not _PictureExists Or _EnvirInvokeUserUpdated Then OnUserUpdated()
|
If Not _PictureExists Or _EnvirInvokeUserUpdated Then OnUserUpdated()
|
||||||
Catch oex As OperationCanceledException When Token.IsCancellationRequested Or TokenPersonal.IsCancellationRequested Or TokenQueue.IsCancellationRequested
|
Catch oex As OperationCanceledException When Token.IsCancellationRequested Or TokenPersonal.IsCancellationRequested Or TokenQueue.IsCancellationRequested
|
||||||
|
UpdateUserInformation_Ex()
|
||||||
MyMainLOG = $"{ToStringForLog()}: downloading canceled"
|
MyMainLOG = $"{ToStringForLog()}: downloading canceled"
|
||||||
Canceled = True
|
Canceled = True
|
||||||
Catch exit_ex As ExitException
|
Catch exit_ex As ExitException
|
||||||
|
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()
|
||||||
Canceled = True
|
Canceled = True
|
||||||
Catch dex As ObjectDisposedException When Disposed
|
Catch dex As ObjectDisposedException When Disposed
|
||||||
Canceled = True
|
Canceled = True
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
|
UpdateUserInformation_Ex()
|
||||||
LogError(ex, "downloading data error")
|
LogError(ex, "downloading data error")
|
||||||
|
If _EnvirInvokeUserUpdated Then OnUserUpdated()
|
||||||
HasError = True
|
HasError = True
|
||||||
Finally
|
Finally
|
||||||
If Not UserExists Then AddNonExistingUserToLog($"User '{ToStringForLog()}' not found on the site")
|
If Not UserExists Then AddNonExistingUserToLog($"User '{ToStringForLog()}' not found on the site")
|
||||||
@@ -1339,6 +1439,16 @@ BlockNullPicture:
|
|||||||
Cache.Validate()
|
Cache.Validate()
|
||||||
Return Cache
|
Return Cache
|
||||||
End Function
|
End Function
|
||||||
|
#Region "GDL File Names"
|
||||||
|
Protected GDLFileNameProvider As ANumbers = Nothing
|
||||||
|
Protected Sub GDLResetFileNameProvider(Optional ByVal GroupSize As Integer? = Nothing)
|
||||||
|
GDLFileNameProvider = New ANumbers With {.FormatOptions = ANumbers.Options.FormatNumberGroup + ANumbers.Options.Groups}
|
||||||
|
GDLFileNameProvider.GroupSize = If(GroupSize, 3)
|
||||||
|
End Sub
|
||||||
|
Protected Function GDLRenameFile(ByVal Input As SFile, ByVal i As Integer) As SFile
|
||||||
|
Return SFile.Rename(Input, $"{Input.PathWithSeparator}{i.NumToString(GDLFileNameProvider)}.{Input.Extension}",, EDP.ThrowException)
|
||||||
|
End Function
|
||||||
|
#End Region
|
||||||
#Region "DownloadSingleObject"
|
#Region "DownloadSingleObject"
|
||||||
Protected IsSingleObjectDownload As Boolean = False
|
Protected IsSingleObjectDownload As Boolean = False
|
||||||
Friend Overridable Sub DownloadSingleObject(ByVal Data As YouTube.Objects.IYouTubeMediaContainer, ByVal Token As CancellationToken) Implements IUserData.DownloadSingleObject
|
Friend Overridable Sub DownloadSingleObject(ByVal Data As YouTube.Objects.IYouTubeMediaContainer, ByVal Token As CancellationToken) Implements IUserData.DownloadSingleObject
|
||||||
@@ -1415,6 +1525,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
|
||||||
@@ -1612,7 +1723,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)
|
||||||
@@ -1621,7 +1733,8 @@ 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 postProcessWebp As Boolean
|
||||||
|
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
|
||||||
@@ -1635,18 +1748,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)
|
||||||
@@ -1678,9 +1793,11 @@ BlockNullPicture:
|
|||||||
If v.URL_BASE.IsEmptyString Then v.URL_BASE = v.URL
|
If v.URL_BASE.IsEmptyString Then v.URL_BASE = v.URL
|
||||||
|
|
||||||
__fileDeleted = False
|
__fileDeleted = False
|
||||||
|
postProcessWebp = 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
|
||||||
@@ -1689,8 +1806,9 @@ BlockNullPicture:
|
|||||||
Case UTypes.Video, UTypes.m3u8 : f.Extension = "mp4"
|
Case UTypes.Video, UTypes.m3u8 : f.Extension = "mp4"
|
||||||
Case UTypes.GIF : f.Extension = "gif"
|
Case UTypes.GIF : f.Extension = "gif"
|
||||||
End Select
|
End Select
|
||||||
ElseIf f.Extension = "webp" And Settings.DownloadNativeImageFormat Then
|
ElseIf f.Extension = UserImage.ExtWebp And Settings.DownloadNativeImageFormat And Settings.FfmpegFile.Exists Then
|
||||||
f.Extension = "jpg"
|
'f.Extension = "jpg"
|
||||||
|
postProcessWebp = True
|
||||||
End If
|
End If
|
||||||
|
|
||||||
If Not v.SpecialFolder.IsEmptyString Then
|
If Not v.SpecialFolder.IsEmptyString Then
|
||||||
@@ -1723,9 +1841,9 @@ BlockNullPicture:
|
|||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
|
|
||||||
updateDownCount()
|
updateDownCount(False)
|
||||||
|
|
||||||
v.File = ChangeFileNameByProvider(f, v)
|
v.File = DownloadContentDefault_ConvertWebp(ChangeFileNameByProvider(f, v), postProcessWebp)
|
||||||
v.State = UStates.Downloaded
|
v.State = UStates.Downloaded
|
||||||
DownloadContentDefault_PostProcessing(v, f, Token)
|
DownloadContentDefault_PostProcessing(v, f, Token)
|
||||||
If UseMD5Comparison And (v.Type = UTypes.GIF Or v.Type = UTypes.Picture) Then
|
If UseMD5Comparison And (v.Type = UTypes.GIF Or v.Type = UTypes.Picture) Then
|
||||||
@@ -1734,7 +1852,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
|
||||||
@@ -1743,7 +1861,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
|
||||||
@@ -1751,7 +1895,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)
|
||||||
@@ -1799,6 +1943,22 @@ BlockNullPicture:
|
|||||||
End Function
|
End Function
|
||||||
Protected Overridable Sub DownloadContentDefault_PostProcessing(ByRef m As UserMedia, ByVal File As SFile, ByVal Token As CancellationToken)
|
Protected Overridable Sub DownloadContentDefault_PostProcessing(ByRef m As UserMedia, ByVal File As SFile, ByVal Token As CancellationToken)
|
||||||
End Sub
|
End Sub
|
||||||
|
Protected Overridable Function DownloadContentDefault_ConvertWebp(ByVal WebpFile As SFile, ByVal Process As Boolean) As SFile
|
||||||
|
Dim f As SFile = WebpFile
|
||||||
|
If Process AndAlso f.Exists Then
|
||||||
|
f.Path = $"{f.PathWithSeparator}Sources"
|
||||||
|
f.Exists(SFO.Path)
|
||||||
|
If WebpFile.Copy(f) Then
|
||||||
|
Dim newFile As SFile = WebpFile
|
||||||
|
newFile.Extension = UserImage.ExtJpg
|
||||||
|
f = UserImage.ConvertWebp(f, newFile)
|
||||||
|
If f.Exists Then WebpFile.Delete(SFO.File, SFODelete.DeletePermanently, EDP.ReturnValue)
|
||||||
|
Else
|
||||||
|
f = WebpFile
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
Return f
|
||||||
|
End Function
|
||||||
Protected Overridable Function DownloadContentDefault_ProcessDownloadException() As Boolean
|
Protected Overridable Function DownloadContentDefault_ProcessDownloadException() As Boolean
|
||||||
Return True
|
Return True
|
||||||
End Function
|
End Function
|
||||||
@@ -1831,6 +1991,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
|
||||||
@@ -1912,13 +2097,14 @@ BlockNullPicture:
|
|||||||
If m.Contains(IUserData.EraseMode.History) Then
|
If m.Contains(IUserData.EraseMode.History) Then
|
||||||
If MyFilePosts.Delete(SFO.File, SFODelete.DeleteToRecycleBin, e) Then result = True
|
If MyFilePosts.Delete(SFO.File, SFODelete.DeleteToRecycleBin, e) Then result = True
|
||||||
If MyFileData.Delete(SFO.File, SFODelete.DeleteToRecycleBin, e) Then result = True
|
If MyFileData.Delete(SFO.File, SFODelete.DeleteToRecycleBin, e) Then result = True
|
||||||
|
If MyMD5File.Delete(SFO.File, SFODelete.DeleteToRecycleBin, e) Then result = True
|
||||||
LastUpdated = Nothing
|
LastUpdated = Nothing
|
||||||
EraseData_AdditionalDataFiles()
|
EraseData_AdditionalDataFiles()
|
||||||
UpdateUserInformation()
|
UpdateUserInformation()
|
||||||
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
|
||||||
@@ -1928,6 +2114,8 @@ BlockNullPicture:
|
|||||||
_TempMediaList.Clear()
|
_TempMediaList.Clear()
|
||||||
_ContentNew.Clear()
|
_ContentNew.Clear()
|
||||||
_ContentList.Clear()
|
_ContentList.Clear()
|
||||||
|
_MD5List.Clear()
|
||||||
|
_MD5Loaded = False
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
@@ -2129,6 +2317,7 @@ BlockNullPicture:
|
|||||||
End Function
|
End Function
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Errors functions"
|
#Region "Errors functions"
|
||||||
|
''' <summary>ToStringForLog(): Message</summary>
|
||||||
Protected Sub LogError(ByVal ex As Exception, ByVal Message As String, Optional ByVal e As ErrorsDescriber = Nothing)
|
Protected Sub LogError(ByVal ex As Exception, ByVal Message As String, Optional ByVal e As ErrorsDescriber = Nothing)
|
||||||
ErrorsDescriber.Execute(If(e.Exists, e, New ErrorsDescriber(EDP.SendToLog)), ex, $"{ToStringForLog()}: {Message}")
|
ErrorsDescriber.Execute(If(e.Exists, e, New ErrorsDescriber(EDP.SendToLog)), ex, $"{ToStringForLog()}: {Message}")
|
||||||
End Sub
|
End Sub
|
||||||
@@ -2159,6 +2348,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
|
||||||
@@ -2180,6 +2380,12 @@ BlockNullPicture:
|
|||||||
Private Sub BTT_CONTEXT_DOWN_KeyClick(sender As Object, e As MyKeyEventArgs) Handles BTT_CONTEXT_DOWN.KeyClick
|
Private Sub BTT_CONTEXT_DOWN_KeyClick(sender As Object, e As MyKeyEventArgs) Handles BTT_CONTEXT_DOWN.KeyClick
|
||||||
Downloader.Add(Me, e.IncludeInTheFeed)
|
Downloader.Add(Me, e.IncludeInTheFeed)
|
||||||
End Sub
|
End Sub
|
||||||
|
Private Sub BTT_CONTEXT_DOWN_LIMIT_KeyClick(sender As Object, e As MyKeyEventArgs) Handles BTT_CONTEXT_DOWN_LIMIT.KeyClick
|
||||||
|
ControlInvokeFast(MainFrameObj.MF, Sub() MainFrameObj.MF.DownloadSelectedUser(MainFrame.DownUserLimits.Number, e.IncludeInTheFeed, Me), EDP.SendToLog)
|
||||||
|
End Sub
|
||||||
|
Private Sub BTT_CONTEXT_DOWN_DATE_KeyClick(sender As Object, e As MyKeyEventArgs) Handles BTT_CONTEXT_DOWN_DATE.KeyClick
|
||||||
|
ControlInvokeFast(MainFrameObj.MF, Sub() MainFrameObj.MF.DownloadSelectedUser(MainFrame.DownUserLimits.Date, e.IncludeInTheFeed, Me), EDP.SendToLog)
|
||||||
|
End Sub
|
||||||
Private Sub BTT_CONTEXT_EDIT_Click(sender As Object, e As EventArgs) Handles BTT_CONTEXT_EDIT.Click
|
Private Sub BTT_CONTEXT_EDIT_Click(sender As Object, e As EventArgs) Handles BTT_CONTEXT_EDIT.Click
|
||||||
Using f As New Editors.UserCreatorForm(Me)
|
Using f As New Editors.UserCreatorForm(Me)
|
||||||
f.ShowDialog()
|
f.ShowDialog()
|
||||||
@@ -2257,9 +2463,12 @@ BlockNullPicture:
|
|||||||
_TempPostsList.Clear()
|
_TempPostsList.Clear()
|
||||||
_MD5List.Clear()
|
_MD5List.Clear()
|
||||||
TokenPersonal = Nothing
|
TokenPersonal = Nothing
|
||||||
|
GDLFileNameProvider = Nothing
|
||||||
If Not ProgressPre Is Nothing Then ProgressPre.Reset() : ProgressPre.Dispose()
|
If Not ProgressPre Is Nothing Then ProgressPre.Reset() : ProgressPre.Dispose()
|
||||||
If Not Responser Is Nothing Then Responser.Dispose()
|
If Not Responser Is Nothing Then Responser.Dispose()
|
||||||
If Not BTT_CONTEXT_DOWN Is Nothing Then BTT_CONTEXT_DOWN.Dispose()
|
If Not BTT_CONTEXT_DOWN Is Nothing Then BTT_CONTEXT_DOWN.Dispose()
|
||||||
|
If Not BTT_CONTEXT_DOWN_LIMIT Is Nothing Then BTT_CONTEXT_DOWN_LIMIT.Dispose()
|
||||||
|
If Not BTT_CONTEXT_DOWN_DATE Is Nothing Then BTT_CONTEXT_DOWN_DATE.Dispose()
|
||||||
If Not BTT_CONTEXT_EDIT Is Nothing Then BTT_CONTEXT_EDIT.Dispose()
|
If Not BTT_CONTEXT_EDIT Is Nothing Then BTT_CONTEXT_EDIT.Dispose()
|
||||||
If Not BTT_CONTEXT_DELETE Is Nothing Then BTT_CONTEXT_DELETE.Dispose()
|
If Not BTT_CONTEXT_DELETE Is Nothing Then BTT_CONTEXT_DELETE.Dispose()
|
||||||
If Not BTT_CONTEXT_ERASE Is Nothing Then BTT_CONTEXT_ERASE.Dispose()
|
If Not BTT_CONTEXT_ERASE Is Nothing Then BTT_CONTEXT_ERASE.Dispose()
|
||||||
|
|||||||
@@ -8,11 +8,8 @@
|
|||||||
' but WITHOUT ANY WARRANTY
|
' but WITHOUT ANY WARRANTY
|
||||||
Namespace API.Base.YTDLP
|
Namespace API.Base.YTDLP
|
||||||
Friend Class YTDLPBatch : Inherits GDL.GDLBatch
|
Friend Class YTDLPBatch : Inherits GDL.GDLBatch
|
||||||
Friend Sub New(ByVal _Token As Threading.CancellationToken)
|
Friend Sub New(ByVal _Token As Threading.CancellationToken, Optional ByVal __MainProcessName As String = Nothing, Optional ByVal WorkingDir As SFile = Nothing)
|
||||||
MyBase.New(_Token)
|
MyBase.New(_Token, __MainProcessName.IfNullOrEmpty(Settings.YtdlpFile.File.Name), WorkingDir.IfNullOrEmpty(Settings.YtdlpFile.File))
|
||||||
Commands.Clear()
|
|
||||||
MainProcessName = Settings.YtdlpFile.File.Name '"yt-dlp"
|
|
||||||
ChangeDirectory(Settings.YtdlpFile.File)
|
|
||||||
End Sub
|
End Sub
|
||||||
End Class
|
End Class
|
||||||
End Namespace
|
End Namespace
|
||||||
@@ -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), SavedPosts>
|
||||||
|
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
|
||||||
382
SCrawler/API/Bluesky/UserData.vb
Normal file
@@ -0,0 +1,382 @@
|
|||||||
|
' 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
|
||||||
|
Private ReadOnly _TmpPosts2 As List(Of String)
|
||||||
|
#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
|
||||||
|
_TmpPosts2 = New List(Of String)
|
||||||
|
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)
|
||||||
|
_TmpPosts2.Clear()
|
||||||
|
Try
|
||||||
|
If Not CBool(MySettings.CookiesEnabled.Value) Then Responser.Cookies.Clear()
|
||||||
|
UpdateToken(, True)
|
||||||
|
_TokenUpdateCount = 0
|
||||||
|
_PostCount = 0
|
||||||
|
DownloadData(String.Empty, Token)
|
||||||
|
Finally
|
||||||
|
_TempPostsList.ListAddList(_TmpPosts2, LNC)
|
||||||
|
_TmpPosts2.Clear()
|
||||||
|
End Try
|
||||||
|
End Sub
|
||||||
|
Private Overloads Sub DownloadData(ByVal Cursor As String, ByVal Token As CancellationToken)
|
||||||
|
Dim URL$ = String.Empty
|
||||||
|
Try
|
||||||
|
If Not IsSavedPosts And ID.IsEmptyString Then GetProfileInfo(Token)
|
||||||
|
If Not IsSavedPosts And ID.IsEmptyString Then Throw New ArgumentNullException("ID", "ID is null")
|
||||||
|
If UpdateToken() Then
|
||||||
|
Dim nextCursor$ = String.Empty
|
||||||
|
Dim c%
|
||||||
|
Dim n$(), p$()
|
||||||
|
If IsSavedPosts Then
|
||||||
|
URL = "https://bsky.social/xrpc/app.bsky.bookmark.getBookmarks"
|
||||||
|
If Not Cursor.IsEmptyString Then URL &= $"?cursor={Cursor}"
|
||||||
|
n = {"bookmarks"}
|
||||||
|
p = {"item"}
|
||||||
|
Else
|
||||||
|
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)}"
|
||||||
|
n = {"feed"}
|
||||||
|
p = {"post"}
|
||||||
|
End If
|
||||||
|
Dim r$ = Responser.GetResponse(URL)
|
||||||
|
TokenUpdateCountReset()
|
||||||
|
If Not r.IsEmptyString Then
|
||||||
|
Using j As EContainer = JsonDocument.Parse(r)
|
||||||
|
If j.ListExists Then
|
||||||
|
nextCursor = j.Value("cursor")
|
||||||
|
With j(n)
|
||||||
|
If .ListExists Then
|
||||||
|
For Each post As EContainer In .Self
|
||||||
|
With post(p)
|
||||||
|
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
|
||||||
|
ElseIf IsSavedPosts Then
|
||||||
|
nextCursor = String.Empty
|
||||||
|
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
|
||||||
|
Const skipReturn% = CInt(DateResult.Skip) * -1
|
||||||
|
Dim postID$, postDate$, __url$, __urlBase$, __txt$, __userId$, __postAuthor$
|
||||||
|
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
|
||||||
|
__userId = .Value({"author"}, "did")
|
||||||
|
__postAuthor = String.Empty
|
||||||
|
With .Item({"record"})
|
||||||
|
If .ListExists Then
|
||||||
|
'2025-01-28T02:42:12.415Z
|
||||||
|
postDate = .Value("createdAt")
|
||||||
|
If Not IsSavedPosts Then NextCursor = postDate
|
||||||
|
If CheckDateLimits Then
|
||||||
|
Select Case CheckDatesLimit(postDate, DateProvider)
|
||||||
|
Case DateResult.Skip : Return skipReturn '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)
|
||||||
|
If _TempPostsList.Contains(postID) Then Return exitReturn Else _TmpPosts2.Add(postID)
|
||||||
|
End If
|
||||||
|
|
||||||
|
If ParseUserMediaOnly And Not IsSavedPosts And Not ID.IsEmptyString And Not __userId.IsEmptyString And Not ID = __userId Then Return skipReturn
|
||||||
|
|
||||||
|
__postAuthor = e.Value({"author"}, "did")
|
||||||
|
__urlBase = $"https://bsky.app/profile/{If(IsSavedPosts, __postAuthor, 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
|
||||||
|
If updateUrl AndAlso Not __url.StartsWith("http") Then _
|
||||||
|
__url = $"https://cdn.bsky.app/img/feed_fullsize/plain/{__postAuthor}/{__url}@jpeg"
|
||||||
|
createMedia(__url, UTypes.Picture)
|
||||||
|
End If
|
||||||
|
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
|
||||||
|
#Region "IDisposable Support"
|
||||||
|
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
|
||||||
|
If disposing Then _TmpPosts2.Clear()
|
||||||
|
MyBase.Dispose(disposing)
|
||||||
|
End Sub
|
||||||
|
#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
|
||||||
@@ -540,10 +676,7 @@ Namespace API.Facebook
|
|||||||
End If
|
End If
|
||||||
Token_Photosby = RegexReplace(r, Regex_Photos_by)
|
Token_Photosby = RegexReplace(r, Regex_Photos_by)
|
||||||
If StoryBucket.IsEmptyString Then StoryBucket = RegexReplace(r, Regex_StoryBucket)
|
If StoryBucket.IsEmptyString Then StoryBucket = RegexReplace(r, Regex_StoryBucket)
|
||||||
If ID.IsEmptyString Then
|
If ID.IsEmptyString Then ID = RegexReplace(r, Regex_UserID)
|
||||||
ID = RegexReplace(r, Regex_UserID)
|
|
||||||
If Not ID.IsEmptyString Then _ForceSaveUserInfo = True
|
|
||||||
End If
|
|
||||||
End If
|
End If
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
ProcessException(ex, Token, "get user token",, resp)
|
ProcessException(ex, Token, "get user token",, resp)
|
||||||
@@ -658,17 +791,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 +832,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 +910,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
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ Namespace API.Instagram
|
|||||||
Friend Const PageTokenRegexPatternDefault As String = "\[\],{""token"":""(.*?)""},\d+\]"
|
Friend Const PageTokenRegexPatternDefault As String = "\[\],{""token"":""(.*?)""},\d+\]"
|
||||||
Friend ReadOnly Regex_UserToken_dtsg As RParams = RParams.DMS("DTSGInitialData["":,.\[\]]*?{\s*.token.:\s*""([^""]+)", 1, EDP.ReturnValue)
|
Friend ReadOnly Regex_UserToken_dtsg As RParams = RParams.DMS("DTSGInitialData["":,.\[\]]*?{\s*.token.:\s*""([^""]+)", 1, EDP.ReturnValue)
|
||||||
Friend ReadOnly Regex_UserToken_lsd As RParams = RParams.DMS("LSD["":,.\[\]]*?{\s*.token.:\s*""([^""]+)", 1, EDP.ReturnValue)
|
Friend ReadOnly Regex_UserToken_lsd As RParams = RParams.DMS("LSD["":,.\[\]]*?{\s*.token.:\s*""([^""]+)", 1, EDP.ReturnValue)
|
||||||
|
Friend ReadOnly Regex_ProfileID As RParams = RParams.DMS("profilePage_(\d+)", 1, EDP.ReturnValue)
|
||||||
Friend Sub UpdateResponser(ByVal Source As IResponse, ByRef Destination As Responser, ByVal UpdateWwwClaim As Boolean)
|
Friend Sub UpdateResponser(ByVal Source As IResponse, ByRef Destination As Responser, ByVal UpdateWwwClaim As Boolean)
|
||||||
Const r_wwwClaimName$ = "x-ig-set-www-claim"
|
Const r_wwwClaimName$ = "x-ig-set-www-claim"
|
||||||
Const r_tokenName$ = SiteSettings.Header_CSRF_TOKEN_COOKIE
|
Const r_tokenName$ = SiteSettings.Header_CSRF_TOKEN_COOKIE
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
' but WITHOUT ANY WARRANTY
|
' but WITHOUT ANY WARRANTY
|
||||||
Imports SCrawler.Plugin.Attributes
|
Imports SCrawler.Plugin.Attributes
|
||||||
Namespace API.Instagram
|
Namespace API.Instagram
|
||||||
Friend 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
|
||||||
@@ -35,7 +35,15 @@ 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
|
||||||
|
Friend Overrides Property UserName As String
|
||||||
|
<PSetting(Address:=SettingAddress.User, Caption:="Verified profile", ToolTip:="This profile has a verified mark")>
|
||||||
|
Friend Property IsVerifiedProfile As Boolean = False
|
||||||
|
<PSetting(Address:=SettingAddress.User, Caption:="Force update UserName", ToolTip:="Try to force update UserName if it is not found on the site")>
|
||||||
|
Friend Property ForceUpdateUserName As Boolean = False
|
||||||
|
<PSetting(Address:=SettingAddress.User, Caption:="Force update user information")>
|
||||||
|
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
|
||||||
@@ -50,9 +58,15 @@ Namespace API.Instagram
|
|||||||
GetTagged_VideoPic = .GetTaggedData_VideoPic
|
GetTagged_VideoPic = .GetTaggedData_VideoPic
|
||||||
|
|
||||||
PutImageVideoFolder = .PutImageVideoFolder
|
PutImageVideoFolder = .PutImageVideoFolder
|
||||||
|
|
||||||
|
IsVerifiedProfile = .IsVerifiedProfile
|
||||||
|
|
||||||
|
ForceUpdateUserName = .ForceUpdateUserName
|
||||||
|
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)
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ Imports PersonalUtilities.Tools.Web.Cookies
|
|||||||
Imports Download = SCrawler.Plugin.ISiteSettings.Download
|
Imports Download = SCrawler.Plugin.ISiteSettings.Download
|
||||||
Imports DN = SCrawler.API.Base.DeclaredNames
|
Imports DN = SCrawler.API.Base.DeclaredNames
|
||||||
Namespace API.Instagram
|
Namespace API.Instagram
|
||||||
<Manifest(InstagramSiteKey), SeparatedTasks(1), SavedPosts, SpecialForm(False)>
|
<Manifest(InstagramSiteKey), SeparatedTasks(1), SavedPosts, SpecialForm(False), UseDownDetector>
|
||||||
Friend Class SiteSettings : Inherits SiteSettingsBase
|
Friend Class SiteSettings : Inherits SiteSettingsBase : Implements DownDetector.IDownDetector
|
||||||
#Region "Declarations"
|
#Region "Declarations"
|
||||||
#Region "Providers"
|
#Region "Providers"
|
||||||
Friend Class TimersChecker : Inherits FieldsCheckerProviderBase
|
Friend Class TimersChecker : Inherits FieldsCheckerProviderBase
|
||||||
@@ -58,8 +58,10 @@ Namespace API.Instagram
|
|||||||
#Region "Categories"
|
#Region "Categories"
|
||||||
Private Const CAT_DOWN As String = "Download data"
|
Private Const CAT_DOWN As String = "Download data"
|
||||||
Private Const CAT_UserDefs_VIDEO As String = DN.CAT_UserDefs & ": extract image from video"
|
Private Const CAT_UserDefs_VIDEO As String = DN.CAT_UserDefs & ": extract image from video"
|
||||||
|
Private Const CAT_ERRORS As String = "Errors"
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Authorization properties"
|
#Region "Properties"
|
||||||
|
#Region "Authorization"
|
||||||
Friend Const Header_IG_APP_ID As String = "x-ig-app-id"
|
Friend Const Header_IG_APP_ID As String = "x-ig-app-id"
|
||||||
Friend Const Header_IG_WWW_CLAIM As String = "x-ig-www-claim"
|
Friend Const Header_IG_WWW_CLAIM As String = "x-ig-www-claim"
|
||||||
Friend Const Header_CSRF_TOKEN As String = "x-csrftoken"
|
Friend Const Header_CSRF_TOKEN As String = "x-csrftoken"
|
||||||
@@ -68,18 +70,18 @@ Namespace API.Instagram
|
|||||||
Friend Const Header_Browser As String = "Sec-Ch-Ua"
|
Friend Const Header_Browser As String = "Sec-Ch-Ua"
|
||||||
Friend Const Header_BrowserExt As String = "Sec-Ch-Ua-Full-Version-List"
|
Friend Const Header_BrowserExt As String = "Sec-Ch-Ua-Full-Version-List"
|
||||||
Friend Const Header_Platform_Verion As String = "Sec-Ch-Ua-Platform-Version"
|
Friend Const Header_Platform_Verion As String = "Sec-Ch-Ua-Platform-Version"
|
||||||
<PropertyOption(ControlText:="x-csrftoken", ControlToolTip:="Can be automatically extracted from cookies", IsAuth:=True, AllowNull:=True), ControlNumber(2), PClonable(Clone:=False)>
|
<PropertyOption(ControlText:="x-csrftoken", ControlToolTip:="Can be automatically extracted from cookies", IsAuth:=True, AllowNull:=True), PClonable(Clone:=False)>
|
||||||
Friend ReadOnly Property HH_CSRF_TOKEN As PropertyValue
|
Friend ReadOnly Property HH_CSRF_TOKEN As PropertyValue
|
||||||
<CookieValueExtractor(NameOf(HH_CSRF_TOKEN))>
|
<CookieValueExtractor(NameOf(HH_CSRF_TOKEN))>
|
||||||
Private Function GetValueFromCookies(ByVal PropName As String, ByVal c As CookieKeeper) As String
|
Private Function GetValueFromCookies(ByVal PropName As String, ByVal c As CookieKeeper) As String
|
||||||
Return c.GetCookieValue(Header_CSRF_TOKEN_COOKIE, PropName, NameOf(HH_CSRF_TOKEN))
|
Return c.GetCookieValue(Header_CSRF_TOKEN_COOKIE, PropName, NameOf(HH_CSRF_TOKEN))
|
||||||
End Function
|
End Function
|
||||||
<PropertyOption(ControlText:="x-ig-app-id", IsAuth:=True, AllowNull:=False), ControlNumber(3), PClonable(Clone:=False)>
|
<PropertyOption(ControlText:="x-ig-app-id", IsAuth:=True, AllowNull:=False), PClonable(Clone:=False)>
|
||||||
Friend ReadOnly Property HH_IG_APP_ID As PropertyValue
|
Friend ReadOnly Property HH_IG_APP_ID As PropertyValue
|
||||||
<PropertyOption(ControlText:="x-asbd-id", IsAuth:=True, AllowNull:=True), ControlNumber(4), PClonable(Clone:=False)>
|
<PropertyOption(ControlText:="x-asbd-id", IsAuth:=True, AllowNull:=True), PClonable(Clone:=False)>
|
||||||
Friend ReadOnly Property HH_ASBD_ID As PropertyValue
|
Friend ReadOnly Property HH_ASBD_ID As PropertyValue
|
||||||
'PropertyOption(ControlText:="x-ig-www-claim", IsAuth:=True, AllowNull:=True)
|
'PropertyOption(ControlText:="x-ig-www-claim", IsAuth:=True, AllowNull:=True)
|
||||||
<ControlNumber(5), PClonable(Clone:=False)>
|
<PClonable(Clone:=False)>
|
||||||
Friend ReadOnly Property HH_IG_WWW_CLAIM As PropertyValue
|
Friend ReadOnly Property HH_IG_WWW_CLAIM As PropertyValue
|
||||||
Private ReadOnly Property HH_IG_WWW_CLAIM_IS_ZERO As Boolean
|
Private ReadOnly Property HH_IG_WWW_CLAIM_IS_ZERO As Boolean
|
||||||
Get
|
Get
|
||||||
@@ -88,16 +90,16 @@ Namespace API.Instagram
|
|||||||
End Get
|
End Get
|
||||||
End Property
|
End Property
|
||||||
<PropertyOption(ControlText:="sec-ch-ua", IsAuth:=True, AllowNull:=True,
|
<PropertyOption(ControlText:="sec-ch-ua", IsAuth:=True, AllowNull:=True,
|
||||||
InheritanceName:=SettingsCLS.HEADER_DEF_sec_ch_ua), ControlNumber(6), PClonable, PXML(OnlyForChecked:=True)>
|
InheritanceName:=SettingsCLS.HEADER_DEF_sec_ch_ua), PClonable, PXML(OnlyForChecked:=True)>
|
||||||
Private ReadOnly Property HH_BROWSER As PropertyValue
|
Private ReadOnly Property HH_BROWSER As PropertyValue
|
||||||
<PropertyOption(ControlText:="sec-ch-ua-full", ControlToolTip:="sec-ch-ua-full-version-list", IsAuth:=True, AllowNull:=True,
|
<PropertyOption(ControlText:="sec-ch-ua-full", ControlToolTip:="sec-ch-ua-full-version-list", IsAuth:=True, AllowNull:=True,
|
||||||
InheritanceName:=SettingsCLS.HEADER_DEF_sec_ch_ua_full_version_list), ControlNumber(7), PClonable, PXML(OnlyForChecked:=True)>
|
InheritanceName:=SettingsCLS.HEADER_DEF_sec_ch_ua_full_version_list), PClonable, PXML(OnlyForChecked:=True)>
|
||||||
Private ReadOnly Property HH_BROWSER_EXT As PropertyValue
|
Private ReadOnly Property HH_BROWSER_EXT As PropertyValue
|
||||||
<PropertyOption(ControlText:="sec-ch-ua-platform-ver", ControlToolTip:="sec-ch-ua-platform-version", IsAuth:=True, AllowNull:=True, LeftOffset:=135,
|
<PropertyOption(ControlText:="sec-ch-ua-platform-ver", ControlToolTip:="sec-ch-ua-platform-version", IsAuth:=True, AllowNull:=True, LeftOffset:=135,
|
||||||
InheritanceName:=SettingsCLS.HEADER_DEF_sec_ch_ua_platform_version), ControlNumber(8), PClonable, PXML(OnlyForChecked:=True)>
|
InheritanceName:=SettingsCLS.HEADER_DEF_sec_ch_ua_platform_version), PClonable, PXML(OnlyForChecked:=True)>
|
||||||
Private ReadOnly Property HH_PLATFORM As PropertyValue
|
Private ReadOnly Property HH_PLATFORM As PropertyValue
|
||||||
<PropertyOption(ControlText:="UserAgent", IsAuth:=True, AllowNull:=True,
|
<PropertyOption(ControlText:="UserAgent", IsAuth:=True, AllowNull:=True,
|
||||||
InheritanceName:=SettingsCLS.HEADER_DEF_UserAgent), ControlNumber(9), PClonable, PXML(OnlyForChecked:=True)>
|
InheritanceName:=SettingsCLS.HEADER_DEF_UserAgent), PClonable, PXML(OnlyForChecked:=True)>
|
||||||
Private ReadOnly Property HH_USER_AGENT As PropertyValue
|
Private ReadOnly Property HH_USER_AGENT As PropertyValue
|
||||||
Friend Overrides Function BaseAuthExists() As Boolean
|
Friend Overrides Function BaseAuthExists() As Boolean
|
||||||
Return Responser.CookiesExists And ACheck(HH_IG_APP_ID.Value) And ACheck(HH_CSRF_TOKEN.Value)
|
Return Responser.CookiesExists And ACheck(HH_IG_APP_ID.Value) And ACheck(HH_CSRF_TOKEN.Value)
|
||||||
@@ -126,113 +128,189 @@ Namespace API.Instagram
|
|||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
#Region "HH_IG_WWW_CLAIM"
|
#Region "HH_IG_WWW_CLAIM"
|
||||||
<PropertyOption(ControlText:="ig-www-claim update interval", IsAuth:=True, LeftOffset:=150), PXML, ControlNumber(10), PClonable, HiddenControl>
|
<PropertyOption(ControlText:="ig-www-claim update interval", IsAuth:=True, LeftOffset:=150), PXML, PClonable, HiddenControl>
|
||||||
Private ReadOnly Property HH_IG_WWW_CLAIM_UPDATE_INTERVAL As PropertyValue
|
Private ReadOnly Property HH_IG_WWW_CLAIM_UPDATE_INTERVAL As PropertyValue
|
||||||
<PropertyOption(ControlText:="ig-www-claim: always 0", ControlToolTip:="Keep token value always = 0", IsAuth:=True),
|
<PropertyOption(ControlText:="ig-www-claim: always 0", ControlToolTip:="Keep token value always = 0", IsAuth:=True),
|
||||||
PXML, ControlNumber(11), PClonable, HiddenControl>
|
PXML, PClonable, HiddenControl>
|
||||||
Friend ReadOnly Property HH_IG_WWW_CLAIM_ALWAYS_ZERO As PropertyValue
|
Friend ReadOnly Property HH_IG_WWW_CLAIM_ALWAYS_ZERO As PropertyValue
|
||||||
<PropertyOption(ControlText:="ig-www-claim: reset each session", ControlToolTip:="Set 'x-ig-www-claim' to '0' before each session", IsAuth:=True),
|
<PropertyOption(ControlText:="ig-www-claim: reset each session", ControlToolTip:="Set 'x-ig-www-claim' to '0' before each session", IsAuth:=True),
|
||||||
PXML, ControlNumber(12), PClonable, HiddenControl>
|
PXML, PClonable, HiddenControl>
|
||||||
Friend ReadOnly Property HH_IG_WWW_CLAIM_RESET_EACH_SESSION As PropertyValue
|
Friend ReadOnly Property HH_IG_WWW_CLAIM_RESET_EACH_SESSION As PropertyValue
|
||||||
<PropertyOption(ControlText:="ig-www-claim: reset each target", ControlToolTip:="Set 'x-ig-www-claim' to '0' before each target", IsAuth:=True),
|
<PropertyOption(ControlText:="ig-www-claim: reset each target", ControlToolTip:="Set 'x-ig-www-claim' to '0' before each target", IsAuth:=True),
|
||||||
PXML, ControlNumber(13), PClonable, HiddenControl>
|
PXML, PClonable, HiddenControl>
|
||||||
Friend ReadOnly Property HH_IG_WWW_CLAIM_RESET_EACH_TARGET As PropertyValue
|
Friend ReadOnly Property HH_IG_WWW_CLAIM_RESET_EACH_TARGET As PropertyValue
|
||||||
<PropertyOption(ControlText:="ig-www-claim: use in requests", IsAuth:=True), PXML, ControlNumber(14), PClonable, HiddenControl>
|
<PropertyOption(ControlText:="ig-www-claim: use in requests", IsAuth:=True), PXML, PClonable, HiddenControl>
|
||||||
Friend ReadOnly Property HH_IG_WWW_CLAIM_USE As PropertyValue
|
Friend ReadOnly Property HH_IG_WWW_CLAIM_USE As PropertyValue
|
||||||
<PropertyOption(ControlText:="ig-www-claim: use default algorithm to update", IsAuth:=True), PXML, ControlNumber(15), PClonable, HiddenControl>
|
<PropertyOption(ControlText:="ig-www-claim: use default algorithm to update", IsAuth:=True), PXML, PClonable, HiddenControl>
|
||||||
Friend ReadOnly Property HH_IG_WWW_CLAIM_USE_DEFAULT_ALGO As PropertyValue
|
Friend ReadOnly Property HH_IG_WWW_CLAIM_USE_DEFAULT_ALGO As PropertyValue
|
||||||
<Provider(NameOf(HH_IG_WWW_CLAIM_UPDATE_INTERVAL), FieldsChecker:=True)>
|
<Provider(NameOf(HH_IG_WWW_CLAIM_UPDATE_INTERVAL), FieldsChecker:=True)>
|
||||||
Private ReadOnly Property TokenUpdateIntervalProvider As IFormatProvider
|
Private ReadOnly Property TokenUpdateIntervalProvider As IFormatProvider
|
||||||
#End Region
|
#End Region
|
||||||
<PropertyOption(ControlText:="Use GraphQL to download", IsAuth:=True), PXML, ControlNumber(16), PClonable>
|
<PropertyOption(ControlText:="Use GraphQL to download", IsAuth:=True), PXML, PClonable>
|
||||||
Friend ReadOnly Property USE_GQL As PropertyValue
|
Friend ReadOnly Property USE_GQL As PropertyValue
|
||||||
|
<PropertyOption(ControlText:="Use GraphQL to download user data", IsAuth:=True), PXML, PClonable, HiddenControl>
|
||||||
|
Friend ReadOnly Property USE_GQL_UserData As PropertyValue
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Download properties"
|
#Region "Download data"
|
||||||
<PropertyOption(ControlText:="DownDetector",
|
<PropertyOption(ControlText:="Download timeline", Category:=CAT_DOWN), PXML, PClonable>
|
||||||
ControlToolTip:="Use 'DownDetector' to determine if the site is accessible. -1 to disable." & vbCr &
|
Friend ReadOnly Property DownloadTimeline As PropertyValue
|
||||||
"The value represents the average number of error reports over the last 4 hours"),
|
<PXML> Private ReadOnly Property DownloadTimeline_Def As PropertyValue
|
||||||
PClonable, PXML, ControlNumber(17)>
|
<PropertyOption(ControlText:="Download reels", Category:=CAT_DOWN), PXML, PClonable>
|
||||||
Private ReadOnly Property DownDetectorValue As PropertyValue
|
Friend ReadOnly Property DownloadReels As PropertyValue
|
||||||
<Provider(NameOf(DownDetectorValue), FieldsChecker:=True)>
|
<PXML> Private ReadOnly Property DownloadReels_Def As PropertyValue
|
||||||
Private ReadOnly Property DownDetectorValueProvider As IFormatProvider
|
<PropertyOption(ControlText:="Download stories", Category:=CAT_DOWN), PXML, PClonable>
|
||||||
<PropertyOption(ControlText:="Add 'DownDetector' information to the log."), PClonable, PXML, ControlNumber(18), HiddenControl>
|
Friend ReadOnly Property DownloadStories As PropertyValue
|
||||||
Private ReadOnly Property DownDetectorValueAddToLog As PropertyValue
|
<PXML> Private ReadOnly Property DownloadStories_Def As PropertyValue
|
||||||
|
<PropertyOption(ControlText:="Download stories: user", Category:=CAT_DOWN), PXML, PClonable>
|
||||||
|
Friend ReadOnly Property DownloadStoriesUser As PropertyValue
|
||||||
|
<PXML> Private ReadOnly Property DownloadStoriesUser_Def As PropertyValue
|
||||||
|
<PropertyOption(ControlText:="Download tagged posts", Category:=CAT_DOWN), PXML, PClonable>
|
||||||
|
Friend ReadOnly Property DownloadTagged As PropertyValue
|
||||||
|
<PXML> Private ReadOnly Property DownloadTagged_Def As PropertyValue
|
||||||
|
<PropertyOption(ControlText:="Number of posts (verified)", ControlToolTip:="The number of posts received per request if the profile has a verified mark", Category:=CAT_DOWN), PXML, PClonable, HiddenControl>
|
||||||
|
Friend ReadOnly Property PostNumberVerified As PropertyValue
|
||||||
|
<Provider(NameOf(PostNumberVerified), FieldsChecker:=True)>
|
||||||
|
Private ReadOnly Property PostNumberVerifiedProvider As IFormatProvider
|
||||||
|
<PropertyOption(ControlText:="Number of posts (unverified)", ControlToolTip:="The number of posts received per request if the profile doesn't have a verified mark", Category:=CAT_DOWN), PXML, PClonable, HiddenControl>
|
||||||
|
Friend ReadOnly Property PostNumberVerifiedNot As PropertyValue
|
||||||
|
<Provider(NameOf(PostNumberVerifiedNot), FieldsChecker:=True)>
|
||||||
|
Private ReadOnly Property PostNumberVerifiedNotProvider As IFormatProvider
|
||||||
|
#End Region
|
||||||
|
#Region "Timers"
|
||||||
Friend Const TimersUrgentTip As String = vbCr & "It is highly recommended not to change the default value."
|
Friend Const TimersUrgentTip As String = vbCr & "It is highly recommended not to change the default value."
|
||||||
<PropertyOption(ControlText:="Request timer (any)",
|
<PropertyOption(ControlText:="Request timer (any)",
|
||||||
ControlToolTip:="The timer (in milliseconds) that SCrawler should wait before executing the next request." &
|
ControlToolTip:="The timer (in milliseconds) that SCrawler should wait before executing the next request." &
|
||||||
vbCr & "The default value is 1'000." & vbCr & "The minimum value is 0." & TimersUrgentTip, AllowNull:=False, Category:=DN.CAT_Timers),
|
vbCr & "The default value is 1'000." & vbCr & "The minimum value is 0." & TimersUrgentTip, AllowNull:=False, Category:=DN.CAT_Timers),
|
||||||
PXML, ControlNumber(19), PClonable>
|
PXML, PClonable>
|
||||||
Friend ReadOnly Property RequestsWaitTimer_Any As PropertyValue
|
Friend ReadOnly Property RequestsWaitTimer_Any As PropertyValue
|
||||||
<Provider(NameOf(RequestsWaitTimer_Any), FieldsChecker:=True)>
|
<Provider(NameOf(RequestsWaitTimer_Any), FieldsChecker:=True)>
|
||||||
Private ReadOnly Property RequestsWaitTimer_AnyProvider As IFormatProvider
|
Private ReadOnly Property RequestsWaitTimer_AnyProvider As IFormatProvider
|
||||||
<PropertyOption(ControlText:="Request timer",
|
<PropertyOption(ControlText:="Request timer",
|
||||||
ControlToolTip:="The time value (in milliseconds) that the program will wait before processing the next 'Request time counter' request." &
|
ControlToolTip:="The time value (in milliseconds) that the program will wait before processing the next 'Request time counter' request." &
|
||||||
vbCr & "The default value is 1'000." & vbCr & "The minimum value is 100." & TimersUrgentTip,
|
vbCr & "The default value is 1'000." & vbCr & "The minimum value is 100." & TimersUrgentTip,
|
||||||
AllowNull:=False, Category:=DN.CAT_Timers), PXML, ControlNumber(20), PClonable>
|
AllowNull:=False, Category:=DN.CAT_Timers), PXML, PClonable>
|
||||||
Friend ReadOnly Property RequestsWaitTimer As PropertyValue
|
Friend ReadOnly Property RequestsWaitTimer As PropertyValue
|
||||||
<Provider(NameOf(RequestsWaitTimer), FieldsChecker:=True)>
|
<Provider(NameOf(RequestsWaitTimer), FieldsChecker:=True)>
|
||||||
Private ReadOnly Property RequestsWaitTimerProvider As IFormatProvider
|
Private ReadOnly Property RequestsWaitTimerProvider As IFormatProvider
|
||||||
<PropertyOption(ControlText:="Request timer counter",
|
<PropertyOption(ControlText:="Request timer counter",
|
||||||
ControlToolTip:="How many requests will be sent to Instagram before the program waits 'Request timer'." &
|
ControlToolTip:="How many requests will be sent to Instagram before the program waits 'Request timer'." &
|
||||||
vbCr & "The default value is 1." & vbCr & "The minimum value is 1." & TimersUrgentTip,
|
vbCr & "The default value is 1." & vbCr & "The minimum value is 1." & TimersUrgentTip,
|
||||||
AllowNull:=False, LeftOffset:=120, Category:=DN.CAT_Timers), PXML, ControlNumber(21), PClonable>
|
AllowNull:=False, LeftOffset:=120, Category:=DN.CAT_Timers), PXML, PClonable>
|
||||||
Friend ReadOnly Property RequestsWaitTimerTaskCount As PropertyValue
|
Friend ReadOnly Property RequestsWaitTimerTaskCount As PropertyValue
|
||||||
<Provider(NameOf(RequestsWaitTimerTaskCount), FieldsChecker:=True)>
|
<Provider(NameOf(RequestsWaitTimerTaskCount), FieldsChecker:=True)>
|
||||||
Private ReadOnly Property RequestsWaitTimerTaskCountProvider As IFormatProvider
|
Private ReadOnly Property RequestsWaitTimerTaskCountProvider As IFormatProvider
|
||||||
<PropertyOption(ControlText:="Posts limit timer",
|
<PropertyOption(ControlText:="Posts limit timer",
|
||||||
ControlToolTip:="The time value (in milliseconds) the program will wait before processing the next request after 195 requests." &
|
ControlToolTip:="The time value (in milliseconds) the program will wait before processing the next request after 195 requests." &
|
||||||
vbCr & "The default value is 60'000." & vbCr & "The minimum value is 10'000." & TimersUrgentTip,
|
vbCr & "The default value is 60'000." & vbCr & "The minimum value is 10'000." & TimersUrgentTip,
|
||||||
AllowNull:=False, Category:=DN.CAT_Timers), PXML, ControlNumber(22), PClonable>
|
AllowNull:=False, Category:=DN.CAT_Timers), PXML, PClonable>
|
||||||
Friend ReadOnly Property SleepTimerOnPostsLimit As PropertyValue
|
Friend ReadOnly Property SleepTimerOnPostsLimit As PropertyValue
|
||||||
<Provider(NameOf(SleepTimerOnPostsLimit), FieldsChecker:=True)>
|
<Provider(NameOf(SleepTimerOnPostsLimit), FieldsChecker:=True)>
|
||||||
Private ReadOnly Property SleepTimerOnPostsLimitProvider As IFormatProvider
|
Private ReadOnly Property SleepTimerOnPostsLimitProvider As IFormatProvider
|
||||||
<PropertyOption(ControlText:="Get timeline", ControlToolTip:="Default value for new users", Category:=DN.CAT_UserDefs), PXML, ControlNumber(23), PClonable>
|
<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
|
||||||
|
#Region "New user defaults"
|
||||||
|
<PropertyOption(ControlText:="Get timeline", ControlToolTip:="Default value for new users", Category:=DN.CAT_UserDefs), PXML, PClonable>
|
||||||
Friend ReadOnly Property GetTimeline As PropertyValue
|
Friend ReadOnly Property GetTimeline As PropertyValue
|
||||||
<PropertyOption(ControlText:="From timeline", ControlToolTip:="Default value for new users", Category:=CAT_UserDefs_VIDEO), PXML, ControlNumber(23), PClonable>
|
<PropertyOption(ControlText:="From timeline", ControlToolTip:="Default value for new users", Category:=CAT_UserDefs_VIDEO), PXML, PClonable>
|
||||||
Friend ReadOnly Property GetTimeline_VideoPic As PropertyValue
|
Friend ReadOnly Property GetTimeline_VideoPic As PropertyValue
|
||||||
<PropertyOption(ControlText:="Get reels", ControlToolTip:="Default value for new users", Category:=DN.CAT_UserDefs), PXML, ControlNumber(24), PClonable>
|
<PropertyOption(ControlText:="Get reels", ControlToolTip:="Default value for new users", Category:=DN.CAT_UserDefs), PXML, PClonable>
|
||||||
Friend ReadOnly Property GetReels As PropertyValue
|
Friend ReadOnly Property GetReels As PropertyValue
|
||||||
<PropertyOption(ControlText:="From reels", ControlToolTip:="Default value for new users", Category:=CAT_UserDefs_VIDEO), PXML, ControlNumber(24), PClonable>
|
<PropertyOption(ControlText:="From reels", ControlToolTip:="Default value for new users", Category:=CAT_UserDefs_VIDEO), PXML, PClonable>
|
||||||
Friend ReadOnly Property GetReels_VideoPic As PropertyValue
|
Friend ReadOnly Property GetReels_VideoPic As PropertyValue
|
||||||
<PropertyOption(ControlText:="Get stories", ControlToolTip:="Default value for new users", Category:=DN.CAT_UserDefs), PXML, ControlNumber(25), PClonable>
|
<PropertyOption(ControlText:="Get stories", ControlToolTip:="Default value for new users", Category:=DN.CAT_UserDefs), PXML, PClonable>
|
||||||
Friend ReadOnly Property GetStories As PropertyValue
|
Friend ReadOnly Property GetStories As PropertyValue
|
||||||
<PropertyOption(ControlText:="From stories", ControlToolTip:="Default value for new users", Category:=CAT_UserDefs_VIDEO), PXML, ControlNumber(25), PClonable>
|
<PropertyOption(ControlText:="From stories", ControlToolTip:="Default value for new users", Category:=CAT_UserDefs_VIDEO), PXML, PClonable>
|
||||||
Friend ReadOnly Property GetStories_VideoPic As PropertyValue
|
Friend ReadOnly Property GetStories_VideoPic As PropertyValue
|
||||||
<PropertyOption(ControlText:="Get stories: user", ControlToolTip:="Default value for new users", Category:=DN.CAT_UserDefs), PXML, ControlNumber(26), PClonable>
|
<PropertyOption(ControlText:="Get stories: user", ControlToolTip:="Default value for new users", Category:=DN.CAT_UserDefs), PXML, PClonable>
|
||||||
Friend ReadOnly Property GetStoriesUser As PropertyValue
|
Friend ReadOnly Property GetStoriesUser As PropertyValue
|
||||||
<PropertyOption(ControlText:="From stories: user", ControlToolTip:="Default value for new users", Category:=CAT_UserDefs_VIDEO), PXML, ControlNumber(26), PClonable>
|
<PropertyOption(ControlText:="From stories: user", ControlToolTip:="Default value for new users", Category:=CAT_UserDefs_VIDEO), PXML, PClonable>
|
||||||
Friend ReadOnly Property GetStoriesUser_VideoPic As PropertyValue
|
Friend ReadOnly Property GetStoriesUser_VideoPic As PropertyValue
|
||||||
<PropertyOption(ControlText:="Get tagged posts", ControlToolTip:="Default value for new users", Category:=DN.CAT_UserDefs), PXML, ControlNumber(27), PClonable>
|
<PropertyOption(ControlText:="Get tagged posts", ControlToolTip:="Default value for new users", Category:=DN.CAT_UserDefs), PXML, PClonable>
|
||||||
Friend ReadOnly Property GetTagged As PropertyValue
|
Friend ReadOnly Property GetTagged As PropertyValue
|
||||||
<PropertyOption(ControlText:="From tagged posts", ControlToolTip:="Default value for new users", Category:=CAT_UserDefs_VIDEO), PXML, ControlNumber(27), PClonable>
|
<PropertyOption(ControlText:="From tagged posts", ControlToolTip:="Default value for new users", Category:=CAT_UserDefs_VIDEO), PXML, PClonable>
|
||||||
Friend ReadOnly Property GetTagged_VideoPic As PropertyValue
|
Friend ReadOnly Property GetTagged_VideoPic As PropertyValue
|
||||||
<PropertyOption(ControlText:="From saved posts", ControlToolTip:="Default value for new users", Category:=CAT_UserDefs_VIDEO), PXML, ControlNumber(28), PClonable>
|
<PropertyOption(ControlText:="From saved posts", ControlToolTip:="Default value for new users", Category:=CAT_UserDefs_VIDEO), PXML, PClonable>
|
||||||
Friend ReadOnly Property GetSavedPosts_VideoPic As PropertyValue
|
Friend ReadOnly Property GetSavedPosts_VideoPic As PropertyValue
|
||||||
<PropertyOption(ControlText:="Place the extracted image into the video folder", ControlToolTip:="Default value for new users", Category:=CAT_UserDefs_VIDEO), PXML, ControlNumber(29), PClonable>
|
<PropertyOption(ControlText:="Place the extracted image into the video folder", ControlToolTip:="Default value for new users", Category:=CAT_UserDefs_VIDEO), PXML, PClonable>
|
||||||
Friend ReadOnly Property PutImageVideoFolder As PropertyValue
|
Friend ReadOnly Property PutImageVideoFolder As PropertyValue
|
||||||
|
#End Region
|
||||||
|
#Region "Errors"
|
||||||
|
Private Const ErrorsDefault As String = "572"
|
||||||
|
<PropertyOption(ControlText:="Skip errors",
|
||||||
|
ControlToolTip:="Skip the following errors (comma separated)." & vbCr &
|
||||||
|
"Facing these errors will not disable the download, but will add a simple line to the log.", Category:=CAT_ERRORS),
|
||||||
|
PClonable, PXML>
|
||||||
|
Private ReadOnly Property SkipErrors As PropertyValue
|
||||||
|
<PropertyOption(ControlText:="Add skipped errors to the log", Category:=CAT_ERRORS), PClonable, PXML>
|
||||||
|
Private ReadOnly Property SkipErrors_AddToLog As PropertyValue
|
||||||
|
<PropertyOption(ControlText:="Skip errors (exclude)",
|
||||||
|
ControlToolTip:="Exclude the following errors from being added to the log (comma separated)", Category:=CAT_ERRORS), PClonable, PXML>
|
||||||
|
Private ReadOnly Property SkipErrors_AddToLog_Silent As PropertyValue
|
||||||
|
Friend ReadOnly Property ErrorSpecialHandling(ByVal ErrCode As Integer) As Boolean
|
||||||
|
Get
|
||||||
|
With CStr(SkipErrors.Value) : Return Not .IsEmptyString AndAlso .Contains(ErrCode) : End With
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
|
Friend ReadOnly Property ErrorSpecialHandling_AddToLog(ByVal ErrCode As Integer) As Boolean
|
||||||
|
Get
|
||||||
|
With CStr(SkipErrors_AddToLog_Silent.Value)
|
||||||
|
Return CBool(SkipErrors_AddToLog.Value) AndAlso (.IsEmptyString OrElse Not .Contains(ErrCode))
|
||||||
|
End With
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
|
<PropertyOption(ControlText:="Ignore stories downloading errors (560)",
|
||||||
|
ControlToolTip:="If checked, error 560 will be skipped and the download will continue. Otherwise, the download will be interrupted.",
|
||||||
|
Category:=CAT_ERRORS), PClonable, PXML>
|
||||||
|
Friend ReadOnly Property IgnoreStoriesDownloadingErrors As PropertyValue
|
||||||
|
#End Region
|
||||||
|
#Region "Other params"
|
||||||
|
<PropertyOption(ControlText:="DownDetector",
|
||||||
|
ControlToolTip:="Use 'DownDetector' to determine if the site is accessible. -1 to disable." & vbCr &
|
||||||
|
"The value represents the average number of error reports over the last 4 hours"),
|
||||||
|
PClonable, PXML>
|
||||||
|
Private ReadOnly Property DownDetectorValue As PropertyValue
|
||||||
|
<Provider(NameOf(DownDetectorValue), FieldsChecker:=True)>
|
||||||
|
Private ReadOnly Property DownDetectorValueProvider As IFormatProvider
|
||||||
|
<PropertyOption(ControlText:="Add 'DownDetector' information to the log."), PClonable, PXML, HiddenControl>
|
||||||
|
Private ReadOnly Property DownDetectorValueAddToLog As PropertyValue
|
||||||
<PropertyOption(ControlText:="Tagged notify limit",
|
<PropertyOption(ControlText:="Tagged notify limit",
|
||||||
ControlToolTip:="If the number of tagged posts exceeds this number you will be notified." & vbCr &
|
ControlToolTip:="If the number of tagged posts exceeds this number you will be notified." & vbCr &
|
||||||
"-1 to disable"), PXML, ControlNumber(27), PClonable>
|
"-1 to disable"), PXML, PClonable>
|
||||||
Friend ReadOnly Property TaggedNotifyLimit As PropertyValue
|
Friend ReadOnly Property TaggedNotifyLimit As PropertyValue
|
||||||
<Provider(NameOf(TaggedNotifyLimit), FieldsChecker:=True)>
|
<Provider(NameOf(TaggedNotifyLimit), FieldsChecker:=True)>
|
||||||
Private ReadOnly Property TaggedNotifyLimitProvider As IFormatProvider
|
Private ReadOnly Property TaggedNotifyLimitProvider As IFormatProvider
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Download ready"
|
#End Region
|
||||||
<PropertyOption(ControlText:="Download timeline", Category:=CAT_DOWN), PXML, ControlNumber(10), PClonable>
|
#Region "IDownDetector Support"
|
||||||
Friend ReadOnly Property DownloadTimeline As PropertyValue
|
Private ReadOnly Property IDownDetector_Value As Integer Implements DownDetector.IDownDetector.Value
|
||||||
<PXML> Private ReadOnly Property DownloadTimeline_Def As PropertyValue
|
Get
|
||||||
<PropertyOption(ControlText:="Download reels", Category:=CAT_DOWN), PXML, ControlNumber(11), PClonable>
|
Return DownDetectorValue.Value
|
||||||
Friend ReadOnly Property DownloadReels As PropertyValue
|
End Get
|
||||||
<PXML> Private ReadOnly Property DownloadReels_Def As PropertyValue
|
End Property
|
||||||
<PropertyOption(ControlText:="Download stories", Category:=CAT_DOWN), PXML, ControlNumber(12), PClonable>
|
Private ReadOnly Property IDownDetector_AddToLog As Boolean Implements DownDetector.IDownDetector.AddToLog
|
||||||
Friend ReadOnly Property DownloadStories As PropertyValue
|
Get
|
||||||
<PXML> Private ReadOnly Property DownloadStories_Def As PropertyValue
|
Return DownDetectorValueAddToLog.Value
|
||||||
<PropertyOption(ControlText:="Download stories: user", Category:=CAT_DOWN), PXML, ControlNumber(13), PClonable>
|
End Get
|
||||||
Friend ReadOnly Property DownloadStoriesUser As PropertyValue
|
End Property
|
||||||
<PXML> Private ReadOnly Property DownloadStoriesUser_Def As PropertyValue
|
Private ReadOnly Property IDownDetector_CheckSite As String Implements DownDetector.IDownDetector.CheckSite
|
||||||
<PropertyOption(ControlText:="Download tagged posts", Category:=CAT_DOWN), PXML, ControlNumber(14), PClonable>
|
Get
|
||||||
Friend ReadOnly Property DownloadTagged As PropertyValue
|
Return "instagram"
|
||||||
<PXML> Private ReadOnly Property DownloadTagged_Def As PropertyValue
|
End Get
|
||||||
|
End Property
|
||||||
|
Private Function IDownDetector_Available(ByVal What As Download, ByVal Silent As Boolean) As Boolean Implements DownDetector.IDownDetector.Available
|
||||||
|
Return MDD.Available(What, Silent)
|
||||||
|
End Function
|
||||||
#End Region
|
#End Region
|
||||||
#Region "429 bypass"
|
#Region "429 bypass"
|
||||||
<PXML("InstagramDownloadingErrorDate")>
|
<PXML("InstagramDownloadingErrorDate")>
|
||||||
@@ -266,8 +344,40 @@ Namespace API.Instagram
|
|||||||
End Get
|
End Get
|
||||||
End Property
|
End Property
|
||||||
Private Const LastDownloadDateResetInterval As Integer = 60
|
Private Const LastDownloadDateResetInterval As Integer = 60
|
||||||
|
Private TooManyRequestsReadyForCatch As Boolean = True
|
||||||
|
Friend Function GetWaitDate() As Date
|
||||||
|
With DownloadingErrorDate
|
||||||
|
If ACheck(Of Date)(.Value) Then
|
||||||
|
Return CDate(.Value).AddMinutes(If(LastApplyingValue, 10))
|
||||||
|
Else
|
||||||
|
Return Now
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
End Function
|
||||||
|
Friend Sub TooManyRequests(ByVal Catched As Boolean)
|
||||||
|
With DownloadingErrorDate
|
||||||
|
If Catched Then
|
||||||
|
If Not ACheck(Of Date)(.Value) Then
|
||||||
|
.Value = Now
|
||||||
|
If TooManyRequestsReadyForCatch Then
|
||||||
|
LastApplyingValue = If(LastApplyingValue, 0) + 10
|
||||||
|
TooManyRequestsReadyForCatch = False
|
||||||
|
MyMainLOG = $"Instagram downloading error: too many requests. Try again after {If(LastApplyingValue, 10)} minutes..."
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
Else
|
||||||
|
.Value = Nothing
|
||||||
|
LastApplyingValue = Nothing
|
||||||
|
TooManyRequestsReadyForCatch = True
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
End Sub
|
||||||
|
#End Region
|
||||||
|
#Region "LastRequestsCount, Label"
|
||||||
<PXML> Private ReadOnly Property LastDownloadDate As PropertyValue
|
<PXML> Private ReadOnly Property LastDownloadDate As PropertyValue
|
||||||
<PXML> Private ReadOnly Property LastRequestsCount As PropertyValue
|
<PXML> Private ReadOnly Property LastRequestsCount As PropertyValue
|
||||||
|
<PropertyOption(IsInformationLabel:=True)>
|
||||||
|
Private ReadOnly Property LastRequestsCountLabel As PropertyValue
|
||||||
Private ReadOnly MyLastRequests As Dictionary(Of Date, Integer)
|
Private ReadOnly MyLastRequests As Dictionary(Of Date, Integer)
|
||||||
Private ReadOnly Property MyLastRequestsDate As Date
|
Private ReadOnly Property MyLastRequestsDate As Date
|
||||||
Get
|
Get
|
||||||
@@ -321,36 +431,6 @@ Namespace API.Instagram
|
|||||||
ErrorsDescriber.Execute(EDP.SendToLog, ex, "[SiteSettings.Instagram.RefreshMyLastRequests]")
|
ErrorsDescriber.Execute(EDP.SendToLog, ex, "[SiteSettings.Instagram.RefreshMyLastRequests]")
|
||||||
End Try
|
End Try
|
||||||
End Sub
|
End Sub
|
||||||
<PropertyOption(IsInformationLabel:=True), ControlNumber(100)>
|
|
||||||
Private ReadOnly Property LastRequestsCountLabel As PropertyValue
|
|
||||||
Private TooManyRequestsReadyForCatch As Boolean = True
|
|
||||||
Friend Function GetWaitDate() As Date
|
|
||||||
With DownloadingErrorDate
|
|
||||||
If ACheck(Of Date)(.Value) Then
|
|
||||||
Return CDate(.Value).AddMinutes(If(LastApplyingValue, 10))
|
|
||||||
Else
|
|
||||||
Return Now
|
|
||||||
End If
|
|
||||||
End With
|
|
||||||
End Function
|
|
||||||
Friend Sub TooManyRequests(ByVal Catched As Boolean)
|
|
||||||
With DownloadingErrorDate
|
|
||||||
If Catched Then
|
|
||||||
If Not ACheck(Of Date)(.Value) Then
|
|
||||||
.Value = Now
|
|
||||||
If TooManyRequestsReadyForCatch Then
|
|
||||||
LastApplyingValue = If(LastApplyingValue, 0) + 10
|
|
||||||
TooManyRequestsReadyForCatch = False
|
|
||||||
MyMainLOG = $"Instagram downloading error: too many requests. Try again after {If(LastApplyingValue, 10)} minutes..."
|
|
||||||
End If
|
|
||||||
End If
|
|
||||||
Else
|
|
||||||
.Value = Nothing
|
|
||||||
LastApplyingValue = Nothing
|
|
||||||
TooManyRequestsReadyForCatch = True
|
|
||||||
End If
|
|
||||||
End With
|
|
||||||
End Sub
|
|
||||||
#End Region
|
#End Region
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Initializer"
|
#Region "Initializer"
|
||||||
@@ -415,6 +495,7 @@ Namespace API.Instagram
|
|||||||
HH_IG_WWW_CLAIM_USE_DEFAULT_ALGO = New PropertyValue(True)
|
HH_IG_WWW_CLAIM_USE_DEFAULT_ALGO = New PropertyValue(True)
|
||||||
TokenUpdateIntervalProvider = New TokenRefreshIntervalProvider
|
TokenUpdateIntervalProvider = New TokenRefreshIntervalProvider
|
||||||
USE_GQL = New PropertyValue(False)
|
USE_GQL = New PropertyValue(False)
|
||||||
|
USE_GQL_UserData = New PropertyValue(True)
|
||||||
|
|
||||||
DownloadTimeline = New PropertyValue(True)
|
DownloadTimeline = New PropertyValue(True)
|
||||||
DownloadTimeline_Def = New PropertyValue(DownloadTimeline.Value, GetType(Boolean))
|
DownloadTimeline_Def = New PropertyValue(DownloadTimeline.Value, GetType(Boolean))
|
||||||
@@ -426,10 +507,11 @@ Namespace API.Instagram
|
|||||||
DownloadStoriesUser_Def = New PropertyValue(DownloadStoriesUser.Value, GetType(Boolean))
|
DownloadStoriesUser_Def = New PropertyValue(DownloadStoriesUser.Value, GetType(Boolean))
|
||||||
DownloadTagged = New PropertyValue(False)
|
DownloadTagged = New PropertyValue(False)
|
||||||
DownloadTagged_Def = New PropertyValue(DownloadTagged.Value, GetType(Boolean))
|
DownloadTagged_Def = New PropertyValue(DownloadTagged.Value, GetType(Boolean))
|
||||||
|
PostNumberVerified = New PropertyValue(50)
|
||||||
|
PostNumberVerifiedProvider = New TimersChecker(12)
|
||||||
|
PostNumberVerifiedNot = New PropertyValue(12)
|
||||||
|
PostNumberVerifiedNotProvider = New TimersChecker(12)
|
||||||
|
|
||||||
DownDetectorValue = New PropertyValue(20)
|
|
||||||
DownDetectorValueProvider = New TimersChecker(-1)
|
|
||||||
DownDetectorValueAddToLog = New PropertyValue(False)
|
|
||||||
RequestsWaitTimer_Any = New PropertyValue(1000)
|
RequestsWaitTimer_Any = New PropertyValue(1000)
|
||||||
RequestsWaitTimer_AnyProvider = New TimersChecker(0)
|
RequestsWaitTimer_AnyProvider = New TimersChecker(0)
|
||||||
RequestsWaitTimer = New PropertyValue(1000)
|
RequestsWaitTimer = New PropertyValue(1000)
|
||||||
@@ -438,6 +520,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)
|
||||||
@@ -451,6 +535,15 @@ Namespace API.Instagram
|
|||||||
GetTagged_VideoPic = New PropertyValue(True)
|
GetTagged_VideoPic = New PropertyValue(True)
|
||||||
GetSavedPosts_VideoPic = New PropertyValue(True)
|
GetSavedPosts_VideoPic = New PropertyValue(True)
|
||||||
PutImageVideoFolder = New PropertyValue(False)
|
PutImageVideoFolder = New PropertyValue(False)
|
||||||
|
|
||||||
|
SkipErrors = New PropertyValue(ErrorsDefault)
|
||||||
|
SkipErrors_AddToLog = New PropertyValue(True)
|
||||||
|
SkipErrors_AddToLog_Silent = New PropertyValue(String.Empty, GetType(String))
|
||||||
|
IgnoreStoriesDownloadingErrors = New PropertyValue(False)
|
||||||
|
|
||||||
|
DownDetectorValue = New PropertyValue(20)
|
||||||
|
DownDetectorValueProvider = New TimersChecker(-1)
|
||||||
|
DownDetectorValueAddToLog = New PropertyValue(False)
|
||||||
TaggedNotifyLimit = New PropertyValue(200)
|
TaggedNotifyLimit = New PropertyValue(200)
|
||||||
TaggedNotifyLimitProvider = New TaggedNotifyLimitChecker
|
TaggedNotifyLimitProvider = New TaggedNotifyLimitChecker
|
||||||
|
|
||||||
@@ -460,23 +553,24 @@ Namespace API.Instagram
|
|||||||
LastRequestsCountLabel = New PropertyValue(String.Empty, GetType(String))
|
LastRequestsCountLabel = New PropertyValue(String.Empty, GetType(String))
|
||||||
MyLastRequests = New Dictionary(Of Date, Integer)
|
MyLastRequests = New Dictionary(Of Date, Integer)
|
||||||
|
|
||||||
|
MDD = New DownDetector.Checker(Of SiteSettings)(Me)
|
||||||
|
|
||||||
_AllowUserAgentUpdate = False
|
_AllowUserAgentUpdate = False
|
||||||
UrlPatternUser = "https://www.instagram.com/{0}/"
|
UrlPatternUser = "https://www.instagram.com/{0}/"
|
||||||
UserRegex = RParams.DMS(String.Format(UserRegexDefaultPattern, "instagram.com/"), 1)
|
UserRegex = RParams.DMS(String.Format(UserRegexDefaultPattern, "instagram.com/"), 1)
|
||||||
ImageVideoContains = "instagram.com"
|
ImageVideoContains = "instagram.com"
|
||||||
End Sub
|
End Sub
|
||||||
Private Const SettingsVersionCurrent As Integer = 2
|
Private Const SettingsVersionCurrent As Integer = 3
|
||||||
Friend Overrides Sub EndInit()
|
Friend Overrides Sub EndInit()
|
||||||
Try : MyLastRequests.Add(LastDownloadDate.Value, LastRequestsCount.Value) : Catch : End Try
|
Try : MyLastRequests.Add(LastDownloadDate.Value, LastRequestsCount.Value) : Catch : End Try
|
||||||
If Not CBool(HH_IG_WWW_CLAIM_USE.Value) Then Responser.Headers.Remove(Header_IG_WWW_CLAIM)
|
If Not CBool(HH_IG_WWW_CLAIM_USE.Value) Then Responser.Headers.Remove(Header_IG_WWW_CLAIM)
|
||||||
If CInt(SettingsVersion.Value) < SettingsVersionCurrent Then
|
If CInt(SettingsVersion.Value) < SettingsVersionCurrent Then
|
||||||
SettingsVersion.Value = SettingsVersionCurrent
|
SettingsVersion.Value = SettingsVersionCurrent
|
||||||
HH_IG_WWW_CLAIM_UPDATE_INTERVAL.Value = 120
|
HH_IG_WWW_CLAIM_RESET_EACH_TARGET.Value = False
|
||||||
HH_IG_WWW_CLAIM_ALWAYS_ZERO.Value = False
|
RequestsWaitTimer_Any.Value = 5000
|
||||||
HH_IG_WWW_CLAIM_RESET_EACH_SESSION.Value = True
|
TaggedNotifyLimit.Value = 50
|
||||||
HH_IG_WWW_CLAIM_RESET_EACH_TARGET.Value = True
|
DownDetectorValue.Value = 30
|
||||||
HH_IG_WWW_CLAIM_USE.Value = True
|
DownDetectorValueAddToLog.Value = True
|
||||||
HH_IG_WWW_CLAIM_USE_DEFAULT_ALGO.Value = True
|
|
||||||
End If
|
End If
|
||||||
MyBase.EndInit()
|
MyBase.EndInit()
|
||||||
End Sub
|
End Sub
|
||||||
@@ -507,20 +601,13 @@ Namespace API.Instagram
|
|||||||
End Function
|
End Function
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Downloading"
|
#Region "Downloading"
|
||||||
Private ____DownloadStarted As Boolean = False
|
Private ReadOnly MDD As DownDetector.Checker(Of SiteSettings)
|
||||||
Private ____AvailableRequested As Boolean = False
|
|
||||||
Private ____AvailableSilent As Boolean = True
|
|
||||||
Private ____AvailableChecked As Boolean = False
|
|
||||||
Private ____AvailableResult As Boolean = False
|
|
||||||
Private Sub ResetDownloadOptions()
|
Private Sub ResetDownloadOptions()
|
||||||
If ActiveJobs < 1 Then
|
If ActiveJobs < 1 Then
|
||||||
____DownloadStarted = False
|
MDD.Reset()
|
||||||
____AvailableRequested = False
|
|
||||||
____AvailableChecked = False
|
|
||||||
____AvailableSilent = True
|
|
||||||
____AvailableResult = False
|
|
||||||
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
|
||||||
@@ -529,79 +616,22 @@ Namespace API.Instagram
|
|||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
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
|
||||||
If MyBase.Available(What, Silent) And ActiveJobs < 2 Then
|
Return MyBase.Available(What, Silent) And ActiveJobs < 2
|
||||||
If CInt(DownDetectorValue.Value) >= 0 Then
|
|
||||||
If ____DownloadStarted Then
|
|
||||||
____AvailableRequested = True
|
|
||||||
____AvailableSilent = Silent
|
|
||||||
Return True
|
|
||||||
Else
|
|
||||||
Return AvailableImpl(What, Silent)
|
|
||||||
End If
|
|
||||||
Else
|
|
||||||
Return True
|
|
||||||
End If
|
|
||||||
Else
|
|
||||||
Return False
|
|
||||||
End If
|
|
||||||
End Function
|
|
||||||
#Disable Warning IDE0060
|
|
||||||
Private Function AvailableImpl(ByVal What As Download, ByVal Silent As Boolean) As Boolean
|
|
||||||
#Enable Warning
|
|
||||||
Try
|
|
||||||
AvailableText = String.Empty
|
|
||||||
If CInt(DownDetectorValue.Value) = -1 Then
|
|
||||||
Return True
|
|
||||||
Else
|
|
||||||
Dim dl As List(Of DownDetector.Data) = DownDetector.GetData("instagram")
|
|
||||||
If dl.ListExists Then
|
|
||||||
dl = dl.Take(4).ToList
|
|
||||||
Dim avg% = dl.Average(Function(d) d.Value)
|
|
||||||
If avg > CInt(DownDetectorValue.Value) Then
|
|
||||||
AvailableText = "Over the past hour, Instagram has received an average of " &
|
|
||||||
avg.NumToString(New ANumbers With {.FormatOptions = ANumbers.Options.GroupIntegral}) & " outage reports:" & vbCr &
|
|
||||||
dl.ListToString(vbCr)
|
|
||||||
If CBool(DownDetectorValueAddToLog.Value) Then MyMainLOG = AvailableText
|
|
||||||
If Silent Then
|
|
||||||
Return False
|
|
||||||
Else
|
|
||||||
Return MsgBoxE({$"{AvailableText}{vbCr}{vbCr}Do you want to continue parsing Instagram data?",
|
|
||||||
"There are outage reports on Instagram"}, vbYesNo) = vbYes
|
|
||||||
End If
|
|
||||||
End If
|
|
||||||
End If
|
|
||||||
Return True
|
|
||||||
End If
|
|
||||||
Catch ex As Exception
|
|
||||||
Return ErrorsDescriber.Execute(EDP.SendToLog + EDP.ReturnValue, ex, "[API.Instagram.SiteSettings.Available]", True)
|
|
||||||
End Try
|
|
||||||
End Function
|
End Function
|
||||||
Friend Property SkipUntilNextSession As Boolean = False
|
Friend Property SkipUntilNextSession As Boolean = False
|
||||||
Friend Overrides Function ReadyToDownload(ByVal What As Download) As Boolean
|
Friend Overrides Function ReadyToDownload(ByVal What As Download) As Boolean
|
||||||
If ActiveJobs < 2 AndAlso Not SkipUntilNextSession AndAlso ReadyForDownload AndAlso BaseAuthExists() AndAlso CBool(DownloadTimeline.Value) Then
|
Return ActiveJobs < 2 AndAlso Not SkipUntilNextSession AndAlso ReadyForDownload AndAlso BaseAuthExists() AndAlso CBool(DownloadTimeline.Value)
|
||||||
If ____DownloadStarted And ____AvailableRequested Then
|
|
||||||
____AvailableResult = AvailableImpl(What, ____AvailableSilent)
|
|
||||||
____AvailableChecked = True
|
|
||||||
____AvailableRequested = False
|
|
||||||
Return ____AvailableResult
|
|
||||||
ElseIf ____AvailableChecked Then
|
|
||||||
Return ____AvailableResult
|
|
||||||
Else
|
|
||||||
Return True
|
|
||||||
End If
|
|
||||||
Else
|
|
||||||
Return False
|
|
||||||
End If
|
|
||||||
End Function
|
End Function
|
||||||
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)
|
||||||
ResetDownloadOptions()
|
ResetDownloadOptions()
|
||||||
ActiveJobs += 1
|
ActiveJobs += 1
|
||||||
If ActiveJobs = 1 Then ____DownloadStarted = True : ActiveSessionDate = Now
|
If ActiveJobs = 1 Then ActiveSessionDate = Now
|
||||||
If Not HH_IG_WWW_CLAIM_IS_ZERO AndAlso
|
If Not HH_IG_WWW_CLAIM_IS_ZERO AndAlso
|
||||||
(
|
(
|
||||||
(CBool(HH_IG_WWW_CLAIM_USE_DEFAULT_ALGO.Value) AndAlso MyLastRequestsDate.AddMinutes(HH_IG_WWW_CLAIM_UPDATE_INTERVAL.Value) < Now) Or
|
(CBool(HH_IG_WWW_CLAIM_USE_DEFAULT_ALGO.Value) AndAlso MyLastRequestsDate.AddMinutes(HH_IG_WWW_CLAIM_UPDATE_INTERVAL.Value) < Now) Or
|
||||||
@@ -632,6 +662,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 +763,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)
|
||||||
|
|||||||
@@ -6,12 +6,13 @@
|
|||||||
'
|
'
|
||||||
' This program is distributed in the hope that it will be useful,
|
' This program is distributed in the hope that it will be useful,
|
||||||
' but WITHOUT ANY WARRANTY
|
' but WITHOUT ANY WARRANTY
|
||||||
|
Imports System.Security.Cryptography
|
||||||
Imports System.Threading
|
Imports System.Threading
|
||||||
Imports SCrawler.API.Base
|
|
||||||
Imports PersonalUtilities.Functions.XML
|
|
||||||
Imports PersonalUtilities.Functions.RegularExpressions
|
Imports PersonalUtilities.Functions.RegularExpressions
|
||||||
|
Imports PersonalUtilities.Functions.XML
|
||||||
Imports PersonalUtilities.Tools.Web.Clients
|
Imports PersonalUtilities.Tools.Web.Clients
|
||||||
Imports PersonalUtilities.Tools.Web.Documents.JSON
|
Imports PersonalUtilities.Tools.Web.Documents.JSON
|
||||||
|
Imports SCrawler.API.Base
|
||||||
Namespace API.Instagram
|
Namespace API.Instagram
|
||||||
Partial Friend Class UserData
|
Partial Friend Class UserData
|
||||||
#Region "Tokens"
|
#Region "Tokens"
|
||||||
@@ -43,9 +44,9 @@ Namespace API.Instagram
|
|||||||
Private Const GQL_UserStories_DocId As String = "25231722019806941"
|
Private Const GQL_UserStories_DocId As String = "25231722019806941"
|
||||||
Private Const GQL_UserStories_FbFriendlyName As String = "PolarisStoriesV3ReelPageStandaloneQuery"
|
Private Const GQL_UserStories_FbFriendlyName As String = "PolarisStoriesV3ReelPageStandaloneQuery"
|
||||||
|
|
||||||
Private Const GQL_Timeline_DocId As String = "7268577773270422"
|
Private Const GQL_Timeline_DocId As String = "7268577773270422" '"34579740524958711" '"7268577773270422"
|
||||||
Private Const GQL_Timeline_FbFriendlyName As String = "PolarisProfilePostsQuery"
|
Private Const GQL_Timeline_FbFriendlyName As String = "PolarisProfilePostsQuery"
|
||||||
Private Const GQL_Timeline_DocId_Second As String = "7286316061475375"
|
Private Const GQL_Timeline_DocId_Second As String = "7286316061475375" '"33944389991841132" '"7286316061475375"
|
||||||
Private Const GQL_Timeline_FbFriendlyName_Second As String = "PolarisProfilePostsTabContentQuery_connection"
|
Private Const GQL_Timeline_FbFriendlyName_Second As String = "PolarisProfilePostsTabContentQuery_connection"
|
||||||
|
|
||||||
Private Const GQL_Reels_DocId As String = "7191572580905225"
|
Private Const GQL_Reels_DocId As String = "7191572580905225"
|
||||||
@@ -64,33 +65,42 @@ Namespace API.Instagram
|
|||||||
Responser.Headers.Add(GQL_HEADER_FB_FRINDLY_NAME, HeaderValue)
|
Responser.Headers.Add(GQL_HEADER_FB_FRINDLY_NAME, HeaderValue)
|
||||||
Responser.Headers.Add(GQL_HEADER_FB_LSD, Token_lsd)
|
Responser.Headers.Add(GQL_HEADER_FB_LSD, Token_lsd)
|
||||||
End Sub
|
End Sub
|
||||||
<Obsolete("Use 'GET' function: 'GetUserData'", False)>
|
'<Obsolete("Use 'GET' function: 'GetUserData'", False)>
|
||||||
Private Sub GetUserDataGQL(ByVal Token As CancellationToken)
|
Private Function GetUserDataGQL(ByVal Token As CancellationToken) As String
|
||||||
Dim vars$ = String.Format(GQL_URL_PATTERN_VARS, GQL_UserData_DocId, Token_lsd, Token_dtsg_Var, GQL_UserData_FbFriendlyName,
|
Dim vars$ = String.Format(GQL_URL_PATTERN_VARS, GQL_UserData_DocId, Token_lsd, Token_dtsg_Var, GQL_UserData_FbFriendlyName,
|
||||||
SymbolsConverter.ASCII.EncodeSymbolsOnly("{" & $"""id"":""{ID}"",""relay_header"":false,""render_surface"":""PROFILE""" & "}"))
|
SymbolsConverter.ASCII.EncodeSymbolsOnly("{" & $"""id"":""{ID}"",""relay_header"":false,""render_surface"":""PROFILE""" & "}"))
|
||||||
UpdateRequestNumber()
|
UpdateRequestNumber()
|
||||||
ChangeResponserMode(True)
|
ChangeResponserMode(True)
|
||||||
UpdateHeadersGQL(GQL_UserData_FbFriendlyName)
|
UpdateHeadersGQL(GQL_UserData_FbFriendlyName)
|
||||||
Dim r$ = Responser.GetResponse(GQL_URL, vars)
|
Dim r$ = Responser.GetResponse(GQL_URL, vars)
|
||||||
If Not r.IsEmptyString Then
|
Return r
|
||||||
Using j As EContainer = JsonDocument.Parse(r)
|
'If Not r.IsEmptyString Then
|
||||||
If j.ListExists Then
|
' Using j As EContainer = JsonDocument.Parse(r)
|
||||||
With j({"data", "user"})
|
' If j.ListExists Then
|
||||||
If .ListExists Then
|
' With j({"data", "user"})
|
||||||
UserSiteName = .Value("full_name").IfNullOrEmpty(UserSiteName)
|
' If .ListExists Then
|
||||||
Dim f As New SFile With {.Path = DownloadContentDefault_GetRootDir(), .Name = "ProfilePicture", .Extension = "jpg"}
|
' UserSiteName = .Value("full_name").IfNullOrEmpty(UserSiteName)
|
||||||
Dim pic$ = .Value({"hd_profile_pic_url_info"}, "url").IfNullOrEmpty(.Value("profile_pic_url"))
|
' IsVerifiedProfile = .Value("is_verified").FromXML(Of Boolean)(False)
|
||||||
If Not pic.IsEmptyString Then GetWebFile(pic, f, EDP.ReturnValue)
|
' IsVerifiedProfile_Checked = True
|
||||||
UserDescriptionUpdate(.Value("biography"))
|
' Dim descr$ = .Value("biography")
|
||||||
End If
|
' If If(.Item("bio_links")?.Count, 0) > 0 Then descr.StringAppend(.Item("bio_links").Select(Function(bl) bl.Value("url")).ListToString(vbNewLine), vbNewLine)
|
||||||
End With
|
' Dim eUrl$ = .Value("external_url")
|
||||||
End If
|
' If Not eUrl.IsEmptyString AndAlso (descr.IsEmptyString OrElse Not descr.Contains(eUrl)) Then descr.StringAppendLine(eUrl)
|
||||||
End Using
|
' UserDescriptionUpdate(descr)
|
||||||
End If
|
|
||||||
End Sub
|
' Dim f As New SFile With {.Path = DownloadContentDefault_GetRootDir(), .Name = "ProfilePicture", .Extension = "jpg"}
|
||||||
|
' Dim pic$ = .Value({"hd_profile_pic_url_info"}, "url").IfNullOrEmpty(.Value("profile_pic_url"))
|
||||||
|
' If Not pic.IsEmptyString Then GetWebFile(pic, f, EDP.ReturnValue)
|
||||||
|
' End If
|
||||||
|
' End With
|
||||||
|
' End If
|
||||||
|
' End Using
|
||||||
|
'End If
|
||||||
|
End Function
|
||||||
Private Function GetTimelineGQL(ByVal Cursor As String, ByVal Token As CancellationToken) As String
|
Private Function GetTimelineGQL(ByVal Cursor As String, ByVal Token As CancellationToken) As String
|
||||||
Const none_cursor$ = "none"
|
Const none_cursor$ = "none"
|
||||||
Dim nextCursor$ = String.Empty, hasNextPage$ = String.Empty
|
Dim nextCursor$ = String.Empty
|
||||||
|
Dim hasNextPage As Boolean = False
|
||||||
Dim vars$
|
Dim vars$
|
||||||
|
|
||||||
ThrowAny(Token)
|
ThrowAny(Token)
|
||||||
@@ -98,14 +108,18 @@ Namespace API.Instagram
|
|||||||
ChangeResponserMode(True)
|
ChangeResponserMode(True)
|
||||||
|
|
||||||
If Cursor.IsEmptyString Then
|
If Cursor.IsEmptyString Then
|
||||||
vars = "{""data"":{""count"":50,""include_relationship_info"":true,""latest_besties_reel_media"":true,""latest_reel_media"":true},""username"":""" &
|
vars = "{""data"":{""count"":" & PostNumberPerRequest & ",""include_relationship_info"":true,""latest_besties_reel_media"":true,""latest_reel_media"":true},""username"":""" &
|
||||||
NameTrue & """,""__relay_internal__pv__PolarisShareMenurelayprovider"":false}"
|
NameTrue & """,""__relay_internal__pv__PolarisShareMenurelayprovider"":false}"
|
||||||
|
'vars = "{""data"":{""count"":" & PostNumberPerRequest & ",""include_reel_media_seen_timestamp"":true,""include_relationship_info"":true,""latest_besties_reel_media"":true,""latest_reel_media"":true},""username"":""" &
|
||||||
|
' NameTrue & """,""__relay_internal__pv__PolarisShareMenurelayprovider"":false}"
|
||||||
vars = String.Format(GQL_URL_PATTERN_VARS, GQL_Timeline_DocId, Token_lsd, Token_dtsg_Var, GQL_Timeline_FbFriendlyName,
|
vars = String.Format(GQL_URL_PATTERN_VARS, GQL_Timeline_DocId, Token_lsd, Token_dtsg_Var, GQL_Timeline_FbFriendlyName,
|
||||||
SymbolsConverter.ASCII.EncodeSymbolsOnly(vars))
|
SymbolsConverter.ASCII.EncodeSymbolsOnly(vars))
|
||||||
UpdateHeadersGQL(GQL_Timeline_FbFriendlyName)
|
UpdateHeadersGQL(GQL_Timeline_FbFriendlyName)
|
||||||
Else
|
Else
|
||||||
vars = "{""after"":""" & Cursor & """,""before"":null,""data"":{""count"":50,""include_relationship_info"":true,""latest_besties_reel_media"":true,""latest_reel_media"":true},""first"":50,""last"":null,""username"":""" &
|
vars = "{""after"":""" & Cursor & """,""before"":null,""data"":{""count"":" & PostNumberPerRequest & ",""include_relationship_info"":true,""latest_besties_reel_media"":true,""latest_reel_media"":true},""first"":" & PostNumberPerRequest & ",""last"":null,""username"":""" &
|
||||||
NameTrue & """,""__relay_internal__pv__PolarisShareMenurelayprovider"":false}"
|
NameTrue & """,""__relay_internal__pv__PolarisShareMenurelayprovider"":false}"
|
||||||
|
'vars = "{""after"":""" & Cursor & """,""before"":null,""data"":{""count"":" & PostNumberPerRequest & ",""include_reel_media_seen_timestamp"":true,""include_relationship_info"":true,""latest_besties_reel_media"":true,""latest_reel_media"":true},""first"":" & PostNumberPerRequest & ",""last"":null,""username"":""" &
|
||||||
|
' NameTrue & """}"
|
||||||
vars = String.Format(GQL_URL_PATTERN_VARS, GQL_Timeline_DocId_Second, Token_lsd, Token_dtsg_Var, GQL_Timeline_FbFriendlyName_Second,
|
vars = String.Format(GQL_URL_PATTERN_VARS, GQL_Timeline_DocId_Second, Token_lsd, Token_dtsg_Var, GQL_Timeline_FbFriendlyName_Second,
|
||||||
SymbolsConverter.ASCII.EncodeSymbolsOnly(vars))
|
SymbolsConverter.ASCII.EncodeSymbolsOnly(vars))
|
||||||
UpdateHeadersGQL(GQL_Timeline_FbFriendlyName_Second)
|
UpdateHeadersGQL(GQL_Timeline_FbFriendlyName_Second)
|
||||||
@@ -140,7 +154,8 @@ Namespace API.Instagram
|
|||||||
End Function
|
End Function
|
||||||
Private Function GetHighlightsGQL_List() As List(Of String)
|
Private Function GetHighlightsGQL_List() As List(Of String)
|
||||||
|
|
||||||
Dim nextCursor$ = String.Empty, hasNextPage$ = String.Empty
|
Dim nextCursor$ = String.Empty
|
||||||
|
Dim hasNextPage As Boolean = False
|
||||||
Dim i% = -1
|
Dim i% = -1
|
||||||
Dim hList As New List(Of String)
|
Dim hList As New List(Of String)
|
||||||
Dim tmpList As New List(Of String)
|
Dim tmpList As New List(Of String)
|
||||||
@@ -178,7 +193,9 @@ Namespace API.Instagram
|
|||||||
Dim tmpList As New List(Of String)
|
Dim tmpList As New List(Of String)
|
||||||
Dim i% = -1
|
Dim i% = -1
|
||||||
If StoriesList.ListExists Then
|
If StoriesList.ListExists Then
|
||||||
tmpList.AddRange(StoriesList.Take(10))
|
'TODO: 5 Instagram stories
|
||||||
|
'tmpList.AddRange(StoriesList.Take(10))
|
||||||
|
tmpList.AddRange(StoriesList.Take(5))
|
||||||
StoriesList.RemoveRange(0, tmpList.Count)
|
StoriesList.RemoveRange(0, tmpList.Count)
|
||||||
|
|
||||||
Dim vars$ = String.Format(GQL_URL_PATTERN_VARS, GQL_Highlights_DocId_Second, Token_lsd, Token_dtsg_Var, GQL_Highlights_FbFriendlyName_Second,
|
Dim vars$ = String.Format(GQL_URL_PATTERN_VARS, GQL_Highlights_DocId_Second, Token_lsd, Token_dtsg_Var, GQL_Highlights_FbFriendlyName_Second,
|
||||||
@@ -238,11 +255,9 @@ Namespace API.Instagram
|
|||||||
Private Function GetReelsGQL(ByVal Cursor As String) As String
|
Private Function GetReelsGQL(ByVal Cursor As String) As String
|
||||||
GetReelsGQL_SetEnvir = True
|
GetReelsGQL_SetEnvir = True
|
||||||
|
|
||||||
Dim errData$ = String.Empty
|
UpdateTokens(Cursor.IsEmptyString)
|
||||||
If Cursor.IsEmptyString And Not ValidateBaseTokens() Then GetPageTokens()
|
|
||||||
If Cursor.IsEmptyString And Not ValidateBaseTokens(errData) Then ValidateBaseTokens_Error(errData)
|
|
||||||
|
|
||||||
Dim vars$ = """data"":{""include_feed_video"":true,""page_size"":50,""target_user_id"":""" & ID & """}"
|
Dim vars$ = """data"":{""include_feed_video"":true,""page_size"":" & PostNumberPerRequest & ",""target_user_id"":""" & ID & """}"
|
||||||
If Not Cursor.IsEmptyString Then vars = $"""after"":""{Cursor}"",""before"":null,{vars},""first"":4,""last"":null"
|
If Not Cursor.IsEmptyString Then vars = $"""after"":""{Cursor}"",""before"":null,{vars},""first"":4,""last"":null"
|
||||||
vars = String.Format(GQL_URL_PATTERN_VARS, GQL_Reels_DocId, Token_lsd, Token_dtsg_Var, GQL_Reels_FbFriendlyName,
|
vars = String.Format(GQL_URL_PATTERN_VARS, GQL_Reels_DocId, Token_lsd, Token_dtsg_Var, GQL_Reels_FbFriendlyName,
|
||||||
SymbolsConverter.ASCII.EncodeSymbolsOnly("{" & vars & "}"))
|
SymbolsConverter.ASCII.EncodeSymbolsOnly("{" & vars & "}"))
|
||||||
@@ -258,10 +273,10 @@ Namespace API.Instagram
|
|||||||
Dim vars$
|
Dim vars$
|
||||||
If Cursor.IsEmptyString Then
|
If Cursor.IsEmptyString Then
|
||||||
vars = String.Format(GQL_URL_PATTERN_VARS, GQL_Tagged_DocId, Token_lsd, Token_dtsg_Var, GQL_Tagged_FbFriendlyName,
|
vars = String.Format(GQL_URL_PATTERN_VARS, GQL_Tagged_DocId, Token_lsd, Token_dtsg_Var, GQL_Tagged_FbFriendlyName,
|
||||||
SymbolsConverter.ASCII.EncodeSymbolsOnly("{" & $"""count"":50,""user_id"":""{ID}""" & "}"))
|
SymbolsConverter.ASCII.EncodeSymbolsOnly("{" & $"""count"":{PostNumberPerRequest},""user_id"":""{ID}""" & "}"))
|
||||||
Else
|
Else
|
||||||
vars = String.Format(GQL_URL_PATTERN_VARS, GQL_Tagged_DocId, Token_lsd, Token_dtsg_Var, GQL_Tagged_FbFriendlyName,
|
vars = String.Format(GQL_URL_PATTERN_VARS, GQL_Tagged_DocId, Token_lsd, Token_dtsg_Var, GQL_Tagged_FbFriendlyName,
|
||||||
SymbolsConverter.ASCII.EncodeSymbolsOnly("{" & $"""after"":""{Cursor}"",""before"":null,""count"":50,""first"":50,""last"":null,""user_id"":""{ID}""" & "}"))
|
SymbolsConverter.ASCII.EncodeSymbolsOnly("{" & $"""after"":""{Cursor}"",""before"":null,""count"":{PostNumberPerRequest},""first"":{PostNumberPerRequest},""last"":null,""user_id"":""{ID}""" & "}"))
|
||||||
End If
|
End If
|
||||||
UpdateRequestNumber()
|
UpdateRequestNumber()
|
||||||
ChangeResponserMode(True)
|
ChangeResponserMode(True)
|
||||||
@@ -270,6 +285,13 @@ Namespace API.Instagram
|
|||||||
End Function
|
End Function
|
||||||
#End Region
|
#End Region
|
||||||
#Region "ValidateBaseTokens"
|
#Region "ValidateBaseTokens"
|
||||||
|
Private Sub UpdateTokens(ByVal process As Boolean)
|
||||||
|
If process Then
|
||||||
|
Dim TokensErrData$ = String.Empty
|
||||||
|
If Not ValidateBaseTokens() Then GetPageTokens()
|
||||||
|
If Not ValidateBaseTokens(TokensErrData) Then ValidateBaseTokens_Error(TokensErrData)
|
||||||
|
End If
|
||||||
|
End Sub
|
||||||
Protected Overridable Overloads Function ValidateBaseTokens() As Boolean
|
Protected Overridable Overloads Function ValidateBaseTokens() As Boolean
|
||||||
Return ValidateBaseTokens(Nothing)
|
Return ValidateBaseTokens(Nothing)
|
||||||
End Function
|
End Function
|
||||||
@@ -307,6 +329,10 @@ Namespace API.Instagram
|
|||||||
Try
|
Try
|
||||||
If Not r.IsEmptyString Then
|
If Not r.IsEmptyString Then
|
||||||
ResetBaseTokens()
|
ResetBaseTokens()
|
||||||
|
If ID.IsEmptyString Then
|
||||||
|
Dim __id$ = RegexReplace(r, Regex_ProfileID)
|
||||||
|
If CLng(AConvert(Of Long)(__id, 0, EDP.ReturnValue)) <> 0 Then ID = __id
|
||||||
|
End If
|
||||||
Select Case Attempt
|
Select Case Attempt
|
||||||
Case 0
|
Case 0
|
||||||
Dim rr As RParams = RParams.DM(PageTokenRegexPatternDefault, 0, RegexReturn.List, EDP.ReturnValue)
|
Dim rr As RParams = RParams.DM(PageTokenRegexPatternDefault, 0, RegexReturn.List, EDP.ReturnValue)
|
||||||
|
|||||||
@@ -37,10 +37,13 @@ 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_ForceUpdateUserInfo As String = "ForceUpdateUserInfo"
|
||||||
|
Private Const Name_IsVerifiedProfile As String = "IsVerifiedProfile"
|
||||||
|
Private Const Name_IsVerifiedProfile_Checked As String = "IsVerifiedProfile_Checked"
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Declarations"
|
#Region "Declarations"
|
||||||
Protected Structure PostKV : Implements IEContainerProvider
|
Friend Structure PostKV : Implements IEContainerProvider
|
||||||
Private Const Name_Code As String = "Code"
|
Private Const Name_Code As String = "Code"
|
||||||
Private Const Name_Section As String = "Section"
|
Private Const Name_Section As String = "Section"
|
||||||
Friend Code As String
|
Friend Code As String
|
||||||
@@ -111,13 +114,16 @@ 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
|
Private UserNameRequested As Boolean = False
|
||||||
Friend ReadOnly Property NameTrue As String
|
Friend Property ForceUpdateUserName As Boolean = False
|
||||||
|
Friend Property ForceUpdateUserInfo As Boolean = False
|
||||||
|
Friend Property IsVerifiedProfile As Boolean = False
|
||||||
|
Friend Property IsVerifiedProfile_Checked As Boolean = False
|
||||||
|
Private ReadOnly Property PostNumberPerRequest As Integer
|
||||||
Get
|
Get
|
||||||
Return _NameTrue.IfNullOrEmpty(Name)
|
With MySiteSettings : Return If(IsVerifiedProfile, .PostNumberVerified, .PostNumberVerifiedNot).Value : End With
|
||||||
End Get
|
End Get
|
||||||
End Property
|
End Property
|
||||||
Private UserNameRequested As Boolean = False
|
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Loader"
|
#Region "Loader"
|
||||||
Protected Overrides Sub LoadUserInformation_OptionalFields(ByRef Container As XmlFile, ByVal Loading As Boolean)
|
Protected Overrides Sub LoadUserInformation_OptionalFields(ByRef Container As XmlFile, ByVal Loading As Boolean)
|
||||||
@@ -137,7 +143,10 @@ 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)
|
||||||
|
ForceUpdateUserInfo = .Value(Name_ForceUpdateUserInfo).FromXML(Of Boolean)(False)
|
||||||
|
IsVerifiedProfile = .Value(Name_IsVerifiedProfile).FromXML(Of Boolean)(False)
|
||||||
|
IsVerifiedProfile_Checked = .Value(Name_IsVerifiedProfile_Checked).FromXML(Of Boolean)(False)
|
||||||
Else
|
Else
|
||||||
.Add(Name_LastCursor, LastCursor)
|
.Add(Name_LastCursor, LastCursor)
|
||||||
.Add(Name_FirstLoadingDone, FirstLoadingDone.BoolToInteger)
|
.Add(Name_FirstLoadingDone, FirstLoadingDone.BoolToInteger)
|
||||||
@@ -153,7 +162,10 @@ 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_ForceUpdateUserInfo, ForceUpdateUserInfo.BoolToInteger)
|
||||||
|
.Add(Name_IsVerifiedProfile, IsVerifiedProfile.BoolToInteger)
|
||||||
|
.Add(Name_IsVerifiedProfile_Checked, IsVerifiedProfile_Checked.BoolToInteger)
|
||||||
End If
|
End If
|
||||||
End With
|
End With
|
||||||
End Sub
|
End Sub
|
||||||
@@ -165,6 +177,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
|
||||||
@@ -178,6 +191,12 @@ Namespace API.Instagram
|
|||||||
GetTaggedData_VideoPic = .GetTagged_VideoPic
|
GetTaggedData_VideoPic = .GetTagged_VideoPic
|
||||||
|
|
||||||
PutImageVideoFolder = .PutImageVideoFolder
|
PutImageVideoFolder = .PutImageVideoFolder
|
||||||
|
|
||||||
|
IsVerifiedProfile = .IsVerifiedProfile
|
||||||
|
If IsVerifiedProfile Then IsVerifiedProfile_Checked = True
|
||||||
|
|
||||||
|
ForceUpdateUserName = .ForceUpdateUserName
|
||||||
|
ForceUpdateUserInfo = .ForceUpdateUserInfo
|
||||||
End With
|
End With
|
||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
@@ -195,15 +214,32 @@ Namespace API.Instagram
|
|||||||
Private WwwClaimUse As Boolean = True
|
Private WwwClaimUse As Boolean = True
|
||||||
Private E560Thrown As Boolean = False
|
Private E560Thrown As Boolean = False
|
||||||
Friend Err5xx As Integer = -1
|
Friend Err5xx As Integer = -1
|
||||||
|
Private _ErrHandling As Integer = -1
|
||||||
|
Private Property ErrHandling As Integer
|
||||||
|
Get
|
||||||
|
Return _ErrHandling
|
||||||
|
End Get
|
||||||
|
Set(ByVal ErrCode As Integer)
|
||||||
|
_ErrHandling = ErrCode
|
||||||
|
Err5xx = ErrCode
|
||||||
|
End Set
|
||||||
|
End Property
|
||||||
|
Private ErrHandlingLog As Boolean = True
|
||||||
|
Private ErrHandlingSection As Sections = Sections.Timeline
|
||||||
|
Private Const ErrHandlingValue As Integer = 100
|
||||||
|
Private Const ErrHandlingValueStories As Integer = 150
|
||||||
Private Class ExitException : Inherits Exception
|
Private Class ExitException : Inherits Exception
|
||||||
Friend Property Is560 As Boolean = False
|
Friend Property Is560 As Boolean = False
|
||||||
Friend Property IsTokens As Boolean = False
|
Friend Property IsTokens As Boolean = False
|
||||||
Friend Property TokensData As String = String.Empty
|
Friend Property TokensData As String = String.Empty
|
||||||
Friend Shared Sub Throw560(ByRef Source As UserData)
|
Friend Shared Sub Throw560(ByRef Source As UserData)
|
||||||
If Not Source.E560Thrown Then
|
With Source
|
||||||
MyMainLOG = $"{Source.ToStringForLog}: ({IIf(Source.Err5xx > 0, Source.Err5xx, 560)}) Download skipped until next session"
|
If Not .E560Thrown Then
|
||||||
Source.E560Thrown = True
|
If .ErrHandling = -1 Or .ErrHandlingLog Then _
|
||||||
End If
|
MyMainLOG = $"{ .ToStringForLog}: ({IIf(.Err5xx > 0, .Err5xx, 560)}) Download skipped {If(.ErrHandling = -1, "until next session", $"({ .ErrHandlingSection})")}"
|
||||||
|
.E560Thrown = True
|
||||||
|
End If
|
||||||
|
End With
|
||||||
Throw New ExitException With {.Is560 = True}
|
Throw New ExitException With {.Is560 = True}
|
||||||
End Sub
|
End Sub
|
||||||
Friend Shared Sub ThrowTokens(ByRef Source As UserData, ByVal Data As String)
|
Friend Shared Sub ThrowTokens(ByRef Source As UserData, ByVal Data As String)
|
||||||
@@ -223,25 +259,28 @@ Namespace API.Instagram
|
|||||||
End If
|
End If
|
||||||
End Get
|
End Get
|
||||||
End Property
|
End Property
|
||||||
Protected Sub LoadSavePostsKV(ByVal Load As Boolean)
|
Friend Overloads Shared Sub LoadSavePostsKV(ByVal Load As Boolean, ByVal fPosts As SFile, ByRef List As List(Of PostKV))
|
||||||
Dim x As XmlFile
|
Dim x As XmlFile
|
||||||
Dim f As SFile = MyFilePostsKV
|
Dim f As SFile = fPosts
|
||||||
If Not f.IsEmptyString Then
|
If Not f.IsEmptyString Then
|
||||||
If Load Then
|
If Load Then
|
||||||
PostsKVIDs.Clear()
|
List.Clear()
|
||||||
x = New XmlFile(f, Protector.Modes.All, False) With {.AllowSameNames = True, .XmlReadOnly = True}
|
x = New XmlFile(f, Protector.Modes.All, False) With {.AllowSameNames = True, .XmlReadOnly = True}
|
||||||
x.LoadData()
|
x.LoadData()
|
||||||
If x.Count > 0 Then PostsKVIDs.ListAddList(x, LAP.IgnoreICopier)
|
If x.Count > 0 Then List.ListAddList(x, LAP.IgnoreICopier)
|
||||||
x.Dispose()
|
x.Dispose()
|
||||||
Else
|
Else
|
||||||
x = New XmlFile With {.AllowSameNames = True}
|
x = New XmlFile With {.AllowSameNames = True}
|
||||||
x.AddRange(PostsKVIDs)
|
x.AddRange(List)
|
||||||
x.Name = "Posts"
|
x.Name = "Posts"
|
||||||
x.Save(f, EDP.SendToLog)
|
x.Save(f, EDP.SendToLog)
|
||||||
x.Dispose()
|
x.Dispose()
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
|
Protected Overloads Sub LoadSavePostsKV(ByVal Load As Boolean)
|
||||||
|
LoadSavePostsKV(Load, MyFilePostsKV, PostsKVIDs)
|
||||||
|
End Sub
|
||||||
Protected Overloads Function PostKvExists(ByVal pkv As PostKV) As Boolean
|
Protected Overloads Function PostKvExists(ByVal pkv As PostKV) As Boolean
|
||||||
Return PostKvExists(pkv.ID, False, pkv.Section) OrElse PostKvExists(pkv.Code, True, pkv.Section)
|
Return PostKvExists(pkv.ID, False, pkv.Section) OrElse PostKvExists(pkv.Code, True, pkv.Section)
|
||||||
End Function
|
End Function
|
||||||
@@ -362,8 +401,25 @@ 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
|
||||||
|
ErrHandlingLog = True
|
||||||
|
ErrHandlingSection = Sections.Timeline
|
||||||
_Limit = If(DownloadTopCount, -1)
|
_Limit = If(DownloadTopCount, -1)
|
||||||
_TotalPostsParsed = 0
|
_TotalPostsParsed = 0
|
||||||
LoadSavePostsKV(True)
|
LoadSavePostsKV(True)
|
||||||
@@ -372,9 +428,11 @@ Namespace API.Instagram
|
|||||||
ThrowAny(Token)
|
ThrowAny(Token)
|
||||||
HasError = False
|
HasError = False
|
||||||
Dim dt As Func(Of Boolean) = Function() (CBool(MySiteSettings.DownloadTimeline.Value) And GetTimeline) Or IsSavedPosts
|
Dim dt As Func(Of Boolean) = Function() (CBool(MySiteSettings.DownloadTimeline.Value) And GetTimeline) Or IsSavedPosts
|
||||||
|
If FirstLoadingDone Then LastCursor = String.Empty
|
||||||
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)
|
||||||
@@ -384,6 +442,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)
|
||||||
@@ -399,6 +458,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()
|
||||||
@@ -408,6 +468,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
|
||||||
@@ -416,6 +477,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
|
||||||
@@ -424,6 +486,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
|
||||||
@@ -444,18 +507,25 @@ Namespace API.Instagram
|
|||||||
If Not errorFound Then LoadSavePostsKV(False)
|
If Not errorFound Then LoadSavePostsKV(False)
|
||||||
End Try
|
End Try
|
||||||
End Sub
|
End Sub
|
||||||
Private 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()
|
||||||
@@ -471,7 +541,7 @@ Namespace API.Instagram
|
|||||||
Protected Overrides Sub Responser_ResponseReceived(ByVal Sender As Object, ByVal e As EventArguments.WebDataResponse)
|
Protected Overrides Sub Responser_ResponseReceived(ByVal Sender As Object, ByVal e As EventArguments.WebDataResponse)
|
||||||
Declarations.UpdateResponser(e, Responser, WwwClaimUpdate)
|
Declarations.UpdateResponser(e, Responser, WwwClaimUpdate)
|
||||||
End Sub
|
End Sub
|
||||||
Protected Enum Sections : Timeline : Reels : Tagged : Stories : UserStories : SavedPosts : End Enum
|
Friend Enum Sections : Timeline : Reels : Tagged : Stories : UserStories : SavedPosts : Reposts : Likes : End Enum
|
||||||
Protected Const StoriesFolder As String = "Stories"
|
Protected Const StoriesFolder As String = "Stories"
|
||||||
Private Const TaggedFolder As String = "Tagged"
|
Private Const TaggedFolder As String = "Tagged"
|
||||||
#Region "429 bypass"
|
#Region "429 bypass"
|
||||||
@@ -609,6 +679,7 @@ Namespace API.Instagram
|
|||||||
Dim StoriesList As List(Of String) = Nothing
|
Dim StoriesList As List(Of String) = Nothing
|
||||||
Dim StoriesRequested As Boolean = False
|
Dim StoriesRequested As Boolean = False
|
||||||
Dim dValue% = 1
|
Dim dValue% = 1
|
||||||
|
Dim __idIsEmpty As Boolean = ID.IsEmptyString
|
||||||
LastCursor = Cursor
|
LastCursor = Cursor
|
||||||
Try
|
Try
|
||||||
Do While dValue = 1
|
Do While dValue = 1
|
||||||
@@ -622,7 +693,6 @@ Namespace API.Instagram
|
|||||||
Dim HasNextPage As Boolean = False
|
Dim HasNextPage As Boolean = False
|
||||||
Dim EndCursor$ = String.Empty
|
Dim EndCursor$ = String.Empty
|
||||||
Dim PostID$ = String.Empty, PostDate$ = String.Empty, SpecFolder$ = String.Empty
|
Dim PostID$ = String.Empty, PostDate$ = String.Empty, SpecFolder$ = String.Empty
|
||||||
Dim TokensErrData$ = String.Empty
|
|
||||||
Dim PostIDKV As PostKV
|
Dim PostIDKV As PostKV
|
||||||
Dim ENode() As Object = Nothing
|
Dim ENode() As Object = Nothing
|
||||||
Dim processGetResponse As Boolean = True
|
Dim processGetResponse As Boolean = True
|
||||||
@@ -630,12 +700,11 @@ Namespace API.Instagram
|
|||||||
|
|
||||||
'Check environment
|
'Check environment
|
||||||
If Not IsSavedPosts Then
|
If Not IsSavedPosts Then
|
||||||
If ID.IsEmptyString Then GetUserData()
|
If _UseGQL And Cursor.IsEmptyString And Not Section = Sections.SavedPosts Then UpdateTokens(True)
|
||||||
If ID.IsEmptyString Then Throw New Plugin.ExitException("can't get user ID")
|
If ID.IsEmptyString Or __idIsEmpty Or Not IsVerifiedProfile_Checked Then GetUserData(Token)
|
||||||
If _UseGQL And Cursor.IsEmptyString And Not Section = Sections.SavedPosts Then
|
If ID.IsEmptyString Then UserExists = False : _ForceSaveUserInfoOnException = True : Throw New Plugin.ExitException("can't get user ID")
|
||||||
If Not ValidateBaseTokens() Then GetPageTokens()
|
If ForceUpdateUserName Then GetUserNameById()
|
||||||
If Not ValidateBaseTokens(TokensErrData) Then ValidateBaseTokens_Error(TokensErrData)
|
If ForceUpdateUserInfo Then GetUserData(Token)
|
||||||
End If
|
|
||||||
End If
|
End If
|
||||||
|
|
||||||
'Create query
|
'Create query
|
||||||
@@ -647,7 +716,7 @@ Namespace API.Instagram
|
|||||||
MySiteSettings.TooManyRequests(False)
|
MySiteSettings.TooManyRequests(False)
|
||||||
GoTo NextPageBlock
|
GoTo NextPageBlock
|
||||||
Else
|
Else
|
||||||
URL = $"https://www.instagram.com/api/v1/feed/user/{NameTrue}/username/?count=50" &
|
URL = $"https://www.instagram.com/api/v1/feed/user/{NameTrue}/username/?count={PostNumberPerRequest}" &
|
||||||
If(Cursor.IsEmptyString, String.Empty, $"&max_id={Cursor}")
|
If(Cursor.IsEmptyString, String.Empty, $"&max_id={Cursor}")
|
||||||
ENode = Nothing
|
ENode = Nothing
|
||||||
End If
|
End If
|
||||||
@@ -670,7 +739,7 @@ Namespace API.Instagram
|
|||||||
ENode = {"data", "xdt_api__v1__usertags__user_id__feed_connection"}
|
ENode = {"data", "xdt_api__v1__usertags__user_id__feed_connection"}
|
||||||
processGetResponse = False
|
processGetResponse = False
|
||||||
Else
|
Else
|
||||||
Dim vars$ = "{""id"":" & ID & ",""first"":50,""after"":""" & Cursor & """}"
|
Dim vars$ = "{""id"":" & ID & $",""first"":{PostNumberPerRequest},""after"":""" & Cursor & """}"
|
||||||
vars = SymbolsConverter.ASCII.EncodeSymbolsOnly(vars)
|
vars = SymbolsConverter.ASCII.EncodeSymbolsOnly(vars)
|
||||||
URL = $"https://www.instagram.com/graphql/query/?doc_id=17946422347485809&variables={vars}"
|
URL = $"https://www.instagram.com/graphql/query/?doc_id=17946422347485809&variables={vars}"
|
||||||
ENode = {"data", "user", "edge_user_to_photos_of_you"}
|
ENode = {"data", "user", "edge_user_to_photos_of_you"}
|
||||||
@@ -718,6 +787,14 @@ Namespace API.Instagram
|
|||||||
Select Case Section
|
Select Case Section
|
||||||
Case Sections.Timeline
|
Case Sections.Timeline
|
||||||
With n
|
With n
|
||||||
|
If If(n("user")?.Count, 0) = 0 And Cursor.IsEmptyString Then
|
||||||
|
If Not UserNameRequested Then
|
||||||
|
ForceUpdateUserName = True
|
||||||
|
Continue Do
|
||||||
|
Else
|
||||||
|
UserExists = False
|
||||||
|
End If
|
||||||
|
End If
|
||||||
HasNextPage = .Value("more_available").FromXML(Of Boolean)(False)
|
HasNextPage = .Value("more_available").FromXML(Of Boolean)(False)
|
||||||
EndCursor = .Value("next_max_id")
|
EndCursor = .Value("next_max_id")
|
||||||
If If(.Item("items")?.Count, 0) > 0 Then
|
If If(.Item("items")?.Count, 0) > 0 Then
|
||||||
@@ -801,6 +878,11 @@ NextPageBlock:
|
|||||||
Throw eex
|
Throw eex
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
dValue = ProcessException(ex, Token, $"data downloading error [{URL}]",, Section, False)
|
dValue = ProcessException(ex, Token, $"data downloading error [{URL}]",, Section, False)
|
||||||
|
If dValue = ErrHandlingValue Then
|
||||||
|
ExitException.Throw560(Me)
|
||||||
|
ElseIf dValue = ErrHandlingValueStories Then
|
||||||
|
Exit Sub
|
||||||
|
End If
|
||||||
End Try
|
End Try
|
||||||
Loop
|
Loop
|
||||||
Catch jsonNull2 As JsonDocumentException When jsonNull2.State = WebDocumentEventArgs.States.Error And
|
Catch jsonNull2 As JsonDocumentException When jsonNull2.State = WebDocumentEventArgs.States.Error And
|
||||||
@@ -920,10 +1002,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
|
||||||
@@ -958,9 +1042,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
|
||||||
@@ -973,6 +1065,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
|
||||||
@@ -1021,7 +1116,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)
|
||||||
@@ -1056,6 +1152,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
|
||||||
@@ -1068,12 +1165,30 @@ NextPageBlock:
|
|||||||
If TryExtractImage Then
|
If TryExtractImage Then
|
||||||
t = 1
|
t = 1
|
||||||
abstractDecision = True
|
abstractDecision = True
|
||||||
If Not SpecialFolder.IsEmptyString AndAlso PutImageVideoFolder Then
|
Dim endsAbs As Boolean
|
||||||
Dim endsAbs As Boolean = SpecialFolder.EndsWith("*")
|
Dim newFolderName$
|
||||||
If endsAbs Then SpecialFolder = SpecialFolder.TrimEnd("*")
|
If PutImageVideoFolder Then
|
||||||
If Not SpecialFolder.IsEmptyString Then SpecialFolder = $"{SpecialFolder.TrimEnd("\")}\{VideoFolderName}{IIf(Not endsAbs, "*", String.Empty)}"
|
If SpecialFolder.IsEmptyString Then
|
||||||
If endsAbs Then SpecialFolder &= "*"
|
newFolderName = $"{VideoFolderName}\*"
|
||||||
|
Else
|
||||||
|
endsAbs = SpecialFolder.EndsWith("*")
|
||||||
|
SpecialFolder = SpecialFolder.TrimEnd({CChar("\"), CChar("*")})
|
||||||
|
If Not endsAbs Then SpecialFolder = $"{SpecialFolder}\{VideoFolderName}"
|
||||||
|
newFolderName = $"{SpecialFolder}*"
|
||||||
|
End If
|
||||||
|
'Dim endsAbs As Boolean = SpecialFolder.EndsWith("*")
|
||||||
|
'If endsAbs Then SpecialFolder = SpecialFolder.TrimEnd("*")
|
||||||
|
'If Not SpecialFolder.IsEmptyString Then SpecialFolder = $"{SpecialFolder.TrimEnd("\")}\{VideoFolderName}{IIf(Not endsAbs, "*", String.Empty)}"
|
||||||
|
'If endsAbs Then SpecialFolder &= "*"
|
||||||
|
ElseIf Not SpecialFolder.IsEmptyString Then
|
||||||
|
endsAbs = SpecialFolder.EndsWith("*")
|
||||||
|
SpecialFolder = SpecialFolder.TrimEnd({CChar("\"), CChar("*")})
|
||||||
|
If endsAbs Then SpecialFolder = $"{SpecialFolder}\Photos"
|
||||||
|
newFolderName = $"{SpecialFolder}*"
|
||||||
|
Else
|
||||||
|
newFolderName = SpecialFolder
|
||||||
End If
|
End If
|
||||||
|
SpecialFolder = newFolderName
|
||||||
ElseIf t = -1 And InitialType = 8 And ObtainMedia_AllowAbstract Then
|
ElseIf t = -1 And InitialType = 8 And ObtainMedia_AllowAbstract Then
|
||||||
If n.Contains(vid) Then
|
If n.Contains(vid) Then
|
||||||
t = 2
|
t = 2
|
||||||
@@ -1097,7 +1212,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
|
||||||
@@ -1114,19 +1229,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
|
||||||
@@ -1139,38 +1254,49 @@ NextPageBlock:
|
|||||||
End Sub
|
End Sub
|
||||||
#End Region
|
#End Region
|
||||||
#Region "GetUserId, GetUserName"
|
#Region "GetUserId, GetUserName"
|
||||||
Private Sub GetUserData()
|
Private Sub GetUserData(ByVal Token As CancellationToken)
|
||||||
Dim __idFound As Boolean = False
|
Dim __idFound As Boolean = False
|
||||||
|
If ForceUpdateUserInfo Then ForceUpdateUserInfo = False : _ForceSaveUserInfo = True
|
||||||
Try
|
Try
|
||||||
ChangeResponserMode(False)
|
Dim r$
|
||||||
UpdateRequestNumber()
|
Dim ____dataGql As Boolean = _UseGQL Or CBool(MySiteSettings.USE_GQL_UserData.Value)
|
||||||
Dim r$ = Responser.GetResponse($"https://i.instagram.com/api/v1/users/web_profile_info/?username={NameTrue}")
|
If ____dataGql Then
|
||||||
|
UpdateTokens(True)
|
||||||
|
r = GetUserDataGQL(Token)
|
||||||
|
If Not _UseGQL Then ChangeResponserMode(_UseGQL)
|
||||||
|
Else
|
||||||
|
ChangeResponserMode(False)
|
||||||
|
UpdateRequestNumber()
|
||||||
|
r = Responser.GetResponse($"https://i.instagram.com/api/v1/users/web_profile_info/?username={NameTrue}")
|
||||||
|
End If
|
||||||
|
|
||||||
If Not r.IsEmptyString Then
|
If Not r.IsEmptyString Then
|
||||||
Using j As EContainer = JsonDocument.Parse(r)
|
Using j As EContainer = JsonDocument.Parse(r)
|
||||||
If Not j Is Nothing AndAlso j.Contains({"data", "user"}) Then
|
If Not j Is Nothing AndAlso j.Contains({"data", "user"}) Then
|
||||||
With j({"data", "user"})
|
With j({"data", "user"})
|
||||||
ID = .Value("id")
|
If Not ____dataGql Or ID.IsEmptyString Then ID = .Value("id")
|
||||||
_ForceSaveUserData = True
|
|
||||||
__idFound = True
|
__idFound = True
|
||||||
UserSiteNameUpdate(.Value("full_name"))
|
UserSiteNameUpdate(.Value("full_name"))
|
||||||
|
IsVerifiedProfile = .Value("is_verified").FromXML(Of Boolean)(False)
|
||||||
|
IsVerifiedProfile_Checked = True
|
||||||
Dim descr$ = .Value("biography")
|
Dim descr$ = .Value("biography")
|
||||||
If If(.Item("bio_links")?.Count, 0) > 0 Then descr.StringAppend(.Item("bio_links").Select(Function(bl) bl.Value("url")).ListToString(vbNewLine), vbNewLine)
|
If If(.Item("bio_links")?.Count, 0) > 0 Then descr.StringAppend(.Item("bio_links").Select(Function(bl) bl.Value("url")).ListToString(vbNewLine), vbNewLine)
|
||||||
Dim eUrl$ = .Value("external_url")
|
Dim eUrl$ = .Value("external_url")
|
||||||
If Not eUrl.IsEmptyString AndAlso (descr.IsEmptyString OrElse Not descr.Contains(eUrl)) Then descr.StringAppendLine(eUrl)
|
If Not eUrl.IsEmptyString AndAlso (descr.IsEmptyString OrElse Not descr.Contains(eUrl)) Then descr.StringAppendLine(eUrl)
|
||||||
UserDescriptionUpdate(descr)
|
UserDescriptionUpdate(descr)
|
||||||
|
|
||||||
Dim f As New SFile With {.Path = DownloadContentDefault_GetRootDir(), .Name = "ProfilePicture", .Extension = "jpg"}
|
Dim f As New SFile With {.Path = DownloadContentDefault_GetRootDir(), .Name = "ProfilePicture", .Extension = "jpg"}
|
||||||
|
f = SFile.IndexReindex(f)
|
||||||
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
|
||||||
End Using
|
End Using
|
||||||
End If
|
End If
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
|
UserExists = False
|
||||||
If Not __idFound Then
|
If Not __idFound Then
|
||||||
If Responser.StatusCode = HttpStatusCode.NotFound Or Responser.StatusCode = HttpStatusCode.BadRequest Then
|
If Responser.StatusCode = HttpStatusCode.NotFound Or Responser.StatusCode = HttpStatusCode.BadRequest Then
|
||||||
Throw ex
|
Throw ex
|
||||||
@@ -1184,6 +1310,7 @@ NextPageBlock:
|
|||||||
End Sub
|
End Sub
|
||||||
Private Function GetUserNameById() As Boolean
|
Private Function GetUserNameById() As Boolean
|
||||||
UserNameRequested = True
|
UserNameRequested = True
|
||||||
|
If ForceUpdateUserName Then ForceUpdateUserName = False : _ForceSaveUserInfo = True
|
||||||
Try
|
Try
|
||||||
If Not ID.IsEmptyString Then
|
If Not ID.IsEmptyString Then
|
||||||
UpdateRequestNumber()
|
UpdateRequestNumber()
|
||||||
@@ -1195,12 +1322,11 @@ 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
|
||||||
_ForceSaveUserData = True
|
|
||||||
End If
|
End If
|
||||||
Return True
|
Return True
|
||||||
End If
|
End If
|
||||||
@@ -1279,20 +1405,15 @@ NextPageBlock:
|
|||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
Private Function GetStoriesList() As List(Of String)
|
Private Function GetStoriesList() As List(Of String)
|
||||||
Try
|
UpdateRequestNumber()
|
||||||
UpdateRequestNumber()
|
Dim r$ = Responser.GetResponse($"https://i.instagram.com/api/v1/highlights/{ID}/highlights_tray/",, EDP.ThrowException)
|
||||||
Dim r$ = Responser.GetResponse($"https://i.instagram.com/api/v1/highlights/{ID}/highlights_tray/",, EDP.ThrowException)
|
If Not r.IsEmptyString Then
|
||||||
If Not r.IsEmptyString Then
|
Dim ee As New ErrorsDescriber(EDP.ReturnValue) With {.DeclaredMessage = New MMessage($"{ToStringForLog()}:")}
|
||||||
Dim ee As New ErrorsDescriber(EDP.ReturnValue) With {.DeclaredMessage = New MMessage($"{ToStringForLog()}:")}
|
Using j As EContainer = JsonDocument.Parse(r, ee).XmlIfNothing()("tray").XmlIfNothing
|
||||||
Using j As EContainer = JsonDocument.Parse(r, ee).XmlIfNothing()("tray").XmlIfNothing
|
If j.Count > 0 Then Return j.Select(Function(jj) jj.Value("id").Replace("highlight:", String.Empty)).ListIfNothing
|
||||||
If j.Count > 0 Then Return j.Select(Function(jj) jj.Value("id").Replace("highlight:", String.Empty)).ListIfNothing
|
End Using
|
||||||
End Using
|
End If
|
||||||
End If
|
Return Nothing
|
||||||
Return Nothing
|
|
||||||
Catch ex As Exception
|
|
||||||
DownloadingException(ex, "API.Instagram.GetStoriesList", False, Sections.Stories)
|
|
||||||
Return Nothing
|
|
||||||
End Try
|
|
||||||
End Function
|
End Function
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Download content"
|
#Region "Download content"
|
||||||
@@ -1338,11 +1459,26 @@ NextPageBlock:
|
|||||||
MyMainLOG = $"Number of requests before error 429: {RequestsCount}"
|
MyMainLOG = $"Number of requests before error 429: {RequestsCount}"
|
||||||
Return 1
|
Return 1
|
||||||
ElseIf Responser.StatusCode = 560 Or Responser.StatusCode = HttpStatusCode.InternalServerError Then '560, 500
|
ElseIf Responser.StatusCode = 560 Or Responser.StatusCode = HttpStatusCode.InternalServerError Then '560, 500
|
||||||
MySiteSettings.SkipUntilNextSession = True
|
If Responser.StatusCode = 560 And s = Sections.Stories And MySiteSettings.IgnoreStoriesDownloadingErrors.Value Then
|
||||||
Err5xx = Responser.StatusCode
|
MyMainLOG = $"{ToStringForLog()}: Stories downloading skipped (560)"
|
||||||
|
Return ErrHandlingValueStories
|
||||||
|
Else
|
||||||
|
MySiteSettings.SkipUntilNextSession = True
|
||||||
|
Err5xx = Responser.StatusCode
|
||||||
|
End If
|
||||||
ElseIf Responser.StatusCode = -1 And Responser.Status = -1 Then
|
ElseIf Responser.StatusCode = -1 And Responser.Status = -1 Then
|
||||||
MySiteSettings.SkipUntilNextSession = True
|
MySiteSettings.SkipUntilNextSession = True
|
||||||
Err5xx = Responser.StatusCode
|
Err5xx = Responser.StatusCode
|
||||||
|
ElseIf MySiteSettings.ErrorSpecialHandling(Responser.StatusCode) Then
|
||||||
|
ErrHandlingLog = MySiteSettings.ErrorSpecialHandling_AddToLog(Responser.StatusCode)
|
||||||
|
ErrHandling = Responser.StatusCode
|
||||||
|
ErrHandlingSection = s
|
||||||
|
Return ErrHandlingValue
|
||||||
|
ElseIf MySiteSettings.ErrorSpecialHandling(Responser.Status) Then
|
||||||
|
ErrHandlingLog = MySiteSettings.ErrorSpecialHandling_AddToLog(Responser.Status)
|
||||||
|
ErrHandling = Responser.Status
|
||||||
|
ErrHandlingSection = s
|
||||||
|
Return ErrHandlingValue
|
||||||
Else
|
Else
|
||||||
MyMainLOG = $"Something is wrong. Your credentials may have expired [{CInt(Responser.StatusCode)}/{CInt(Responser.Status)}]: {ToString()} [{s}]"
|
MyMainLOG = $"Something is wrong. Your credentials may have expired [{CInt(Responser.StatusCode)}/{CInt(Responser.Status)}]: {ToString()} [{s}]"
|
||||||
DisableSection(s)
|
DisableSection(s)
|
||||||
@@ -1380,13 +1516,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
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ Namespace API.Mastodon
|
|||||||
<PSetting(Address:=SettingAddress.None)> Friend Overrides Property DownloadModelSearch As Boolean
|
<PSetting(Address:=SettingAddress.None)> Friend Overrides Property DownloadModelSearch As Boolean
|
||||||
<PSetting(Address:=SettingAddress.None)> Friend Overrides Property DownloadModelForceApply As Boolean
|
<PSetting(Address:=SettingAddress.None)> Friend Overrides Property DownloadModelForceApply As Boolean
|
||||||
<PSetting(Address:=SettingAddress.None)> Friend Overrides Property DownloadModelLikes As Boolean
|
<PSetting(Address:=SettingAddress.None)> Friend Overrides Property DownloadModelLikes As Boolean
|
||||||
|
<PSetting(Address:=SettingAddress.None)> Friend Overrides Property DownloadBroadcasts As Boolean
|
||||||
|
<PSetting(Address:=SettingAddress.None)> Friend Overrides Property UserName As String
|
||||||
Friend Sub New(ByVal s As SiteSettings)
|
Friend Sub New(ByVal s As SiteSettings)
|
||||||
MyBase.New(s)
|
MyBase.New(s)
|
||||||
End Sub
|
End Sub
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -219,12 +219,12 @@ Namespace API.OnlyFans
|
|||||||
DynamicRulesXml.Extension = "xml"
|
DynamicRulesXml.Extension = "xml"
|
||||||
ReplacePattern_RepoToRaw = New RParams("(.*github.com/([^/]+)/([^/]+)/blob/(.+))", Nothing, 0,
|
ReplacePattern_RepoToRaw = New RParams("(.*github.com/([^/]+)/([^/]+)/blob/(.+))", Nothing, 0,
|
||||||
RegexReturn.ReplaceChangeListMatch, EDP.ReturnValue) With {
|
RegexReturn.ReplaceChangeListMatch, EDP.ReturnValue) With {
|
||||||
.PatternReplacement = "https://raw.githubusercontent.com/{2}/{3}/{4}"}
|
.PatternReplacement = "https://raw.githubusercontent.com/{2}/{3}/refs/heads/{4}"}
|
||||||
ReplacePattern_JsonInfo = ReplacePattern_RepoToRaw.Copy
|
ReplacePattern_JsonInfo = ReplacePattern_RepoToRaw.Copy
|
||||||
ReplacePattern_JsonInfo.PatternReplacement = "https://github.com/{2}/{3}/latest-commit/{4}"
|
ReplacePattern_JsonInfo.PatternReplacement = "https://github.com/{2}/{3}/latest-commit/{4}"
|
||||||
ReplacePattern_RawToRepo = ReplacePattern_RepoToRaw.Copy
|
ReplacePattern_RawToRepo = ReplacePattern_RepoToRaw.Copy
|
||||||
ReplacePattern_RawToRepo.Pattern = "(.*raw.githubusercontent.com/([^/]+)/([^/]+)/([^/]+)/(.+))"
|
ReplacePattern_RawToRepo.Pattern = "(.*raw.githubusercontent.com/([^/]+)/([^/]+)(/refs/heads)?/([^/]+)/(.+))"
|
||||||
ReplacePattern_RawToRepo.PatternReplacement = "https://github.com/{2}/{3}/blob/{4}/{5}"
|
ReplacePattern_RawToRepo.PatternReplacement = "https://github.com/{2}/{3}/blob/{5}/{6}"
|
||||||
ConfigRulesExtract = RParams.DMS("DYNAMIC_RULE"":(\{.+?\}[\r\n]+)", 1, RegexOptions.Singleline, EDP.ReturnValue)
|
ConfigRulesExtract = RParams.DMS("DYNAMIC_RULE"":(\{.+?\}[\r\n]+)", 1, RegexOptions.Singleline, EDP.ReturnValue)
|
||||||
OFLOG = New TextSaver($"LOGs\OF_{Now:yyyyMMdd_HHmmss}.txt") With {.LogMode = True, .AutoSave = True, .AutoClear = True}
|
OFLOG = New TextSaver($"LOGs\OF_{Now:yyyyMMdd_HHmmss}.txt") With {.LogMode = True, .AutoSave = True, .AutoClear = True}
|
||||||
AddHandler OFLOG.TextSaved, AddressOf OFLOG_TextSaved
|
AddHandler OFLOG.TextSaved, AddressOf OFLOG_TextSaved
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ Namespace API.OnlyFans
|
|||||||
#Region "Declarations"
|
#Region "Declarations"
|
||||||
#Region "Categories"
|
#Region "Categories"
|
||||||
Private Const CAT_OFS As String = "OF-Scraper support"
|
Private Const CAT_OFS As String = "OF-Scraper support"
|
||||||
|
Private Const CAT_ERRORS As String = "Errors"
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Options"
|
#Region "Options"
|
||||||
<PropertyOption(ControlText:="Download timeline", ControlToolTip:="Download user timeline", Category:=DN.CAT_UserDefs), PXML, PClonable>
|
<PropertyOption(ControlText:="Download timeline", ControlToolTip:="Download user timeline", Category:=DN.CAT_UserDefs), PXML, PClonable>
|
||||||
@@ -35,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
|
||||||
@@ -72,6 +81,36 @@ Namespace API.OnlyFans
|
|||||||
End If
|
End If
|
||||||
Return String.Empty
|
Return String.Empty
|
||||||
End Function
|
End Function
|
||||||
|
<PropertyOption(ControlText:="Update cookies during requests",
|
||||||
|
ControlToolTip:="If unchecked, cookies will not be updated during requests. Initial cookies will always be used.", IsAuth:=True),
|
||||||
|
PClonable, PXML, HiddenControl>
|
||||||
|
Friend ReadOnly Property EnableCookiesUpdate As PropertyValue
|
||||||
|
#End Region
|
||||||
|
#Region "Errors"
|
||||||
|
<PClonable, PXML("UpdateRules401")> Private ReadOnly Property UpdateRules401_XML As PropertyValue
|
||||||
|
<PropertyOption(ControlText:="Try updating rules when you get a 401 error", Category:=CAT_ERRORS), HiddenControl>
|
||||||
|
Friend ReadOnly Property UpdateRules401 As PropertyValue
|
||||||
|
Get
|
||||||
|
If Not DefaultInstance Is Nothing Then
|
||||||
|
Return DirectCast(DefaultInstance, SiteSettings).UpdateRules401_XML
|
||||||
|
Else
|
||||||
|
Return UpdateRules401_XML
|
||||||
|
End If
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
|
#End Region
|
||||||
|
#Region "Other"
|
||||||
|
<PClonable, PXML("OpenPostsUsingID")> Private ReadOnly Property OpenPostsUsingID_XML As PropertyValue
|
||||||
|
<PropertyOption(ControlText:="Open posts using ID", ControlToolTip:="Open posts using the user ID instead of the user name"), HiddenControl>
|
||||||
|
Private ReadOnly Property OpenPostsUsingID As PropertyValue
|
||||||
|
Get
|
||||||
|
If Not DefaultInstance Is Nothing Then
|
||||||
|
Return DirectCast(DefaultInstance, SiteSettings).OpenPostsUsingID_XML
|
||||||
|
Else
|
||||||
|
Return OpenPostsUsingID_XML
|
||||||
|
End If
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
#End Region
|
#End Region
|
||||||
#Region "OFScraper"
|
#Region "OFScraper"
|
||||||
<PClonable, PXML("OFScraperPath")> Private ReadOnly Property OFScraperPath_XML As PropertyValue
|
<PClonable, PXML("OFScraperPath")> Private ReadOnly Property OFScraperPath_XML As PropertyValue
|
||||||
@@ -98,7 +137,7 @@ Namespace API.OnlyFans
|
|||||||
End Property
|
End Property
|
||||||
Friend Const KeyModeDefault_Default As String = "cdrm"
|
Friend Const KeyModeDefault_Default As String = "cdrm"
|
||||||
<PClonable, PXML("KeyModeDefault")> Private ReadOnly Property KeyModeDefault_XML As PropertyValue
|
<PClonable, PXML("KeyModeDefault")> Private ReadOnly Property KeyModeDefault_XML As PropertyValue
|
||||||
<PropertyOption(ControlText:="key-mode-default", Category:=CAT_OFS)>
|
<PropertyOption(ControlText:="key-mode-default", ControlToolTip:="Examples: cdrm, cdrm2, keydb, manual", Category:=CAT_OFS)>
|
||||||
Friend ReadOnly Property KeyModeDefault As PropertyValue
|
Friend ReadOnly Property KeyModeDefault As PropertyValue
|
||||||
Get
|
Get
|
||||||
If Not DefaultInstance Is Nothing Then
|
If Not DefaultInstance Is Nothing Then
|
||||||
@@ -119,6 +158,80 @@ Namespace API.OnlyFans
|
|||||||
End If
|
End If
|
||||||
End Get
|
End Get
|
||||||
End Property
|
End Property
|
||||||
|
<PClonable, PXML("KEYS_Key")> Private ReadOnly Property OFS_KEYS_Key_XML As PropertyValue
|
||||||
|
<PropertyOption(ControlText:="Private key", ControlToolTip:="Path to the DRM key file 'private_key.pem'", Category:=CAT_OFS)>
|
||||||
|
Friend ReadOnly Property OFS_KEYS_Key As PropertyValue
|
||||||
|
Get
|
||||||
|
If Not DefaultInstance Is Nothing Then
|
||||||
|
Return DirectCast(DefaultInstance, SiteSettings).OFS_KEYS_Key_XML
|
||||||
|
Else
|
||||||
|
Return OFS_KEYS_Key_XML
|
||||||
|
End If
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
|
<PClonable, PXML("KEYS_ClientID")> Private ReadOnly Property OFS_KEYS_ClientID_XML As PropertyValue
|
||||||
|
<PropertyOption(ControlText:="Client ID", ControlToolTip:="Path to the DRM key file 'client_id.bin'", Category:=CAT_OFS)>
|
||||||
|
Friend ReadOnly Property OFS_KEYS_ClientID As PropertyValue
|
||||||
|
Get
|
||||||
|
If Not DefaultInstance Is Nothing Then
|
||||||
|
Return DirectCast(DefaultInstance, SiteSettings).OFS_KEYS_ClientID_XML
|
||||||
|
Else
|
||||||
|
Return OFS_KEYS_ClientID_XML
|
||||||
|
End If
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
|
<PropertiesDataChecker({NameOf(KeyModeDefault), NameOf(OFS_KEYS_Key), NameOf(OFS_KEYS_ClientID)})>
|
||||||
|
Private Function OFS_KEYS_CHECKER(ByVal p As IEnumerable(Of PropertyData)) As Boolean
|
||||||
|
Const manualMode$ = "manual"
|
||||||
|
If p.ListExists Then
|
||||||
|
Dim m$ = String.Empty, k$ = String.Empty, cid$ = String.Empty
|
||||||
|
For Each pp As PropertyData In p
|
||||||
|
Select Case pp.Name
|
||||||
|
Case NameOf(KeyModeDefault) : m = pp.Value
|
||||||
|
Case NameOf(OFS_KEYS_Key) : k = pp.Value
|
||||||
|
Case NameOf(OFS_KEYS_ClientID) : cid = pp.Value
|
||||||
|
Case Else : Throw New ArgumentException($"Property name '{pp.Name}' is not implemented", "Property Name")
|
||||||
|
End Select
|
||||||
|
Next
|
||||||
|
If k.IsEmptyString And cid.IsEmptyString Then
|
||||||
|
Return True
|
||||||
|
ElseIf Not k.IsEmptyString And Not cid.IsEmptyString Then
|
||||||
|
If m = manualMode Then
|
||||||
|
Return True
|
||||||
|
Else
|
||||||
|
Return MsgBoxE({$"You are using key files and have selected '{m}' mode." & vbCr &
|
||||||
|
$"To use key files, you should use the '{manualMode}' mode" & vbCr &
|
||||||
|
"Are you sure you want to use this mode?", "Incorrect mode"}, vbExclamation + vbYesNo) = vbYes
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
Dim t As New MMessage("", "Key missing",, vbCritical)
|
||||||
|
If k.IsEmptyString Then
|
||||||
|
t.Text = "'Private key' is missing"
|
||||||
|
ElseIf cid.IsEmptyString Then
|
||||||
|
t.Text = "'Client ID' is missing"
|
||||||
|
End If
|
||||||
|
If Not t.Text.IsEmptyString Then t.Show()
|
||||||
|
End If
|
||||||
|
Return False
|
||||||
|
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"
|
||||||
@@ -151,12 +264,14 @@ 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(False)
|
||||||
|
|
||||||
DownloadTimeline = New PropertyValue(True)
|
DownloadTimeline = New PropertyValue(True)
|
||||||
DownloadStories = New PropertyValue(True)
|
DownloadStories = New PropertyValue(True)
|
||||||
DownloadHighlights = New PropertyValue(True)
|
DownloadHighlights = New PropertyValue(True)
|
||||||
@@ -177,11 +292,27 @@ Namespace API.OnlyFans
|
|||||||
OFScraperMP4decrypt_XML = New PropertyValue(String.Empty, GetType(String))
|
OFScraperMP4decrypt_XML = New PropertyValue(String.Empty, GetType(String))
|
||||||
KeyModeDefault_XML = New PropertyValue(KeyModeDefault_Default)
|
KeyModeDefault_XML = New PropertyValue(KeyModeDefault_Default)
|
||||||
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_ClientID_XML = New PropertyValue(String.Empty, GetType(String))
|
||||||
|
OFS_BACKEND_XML = New PropertyValue(BackendDefault)
|
||||||
|
|
||||||
|
UpdateRules401_XML = New PropertyValue(False)
|
||||||
|
|
||||||
|
OpenPostsUsingID_XML = New PropertyValue(True)
|
||||||
|
|
||||||
UserRegex = RParams.DMS(String.Format(UserRegexDefaultPattern, "onlyfans.com/"), 1, EDP.ReturnValue)
|
UserRegex = RParams.DMS(String.Format(UserRegexDefaultPattern, "onlyfans.com/"), 1, EDP.ReturnValue)
|
||||||
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
|
||||||
@@ -232,7 +363,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
|
||||||
@@ -247,8 +378,10 @@ Namespace API.OnlyFans
|
|||||||
End If
|
End If
|
||||||
If p.IsEmptyString Then
|
If p.IsEmptyString Then
|
||||||
Return GetUserUrl(User)
|
Return GetUserUrl(User)
|
||||||
|
ElseIf CBool(OpenPostsUsingID.Value) Then
|
||||||
|
Return String.Format(UserPostPattern, p, If(User.ID.IsEmptyString, User.NameTrue, $"u{User.ID}"))
|
||||||
Else
|
Else
|
||||||
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,8 +85,10 @@ 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 _TimelineDownloading As Boolean = False
|
||||||
Private Sub ValidateOFScraper()
|
Private Sub ValidateOFScraper()
|
||||||
_OFScraperExists = ACheck(MySettings.OFScraperPath.Value) AndAlso CStr(MySettings.OFScraperPath.Value).CSFile.Exists
|
_OFScraperExists = ACheck(MySettings.OFScraperPath.Value) AndAlso CStr(MySettings.OFScraperPath.Value).CSFile.Exists
|
||||||
End Sub
|
End Sub
|
||||||
@@ -95,11 +98,12 @@ 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
|
||||||
Responser.Cookies.Clear()
|
Responser.Cookies.Clear()
|
||||||
AddHandler Responser.ResponseReceived, AddressOf Responser_ResponseReceived
|
If MySettings.EnableCookiesUpdate.Value Then AddHandler Responser.ResponseReceived, AddressOf Responser_ResponseReceived
|
||||||
UpdateCookieHeader()
|
UpdateCookieHeader()
|
||||||
|
|
||||||
If Not IsSavedPosts Then
|
If Not IsSavedPosts Then
|
||||||
@@ -107,19 +111,22 @@ Namespace API.OnlyFans
|
|||||||
If ID.IsEmptyString Then Throw New ArgumentNullException("ID", "Unable to get user ID")
|
If ID.IsEmptyString Then Throw New ArgumentNullException("ID", "Unable to get user ID")
|
||||||
End If
|
End If
|
||||||
|
|
||||||
|
_TimelineDownloading = True
|
||||||
If MediaDownloadTimeline Then DownloadTimeline(IIf(IsSavedPosts, 0, String.Empty), Token)
|
If MediaDownloadTimeline Then DownloadTimeline(IIf(IsSavedPosts, 0, String.Empty), Token)
|
||||||
|
_TimelineDownloading = False
|
||||||
If Not IsSavedPosts Then
|
If Not IsSavedPosts Then
|
||||||
If MediaDownloadStories And FunctionErr = FunctionErrDef Then DownloadStories(Token)
|
If MediaDownloadStories And FunctionErr = FunctionErrDef Then DownloadStories(Token)
|
||||||
If MediaDownloadHighlights And FunctionErr = FunctionErrDef Then DownloadHighlights(Token)
|
If MediaDownloadHighlights And FunctionErr = FunctionErrDef Then DownloadHighlights(Token)
|
||||||
If MediaDownloadChatMedia And FunctionErr = FunctionErrDef Then DownloadChatMedia(0, Token)
|
If MediaDownloadChatMedia And FunctionErr = FunctionErrDef Then DownloadChatMedia(0, Token)
|
||||||
End If
|
End If
|
||||||
|
If _TempMediaList.Count > 0 And Not _NameUpdated Then GetUserID(True)
|
||||||
End If
|
End If
|
||||||
Finally
|
Finally
|
||||||
Responser_ResponseReceived_RemoveHandler()
|
Responser_ResponseReceived_RemoveHandler()
|
||||||
End Try
|
End Try
|
||||||
End Sub
|
End Sub
|
||||||
Protected Overrides Sub Responser_ResponseReceived(ByVal Sender As Object, ByVal e As WebDataResponse)
|
Protected Overrides Sub Responser_ResponseReceived(ByVal Sender As Object, ByVal e As WebDataResponse)
|
||||||
If e.CookiesExists Then
|
If e.CookiesExists And CBool(MySettings.EnableCookiesUpdate.Value) Then
|
||||||
CCookie.Update(e.Cookies, CookieKeeper.UpdateModes.ReplaceByNameAll,, EDP.ReturnValue)
|
CCookie.Update(e.Cookies, CookieKeeper.UpdateModes.ReplaceByNameAll,, EDP.ReturnValue)
|
||||||
UpdateCookieHeader()
|
UpdateCookieHeader()
|
||||||
End If
|
End If
|
||||||
@@ -144,7 +151,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 +196,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 +221,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,14 +427,14 @@ 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)
|
||||||
Result = False
|
Result = False
|
||||||
With n("media")
|
With n("media")
|
||||||
If .ListExists Then
|
If .ListExists Then
|
||||||
For Each m In .Self
|
For Each m As EContainer In .Self
|
||||||
postUrl = GetMediaURL(m)
|
postUrl = GetMediaURL(m)
|
||||||
'If IsHL Then
|
'If IsHL Then
|
||||||
' 'postUrl = m.Value({"files", "source"}, "url")
|
' 'postUrl = m.Value({"files", "source"}, "url")
|
||||||
@@ -421,62 +443,61 @@ Namespace API.OnlyFans
|
|||||||
' 'postUrl = m.Value({"source"}, "source").IfNullOrEmpty(m.Value("full"))
|
' 'postUrl = m.Value({"source"}, "source").IfNullOrEmpty(m.Value("full"))
|
||||||
' postUrl = GetMediaURL(m)
|
' postUrl = GetMediaURL(m)
|
||||||
'End If
|
'End If
|
||||||
postUrlBase = String.Empty
|
If m.Value("canView").FromXML(Of Boolean)(True) Then
|
||||||
Select Case m.Value("type")
|
postUrlBase = String.Empty
|
||||||
Case "photo" : t = UTypes.Picture : ext = "jpg"
|
Select Case m.Value("type")
|
||||||
Case "video"
|
Case "photo" : t = UTypes.Picture : ext = "jpg"
|
||||||
t = UTypes.Video
|
Case "video", "gif"
|
||||||
ext = "mp4"
|
t = UTypes.Video
|
||||||
If postUrl.IsEmptyString And Not IsHL And TryUseOFS Then
|
ext = "mp4"
|
||||||
t = UTypes.VideoPre
|
If postUrl.IsEmptyString And Not IsHL And TryUseOFS Then
|
||||||
_AbsMediaIndex += 1
|
t = UTypes.VideoPre
|
||||||
If Not PostUserID.IsEmptyString And IsSingleObjectDownload Then _
|
_AbsMediaIndex += 1
|
||||||
postUrlBase = String.Format(SiteSettings.UserPostPattern, PostID, $"u{PostUserID}")
|
If Not PostUserID.IsEmptyString And IsSingleObjectDownload Then _
|
||||||
End If
|
postUrlBase = String.Format(SiteSettings.UserPostPattern, PostID, $"u{PostUserID}")
|
||||||
Case Else : t = UTypes.Undefined : ext = String.Empty
|
End If
|
||||||
End Select
|
Case Else : t = UTypes.Undefined : ext = String.Empty
|
||||||
If Not t = UTypes.Undefined And (Not postUrl.IsEmptyString Or t = UTypes.VideoPre) Then
|
End Select
|
||||||
Dim media As New UserMedia(postUrl.IfNullOrEmpty(IIf(t = UTypes.VideoPre, $"{t}{_AbsMediaIndex}", String.Empty)), t) With {
|
If Not t = UTypes.Undefined And (Not postUrl.IsEmptyString Or t = UTypes.VideoPre) Then
|
||||||
.Post = New UserPost(PostID, AConvert(Of Date)(PostDate, DateProvider, Nothing)),
|
Dim media As New UserMedia(postUrl.IfNullOrEmpty(IIf(t = UTypes.VideoPre, $"{t}{_AbsMediaIndex}", String.Empty)), t) With {
|
||||||
.SpecialFolder = SpecFolder
|
.Post = New UserPost(PostID, AConvert(Of Date)(PostDate, DateProvider, Nothing)),
|
||||||
}
|
.SpecialFolder = SpecFolder,
|
||||||
If postUrlBase.IsEmptyString And Not IsSingleObjectDownload Then postUrlBase = GetPostUrl(Me, media)
|
.PostText = PostText,
|
||||||
If Not postUrlBase.IsEmptyString Then media.URL_BASE = postUrlBase
|
.PostTextFileSpecialFolder = DownloadTextSpecialFolder
|
||||||
media.File.Extension = ext
|
}
|
||||||
Result = True
|
If postUrlBase.IsEmptyString And Not IsSingleObjectDownload Then postUrlBase = GetPostUrl(Me, media)
|
||||||
mList.Add(media)
|
If Not postUrlBase.IsEmptyString Then media.URL_BASE = postUrlBase
|
||||||
|
media.File.Extension = ext
|
||||||
|
Result = True
|
||||||
|
mList.Add(media)
|
||||||
|
End If
|
||||||
End If
|
End If
|
||||||
Next
|
Next
|
||||||
End If
|
End If
|
||||||
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
|
|
||||||
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,11 +629,12 @@ 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)
|
||||||
'#End If
|
'#End If
|
||||||
Using b As New TokenBatch(Token) : b.Execute(command) : End Using
|
Using b As New TokenBatch(Token) With {.DebugMode = False} : b.Execute(command) : End Using
|
||||||
Return SFile.GetFiles(conf, "*.mp4", IO.SearchOption.AllDirectories, EDP.ReturnValue)
|
Return SFile.GetFiles(conf, "*.mp4", IO.SearchOption.AllDirectories, EDP.ReturnValue)
|
||||||
End If
|
End If
|
||||||
Return Nothing
|
Return Nothing
|
||||||
@@ -623,7 +645,13 @@ Namespace API.OnlyFans
|
|||||||
Private Function OFS_CreateConfig() As SFile
|
Private Function OFS_CreateConfig() As SFile
|
||||||
Try
|
Try
|
||||||
Const confMainPattern$ = "{0}"": ""([^""]*)"""
|
Const confMainPattern$ = "{0}"": ""([^""]*)"""
|
||||||
|
Const confMainPattern_Keys$ = "{0}"": ([^,]*)"
|
||||||
Const confMainPatternRulesManual$ = "DYNAMIC_RULE"": (""[^""]*"")"
|
Const confMainPatternRulesManual$ = "DYNAMIC_RULE"": (""[^""]*"")"
|
||||||
|
|
||||||
|
Const m1 As Byte = 0 'not rules
|
||||||
|
Const m2 As Byte = 1 'rules
|
||||||
|
Const m3 As Byte = 2 'keys
|
||||||
|
|
||||||
If OFSCache Is Nothing Then OFSCache = If(IsSingleObjectDownload, Settings.Cache.NewInstance, CreateCache())
|
If OFSCache Is Nothing Then OFSCache = If(IsSingleObjectDownload, Settings.Cache.NewInstance, CreateCache())
|
||||||
Dim currentCache As CacheKeeper = OFSCache.NewInstance
|
Dim currentCache As CacheKeeper = OFSCache.NewInstance
|
||||||
currentCache.Validate()
|
currentCache.Validate()
|
||||||
@@ -637,35 +665,48 @@ Namespace API.OnlyFans
|
|||||||
CType(Function(input) replaceValue, Func(Of String, String)), String.Empty, EDP.ReturnValue)
|
CType(Function(input) replaceValue, Func(Of String, String)), String.Empty, EDP.ReturnValue)
|
||||||
Dim ff As SFile
|
Dim ff As SFile
|
||||||
configText = f.GetText
|
configText = f.GetText
|
||||||
Dim updateConf As Action(Of String, String, Boolean) =
|
Dim updateConf As Action(Of String, String, Byte) =
|
||||||
Sub(ByVal patternValue As String, ByVal __replaceValue As String, ByVal __isRules As Boolean)
|
Sub(ByVal patternValue As String, ByVal __replaceValue As String, ByVal mode As Byte)
|
||||||
rp.Pattern = String.Format(IIf(__isRules, confMainPatternRulesManual, confMainPattern), patternValue)
|
Select Case mode
|
||||||
|
Case m1 : rp.Pattern = String.Format(confMainPattern, patternValue)
|
||||||
|
Case m2 : rp.Pattern = String.Format(confMainPatternRulesManual, patternValue)
|
||||||
|
Case m3 : rp.Pattern = String.Format(confMainPattern_Keys, patternValue) : __replaceValue = $"""{__replaceValue}"""
|
||||||
|
Case Else : Throw New ArgumentException($"Mode '{mode}' is not implemented", "mode")
|
||||||
|
End Select
|
||||||
rp.Nothing = configText
|
rp.Nothing = configText
|
||||||
replaceValue = __replaceValue
|
replaceValue = __replaceValue
|
||||||
configText = RegexReplace(configText, rp)
|
configText = RegexReplace(configText, rp)
|
||||||
End Sub
|
End Sub
|
||||||
If Not configText.IsEmptyString Then
|
If Not configText.IsEmptyString Then
|
||||||
updateConf("save_location", cacheRoot.PathNoSeparator.Replace("\", "/"), False)
|
updateConf("save_location", cacheRoot.PathNoSeparator.Replace("\", "/"), m1)
|
||||||
If ACheck(MySettings.OFScraperMP4decrypt.Value) Then
|
If ACheck(MySettings.OFScraperMP4decrypt.Value) Then
|
||||||
ff = CStr(MySettings.OFScraperMP4decrypt.Value)
|
ff = CStr(MySettings.OFScraperMP4decrypt.Value)
|
||||||
If ff.Exists Then updateConf("mp4decrypt", ff.ToString.Replace("\", "/"), False)
|
If ff.Exists Then updateConf("mp4decrypt", ff.ToString.Replace("\", "/"), m1)
|
||||||
End If
|
End If
|
||||||
If Settings.FfmpegFile.Exists Then updateConf("ffmpeg", Settings.FfmpegFile.File.ToString.Replace("\", "/"), False)
|
If Settings.FfmpegFile.Exists Then updateConf("ffmpeg", Settings.FfmpegFile.File.ToString.Replace("\", "/"), m1)
|
||||||
updateConf("key-mode-default", CStr(MySettings.KeyModeDefault.Value).IfNullOrEmpty(SiteSettings.KeyModeDefault_Default), False)
|
|
||||||
updateConf("keydb_api", CStr(MySettings.Keydb_Api.Value), False)
|
updateConf("key-mode-default", CStr(MySettings.KeyModeDefault.Value).IfNullOrEmpty(SiteSettings.KeyModeDefault_Default), 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
|
||||||
|
updateConf("private-key", CStr(MySettings.OFS_KEYS_Key.Value).Replace("\", "/"), m3)
|
||||||
|
updateConf("client-id", CStr(MySettings.OFS_KEYS_ClientID.Value).Replace("\", "/"), m3)
|
||||||
|
End If
|
||||||
|
|
||||||
If Rules.RulesReplaceConfig Then
|
If Rules.RulesReplaceConfig Then
|
||||||
If Rules.RulesConfigManualMode Then
|
If Rules.RulesConfigManualMode Then
|
||||||
updateConf(DynamicRulesEnv.DynamicRulesConfig_Mode_NodeName, "manual", False)
|
updateConf(DynamicRulesEnv.DynamicRulesConfig_Mode_NodeName, "manual", m1)
|
||||||
configText = configText.Replace(DynamicRulesEnv.DynamicRulesConfigNodeName_URL, DynamicRulesEnv.DynamicRulesConfigNodeName_RULES)
|
configText = configText.Replace(DynamicRulesEnv.DynamicRulesConfigNodeName_URL, DynamicRulesEnv.DynamicRulesConfigNodeName_RULES)
|
||||||
updateConf(DynamicRulesEnv.DynamicRulesConfigNodeName_RULES, Rules.CurrentContainerRulesText, True)
|
updateConf(DynamicRulesEnv.DynamicRulesConfigNodeName_RULES, Rules.CurrentContainerRulesText, m2)
|
||||||
Else
|
Else
|
||||||
Dim confUrlNode$ = If(Rules.RulesConstants.ContainsKey(DynamicRulesEnv.DynamicRulesConfigNodeName_URL_CONST_NAME),
|
Dim confUrlNode$ = If(Rules.RulesConstants.ContainsKey(DynamicRulesEnv.DynamicRulesConfigNodeName_URL_CONST_NAME),
|
||||||
Rules.RulesConstants(DynamicRulesEnv.DynamicRulesConfigNodeName_URL_CONST_NAME),
|
Rules.RulesConstants(DynamicRulesEnv.DynamicRulesConfigNodeName_URL_CONST_NAME),
|
||||||
DynamicRulesEnv.DynamicRulesConfigNodeName_URL)
|
DynamicRulesEnv.DynamicRulesConfigNodeName_URL)
|
||||||
updateConf(DynamicRulesEnv.DynamicRulesConfigNodeName_URL, Rules.CurrentRule.UrlRaw, False)
|
updateConf(DynamicRulesEnv.DynamicRulesConfigNodeName_URL, Rules.CurrentRule.UrlRaw, m1)
|
||||||
configText = configText.Replace(DynamicRulesEnv.DynamicRulesConfigNodeName_URL, confUrlNode)
|
configText = configText.Replace(DynamicRulesEnv.DynamicRulesConfigNodeName_URL, confUrlNode)
|
||||||
If Rules.RulesConstants.ContainsKey(DynamicRulesEnv.DynamicRulesConfig_Mode_NodeName) Then _
|
If Rules.RulesConstants.ContainsKey(DynamicRulesEnv.DynamicRulesConfig_Mode_NodeName) Then _
|
||||||
updateConf(DynamicRulesEnv.DynamicRulesConfig_Mode_NodeName, Rules.RulesConstants(DynamicRulesEnv.DynamicRulesConfig_Mode_NodeName), False)
|
updateConf(DynamicRulesEnv.DynamicRulesConfig_Mode_NodeName, Rules.RulesConstants(DynamicRulesEnv.DynamicRulesConfig_Mode_NodeName), m1)
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
f = currentCache
|
f = currentCache
|
||||||
@@ -720,6 +761,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
|
||||||
@@ -760,14 +802,20 @@ Namespace API.OnlyFans
|
|||||||
Private _DownloadingException_AuthFileUpdate As Boolean = False
|
Private _DownloadingException_AuthFileUpdate As Boolean = False
|
||||||
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.BadRequest Then '400
|
If Responser.StatusCode = Net.HttpStatusCode.BadRequest Or
|
||||||
|
(Responser.StatusCode = Net.HttpStatusCode.Unauthorized And CBool(MySettings.UpdateRules401.Value)) Then '400, [401]
|
||||||
If Not _DownloadingException_AuthFileUpdate AndAlso Rules.Update(True) Then
|
If Not _DownloadingException_AuthFileUpdate AndAlso Rules.Update(True) Then
|
||||||
_DownloadingException_AuthFileUpdate = True
|
_DownloadingException_AuthFileUpdate = True
|
||||||
Return 2
|
Return 2
|
||||||
Else
|
Else
|
||||||
MySettings.SessionAborted = True
|
MySettings.SessionAborted = True
|
||||||
MyMainLOG = $"{ToStringForLog()} [{CInt(Responser.StatusCode)}]: OnlyFans credentials expired"
|
MyMainLOG = $"{ToStringForLog()} [{CInt(Responser.StatusCode)}]: OnlyFans credentials expired"
|
||||||
Return 1
|
If Responser.StatusCode = Net.HttpStatusCode.BadRequest Then
|
||||||
|
Return 1
|
||||||
|
Else
|
||||||
|
MyMainLOG = $"{ToStringForLog()}: Rules updated (401)"
|
||||||
|
Return 3
|
||||||
|
End If
|
||||||
End If
|
End If
|
||||||
ElseIf Responser.StatusCode = Net.HttpStatusCode.NotFound Then '404
|
ElseIf Responser.StatusCode = Net.HttpStatusCode.NotFound Then '404
|
||||||
UserExists = False
|
UserExists = False
|
||||||
@@ -782,6 +830,8 @@ Namespace API.OnlyFans
|
|||||||
Return 3
|
Return 3
|
||||||
ElseIf Responser.StatusCode = Net.HttpStatusCode.InternalServerError Then '500
|
ElseIf Responser.StatusCode = Net.HttpStatusCode.InternalServerError Then '500
|
||||||
Return 3
|
Return 3
|
||||||
|
ElseIf Not _TimelineDownloading And Responser.StatusCode = Net.HttpStatusCode.BadGateway Then '502
|
||||||
|
Return 3
|
||||||
Else
|
Else
|
||||||
Return 0
|
Return 0
|
||||||
End If
|
End If
|
||||||
|
|||||||