Compare commits

..

19 Commits

Author SHA1 Message Date
Andy
09760a6926 2024.2.25.0 2024-02-25 11:31:33 +03:00
Andy
75039ac4d2 2024.2.24.0
Feed: improve move/copy
2024-02-24 12:24:05 +03:00
Andy
03e3a07947 2024.2.22.1
Feed: add the ability to update file location when moving media
Automation: make the automation file relative
2024-02-22 19:58:46 +03:00
Andy
d283d9c9f9 2024.2.22.0
Feed: add the ability to move/copy media
2024-02-22 13:40:04 +03:00
Andy
b9100bd3c1 2024.2.21.0
API.UserDataBase: incorrect comparison when 'Other' is 'UserDataBind'
DownloadFeedForm: add saved session name to feed title; remove menu hiding when session saving is disabled; remove menu tooltip
GlobalSettingsForm: update 'FeedParametersChanged'
2024-02-21 09:19:40 +03:00
Andy
0ea2156ada 2024.2.17.0
YT
Add the ability to edit playlist items
Add 'Open file' to the context menu
Add the ability to embed thumbnail in the audio/video as cover art
VideoOptionsForm: audio codec does not change when changing audio/video in the video options form

SCrawler
DownloadFeedForm: add ability to merge multiple special feeds into one
AutoDownloader: fix bug when users are added during pool reconfiguration
Scheduler: add the ability to move tasks
FeedMedia: fix image rendering bug
Feed: add select all/none; add the ability to add to a special feed(s) with removal from the current one; add loaded feed name to the title; refresh the loaded feed using the 'Refresh' button
FeedSpecialCollection: add 'Add' button to feed chooser; fixed a bug in the 'Delete' function
SettingsHostCollection, PluginHost: add 'IDisposable' support
API.UserDataBase: add Responser handler options
API.OnlyFans: handle 500 error
API.Threads: extract 'csrftoken' from cookies; simplify 500 error when updating tokens
API.Instagram: update handling of JSON parsing error when downloading reels; fix error downloading single post
API.Facebook: simplify token update errors
API.Twitter: update handling of JSON parsing error
2024-02-18 00:10:39 +03:00
Andy
520280b038 2024.2.12.0
API.Instagram: extract 'csrftoken' from cookies; remove 'x-ig-www-claim' from settings
2024-02-12 10:28:21 +03:00
Andy
10516f229b 2024.2.10.0
Plugins: added `ReplaceInternalPluginAttribute` attribute

SCrawler
API: update user regex for some sites
API.Instagram: simplify 5xx errors; hide JSON deserialization error
API.TikTok: files with long names aren't downloaded (PathTooLongException)
2024-02-10 08:19:08 +03:00
Andy
c3f0831768 2024.2.9.0
Add a 'Feed' button to notifications
SCrawler.StandaloneDownloader: url array form doesn't show scrollbars
2024-02-09 10:00:04 +03:00
Andy
74a0404670 Update README.md 2024-02-03 08:19:53 +03:00
Andy
52a43b9207 2024.1.26.0
YT
YouTubeSettings: add property DefaultVideoFPS
VideoOptionsForm, YouTubeMediaContainerBase: add FPS reduction

SCrawler
API.Instagram: change back aspect ratio determining
API.TikTok: add the ability to use a regex to clean the title
API.YouTube: add the ability to ignore community errors
2024-01-26 04:13:42 +03:00
Andy
5bc559c448 2024.1.20.0
API.Instagram: add reels support (separate)
API.LPSG: handle 404 error
2024-01-20 00:00:23 +03:00
Andy
b37f641582 2024.1.18.0
YT: url array form doesn't show scrollbars
API.Instagram: change aspect ratio determining
API.xHamster: some user videos were not downloaded
API.UserDataBind: incorrect collection sorting
DownloadFeedForm: change separator in result dialog when merging feeds
2024-01-18 01:23:55 +03:00
Andy
e00dfec701 2024.1.12.1
API.Instagram: stories (user) downloading with the wrong aspect ratio for some users
API.YouTube: fix incorrect opening of a post from the feed; fix wrong date to data parsing; add data downloading by dates

DownloadFeedForm: add merging multiple session feeds into one
2024-01-12 19:58:17 +03:00
Andy
94edf23570 2024.1.12.0
DownloadFeedForm: add an option to create a new feed when adding checked items; add a prompt before clearing the current session
MainFrame: add scheduler to tray menu

API.Instagram: fix tagged posts downloading
API.xHamster: fix profiles downloading; add creators downloading
API.YouTube: add error to log (communities)
2024-01-11 23:39:56 +03:00
Andy
0246af9b69 2023.12.27.0
API.OnlyFans: add OF-Scraper support
ProfileSaved: save files when adding new data
2023-12-27 16:10:02 +03:00
Andy
c458f1cd1d 2023.12.26.0
SiteEditorForm: sort controls only if some of them have numbers
UserCreatorForm: reset site options for new user only; add host reset when changing account for created user
PropertyValueHost: add 'UpdateMember' function
SettingsHost: add 'DefaultInstanceChanged' function to update properties when setting default instance
SettingsHostCollection: update properties when setting default instance
2023-12-26 14:34:53 +03:00
Andy
e3da1bf1d3 2023.12.21.0
Update 'new log data' notification
Feed: improve last session loading
2023-12-21 10:01:30 +03:00
Andy
dde024276b 2023.12.20.0
API.Twitter: simplify JSON error string
Add notification of new log data
Add deleting permanent cache path if empty
2023-12-20 15:37:40 +03:00
101 changed files with 4415 additions and 764 deletions

View File

@@ -5,7 +5,12 @@ I welcome requests! Follow these steps to contribute:
1. Find an [issue](https://github.com/AAndyProgram/SCrawler/issues) that needs assistance. 1. Find an [issue](https://github.com/AAndyProgram/SCrawler/issues) that needs assistance.
1. Let me know you are working on it by posting a comment on the issue. 1. Let me know you are working on it by posting a comment on the issue.
1. If you find an error in the code, please provide a link to the file and the line number. 1. If you find an error in the code, please provide a link to the file and the line number.
1. If you have a code change suggestion, you can post a replacement code block. I also accept pull requests. 1. If you have a code change suggestion, you can post a replacement code block.<!-- I also accept pull requests.-->
# How to report a problem
1. Attach a **profile URL** that you cannot download.
1. Attach the **LOG** if it exists.
1. **Attach information to the issue with data copied from SCrawler (click the top right info button in the main window, then the `Environment` button, then the `Copy` button, and paste the copied text into the issue).**
# How to build from source # How to build from source
1. Delete the `PersonalUtilities` project from the solution. 1. Delete the `PersonalUtilities` project from the solution.

View File

@@ -1,3 +1,110 @@
# 2024.2.25.0
*2024-02-25*
- Added
- A `Feed` button has been added to notifications
- Feed:
- ability to merge multiple special feeds into one
- ability to select all/none media
- ability to add to a special feed(s) with removal from the current one
- the name of the loaded feed is now displayed in the form title
- `Refresh` button now refreshes the loaded feed
- ability to move/copy media
- Scheduler: the ability to move tasks (higher, lower) *(just a view attribute, doesn't affect the scheduler)*
- YouTube (standalone app): add `Open file` to the context menu
- YouTube (standalone app): **the ability to edit each playlist item**
- YouTube (standalone app): **embed thumbnail in the audio/video as cover art** (Settings: `Defaults Audio` - `Embed thumbnail`; `Defaults Video` - `Embed thumbnail (video)`)
- Instagram: the `csrftoken` can now be automatically extracted from cookies
- Instagram: remove `x-ig-www-claim` from settings
- Threads: the `csrftoken` can now be automatically extracted from cookies
- Threads: simplify 500 error when updating tokens
- Facebook: simplify token update errors
- OnlyFans: handle 500 error
- Plugins: added `ReplaceInternalPluginAttribute` attribute
- Other improvements
- Fixed
- Main window: incorrect sorting of profiles and collections
- Standalone downloader: url array form doesn't show scrollbars
- Feed: image rendering bug
- YouTube (standalone app): audio codec does not change when changing audio/video in the video options form
- Instagram: error downloading single post
- TikTok: files with long names aren't downloaded
- Minor bugs
# 2024.1.26.0
*2024-01-26*
- Added
- YouTube (standalone app): **the ability to reduce video FPS**
- TikTok: the ability to use a regex to clean the title
- YouTube (SCrawler): the ability to ignore community errors
- Fixed
- Instagram: stories (user) downloading with the wrong aspect ratio for some users
- Minor bugs
# 2024.1.20.0
*2024-01-20*
- Added
- Instagram: **the ability to download reels**
- LPSG: handle 404 error
# 2024.1.18.0
*2024-01-18*
- Fixed
- Main window: incorrect collection sorting
- xHamster: some user videos were not downloaded
- YouTube (standalone app): URL array form doesn't show scrollbars
- Minor bugs
# 2024.1.12.1
*2024-01-12*
- Added
- YouTube (SCrawler): data downloading by dates
- Feed: ability to merge multiple session feeds into one
- Feed: remove session number from special feeds
- Fixed
- **Instagram**: stories (user) downloading with the wrong aspect ratio for some users
- YouTube: incorrect opening of a post from the feed
- YouTube: wrong date to data parsing
# 2024.1.12.0
*2024-01-12*
- Added
- Feed: added a prompt before clearing the current session
- xHamster: creators
- YouTube communities: add error to log
- Added scheduler to tray menu
- Other improvements
- Fixed
- Feed: there is no option to create a new feed when adding checked items
- **Instagram**: downloading of tagged posts
- xHamster: profiles are not downloading
- Minor bugs
# 2023.12.27.0
*2023-12-27*
- Added
- Notification of new log data
- OnlyFans: **OF-Scrapper support to download DRM protected videos**
- Other improvements
- Fixed
- The default options are changed (`Favorite`, `Temporary`, etc.) when changing an account for a created user
- When changing the account for a created user, the new account does not apply to that user until SCrawler is restarted
- Saved posts: session file is not updated when new data is added
- Minor bugs
# 2023.12.15.0 # 2023.12.15.0
*2023-12-15* *2023-12-15*

19
FAQ.md
View File

@@ -14,8 +14,6 @@ Any other questions I will keep in this file.
A: https://github.com/AAndyProgram/SCrawler/wiki/Settings#how-to-set-up-cookies A: https://github.com/AAndyProgram/SCrawler/wiki/Settings#how-to-set-up-cookies
<!---**ATTENTION! If you need to use cookies but cannot import them, I highly recommend that you don't use SCrawler and use another program. Don't create issues, discussions, or write to me on Discord. Any issue or discussion about cookies will be deleted immediately without a response. Any user who asks me about cookies on Discord will be banned.**--->
---- ----
#### Q: **Does this program have GUI or CLI.** #### Q: **Does this program have GUI or CLI.**
@@ -41,13 +39,16 @@ A: NO.
A: Check your credentials and **[SITES REQUIREMENTS](https://github.com/AAndyProgram/SCrawler/wiki/Settings#sites-requirements)**. If all settings are set, but nothing works, go to [create a new issue](https://github.com/AAndyProgram/SCrawler/issues). Don't forget to attach the LOG. A: Check your credentials and **[SITES REQUIREMENTS](https://github.com/AAndyProgram/SCrawler/wiki/Settings#sites-requirements)**. If all settings are set, but nothing works, go to [create a new issue](https://github.com/AAndyProgram/SCrawler/issues). Don't forget to attach the LOG.
**You also can join our Discord server**: https://discord.gg/uFNUXvFFmg
<br/>*You can get help faster there!*
**ATTENTION! Issues without URLs will be closed without a response!** **ATTENTION! Issues without URLs will be closed without a response!**
---- ----
#### Q: **I have set credentials but still nothing is downloading** #### Q: **I have set credentials but still nothing is downloading**
A: Click the ```Start downloading``` button A: Click the `Start downloading` button or press `F5`
---- ----
@@ -59,7 +60,7 @@ A: https://github.com/AAndyProgram/SCrawler/releases/latest
#### Q: **How to run the program?** #### Q: **How to run the program?**
A: Double-click ```SCrawler.exe``` A: Double-click `SCrawler.exe`
---- ----
@@ -77,19 +78,19 @@ A: The program stored posts IDs in users' folders. For the first time, the progr
#### Q: **How to redownload all data** #### Q: **How to redownload all data**
A: Double-click on the user you want to redownload. In the opened window open folder setting. Delete the files ending with ```_Data.xml``` and ```_Posts.txt```. Restart SCrawler. Download this user again. A: https://github.com/AAndyProgram/SCrawler/wiki#redownload-user
---- ----
#### Q: **How to remove the label** #### Q: **How to remove the label**
A: There is no functionality to remove an individual label. You can open the ```Labels.txt``` file in the program settings folder and delete any label you want. You also can delete this file (```Labels.txt```). In this case, when the program starts, the list of labels list will be updated with only existing labels (from the user data files). A: There is no functionality to remove an individual label. You can open the `Labels.txt` file in the program settings folder and delete any label you want. You also can delete this file (`Labels.txt`). In this case, when the program starts, the list of labels list will be updated with only existing labels (from the user data files).
---- ----
#### Q: **How to remove a user from the blacklist** #### Q: **How to remove a user from the blacklist**
A: Just add that user back to the program. In the dialog box that opens, click on the ```Add and remove from blacklist``` button. A: Just add that user back to the program. In the dialog box that opens, click on the `Add and remove from blacklist` button.
---- ----
@@ -113,8 +114,8 @@ A: I can only [suggest](#q-you-lost-me-your-program-is-too-complicated) you find
#### Q: **Can you add a step-by-step guide or video on how to use the program?** #### Q: **Can you add a step-by-step guide or video on how to use the program?**
A: **NO! NEVER!** The guide fully covers all the functionality of SCrawler! If you don't respect my work, I don't waste my time. If you want, you can create a video tutorial and send it to me. Then I add it. All options and what each option does described on the wiki. The wiki also contains a description of all settings and how-to configure them. For complex settings, there is a steep-by-steep guide. Read the [main](README.md) information and [GUIDE](https://github.com/AAndyProgram/SCrawler/wiki/) and you won't have any problems. I have developed a program with an intuitive interface. There is a Settings button, download buttons, a context menu that drops down when a user is clicked, and other controls. Anyone can use it. A: **NO!** The guide fully covers all the functionality of SCrawler! If you don't respect my work, I don't waste my time. If you want, you can create a video tutorial and send it to me. Then I add it. All options and what each option does described on the wiki. The wiki also contains a description of all settings and how-to configure them. For complex settings, there is a steep-by-steep guide. Read the [main](README.md) information and [GUIDE](https://github.com/AAndyProgram/SCrawler/wiki/) and you won't have any problems. I have developed a program with an intuitive interface. There is a Settings button, download buttons, a context menu that drops down when a user is clicked, and other controls. Anyone can use it.
**The following video shows how to add credentials:** **The following video was recorded by a user who loves SCrawler and demonstrates how to add credentials using Instagram as an example:**
[![How to configure](https://img.youtube.com/vi/XDn7zG4I700/0.jpg)](https://www.youtube.com/watch?v=XDn7zG4I700) [![How to configure](https://img.youtube.com/vi/XDn7zG4I700/0.jpg)](https://www.youtube.com/watch?v=XDn7zG4I700)

View File

@@ -2,6 +2,8 @@ You can create a plugin for any site you want. **To create a plugin, read [this
If you've created a plugin, you can create a [new issue](https://github.com/AAndyProgram/SCrawler/issues/new?assignees=&labels=New+Plugin&projects=&template=plugin_add.md&title=%5BNEW+PLUGIN%5D) and I'll add your plugin to the list below. If you've created a plugin, you can create a [new issue](https://github.com/AAndyProgram/SCrawler/issues/new?assignees=&labels=New+Plugin&projects=&template=plugin_add.md&title=%5BNEW+PLUGIN%5D) and I'll add your plugin to the list below.
----
List of available plugins: List of available plugins:
Tools: Tools:

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 491 KiB

After

Width:  |  Height:  |  Size: 472 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 103 KiB

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

@@ -6,11 +6,19 @@ https://github.com/yt-dlp/yt-dlp/
SCrawler has advanced user management, collections, labels, groups, automatic downloads, a beautiful view, GUI, the ability to add plugins for other sites and much more. Just try it and compare. SCrawler has advanced user management, collections, labels, groups, automatic downloads, a beautiful view, GUI, the ability to add plugins for other sites and much more. Just try it and compare.
# gallery-dl
https://github.com/mikf/gallery-dl
**Great powerful CLI tool that supports hundreds of sites.**
SCrawler has advanced user management, collections, labels, groups, automatic downloads, a beautiful view, GUI, the ability to add plugins for other sites and much more. Just try it and compare.
# 4K Video Downloader # 4K Video Downloader
https://www.4kdownload.com/-plbrz/video-downloader https://www.4kdownload.com/-plbrz/video-downloader
| Option | SCrawler | 4K Stogram | | Option | SCrawler | 4K Video Downloader |
| ---- | ---- | ---- | | ---- | ---- | ---- |
| User managament | **Advanced** | No | | User managament | **Advanced** | No |
| Automatic downloads | **Yes** | No | | Automatic downloads | **Yes** | No |
@@ -121,10 +129,3 @@ https://github.com/RipMeApp/ripme
| Other sites support | **Yes** | No | | Other sites support | **Yes** | No |
| Still supported | **Yes** | **No (last release date May 4, 2021)** | | Still supported | **Yes** | **No (last release date May 4, 2021)** |
# gallery-dl
https://github.com/mikf/gallery-dl
**CLI tool**
SCrawler has advanced user management, collections, labels, groups, automatic downloads, a beautiful view, GUI, the ability to add plugins for other sites and much more. Just try it and compare.

View File

@@ -15,6 +15,10 @@
A program to download photo and video from [any site](#supported-sites) (e.g. YouTube, YouTube Music, OnlyFans, Reddit, Twitter, Mastodon, Instagram, Threads, Facebook, TikTok, RedGifs, JustForFans, PornHub, XHamster, XVIDEOS, ThisVid, LPSG, Pinterest). A program to download photo and video from [any site](#supported-sites) (e.g. YouTube, YouTube Music, OnlyFans, Reddit, Twitter, Mastodon, Instagram, Threads, Facebook, TikTok, RedGifs, JustForFans, PornHub, XHamster, XVIDEOS, ThisVid, LPSG, Pinterest).
**If you like SCrawler, please like the program on [this site](https://alternativeto.net/software/scrawler/about/) and/or [this](https://www.softpedia.com/get/Internet/Download-Managers/Social-networks-crawler.shtml)** **If you like SCrawler, please like the program on [this site](https://alternativeto.net/software/scrawler/about/) and/or [this](https://www.softpedia.com/get/Internet/Download-Managers/Social-networks-crawler.shtml)**
**Join our Discord server**: https://discord.gg/uFNUXvFFmg
<br/>*If you have problems using the program, you can get help faster on our Discord server!*
<!---Do you like this program? Consider adding to my coffee fund by making a donation to show your support. :blush: <!---Do you like this program? Consider adding to my coffee fund by making a donation to show your support. :blush:
[![ko-fi](https://www.ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/andyprogram)---> [![ko-fi](https://www.ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/andyprogram)--->
**Bitcoin**: BC1Q0NH839FT5TA44DD7L7RLR97XDQAG9V8D6N7XET **Bitcoin**: BC1Q0NH839FT5TA44DD7L7RLR97XDQAG9V8D6N7XET
@@ -74,12 +78,12 @@ A program to download photo and video from [any site](#supported-sites) (e.g. Yo
- **YouTube Music** - **YouTube Music**
- **Reddit** - **Reddit**
- **Twitter** - **Twitter**
- **OnlyFans** - **OnlyFans** *(partial support)*[^1]
- **Mastodon** - **Mastodon**
- **Instagram** - **Instagram**
- **Threads** - **Threads**
- **Facebook** - **Facebook**
- JustForFans - JustForFans *(partial support)*[^1]
- TikTok - TikTok
- RedGifs - RedGifs
- Pinterest - Pinterest
@@ -155,9 +159,15 @@ First, the program downloads the full profile. After the program downloads only
**Don't put program in the ```Program Files``` system folder (this is portable program and program settings are stored in the program folder)** **Don't put program in the ```Program Files``` system folder (this is portable program and program settings are stored in the program folder)**
**I highly doubt you can run SCrawler on Linux or Mac. SCrawler is a program that is heavily dependent on Windows.**
# Updating # Updating
Just download [latest](https://github.com/AAndyProgram/SCrawler/releases/latest) version and unpack it into the program folder. **Before starting a new version, I recommend making a backup copy of the program settings folder.** Just download [latest](https://github.com/AAndyProgram/SCrawler/releases/latest) version and unpack it into the program folder. **Before launching a new version, I recommend making a backup copy of the program settings folder and user settings/data files.**
**You can also use the updater included in the release package.**
# [How to report a problem](CONTRIBUTING.md#how-to-report-a-problem)
# [How to build from source](CONTRIBUTING.md#how-to-build-from-source) # [How to build from source](CONTRIBUTING.md#how-to-build-from-source)
@@ -216,3 +226,5 @@ Discord server: https://discord.gg/uFNUXvFFmg
[Wire](https://account.wire.com/user-profile/?id=93985052-cf2c-4b72-ac75-bbe3231cf544): @andyprogram [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.

View File

@@ -188,4 +188,13 @@ Namespace Plugin.Attributes
Repository = RepoName Repository = RepoName
End Sub End Sub
End Class End Class
''' <summary>Replace internal plugin with the current one</summary>
<AttributeUsage(AttributeTargets.Class, AllowMultiple:=False, Inherited:=False)> Public NotInheritable Class ReplaceInternalPluginAttribute : Inherits Attribute
Public ReadOnly SiteName As String
Public ReadOnly PluginKey As String
Public Sub New(ByVal PluginKey As String, Optional ByVal SiteName As String = Nothing)
Me.PluginKey = PluginKey
Me.SiteName = SiteName
End Sub
End Class
End Namespace End Namespace

View File

@@ -32,6 +32,6 @@ Imports System.Runtime.InteropServices
' by using the '*' as shown below: ' by using the '*' as shown below:
' <Assembly: AssemblyVersion("1.0.*")> ' <Assembly: AssemblyVersion("1.0.*")>
<Assembly: AssemblyVersion("2023.11.24.0")> <Assembly: AssemblyVersion("2024.2.25.0")>
<Assembly: AssemblyFileVersion("2023.11.24.0")> <Assembly: AssemblyFileVersion("2024.2.25.0")>
<Assembly: NeutralResourcesLanguage("en")> <Assembly: NeutralResourcesLanguage("en")>

View File

@@ -15,6 +15,7 @@ Imports PersonalUtilities.Forms
Imports PersonalUtilities.Functions.XML Imports PersonalUtilities.Functions.XML
Imports PersonalUtilities.Functions.XML.Base Imports PersonalUtilities.Functions.XML.Base
Imports PersonalUtilities.Functions.XML.Objects Imports PersonalUtilities.Functions.XML.Objects
Imports PersonalUtilities.Functions.XML.Attributes
Imports PersonalUtilities.Functions.XML.Attributes.Specialized Imports PersonalUtilities.Functions.XML.Attributes.Specialized
Imports PersonalUtilities.Tools Imports PersonalUtilities.Tools
Imports PersonalUtilities.Tools.Grid.Base Imports PersonalUtilities.Tools.Grid.Base
@@ -272,9 +273,77 @@ 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"}, False), Category("Defaults Video"), DisplayName("Embed thumbnail (video)"),
Description("Embed thumbnail in the video as cover art. Default: true.")>
Public ReadOnly Property DefaultVideoEmbedThumbnail 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)
<Browsable(False), XMLV("DefaultVideoFPS", {"DefaultsVideo"}, -1)>
Private ReadOnly Property DefaultVideoFPS_XML As XMLValue(Of Double)
<Browsable(True), GridVisible, Category("Defaults Video"), DisplayName("Default video FPS"),
Description("Set default video FPS (only to reduce video FPS). Default: -1 (disabled)."),
TypeConverter(GetType(FieldsTypeConverter)), GridFormatProvider(GetType(FpsFormatProvider))>
Public Property DefaultVideoFPS As Double
Get
Return DefaultVideoFPS_XML
End Get
Set(ByVal fps As Double)
DefaultVideoFPS_XML.Value = fps
End Set
End Property
Private Function ShouldSerializeDefaultVideoFPS() As Boolean
Return DefaultVideoFPS <> DefaultVideoFPS_XML.Value
End Function
Private Sub ResetDefaultVideoFPS()
DefaultVideoFPS = -1
End Sub
Friend Class FpsFormatProvider : Implements IGridConversionProvider
Private Property Converter As TypeConverter Implements IGridConversionProvider.Converter
Private Property Context As ITypeDescriptorContext Implements IGridConversionProvider.Context
Private Property DataType As Type Implements IGridConversionProvider.DataType
Private Property Instance As Object Implements IGridConversionProvider.Instance
Friend Shared ReadOnly Property MyProviderDefault As ANumbers
Get
Return New ANumbers(ANumbers.Cultures.Primitive) With {.DecimalDigits = 5, .TrimDecimalDigits = True}
End Get
End Property
Friend Const ErrorMessageDefault As String = "The fps value must be a number"
Private ReadOnly MyProvider As ANumbers = MyProviderDefault
Friend Function ToObject(ByVal Context As ITypeDescriptorContext, ByVal Culture As CultureInfo, ByVal Value As Object) As Object Implements IGridConversionProvider.ToObject
Return AConvert(Of Double)(Value, MyProvider, -1)
End Function
Friend Overloads Function ToString(ByVal Context As ITypeDescriptorContext, ByVal Culture As CultureInfo, ByVal Value As Object,
ByVal DestinationType As Type) As Object Implements IGridConversionProvider.ToString
If ACheck(Of Double)(Value, AModes.Var, MyProvider) Then
Return Value.ToString
Else
Return -1
End If
End Function
Friend Function CreateInstance(ByVal Context As ITypeDescriptorContext, ByVal NewValue As Object, ByRef RefreshGrid As Boolean) As Object Implements IGridConversionProvider.CreateInstance
If ACheck(Of Double)(NewValue, AModes.Var, MyProvider) Then
Return NewValue
Else
RefreshGrid = True
Return -1
End If
End Function
Friend 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
Return AConvert(Value, AModes.Var, DestinationType,, True, -1, MyProvider, EDP.ReturnValue)
End Function
Friend Function IsValid(ByVal Context As ITypeDescriptorContext, ByVal Value As Object, ByVal DestinationType As Type) As Boolean Implements IGridValidator.IsValid
If ACheck(Of Double)(Value, AModes.Var, MyProvider) Then
Return True
Else
Throw New FormatException(ErrorMessageDefault)
End If
End Function
Private Function GetFormat(ByVal FormatType As Type) As Object Implements IFormatProvider.GetFormat
Throw New NotImplementedException("'GetFormat' is not available in 'FpsFormatProvider'")
End Function
End Class
#End Region #End Region
#Region "Defaults Audio" #Region "Defaults Audio"
<Browsable(True), GridVisible, XMLVN({"DefaultsAudio"}, "AAC"), Category("Defaults Audio"), DisplayName("Default codec"), <Browsable(True), GridVisible, XMLVN({"DefaultsAudio"}, "AAC"), Category("Defaults Audio"), DisplayName("Default codec"),
@@ -294,6 +363,9 @@ Namespace API.YouTube.Base
TypeConverter(GetType(ValueCollectionConverter)), TypeConverter(GetType(ValueCollectionConverter)),
Description("Additional audio format for downloading videos. This means that the audio will be extracted and saved as a separate file in these formats.")> Description("Additional audio format for downloading videos. This means that the audio will be extracted and saved as a separate file in these formats.")>
Public ReadOnly Property DefaultAudioCodecAddit As XMLValuesCollection(Of String) Public ReadOnly Property DefaultAudioCodecAddit As XMLValuesCollection(Of String)
<Browsable(True), GridVisible, XMLVN({"DefaultsAudio"}, True), Category("Defaults Audio"), DisplayName("Embed thumbnail"),
Description("Embed thumbnail in the audio as cover art. Default: true.")>
Public ReadOnly Property DefaultAudioEmbedThumbnail As XMLValue(Of Boolean)
#End Region #End Region
#Region "Defaults Subtitles" #Region "Defaults Subtitles"
<XMLVN({"DefaultsSubtitles"}, {"en"}, CollectionMode:=IXMLValuesCollection.Modes.String)> <XMLVN({"DefaultsSubtitles"}, {"en"}, CollectionMode:=IXMLValuesCollection.Modes.String)>

View File

@@ -100,6 +100,7 @@ Namespace API.YouTube.Controls
Me.TXT_URLS.MaxLength = 2147483647 Me.TXT_URLS.MaxLength = 2147483647
Me.TXT_URLS.Multiline = True Me.TXT_URLS.Multiline = True
Me.TXT_URLS.Name = "TXT_URLS" Me.TXT_URLS.Name = "TXT_URLS"
Me.TXT_URLS.ScrollBars = System.Windows.Forms.ScrollBars.Both
Me.TXT_URLS.Size = New System.Drawing.Size(372, 261) Me.TXT_URLS.Size = New System.Drawing.Size(372, 261)
Me.TXT_URLS.TabIndex = 0 Me.TXT_URLS.TabIndex = 0
' '

View File

@@ -50,6 +50,7 @@ Namespace API.YouTube.Controls
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()
Dim ActionButton10 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton10 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton11 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Me.ICON_VIDEO = New System.Windows.Forms.PictureBox() Me.ICON_VIDEO = New System.Windows.Forms.PictureBox()
Me.LBL_TITLE = New System.Windows.Forms.Label() Me.LBL_TITLE = New System.Windows.Forms.Label()
Me.TP_HEADER_INFO_2 = New System.Windows.Forms.TableLayoutPanel() Me.TP_HEADER_INFO_2 = New System.Windows.Forms.TableLayoutPanel()
@@ -71,6 +72,7 @@ Namespace API.YouTube.Controls
Me.CMB_FORMAT = New System.Windows.Forms.ComboBox() Me.CMB_FORMAT = New System.Windows.Forms.ComboBox()
Me.CMB_AUDIO_CODEC = New System.Windows.Forms.ComboBox() Me.CMB_AUDIO_CODEC = New System.Windows.Forms.ComboBox()
Me.NUM_RES = New System.Windows.Forms.NumericUpDown() Me.NUM_RES = New System.Windows.Forms.NumericUpDown()
Me.TXT_FPS = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.TP_CONTROLS = New System.Windows.Forms.TableLayoutPanel() Me.TP_CONTROLS = New System.Windows.Forms.TableLayoutPanel()
Me.TXT_SUBS_ADDIT = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.TXT_SUBS_ADDIT = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.TXT_EXTRA_AUDIO_FORMATS = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.TXT_EXTRA_AUDIO_FORMATS = New PersonalUtilities.Forms.Controls.TextBoxExtended()
@@ -105,6 +107,7 @@ Namespace API.YouTube.Controls
Me.TP_MAIN.SuspendLayout() Me.TP_MAIN.SuspendLayout()
Me.TP_OPTIONS.SuspendLayout() Me.TP_OPTIONS.SuspendLayout()
CType(Me.NUM_RES, System.ComponentModel.ISupportInitialize).BeginInit() CType(Me.NUM_RES, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.TXT_FPS, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.TXT_SUBS_ADDIT, System.ComponentModel.ISupportInitialize).BeginInit() CType(Me.TXT_SUBS_ADDIT, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.TXT_EXTRA_AUDIO_FORMATS, System.ComponentModel.ISupportInitialize).BeginInit() CType(Me.TXT_EXTRA_AUDIO_FORMATS, System.ComponentModel.ISupportInitialize).BeginInit()
Me.SuspendLayout() Me.SuspendLayout()
@@ -123,7 +126,7 @@ Namespace API.YouTube.Controls
TP_HEADER.Name = "TP_HEADER" TP_HEADER.Name = "TP_HEADER"
TP_HEADER.RowCount = 1 TP_HEADER.RowCount = 1
TP_HEADER.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) TP_HEADER.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_HEADER.Size = New System.Drawing.Size(599, 63) TP_HEADER.Size = New System.Drawing.Size(719, 63)
TP_HEADER.TabIndex = 0 TP_HEADER.TabIndex = 0
' '
'ICON_VIDEO 'ICON_VIDEO
@@ -152,7 +155,7 @@ Namespace API.YouTube.Controls
TP_HEADER_INFO.RowCount = 2 TP_HEADER_INFO.RowCount = 2
TP_HEADER_INFO.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50.0!)) TP_HEADER_INFO.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
TP_HEADER_INFO.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50.0!)) TP_HEADER_INFO.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
TP_HEADER_INFO.Size = New System.Drawing.Size(469, 63) TP_HEADER_INFO.Size = New System.Drawing.Size(589, 63)
TP_HEADER_INFO.TabIndex = 0 TP_HEADER_INFO.TabIndex = 0
' '
'LBL_TITLE 'LBL_TITLE
@@ -161,7 +164,7 @@ Namespace API.YouTube.Controls
Me.LBL_TITLE.Font = New System.Drawing.Font("Arial", 9.0!, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, CType(204, Byte)) Me.LBL_TITLE.Font = New System.Drawing.Font("Arial", 9.0!, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, CType(204, Byte))
Me.LBL_TITLE.Location = New System.Drawing.Point(3, 0) Me.LBL_TITLE.Location = New System.Drawing.Point(3, 0)
Me.LBL_TITLE.Name = "LBL_TITLE" Me.LBL_TITLE.Name = "LBL_TITLE"
Me.LBL_TITLE.Size = New System.Drawing.Size(463, 31) Me.LBL_TITLE.Size = New System.Drawing.Size(583, 31)
Me.LBL_TITLE.TabIndex = 0 Me.LBL_TITLE.TabIndex = 0
Me.LBL_TITLE.Text = "Video title" Me.LBL_TITLE.Text = "Video title"
Me.LBL_TITLE.TextAlign = System.Drawing.ContentAlignment.MiddleLeft Me.LBL_TITLE.TextAlign = System.Drawing.ContentAlignment.MiddleLeft
@@ -183,7 +186,7 @@ Namespace API.YouTube.Controls
Me.TP_HEADER_INFO_2.Name = "TP_HEADER_INFO_2" Me.TP_HEADER_INFO_2.Name = "TP_HEADER_INFO_2"
Me.TP_HEADER_INFO_2.RowCount = 1 Me.TP_HEADER_INFO_2.RowCount = 1
Me.TP_HEADER_INFO_2.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) Me.TP_HEADER_INFO_2.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
Me.TP_HEADER_INFO_2.Size = New System.Drawing.Size(469, 32) Me.TP_HEADER_INFO_2.Size = New System.Drawing.Size(589, 32)
Me.TP_HEADER_INFO_2.TabIndex = 1 Me.TP_HEADER_INFO_2.TabIndex = 1
' '
'ICON_CLOCK 'ICON_CLOCK
@@ -230,7 +233,7 @@ Namespace API.YouTube.Controls
Me.LBL_URL.LinkColor = System.Drawing.Color.FromArgb(CType(CType(0, Byte), Integer), CType(CType(0, Byte), Integer), CType(CType(192, Byte), Integer)) Me.LBL_URL.LinkColor = System.Drawing.Color.FromArgb(CType(CType(0, Byte), Integer), CType(CType(0, Byte), Integer), CType(CType(192, Byte), Integer))
Me.LBL_URL.Location = New System.Drawing.Point(115, 0) Me.LBL_URL.Location = New System.Drawing.Point(115, 0)
Me.LBL_URL.Name = "LBL_URL" Me.LBL_URL.Name = "LBL_URL"
Me.LBL_URL.Size = New System.Drawing.Size(351, 32) Me.LBL_URL.Size = New System.Drawing.Size(471, 32)
Me.LBL_URL.TabIndex = 1 Me.LBL_URL.TabIndex = 1
Me.LBL_URL.TabStop = True Me.LBL_URL.TabStop = True
Me.LBL_URL.Text = "https://www.youtube.com/watch?v=abcdefghijk" Me.LBL_URL.Text = "https://www.youtube.com/watch?v=abcdefghijk"
@@ -250,7 +253,7 @@ Namespace API.YouTube.Controls
TP_FOOTER.RowCount = 2 TP_FOOTER.RowCount = 2
TP_FOOTER.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50.0!)) TP_FOOTER.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
TP_FOOTER.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50.0!)) TP_FOOTER.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
TP_FOOTER.Size = New System.Drawing.Size(589, 52) TP_FOOTER.Size = New System.Drawing.Size(709, 52)
TP_FOOTER.TabIndex = 5 TP_FOOTER.TabIndex = 5
' '
'TP_DESTINATION 'TP_DESTINATION
@@ -266,7 +269,7 @@ Namespace API.YouTube.Controls
TP_DESTINATION.Name = "TP_DESTINATION" TP_DESTINATION.Name = "TP_DESTINATION"
TP_DESTINATION.RowCount = 1 TP_DESTINATION.RowCount = 1
TP_DESTINATION.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) TP_DESTINATION.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_DESTINATION.Size = New System.Drawing.Size(589, 26) TP_DESTINATION.Size = New System.Drawing.Size(709, 26)
TP_DESTINATION.TabIndex = 0 TP_DESTINATION.TabIndex = 0
' '
'TXT_FILE 'TXT_FILE
@@ -290,14 +293,14 @@ Namespace API.YouTube.Controls
Me.TXT_FILE.Location = New System.Drawing.Point(1, 1) Me.TXT_FILE.Location = New System.Drawing.Point(1, 1)
Me.TXT_FILE.Margin = New System.Windows.Forms.Padding(1) Me.TXT_FILE.Margin = New System.Windows.Forms.Padding(1)
Me.TXT_FILE.Name = "TXT_FILE" Me.TXT_FILE.Name = "TXT_FILE"
Me.TXT_FILE.Size = New System.Drawing.Size(507, 22) Me.TXT_FILE.Size = New System.Drawing.Size(627, 22)
Me.TXT_FILE.TabIndex = 0 Me.TXT_FILE.TabIndex = 0
Me.TXT_FILE.TextBoxBorderStyle = System.Windows.Forms.BorderStyle.FixedSingle Me.TXT_FILE.TextBoxBorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
' '
'BTT_BROWSE 'BTT_BROWSE
' '
Me.BTT_BROWSE.Dock = System.Windows.Forms.DockStyle.Fill Me.BTT_BROWSE.Dock = System.Windows.Forms.DockStyle.Fill
Me.BTT_BROWSE.Location = New System.Drawing.Point(512, 2) Me.BTT_BROWSE.Location = New System.Drawing.Point(632, 2)
Me.BTT_BROWSE.Margin = New System.Windows.Forms.Padding(3, 2, 3, 2) Me.BTT_BROWSE.Margin = New System.Windows.Forms.Padding(3, 2, 3, 2)
Me.BTT_BROWSE.Name = "BTT_BROWSE" Me.BTT_BROWSE.Name = "BTT_BROWSE"
Me.BTT_BROWSE.Size = New System.Drawing.Size(74, 22) Me.BTT_BROWSE.Size = New System.Drawing.Size(74, 22)
@@ -321,13 +324,13 @@ Namespace API.YouTube.Controls
TP_OK_CANCEL.RowCount = 1 TP_OK_CANCEL.RowCount = 1
TP_OK_CANCEL.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) TP_OK_CANCEL.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_OK_CANCEL.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 26.0!)) TP_OK_CANCEL.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 26.0!))
TP_OK_CANCEL.Size = New System.Drawing.Size(589, 26) TP_OK_CANCEL.Size = New System.Drawing.Size(709, 26)
TP_OK_CANCEL.TabIndex = 1 TP_OK_CANCEL.TabIndex = 1
' '
'BTT_DOWN 'BTT_DOWN
' '
Me.BTT_DOWN.Dock = System.Windows.Forms.DockStyle.Fill Me.BTT_DOWN.Dock = System.Windows.Forms.DockStyle.Fill
Me.BTT_DOWN.Location = New System.Drawing.Point(432, 2) Me.BTT_DOWN.Location = New System.Drawing.Point(552, 2)
Me.BTT_DOWN.Margin = New System.Windows.Forms.Padding(3, 2, 3, 2) Me.BTT_DOWN.Margin = New System.Windows.Forms.Padding(3, 2, 3, 2)
Me.BTT_DOWN.Name = "BTT_DOWN" Me.BTT_DOWN.Name = "BTT_DOWN"
Me.BTT_DOWN.Size = New System.Drawing.Size(74, 22) Me.BTT_DOWN.Size = New System.Drawing.Size(74, 22)
@@ -339,7 +342,7 @@ Namespace API.YouTube.Controls
' '
Me.BTT_CANCEL.DialogResult = System.Windows.Forms.DialogResult.Cancel Me.BTT_CANCEL.DialogResult = System.Windows.Forms.DialogResult.Cancel
Me.BTT_CANCEL.Dock = System.Windows.Forms.DockStyle.Fill Me.BTT_CANCEL.Dock = System.Windows.Forms.DockStyle.Fill
Me.BTT_CANCEL.Location = New System.Drawing.Point(512, 2) Me.BTT_CANCEL.Location = New System.Drawing.Point(632, 2)
Me.BTT_CANCEL.Margin = New System.Windows.Forms.Padding(3, 2, 3, 2) Me.BTT_CANCEL.Margin = New System.Windows.Forms.Padding(3, 2, 3, 2)
Me.BTT_CANCEL.Name = "BTT_CANCEL" Me.BTT_CANCEL.Name = "BTT_CANCEL"
Me.BTT_CANCEL.Size = New System.Drawing.Size(74, 22) Me.BTT_CANCEL.Size = New System.Drawing.Size(74, 22)
@@ -354,7 +357,7 @@ Namespace API.YouTube.Controls
LB_SEP_1.Location = New System.Drawing.Point(6, 179) LB_SEP_1.Location = New System.Drawing.Point(6, 179)
LB_SEP_1.Margin = New System.Windows.Forms.Padding(6, 0, 6, 0) LB_SEP_1.Margin = New System.Windows.Forms.Padding(6, 0, 6, 0)
LB_SEP_1.Name = "LB_SEP_1" LB_SEP_1.Name = "LB_SEP_1"
LB_SEP_1.Size = New System.Drawing.Size(589, 1) LB_SEP_1.Size = New System.Drawing.Size(709, 1)
LB_SEP_1.TabIndex = 3 LB_SEP_1.TabIndex = 3
' '
'LB_SEP_2 'LB_SEP_2
@@ -364,7 +367,7 @@ Namespace API.YouTube.Controls
LB_SEP_2.Location = New System.Drawing.Point(6, 209) LB_SEP_2.Location = New System.Drawing.Point(6, 209)
LB_SEP_2.Margin = New System.Windows.Forms.Padding(6, 0, 6, 0) LB_SEP_2.Margin = New System.Windows.Forms.Padding(6, 0, 6, 0)
LB_SEP_2.Name = "LB_SEP_2" LB_SEP_2.Name = "LB_SEP_2"
LB_SEP_2.Size = New System.Drawing.Size(589, 1) LB_SEP_2.Size = New System.Drawing.Size(709, 1)
LB_SEP_2.TabIndex = 5 LB_SEP_2.TabIndex = 5
' '
'TP_WHAT 'TP_WHAT
@@ -436,7 +439,7 @@ Namespace API.YouTube.Controls
' '
LBL_SUBS_FORMAT.AutoSize = True LBL_SUBS_FORMAT.AutoSize = True
LBL_SUBS_FORMAT.Dock = System.Windows.Forms.DockStyle.Fill LBL_SUBS_FORMAT.Dock = System.Windows.Forms.DockStyle.Fill
LBL_SUBS_FORMAT.Location = New System.Drawing.Point(432, 0) LBL_SUBS_FORMAT.Location = New System.Drawing.Point(552, 0)
LBL_SUBS_FORMAT.Name = "LBL_SUBS_FORMAT" LBL_SUBS_FORMAT.Name = "LBL_SUBS_FORMAT"
LBL_SUBS_FORMAT.Size = New System.Drawing.Size(74, 28) LBL_SUBS_FORMAT.Size = New System.Drawing.Size(74, 28)
LBL_SUBS_FORMAT.TabIndex = 2 LBL_SUBS_FORMAT.TabIndex = 2
@@ -448,7 +451,7 @@ Namespace API.YouTube.Controls
' '
Me.LBL_AUDIO_CODEC.AutoSize = True Me.LBL_AUDIO_CODEC.AutoSize = True
Me.LBL_AUDIO_CODEC.Dock = System.Windows.Forms.DockStyle.Fill Me.LBL_AUDIO_CODEC.Dock = System.Windows.Forms.DockStyle.Fill
Me.LBL_AUDIO_CODEC.Location = New System.Drawing.Point(432, 0) Me.LBL_AUDIO_CODEC.Location = New System.Drawing.Point(552, 0)
Me.LBL_AUDIO_CODEC.Name = "LBL_AUDIO_CODEC" Me.LBL_AUDIO_CODEC.Name = "LBL_AUDIO_CODEC"
Me.LBL_AUDIO_CODEC.Size = New System.Drawing.Size(74, 28) Me.LBL_AUDIO_CODEC.Size = New System.Drawing.Size(74, 28)
Me.LBL_AUDIO_CODEC.TabIndex = 5 Me.LBL_AUDIO_CODEC.TabIndex = 5
@@ -470,7 +473,7 @@ Namespace API.YouTube.Controls
Me.TP_HEADER_BASE.RowCount = 1 Me.TP_HEADER_BASE.RowCount = 1
Me.TP_HEADER_BASE.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) Me.TP_HEADER_BASE.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
Me.TP_HEADER_BASE.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 64.0!)) Me.TP_HEADER_BASE.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 64.0!))
Me.TP_HEADER_BASE.Size = New System.Drawing.Size(601, 65) Me.TP_HEADER_BASE.Size = New System.Drawing.Size(721, 65)
Me.TP_HEADER_BASE.TabIndex = 6 Me.TP_HEADER_BASE.TabIndex = 6
' '
'TP_SUBS 'TP_SUBS
@@ -488,7 +491,7 @@ Namespace API.YouTube.Controls
Me.TP_SUBS.Name = "TP_SUBS" Me.TP_SUBS.Name = "TP_SUBS"
Me.TP_SUBS.RowCount = 1 Me.TP_SUBS.RowCount = 1
Me.TP_SUBS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) Me.TP_SUBS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
Me.TP_SUBS.Size = New System.Drawing.Size(589, 28) Me.TP_SUBS.Size = New System.Drawing.Size(709, 28)
Me.TP_SUBS.TabIndex = 2 Me.TP_SUBS.TabIndex = 2
' '
'TXT_SUBS 'TXT_SUBS
@@ -516,7 +519,7 @@ Namespace API.YouTube.Controls
Me.TXT_SUBS.Dock = System.Windows.Forms.DockStyle.Fill Me.TXT_SUBS.Dock = System.Windows.Forms.DockStyle.Fill
Me.TXT_SUBS.Location = New System.Drawing.Point(3, 3) Me.TXT_SUBS.Location = New System.Drawing.Point(3, 3)
Me.TXT_SUBS.Name = "TXT_SUBS" Me.TXT_SUBS.Name = "TXT_SUBS"
Me.TXT_SUBS.Size = New System.Drawing.Size(423, 22) Me.TXT_SUBS.Size = New System.Drawing.Size(543, 22)
Me.TXT_SUBS.TabIndex = 0 Me.TXT_SUBS.TabIndex = 0
Me.TXT_SUBS.TextBoxReadOnly = True Me.TXT_SUBS.TextBoxReadOnly = True
' '
@@ -525,7 +528,7 @@ Namespace API.YouTube.Controls
Me.CMB_SUBS_FORMAT.Dock = System.Windows.Forms.DockStyle.Fill Me.CMB_SUBS_FORMAT.Dock = System.Windows.Forms.DockStyle.Fill
Me.CMB_SUBS_FORMAT.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList Me.CMB_SUBS_FORMAT.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList
Me.CMB_SUBS_FORMAT.FormattingEnabled = True Me.CMB_SUBS_FORMAT.FormattingEnabled = True
Me.CMB_SUBS_FORMAT.Location = New System.Drawing.Point(512, 3) Me.CMB_SUBS_FORMAT.Location = New System.Drawing.Point(632, 3)
Me.CMB_SUBS_FORMAT.Name = "CMB_SUBS_FORMAT" Me.CMB_SUBS_FORMAT.Name = "CMB_SUBS_FORMAT"
Me.CMB_SUBS_FORMAT.Size = New System.Drawing.Size(74, 21) Me.CMB_SUBS_FORMAT.Size = New System.Drawing.Size(74, 21)
Me.CMB_SUBS_FORMAT.TabIndex = 1 Me.CMB_SUBS_FORMAT.TabIndex = 1
@@ -557,31 +560,33 @@ Namespace API.YouTube.Controls
Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 5.0!)) Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 5.0!))
Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 58.0!)) Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 58.0!))
Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle()) Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle())
Me.TP_MAIN.Size = New System.Drawing.Size(601, 271) Me.TP_MAIN.Size = New System.Drawing.Size(721, 271)
Me.TP_MAIN.TabIndex = 0 Me.TP_MAIN.TabIndex = 0
' '
'TP_OPTIONS 'TP_OPTIONS
' '
Me.TP_OPTIONS.ColumnCount = 6 Me.TP_OPTIONS.ColumnCount = 7
Me.TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) Me.TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
Me.TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 80.0!)) Me.TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 80.0!))
Me.TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 80.0!)) Me.TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 80.0!))
Me.TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 80.0!)) Me.TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 80.0!))
Me.TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 120.0!))
Me.TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 80.0!)) Me.TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 80.0!))
Me.TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 80.0!)) Me.TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 80.0!))
Me.TP_OPTIONS.Controls.Add(LBL_FORMAT, 1, 0) Me.TP_OPTIONS.Controls.Add(LBL_FORMAT, 1, 0)
Me.TP_OPTIONS.Controls.Add(TP_WHAT, 0, 0) Me.TP_OPTIONS.Controls.Add(TP_WHAT, 0, 0)
Me.TP_OPTIONS.Controls.Add(Me.CMB_FORMAT, 2, 0) Me.TP_OPTIONS.Controls.Add(Me.CMB_FORMAT, 2, 0)
Me.TP_OPTIONS.Controls.Add(Me.LBL_AUDIO_CODEC, 4, 0) Me.TP_OPTIONS.Controls.Add(Me.LBL_AUDIO_CODEC, 5, 0)
Me.TP_OPTIONS.Controls.Add(Me.CMB_AUDIO_CODEC, 5, 0) Me.TP_OPTIONS.Controls.Add(Me.CMB_AUDIO_CODEC, 6, 0)
Me.TP_OPTIONS.Controls.Add(Me.NUM_RES, 3, 0) Me.TP_OPTIONS.Controls.Add(Me.NUM_RES, 3, 0)
Me.TP_OPTIONS.Controls.Add(Me.TXT_FPS, 4, 0)
Me.TP_OPTIONS.Dock = System.Windows.Forms.DockStyle.Fill Me.TP_OPTIONS.Dock = System.Windows.Forms.DockStyle.Fill
Me.TP_OPTIONS.Location = New System.Drawing.Point(6, 65) Me.TP_OPTIONS.Location = New System.Drawing.Point(6, 65)
Me.TP_OPTIONS.Margin = New System.Windows.Forms.Padding(6, 0, 6, 0) Me.TP_OPTIONS.Margin = New System.Windows.Forms.Padding(6, 0, 6, 0)
Me.TP_OPTIONS.Name = "TP_OPTIONS" Me.TP_OPTIONS.Name = "TP_OPTIONS"
Me.TP_OPTIONS.RowCount = 1 Me.TP_OPTIONS.RowCount = 1
Me.TP_OPTIONS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) Me.TP_OPTIONS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
Me.TP_OPTIONS.Size = New System.Drawing.Size(589, 28) Me.TP_OPTIONS.Size = New System.Drawing.Size(709, 28)
Me.TP_OPTIONS.TabIndex = 1 Me.TP_OPTIONS.TabIndex = 1
' '
'CMB_FORMAT 'CMB_FORMAT
@@ -599,7 +604,7 @@ Namespace API.YouTube.Controls
Me.CMB_AUDIO_CODEC.Dock = System.Windows.Forms.DockStyle.Fill Me.CMB_AUDIO_CODEC.Dock = System.Windows.Forms.DockStyle.Fill
Me.CMB_AUDIO_CODEC.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList Me.CMB_AUDIO_CODEC.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList
Me.CMB_AUDIO_CODEC.FormattingEnabled = True Me.CMB_AUDIO_CODEC.FormattingEnabled = True
Me.CMB_AUDIO_CODEC.Location = New System.Drawing.Point(512, 3) Me.CMB_AUDIO_CODEC.Location = New System.Drawing.Point(632, 3)
Me.CMB_AUDIO_CODEC.Name = "CMB_AUDIO_CODEC" Me.CMB_AUDIO_CODEC.Name = "CMB_AUDIO_CODEC"
Me.CMB_AUDIO_CODEC.Size = New System.Drawing.Size(74, 21) Me.CMB_AUDIO_CODEC.Size = New System.Drawing.Size(74, 21)
Me.CMB_AUDIO_CODEC.TabIndex = 3 Me.CMB_AUDIO_CODEC.TabIndex = 3
@@ -616,6 +621,24 @@ Namespace API.YouTube.Controls
Me.NUM_RES.TextAlign = System.Windows.Forms.HorizontalAlignment.Center Me.NUM_RES.TextAlign = System.Windows.Forms.HorizontalAlignment.Center
Me.NUM_RES.Value = New Decimal(New Integer() {1080, 0, 0, 0}) Me.NUM_RES.Value = New Decimal(New Integer() {1080, 0, 0, 0})
' '
'TXT_FPS
'
ActionButton5.BackgroundImage = CType(resources.GetObject("ActionButton5.BackgroundImage"), System.Drawing.Image)
ActionButton5.Name = "Clear"
ActionButton5.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
Me.TXT_FPS.Buttons.Add(ActionButton5)
Me.TXT_FPS.CaptionText = "FPS"
Me.TXT_FPS.CaptionToolTipEnabled = True
Me.TXT_FPS.CaptionToolTipText = "You can reduce the video FPS by setting the FPS value in this field."
Me.TXT_FPS.CaptionWidth = 30.0R
Me.TXT_FPS.Dock = System.Windows.Forms.DockStyle.Fill
Me.TXT_FPS.Location = New System.Drawing.Point(432, 2)
Me.TXT_FPS.Margin = New System.Windows.Forms.Padding(3, 2, 3, 3)
Me.TXT_FPS.Name = "TXT_FPS"
Me.TXT_FPS.Size = New System.Drawing.Size(114, 22)
Me.TXT_FPS.TabIndex = 6
Me.TXT_FPS.TextBoxWidthMinimal = 30
'
'TP_CONTROLS 'TP_CONTROLS
' '
Me.TP_CONTROLS.ColumnCount = 1 Me.TP_CONTROLS.ColumnCount = 1
@@ -626,29 +649,29 @@ Namespace API.YouTube.Controls
Me.TP_CONTROLS.Name = "TP_CONTROLS" Me.TP_CONTROLS.Name = "TP_CONTROLS"
Me.TP_CONTROLS.RowCount = 1 Me.TP_CONTROLS.RowCount = 1
Me.TP_CONTROLS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) Me.TP_CONTROLS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
Me.TP_CONTROLS.Size = New System.Drawing.Size(595, 25) Me.TP_CONTROLS.Size = New System.Drawing.Size(715, 25)
Me.TP_CONTROLS.TabIndex = 0 Me.TP_CONTROLS.TabIndex = 0
' '
'TXT_SUBS_ADDIT 'TXT_SUBS_ADDIT
' '
ActionButton5.BackgroundImage = CType(resources.GetObject("ActionButton5.BackgroundImage"), System.Drawing.Image)
ActionButton5.Enabled = False
ActionButton5.Name = "Open"
ActionButton5.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Open
ActionButton5.ToolTipText = "Choose additional formats"
ActionButton6.BackgroundImage = CType(resources.GetObject("ActionButton6.BackgroundImage"), System.Drawing.Image) ActionButton6.BackgroundImage = CType(resources.GetObject("ActionButton6.BackgroundImage"), System.Drawing.Image)
ActionButton6.Enabled = False ActionButton6.Enabled = False
ActionButton6.Name = "Refresh" ActionButton6.Name = "Open"
ActionButton6.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Refresh ActionButton6.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Open
ActionButton6.ToolTipText = "Fill in additional formats from the defaults" ActionButton6.ToolTipText = "Choose additional formats"
ActionButton7.BackgroundImage = CType(resources.GetObject("ActionButton7.BackgroundImage"), System.Drawing.Image) ActionButton7.BackgroundImage = CType(resources.GetObject("ActionButton7.BackgroundImage"), System.Drawing.Image)
ActionButton7.Enabled = False ActionButton7.Enabled = False
ActionButton7.Name = "Clear" ActionButton7.Name = "Refresh"
ActionButton7.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear ActionButton7.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Refresh
ActionButton7.ToolTipText = "Remove all additional formats" ActionButton7.ToolTipText = "Fill in additional formats from the defaults"
Me.TXT_SUBS_ADDIT.Buttons.Add(ActionButton5) ActionButton8.BackgroundImage = CType(resources.GetObject("ActionButton8.BackgroundImage"), System.Drawing.Image)
ActionButton8.Enabled = False
ActionButton8.Name = "Clear"
ActionButton8.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
ActionButton8.ToolTipText = "Remove all additional formats"
Me.TXT_SUBS_ADDIT.Buttons.Add(ActionButton6) Me.TXT_SUBS_ADDIT.Buttons.Add(ActionButton6)
Me.TXT_SUBS_ADDIT.Buttons.Add(ActionButton7) Me.TXT_SUBS_ADDIT.Buttons.Add(ActionButton7)
Me.TXT_SUBS_ADDIT.Buttons.Add(ActionButton8)
Me.TXT_SUBS_ADDIT.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.CheckBox Me.TXT_SUBS_ADDIT.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.CheckBox
Me.TXT_SUBS_ADDIT.CaptionText = "Additional subtitle formats" Me.TXT_SUBS_ADDIT.CaptionText = "Additional subtitle formats"
Me.TXT_SUBS_ADDIT.CaptionToolTipEnabled = True Me.TXT_SUBS_ADDIT.CaptionToolTipEnabled = True
@@ -659,31 +682,31 @@ Namespace API.YouTube.Controls
Me.TXT_SUBS_ADDIT.Location = New System.Drawing.Point(6, 124) Me.TXT_SUBS_ADDIT.Location = New System.Drawing.Point(6, 124)
Me.TXT_SUBS_ADDIT.Margin = New System.Windows.Forms.Padding(6, 3, 6, 3) Me.TXT_SUBS_ADDIT.Margin = New System.Windows.Forms.Padding(6, 3, 6, 3)
Me.TXT_SUBS_ADDIT.Name = "TXT_SUBS_ADDIT" Me.TXT_SUBS_ADDIT.Name = "TXT_SUBS_ADDIT"
Me.TXT_SUBS_ADDIT.Size = New System.Drawing.Size(589, 22) Me.TXT_SUBS_ADDIT.Size = New System.Drawing.Size(709, 22)
Me.TXT_SUBS_ADDIT.TabIndex = 3 Me.TXT_SUBS_ADDIT.TabIndex = 3
Me.TXT_SUBS_ADDIT.Tag = "s" Me.TXT_SUBS_ADDIT.Tag = "s"
Me.TXT_SUBS_ADDIT.TextBoxReadOnly = True Me.TXT_SUBS_ADDIT.TextBoxReadOnly = True
' '
'TXT_EXTRA_AUDIO_FORMATS 'TXT_EXTRA_AUDIO_FORMATS
' '
ActionButton8.BackgroundImage = CType(resources.GetObject("ActionButton8.BackgroundImage"), System.Drawing.Image)
ActionButton8.Enabled = False
ActionButton8.Name = "Open"
ActionButton8.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Open
ActionButton8.ToolTipText = "Choose additional formats"
ActionButton9.BackgroundImage = CType(resources.GetObject("ActionButton9.BackgroundImage"), System.Drawing.Image) ActionButton9.BackgroundImage = CType(resources.GetObject("ActionButton9.BackgroundImage"), System.Drawing.Image)
ActionButton9.Enabled = False ActionButton9.Enabled = False
ActionButton9.Name = "Refresh" ActionButton9.Name = "Open"
ActionButton9.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Refresh ActionButton9.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Open
ActionButton9.ToolTipText = "Fill in additional formats from the defaults" ActionButton9.ToolTipText = "Choose additional formats"
ActionButton10.BackgroundImage = CType(resources.GetObject("ActionButton10.BackgroundImage"), System.Drawing.Image) ActionButton10.BackgroundImage = CType(resources.GetObject("ActionButton10.BackgroundImage"), System.Drawing.Image)
ActionButton10.Enabled = False ActionButton10.Enabled = False
ActionButton10.Name = "Clear" ActionButton10.Name = "Refresh"
ActionButton10.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear ActionButton10.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Refresh
ActionButton10.ToolTipText = "Choose additional formats" ActionButton10.ToolTipText = "Fill in additional formats from the defaults"
Me.TXT_EXTRA_AUDIO_FORMATS.Buttons.Add(ActionButton8) ActionButton11.BackgroundImage = CType(resources.GetObject("ActionButton11.BackgroundImage"), System.Drawing.Image)
ActionButton11.Enabled = False
ActionButton11.Name = "Clear"
ActionButton11.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
ActionButton11.ToolTipText = "Choose additional formats"
Me.TXT_EXTRA_AUDIO_FORMATS.Buttons.Add(ActionButton9) Me.TXT_EXTRA_AUDIO_FORMATS.Buttons.Add(ActionButton9)
Me.TXT_EXTRA_AUDIO_FORMATS.Buttons.Add(ActionButton10) Me.TXT_EXTRA_AUDIO_FORMATS.Buttons.Add(ActionButton10)
Me.TXT_EXTRA_AUDIO_FORMATS.Buttons.Add(ActionButton11)
Me.TXT_EXTRA_AUDIO_FORMATS.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.CheckBox Me.TXT_EXTRA_AUDIO_FORMATS.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.CheckBox
Me.TXT_EXTRA_AUDIO_FORMATS.CaptionText = "Additional audio formats" Me.TXT_EXTRA_AUDIO_FORMATS.CaptionText = "Additional audio formats"
Me.TXT_EXTRA_AUDIO_FORMATS.CaptionToolTipEnabled = True Me.TXT_EXTRA_AUDIO_FORMATS.CaptionToolTipEnabled = True
@@ -693,7 +716,7 @@ Namespace API.YouTube.Controls
Me.TXT_EXTRA_AUDIO_FORMATS.Location = New System.Drawing.Point(6, 152) Me.TXT_EXTRA_AUDIO_FORMATS.Location = New System.Drawing.Point(6, 152)
Me.TXT_EXTRA_AUDIO_FORMATS.Margin = New System.Windows.Forms.Padding(6, 3, 6, 3) Me.TXT_EXTRA_AUDIO_FORMATS.Margin = New System.Windows.Forms.Padding(6, 3, 6, 3)
Me.TXT_EXTRA_AUDIO_FORMATS.Name = "TXT_EXTRA_AUDIO_FORMATS" Me.TXT_EXTRA_AUDIO_FORMATS.Name = "TXT_EXTRA_AUDIO_FORMATS"
Me.TXT_EXTRA_AUDIO_FORMATS.Size = New System.Drawing.Size(589, 22) Me.TXT_EXTRA_AUDIO_FORMATS.Size = New System.Drawing.Size(709, 22)
Me.TXT_EXTRA_AUDIO_FORMATS.TabIndex = 4 Me.TXT_EXTRA_AUDIO_FORMATS.TabIndex = 4
Me.TXT_EXTRA_AUDIO_FORMATS.Tag = "a" Me.TXT_EXTRA_AUDIO_FORMATS.Tag = "a"
Me.TXT_EXTRA_AUDIO_FORMATS.TextBoxReadOnly = True Me.TXT_EXTRA_AUDIO_FORMATS.TextBoxReadOnly = True
@@ -704,13 +727,14 @@ Namespace API.YouTube.Controls
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!) Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.CancelButton = Me.BTT_CANCEL Me.CancelButton = Me.BTT_CANCEL
Me.ClientSize = New System.Drawing.Size(601, 271) Me.ClientSize = New System.Drawing.Size(721, 271)
Me.Controls.Add(Me.TP_MAIN) Me.Controls.Add(Me.TP_MAIN)
Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle
Me.Icon = Global.SCrawler.My.Resources.SiteYouTube.YouTubeIcon_32 Me.Icon = Global.SCrawler.My.Resources.SiteYouTube.YouTubeIcon_32
Me.KeyPreview = True Me.KeyPreview = True
Me.MaximizeBox = False Me.MaximizeBox = False
Me.MinimizeBox = False Me.MinimizeBox = False
Me.MinimumSize = New System.Drawing.Size(737, 310)
Me.Name = "VideoOptionsForm" Me.Name = "VideoOptionsForm"
Me.ShowInTaskbar = False Me.ShowInTaskbar = False
Me.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide Me.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide
@@ -736,6 +760,7 @@ Namespace API.YouTube.Controls
Me.TP_OPTIONS.ResumeLayout(False) Me.TP_OPTIONS.ResumeLayout(False)
Me.TP_OPTIONS.PerformLayout() Me.TP_OPTIONS.PerformLayout()
CType(Me.NUM_RES, System.ComponentModel.ISupportInitialize).EndInit() CType(Me.NUM_RES, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.TXT_FPS, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.TXT_SUBS_ADDIT, System.ComponentModel.ISupportInitialize).EndInit() CType(Me.TXT_SUBS_ADDIT, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.TXT_EXTRA_AUDIO_FORMATS, System.ComponentModel.ISupportInitialize).EndInit() CType(Me.TXT_EXTRA_AUDIO_FORMATS, System.ComponentModel.ISupportInitialize).EndInit()
Me.ResumeLayout(False) Me.ResumeLayout(False)
@@ -765,5 +790,6 @@ Namespace API.YouTube.Controls
Private WithEvents BTT_DOWN As Button Private WithEvents BTT_DOWN As Button
Private WithEvents BTT_CANCEL As Button Private WithEvents BTT_CANCEL As Button
Private WithEvents TP_HEADER_INFO_2 As TableLayoutPanel Private WithEvents TP_HEADER_INFO_2 As TableLayoutPanel
Private WithEvents TXT_FPS As PersonalUtilities.Forms.Controls.TextBoxExtended
End Class End Class
End Namespace End Namespace

View File

@@ -289,6 +289,14 @@
</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>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value>
</data>
<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+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP
@@ -299,7 +307,7 @@
cMaRN0UdBBkAAAAASUVORK5CYII= cMaRN0UdBBkAAAAASUVORK5CYII=
</value> </value>
</data> </data>
<data name="ActionButton6.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/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6 iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOElE JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOElE
@@ -315,7 +323,7 @@
VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg== VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg==
</value> </value>
</data> </data>
<data name="ActionButton7.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton8.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
@@ -323,7 +331,7 @@
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value> </value>
</data> </data>
<data name="ActionButton8.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton9.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP
@@ -334,7 +342,7 @@
cMaRN0UdBBkAAAAASUVORK5CYII= cMaRN0UdBBkAAAAASUVORK5CYII=
</value> </value>
</data> </data>
<data name="ActionButton9.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton10.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6 iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOElE JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOElE
@@ -350,7 +358,7 @@
VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg== VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg==
</value> </value>
</data> </data>
<data name="ActionButton10.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 xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go

View File

@@ -22,6 +22,7 @@ Namespace API.YouTube.Controls
Friend Class VideoOptionsForm : Implements IDesignXMLContainer Friend Class VideoOptionsForm : Implements IDesignXMLContainer
#Region "Declarations" #Region "Declarations"
Private MyView As FormView Private MyView As FormView
Private ReadOnly MyFieldsChecker As FieldsChecker
Friend Property DesignXML As EContainer Implements IDesignXMLContainer.DesignXML Friend Property DesignXML As EContainer Implements IDesignXMLContainer.DesignXML
Private Property DesignXMLNodes As String() Implements IDesignXMLContainer.DesignXMLNodes Private Property DesignXMLNodes As String() Implements IDesignXMLContainer.DesignXMLNodes
Private Property DesignXMLNodeName As String Implements IDesignXMLContainer.DesignXMLNodeName Private Property DesignXMLNodeName As String Implements IDesignXMLContainer.DesignXMLNodeName
@@ -29,14 +30,34 @@ Namespace API.YouTube.Controls
Private ReadOnly Property CNT_PROCESSOR As TableControlsProcessor Private ReadOnly Property CNT_PROCESSOR As TableControlsProcessor
Friend Property MyContainer As YouTubeMediaContainerBase Friend Property MyContainer As YouTubeMediaContainerBase
Private Initialization As Boolean = True Private Initialization As Boolean = True
Private ReadOnly IsSavedObject As Boolean Private ReadOnly InheritsFromContainer As Boolean
Private Class FpsFieldChecker : Inherits FieldsCheckerProviderBase
Private ReadOnly MyProvider As ANumbers = YouTubeSettings.FpsFormatProvider.MyProviderDefault
Public Overrides Property ErrorMessage As String
Get
Return IIf(HasError, YouTubeSettings.FpsFormatProvider.ErrorMessageDefault, String.Empty)
End Get
Set : End Set
End Property
Public Overrides 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
If ACheck(Of Double)(Value, AModes.Var, MyProvider) Then
Return Value
Else
HasError = True
TypeError = True
Return Nothing
End If
End Function
End Class
#End Region #End Region
#Region "Initializers" #Region "Initializers"
Friend Sub New(ByVal Container As YouTubeMediaContainerBase, Optional ByVal IsSavedObject As Boolean = False) Friend Sub New(ByVal Container As YouTubeMediaContainerBase, Optional ByVal InheritsFromContainer As Boolean = False)
InitializeComponent() InitializeComponent()
MyContainer = Container MyContainer = Container
CNT_PROCESSOR = New TableControlsProcessor(TP_CONTROLS) CNT_PROCESSOR = New TableControlsProcessor(TP_CONTROLS)
Me.IsSavedObject = IsSavedObject Me.InheritsFromContainer = InheritsFromContainer
MyFieldsChecker = New FieldsChecker
End Sub End Sub
#End Region #End Region
#Region "Form handlers" #Region "Form handlers"
@@ -68,8 +89,8 @@ Namespace API.YouTube.Controls
If Not .PlaylistTitle.IsEmptyString Or Not .Title.IsEmptyString Then Text &= $" - { .PlaylistTitle.IfNullOrEmpty(.Title)}" If Not .PlaylistTitle.IsEmptyString Or Not .Title.IsEmptyString Then Text &= $" - { .PlaylistTitle.IfNullOrEmpty(.Title)}"
TP_MAIN.Controls.Remove(TP_HEADER_BASE) TP_MAIN.Controls.Remove(TP_HEADER_BASE)
TP_MAIN.RowStyles(0).Height = 0 TP_MAIN.RowStyles(0).Height = 0
Dim def% = If(IsSavedObject, .ArrayMaxResolution, MyYouTubeSettings.DefaultVideoDefinition.Value) Dim def% = If(InheritsFromContainer, .ArrayMaxResolution, MyYouTubeSettings.DefaultVideoDefinition.Value)
If IsSavedObject Then If InheritsFromContainer Then
__audioOnly = def = -2 __audioOnly = def = -2
If def <= 0 Then def = MyYouTubeSettings.DefaultVideoDefinition If def <= 0 Then def = MyYouTubeSettings.DefaultVideoDefinition
Else Else
@@ -98,7 +119,7 @@ Namespace API.YouTube.Controls
LBL_URL.Text = .URL LBL_URL.Text = .URL
End If End If
If .IsMusic Or __audioOnly Then If .IsMusic Or __audioOnly Or (InheritsFromContainer And .IsAudioSelected) Then
OPT_AUDIO.Checked = True OPT_AUDIO.Checked = True
Else Else
OPT_VIDEO.Checked = True OPT_VIDEO.Checked = True
@@ -107,7 +128,7 @@ Namespace API.YouTube.Controls
arr = AvailableVideoFormats arr = AvailableVideoFormats
CMB_FORMAT.Items.AddRange(arr) CMB_FORMAT.Items.AddRange(arr)
If IsSavedObject Then If InheritsFromContainer Then
__optionValue = .OutputVideoExtension.IfNullOrEmpty(MyYouTubeSettings.DefaultVideoFormat.Value) __optionValue = .OutputVideoExtension.IfNullOrEmpty(MyYouTubeSettings.DefaultVideoFormat.Value)
Else Else
__optionValue = MyYouTubeSettings.DefaultVideoFormat.Value __optionValue = MyYouTubeSettings.DefaultVideoFormat.Value
@@ -116,7 +137,7 @@ Namespace API.YouTube.Controls
arr = AvailableAudioFormats arr = AvailableAudioFormats
CMB_AUDIO_CODEC.Items.AddRange(arr) CMB_AUDIO_CODEC.Items.AddRange(arr)
If IsSavedObject Then If InheritsFromContainer Then
__optionValue = .OutputAudioCodec.IfNullOrEmpty(IIf(.IsMusic, MyYouTubeSettings.DefaultAudioCodecMusic.Value, MyYouTubeSettings.DefaultAudioCodec.Value)) __optionValue = .OutputAudioCodec.IfNullOrEmpty(IIf(.IsMusic, MyYouTubeSettings.DefaultAudioCodecMusic.Value, MyYouTubeSettings.DefaultAudioCodec.Value))
Else Else
__optionValue = IIf(.IsMusic, MyYouTubeSettings.DefaultAudioCodecMusic.Value, MyYouTubeSettings.DefaultAudioCodec.Value) __optionValue = IIf(.IsMusic, MyYouTubeSettings.DefaultAudioCodecMusic.Value, MyYouTubeSettings.DefaultAudioCodec.Value)
@@ -125,13 +146,20 @@ Namespace API.YouTube.Controls
arr = AvailableSubtitlesFormats arr = AvailableSubtitlesFormats
CMB_SUBS_FORMAT.Items.AddRange(arr) CMB_SUBS_FORMAT.Items.AddRange(arr)
If IsSavedObject Then If InheritsFromContainer Then
__optionValue = .OutputSubtitlesFormat.IfNullOrEmpty(IIf(.IsMusic, "LRC", MyYouTubeSettings.DefaultSubtitlesFormat.Value)) __optionValue = .OutputSubtitlesFormat.IfNullOrEmpty(IIf(.IsMusic, "LRC", MyYouTubeSettings.DefaultSubtitlesFormat.Value))
Else Else
__optionValue = IIf(.IsMusic, "LRC", MyYouTubeSettings.DefaultSubtitlesFormat.Value) __optionValue = IIf(.IsMusic, "LRC", MyYouTubeSettings.DefaultSubtitlesFormat.Value)
End If End If
setDef(CMB_SUBS_FORMAT, __optionValue) setDef(CMB_SUBS_FORMAT, __optionValue)
If InheritsFromContainer Then
If .OutputVideoFPS > 0 Then TXT_FPS.Text = .OutputVideoFPS
Else
If MyYouTubeSettings.DefaultVideoFPS > 0 Then TXT_FPS.Text = MyYouTubeSettings.DefaultVideoFPS
End If
MyFieldsChecker.AddControl(Of Double)(TXT_FPS, TXT_FPS.CaptionText, True, New FpsFieldChecker)
MyFieldsChecker.EndLoaderOperations()
TP_SUBS.Enabled = .Subtitles.Count > 0 TP_SUBS.Enabled = .Subtitles.Count > 0
TXT_SUBS_ADDIT.Enabled = .Subtitles.Count > 0 TXT_SUBS_ADDIT.Enabled = .Subtitles.Count > 0
RefillTextBoxes() RefillTextBoxes()
@@ -151,6 +179,7 @@ Namespace API.YouTube.Controls
End Sub End Sub
Private Sub VideoOptionsForm_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing Private Sub VideoOptionsForm_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
MyView.DisposeIfReady() MyView.DisposeIfReady()
MyFieldsChecker.DisposeIfReady()
End Sub End Sub
#End Region #End Region
#Region "Refill" #Region "Refill"
@@ -183,7 +212,7 @@ Namespace API.YouTube.Controls
Dim data As IEnumerable(Of Control) Dim data As IEnumerable(Of Control)
If .HasElements Then If .HasElements Then
data = .Elements.Select(Function(ee) New MediaItem(ee) With {.Dock = DockStyle.Fill, .Checked = ee.Checked, .IgnoreDownloadState = True}) data = .Elements.Select(Function(ee) New MediaItem(ee, True) With {.Dock = DockStyle.Fill, .Checked = ee.Checked})
Else Else
data = (From m As MediaObject In .Self.MediaObjects data = (From m As MediaObject In .Self.MediaObjects
Where m.Type = __contentType Where m.Type = __contentType
@@ -204,6 +233,8 @@ Namespace API.YouTube.Controls
If MyContainer.HasElements Then If MyContainer.HasElements Then
With DirectCast(d, MediaItem) With DirectCast(d, MediaItem)
AddHandler .CheckedChanged, AddressOf MediaItem_CheckedChanged AddHandler .CheckedChanged, AddressOf MediaItem_CheckedChanged
AddHandler .BeforeOpenEditor, AddressOf MediaItem_BeforeOpenEditor
AddHandler .BeforeOpenEditorFull, AddressOf MediaItem_BeforeOpenEditorFull
AddHandler .Click, AddressOf CNT_PROCESSOR.MediaItem_Click AddHandler .Click, AddressOf CNT_PROCESSOR.MediaItem_Click
AddHandler .KeyDown, AddressOf CNT_PROCESSOR.MediaItem_KeyDown AddHandler .KeyDown, AddressOf CNT_PROCESSOR.MediaItem_KeyDown
End With End With
@@ -271,10 +302,33 @@ Namespace API.YouTube.Controls
Private Sub MediaItem_CheckedChanged(ByVal Sender As MediaItem, ByVal Container As IYouTubeMediaContainer) Private Sub MediaItem_CheckedChanged(ByVal Sender As MediaItem, ByVal Container As IYouTubeMediaContainer)
ControlInvokeFast(TP_CONTROLS, Sub() Container.Checked = Sender.Checked, EDP.None) ControlInvokeFast(TP_CONTROLS, Sub() Container.Checked = Sender.Checked, EDP.None)
End Sub End Sub
Private Sub MediaItem_BeforeOpenEditor(ByVal Sender As MediaItem, ByVal Container As IYouTubeMediaContainer)
MediaItem_BeforeOpenEditorImpl(Sender, Container, False)
End Sub
Private Sub MediaItem_BeforeOpenEditorFull(ByVal Sender As MediaItem, ByVal Container As IYouTubeMediaContainer)
MediaItem_BeforeOpenEditorImpl(Sender, Container, True)
End Sub
Private Sub MediaItem_BeforeOpenEditorImpl(ByVal Sender As MediaItem, ByVal Container As IYouTubeMediaContainer, ByVal Full As Boolean)
If MyContainer.HasElements Then
ControlInvokeFast(TP_CONTROLS, Sub()
With DirectCast(Container, YouTubeMediaContainerBase)
.File = $"{TXT_FILE.Text.CSFilePS}{ .File.File}"
If Full Then
.OutputVideoExtension = CMB_FORMAT.Text.StringToLower
.OutputVideoFPS = AConvert(Of Double)(TXT_FPS.Text, YouTubeSettings.FpsFormatProvider.MyProviderDefault, -1)
.OutputAudioCodec = CMB_AUDIO_CODEC.Text.StringToLower
.OutputSubtitlesFormat = CMB_SUBS_FORMAT.Text.StringToLower
.IsAudioSelected = OPT_AUDIO.Checked
End If
End With
End Sub, EDP.None)
End If
End Sub
#End Region #End Region
#Region "OK, Cancel" #Region "OK, Cancel"
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
Try Try
If Not MyFieldsChecker.AllParamsOK Then Exit Sub
Dim f As SFile Dim f As SFile
If MyContainer.HasElements Then If MyContainer.HasElements Then
f = TXT_FILE.Text.CSFileP f = TXT_FILE.Text.CSFileP
@@ -284,6 +338,7 @@ Namespace API.YouTube.Controls
If f.IsEmptyString Then Throw New ArgumentNullException("File", "The output file cannot be null") If f.IsEmptyString Then Throw New ArgumentNullException("File", "The output file cannot be null")
With MyContainer With MyContainer
.OutputVideoExtension = CMB_FORMAT.Text.StringToLower .OutputVideoExtension = CMB_FORMAT.Text.StringToLower
.OutputVideoFPS = AConvert(Of Double)(TXT_FPS.Text, YouTubeSettings.FpsFormatProvider.MyProviderDefault, -1)
.OutputAudioCodec = CMB_AUDIO_CODEC.Text.StringToLower .OutputAudioCodec = CMB_AUDIO_CODEC.Text.StringToLower
.OutputSubtitlesFormat = CMB_SUBS_FORMAT.Text.StringToLower .OutputSubtitlesFormat = CMB_SUBS_FORMAT.Text.StringToLower
@@ -346,6 +401,19 @@ Namespace API.YouTube.Controls
Private Sub OPT_VIDEO_AUDIO_CheckedChanged(sender As Object, e As EventArgs) Handles OPT_VIDEO.CheckedChanged, OPT_AUDIO.CheckedChanged Private Sub OPT_VIDEO_AUDIO_CheckedChanged(sender As Object, e As EventArgs) Handles OPT_VIDEO.CheckedChanged, OPT_AUDIO.CheckedChanged
If Not Initialization Then If Not Initialization Then
CMB_FORMAT.Enabled = OPT_VIDEO.Checked CMB_FORMAT.Enabled = OPT_VIDEO.Checked
Dim upFormat As Action(Of String) = Sub(ByVal format As String)
If Not format.IsEmptyString Then
format = format.ToLower
Dim fIndex% = CMB_AUDIO_CODEC.Items.Cast(Of String).ListIndexOf(Function(f) f.ToLower = format)
If fIndex >= 0 Then CMB_AUDIO_CODEC.SelectedIndex = fIndex
End If
End Sub
If OPT_VIDEO.Checked Then
upFormat(MyYouTubeSettings.DefaultAudioCodec)
Else
upFormat(MyYouTubeSettings.DefaultAudioCodecMusic)
End If
If MyContainer.HasElements Then If MyContainer.HasElements Then
NUM_RES.Enabled = OPT_VIDEO.Checked NUM_RES.Enabled = OPT_VIDEO.Checked
Else Else

View File

@@ -30,11 +30,16 @@ Namespace DownloadObjects.STDownloader
Me.BTT_DOWN = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_DOWN = New System.Windows.Forms.ToolStripMenuItem()
Me.SEP_DOWN = New System.Windows.Forms.ToolStripSeparator() Me.SEP_DOWN = New System.Windows.Forms.ToolStripSeparator()
Me.BTT_OPEN_FOLDER = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_OPEN_FOLDER = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_OPEN_FILE = New System.Windows.Forms.ToolStripMenuItem()
Me.SEP_FOLDER = New System.Windows.Forms.ToolStripSeparator() Me.SEP_FOLDER = New System.Windows.Forms.ToolStripSeparator()
Me.BTT_PLS_ITEM_EDIT = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_PLS_ITEM_EDIT_FULL = New System.Windows.Forms.ToolStripMenuItem()
Me.SEP_PLS_ITEM_EDIT = New System.Windows.Forms.ToolStripSeparator()
Me.BTT_COPY_LINK = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_COPY_LINK = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_OPEN_IN_BROWSER = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_OPEN_IN_BROWSER = New System.Windows.Forms.ToolStripMenuItem()
Me.SEP_DOWN_AGAIN = New System.Windows.Forms.ToolStripSeparator() Me.SEP_DOWN_AGAIN = New System.Windows.Forms.ToolStripSeparator()
Me.BTT_DOWN_AGAIN = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_DOWN_AGAIN = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_VIEW_SETTINGS = New System.Windows.Forms.ToolStripMenuItem()
Me.SEP_DEL = New System.Windows.Forms.ToolStripSeparator() Me.SEP_DEL = New System.Windows.Forms.ToolStripSeparator()
Me.BTT_REMOVE_FROM_LIST = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_REMOVE_FROM_LIST = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_DELETE_FILE = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_DELETE_FILE = New System.Windows.Forms.ToolStripMenuItem()
@@ -42,7 +47,6 @@ Namespace DownloadObjects.STDownloader
Me.TP_CHECKED_TITLE = New System.Windows.Forms.TableLayoutPanel() Me.TP_CHECKED_TITLE = New System.Windows.Forms.TableLayoutPanel()
Me.LBL_TITLE = New System.Windows.Forms.Label() Me.LBL_TITLE = New System.Windows.Forms.Label()
Me.CH_CHECKED = New System.Windows.Forms.CheckBox() Me.CH_CHECKED = New System.Windows.Forms.CheckBox()
Me.BTT_VIEW_SETTINGS = New System.Windows.Forms.ToolStripMenuItem()
TP_MAIN = New System.Windows.Forms.TableLayoutPanel() TP_MAIN = New System.Windows.Forms.TableLayoutPanel()
TP_MAIN.SuspendLayout() TP_MAIN.SuspendLayout()
CType(Me.ICON_VIDEO, System.ComponentModel.ISupportInitialize).BeginInit() CType(Me.ICON_VIDEO, System.ComponentModel.ISupportInitialize).BeginInit()
@@ -83,10 +87,10 @@ Namespace DownloadObjects.STDownloader
' '
'CONTEXT_MAIN 'CONTEXT_MAIN
' '
Me.CONTEXT_MAIN.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.BTT_DOWN, Me.SEP_DOWN, Me.BTT_OPEN_FOLDER, Me.SEP_FOLDER, Me.BTT_COPY_LINK, Me.BTT_OPEN_IN_BROWSER, Me.SEP_DOWN_AGAIN, Me.BTT_DOWN_AGAIN, Me.BTT_VIEW_SETTINGS, Me.SEP_DEL, Me.BTT_REMOVE_FROM_LIST, Me.BTT_DELETE_FILE}) Me.CONTEXT_MAIN.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.BTT_DOWN, Me.SEP_DOWN, Me.BTT_OPEN_FOLDER, Me.BTT_OPEN_FILE, Me.SEP_FOLDER, Me.BTT_PLS_ITEM_EDIT, Me.BTT_PLS_ITEM_EDIT_FULL, Me.SEP_PLS_ITEM_EDIT, Me.BTT_COPY_LINK, Me.BTT_OPEN_IN_BROWSER, Me.SEP_DOWN_AGAIN, Me.BTT_DOWN_AGAIN, Me.BTT_VIEW_SETTINGS, Me.SEP_DEL, Me.BTT_REMOVE_FROM_LIST, Me.BTT_DELETE_FILE})
Me.CONTEXT_MAIN.Name = "CONTEXT_MAIN" Me.CONTEXT_MAIN.Name = "CONTEXT_MAIN"
Me.CONTEXT_MAIN.ShowItemToolTips = False Me.CONTEXT_MAIN.ShowItemToolTips = False
Me.CONTEXT_MAIN.Size = New System.Drawing.Size(185, 226) Me.CONTEXT_MAIN.Size = New System.Drawing.Size(185, 298)
' '
'BTT_DOWN 'BTT_DOWN
' '
@@ -107,11 +111,42 @@ Namespace DownloadObjects.STDownloader
Me.BTT_OPEN_FOLDER.Size = New System.Drawing.Size(184, 22) Me.BTT_OPEN_FOLDER.Size = New System.Drawing.Size(184, 22)
Me.BTT_OPEN_FOLDER.Text = "Open folder" Me.BTT_OPEN_FOLDER.Text = "Open folder"
' '
'BTT_OPEN_FILE
'
Me.BTT_OPEN_FILE.Image = CType(resources.GetObject("BTT_OPEN_FILE.Image"), System.Drawing.Image)
Me.BTT_OPEN_FILE.Name = "BTT_OPEN_FILE"
Me.BTT_OPEN_FILE.Size = New System.Drawing.Size(184, 22)
Me.BTT_OPEN_FILE.Text = "Open file"
'
'SEP_FOLDER 'SEP_FOLDER
' '
Me.SEP_FOLDER.Name = "SEP_FOLDER" Me.SEP_FOLDER.Name = "SEP_FOLDER"
Me.SEP_FOLDER.Size = New System.Drawing.Size(181, 6) Me.SEP_FOLDER.Size = New System.Drawing.Size(181, 6)
' '
'BTT_PLS_ITEM_EDIT
'
Me.BTT_PLS_ITEM_EDIT.Image = CType(resources.GetObject("BTT_PLS_ITEM_EDIT.Image"), System.Drawing.Image)
Me.BTT_PLS_ITEM_EDIT.Name = "BTT_PLS_ITEM_EDIT"
Me.BTT_PLS_ITEM_EDIT.Size = New System.Drawing.Size(184, 22)
Me.BTT_PLS_ITEM_EDIT.Text = "Edit"
Me.BTT_PLS_ITEM_EDIT.Visible = False
'
'BTT_PLS_ITEM_EDIT_FULL
'
Me.BTT_PLS_ITEM_EDIT_FULL.AutoToolTip = True
Me.BTT_PLS_ITEM_EDIT_FULL.Image = CType(resources.GetObject("BTT_PLS_ITEM_EDIT_FULL.Image"), System.Drawing.Image)
Me.BTT_PLS_ITEM_EDIT_FULL.Name = "BTT_PLS_ITEM_EDIT_FULL"
Me.BTT_PLS_ITEM_EDIT_FULL.Size = New System.Drawing.Size(184, 22)
Me.BTT_PLS_ITEM_EDIT_FULL.Text = "Edit (inherit settings)"
Me.BTT_PLS_ITEM_EDIT_FULL.ToolTipText = "Inherit settings selected in the form"
Me.BTT_PLS_ITEM_EDIT_FULL.Visible = False
'
'SEP_PLS_ITEM_EDIT
'
Me.SEP_PLS_ITEM_EDIT.Name = "SEP_PLS_ITEM_EDIT"
Me.SEP_PLS_ITEM_EDIT.Size = New System.Drawing.Size(181, 6)
Me.SEP_PLS_ITEM_EDIT.Visible = False
'
'BTT_COPY_LINK 'BTT_COPY_LINK
' '
Me.BTT_COPY_LINK.Image = Global.SCrawler.My.Resources.Resources.LinkPic_32 Me.BTT_COPY_LINK.Image = Global.SCrawler.My.Resources.Resources.LinkPic_32
@@ -138,6 +173,13 @@ Namespace DownloadObjects.STDownloader
Me.BTT_DOWN_AGAIN.Size = New System.Drawing.Size(184, 22) Me.BTT_DOWN_AGAIN.Size = New System.Drawing.Size(184, 22)
Me.BTT_DOWN_AGAIN.Text = "Download again" Me.BTT_DOWN_AGAIN.Text = "Download again"
' '
'BTT_VIEW_SETTINGS
'
Me.BTT_VIEW_SETTINGS.Image = Global.SCrawler.My.Resources.Resources.SettingsPic_16
Me.BTT_VIEW_SETTINGS.Name = "BTT_VIEW_SETTINGS"
Me.BTT_VIEW_SETTINGS.Size = New System.Drawing.Size(184, 22)
Me.BTT_VIEW_SETTINGS.Text = "View settings"
'
'SEP_DEL 'SEP_DEL
' '
Me.SEP_DEL.Name = "SEP_DEL" Me.SEP_DEL.Name = "SEP_DEL"
@@ -212,13 +254,6 @@ Namespace DownloadObjects.STDownloader
Me.CH_CHECKED.TabIndex = 0 Me.CH_CHECKED.TabIndex = 0
Me.CH_CHECKED.UseVisualStyleBackColor = True Me.CH_CHECKED.UseVisualStyleBackColor = True
' '
'BTT_VIEW_SETTINGS
'
Me.BTT_VIEW_SETTINGS.Image = Global.SCrawler.My.Resources.Resources.SettingsPic_16
Me.BTT_VIEW_SETTINGS.Name = "BTT_VIEW_SETTINGS"
Me.BTT_VIEW_SETTINGS.Size = New System.Drawing.Size(184, 22)
Me.BTT_VIEW_SETTINGS.Text = "View settings"
'
'MediaItem 'MediaItem
' '
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!) Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
@@ -253,5 +288,9 @@ Namespace DownloadObjects.STDownloader
Private WithEvents SEP_DOWN_AGAIN As ToolStripSeparator Private WithEvents SEP_DOWN_AGAIN As ToolStripSeparator
Private WithEvents SEP_DEL As ToolStripSeparator Private WithEvents SEP_DEL As ToolStripSeparator
Private WithEvents BTT_VIEW_SETTINGS As ToolStripMenuItem Private WithEvents BTT_VIEW_SETTINGS As ToolStripMenuItem
Private WithEvents BTT_OPEN_FILE As ToolStripMenuItem
Private WithEvents BTT_PLS_ITEM_EDIT As ToolStripMenuItem
Private WithEvents SEP_PLS_ITEM_EDIT As ToolStripSeparator
Private WithEvents BTT_PLS_ITEM_EDIT_FULL As ToolStripMenuItem
End Class End Class
End Namespace End Namespace

View File

@@ -138,6 +138,138 @@
PNWfb/GWbyQQ2Z/pgjaJ9XsI91sIjr1H+fgUVeYh/KVrFs8Itp6O1B2RR+fAdhzupEHDXnw3U3GVpuAq PNWfb/GWbyQQ2Z/pgjaJ9XsI91sIjr1H+fgUVeYh/KVrFs8Itp6O1B2RR+fAdhzupEHDXnw3U3GVpuAq
+w/y3l2wnHCNxMrhGIGMcp2WpkyYWeqcC30Co5OYu0gvwZIRtc4b606cpoUYtF9y3BgvNkFSmhcSO25a +w/y3l2wnHCNxMrhGIGMcp2WpkyYWeqcC30Co5OYu0gvwZIRtc4b606cpoUYtF9y3BgvNkFSmhcSO25a
TGCkk99shOQwl9bXawAAAABJRU5ErkJggg== TGCkk99shOQwl9bXawAAAABJRU5ErkJggg==
</value>
</data>
<data name="BTT_OPEN_FILE.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
wwAADsMBx2+oZAAAAk9JREFUOE+Nk0tIVGEUgKcWZlZWEK1aZEmZUlmpEQUtrF1Q0WNfUUgtCqKZLMXQ
UPJRmuY4TYYKmbPJcVSCAkuFQislzCx7rSo3Oc5T7zzu17njdZosxMXH/bn/+b97zn/ONfBjAJoPQctR
sB2bH1rsw8OEvnVj0BbUbdNJ19HW2+fmbgZO4wIR2MRm3irIQcsO2RA0Qe3mf9EOajGRuEycuXEiaDky
vdlXTfjrc0Kfu1BfVkJjtqR68G80cfRDIrgSL4Km/fCinFC/GU9JEs7CTUy25hAafYIy8hhl2IEy2Iwy
0IzacRaq1kNNClizdEHjPhiw4nFcRClKFLukWZvG1PWVuI0GPMVr8LYb8XZcRvX/gqEH0HZSskmPEbyu
w9N+CaV41bS9/Qx86oQPdhh1EOwuwesw4bGdY7LvPoHhNgIlq5nIS5gl0DLoyIF3LfgbDjBhFap348uL
Q5EDyrVEgvZT+Htv4ytYiit/WYzAfh6lIgl1bBB/xQYmi1YQqkomVJmMapbLswhN2ajfX+ErW8dU+Vpc
eUtiBRcIPDpBoKcU99V4uJf1p2Va+2q3QE8hSvcN3PkJUL9r5g6kXW8sUoKRqSE7vlupBCUTrJl6u3SB
PNWfb/GWbyQQ2Z/pgjaJ9XsI91sIjr1H+fgUVeYh/KVrFs8Itp6O1B2RR+fAdhzupEHDXnw3U3GVpuAq
+w/y3l2wnHCNxMrhGIGMcp2WpkyYWeqcC30Co5OYu0gvwZIRtc4b606cpoUYtF9y3BgvNkFSmhcSO25a
TGCkk99shOQwl9bXawAAAABJRU5ErkJggg==
</value>
</data>
<data name="BTT_PLS_ITEM_EDIT.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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
AAAASUVORK5CYII=
</value>
</data>
<data name="BTT_PLS_ITEM_EDIT_FULL.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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
AAAASUVORK5CYII=
</value> </value>
</data> </data>
<data name="BTT_OPEN_IN_BROWSER.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="BTT_OPEN_IN_BROWSER.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">

View File

@@ -23,6 +23,8 @@ Namespace DownloadObjects.STDownloader
Public Event DownloadAgain As MediaItemEventHandler Public Event DownloadAgain As MediaItemEventHandler
Public Event DownloadRequested As MediaItemEventHandler Public Event DownloadRequested As MediaItemEventHandler
Public Event CheckedChanged As MediaItemEventHandler Public Event CheckedChanged As MediaItemEventHandler
Public Event BeforeOpenEditor As MediaItemEventHandler
Public Event BeforeOpenEditorFull As MediaItemEventHandler
#End Region #End Region
#Region "Declarations" #Region "Declarations"
#Region "Controls" #Region "Controls"
@@ -51,8 +53,8 @@ Namespace DownloadObjects.STDownloader
ControlInvokeFast(CH_CHECKED, Sub() CH_CHECKED.Checked = _Checked, EDP.None) ControlInvokeFast(CH_CHECKED, Sub() CH_CHECKED.Checked = _Checked, EDP.None)
End Set End Set
End Property End Property
<Browsable(False)> Public Property IgnoreDownloadState As Boolean = False
Private ReadOnly FileOption As SFO = SFO.File Private ReadOnly FileOption As SFO = SFO.File
Private ReadOnly ContainerHasElements As Boolean = False
#End Region #End Region
#Region "Initializers" #Region "Initializers"
Public Sub New() Public Sub New()
@@ -111,16 +113,18 @@ Namespace DownloadObjects.STDownloader
.ContextMenuStrip = CONTEXT_MAIN .ContextMenuStrip = CONTEXT_MAIN
} }
End Sub End Sub
Public Sub New(ByVal Container As IYouTubeMediaContainer) Public Sub New(ByVal Container As IYouTubeMediaContainer, Optional ByVal HasElements As Boolean = False)
Me.New Me.New
Const d$ = " " & ChrW(183) & " " Const d$ = " " & ChrW(183) & " "
MyContainer = Container MyContainer = Container
ContainerHasElements = HasElements
With MyContainer With MyContainer
.Progress = MyProgress .Progress = MyProgress
If HasElements Then BTT_PLS_ITEM_EDIT.Visible = True : BTT_PLS_ITEM_EDIT_FULL.Visible = True : SEP_PLS_ITEM_EDIT.Visible = True
If .HasElements Then FileOption = SFO.Path Else FileOption = SFO.File If .HasElements Then FileOption = SFO.Path Else FileOption = SFO.File
If .DownloadState = Plugin.UserMediaStates.Downloaded AndAlso If .DownloadState = Plugin.UserMediaStates.Downloaded AndAlso
(.ObjectType = Base.YouTubeMediaType.Channel Or .ObjectType = Base.YouTubeMediaType.PlayList) AndAlso FileOption = SFO.File AndAlso (.ObjectType = Base.YouTubeMediaType.Channel Or .ObjectType = Base.YouTubeMediaType.PlayList) AndAlso FileOption = SFO.File AndAlso
Not .File.Exists AndAlso .File.Exists(SFO.Path, False) Then FileOption = SFO.Path Not .File.Exists AndAlso .File.Exists(SFO.Path, False) Then FileOption = SFO.Path : BTT_OPEN_FILE.Visible = False
If Not .SiteKey = YouTubeSiteKey Then If Not .SiteKey = YouTubeSiteKey Then
BTT_DOWN_AGAIN.Visible = False BTT_DOWN_AGAIN.Visible = False
SEP_DOWN_AGAIN.Visible = False SEP_DOWN_AGAIN.Visible = False
@@ -224,11 +228,17 @@ Namespace DownloadObjects.STDownloader
.Controls.Clear() .Controls.Clear()
.ColumnStyles.Clear() .ColumnStyles.Clear()
.ColumnCount = 0 .ColumnCount = 0
If IgnoreDownloadState Or MyContainer.MediaState = Plugin.UserMediaStates.Downloaded Then If ContainerHasElements Or MyContainer.MediaState = Plugin.UserMediaStates.Downloaded Then
If Not MyContainer.SiteKey = YouTubeSiteKey Then UpdateMediaIcon() If Not MyContainer.SiteKey = YouTubeSiteKey Then UpdateMediaIcon()
If IgnoreDownloadState Then If ContainerHasElements Then
BTT_OPEN_FOLDER.Visible = False BTT_OPEN_FOLDER.Visible = False
BTT_OPEN_FILE.Visible = False
SEP_FOLDER.Visible = False SEP_FOLDER.Visible = False
If Not ContainerHasElements Then
BTT_PLS_ITEM_EDIT.Visible = False
BTT_PLS_ITEM_EDIT_FULL.Visible = False
SEP_PLS_ITEM_EDIT.Visible = False
End If
BTT_DOWN_AGAIN.Visible = False BTT_DOWN_AGAIN.Visible = False
SEP_DOWN_AGAIN.Visible = False SEP_DOWN_AGAIN.Visible = False
BTT_REMOVE_FROM_LIST.Visible = False BTT_REMOVE_FROM_LIST.Visible = False
@@ -369,7 +379,7 @@ Namespace DownloadObjects.STDownloader
ICON_WHAT.DoubleClick, LBL_TIME.DoubleClick, ICON_SIZE.DoubleClick, LBL_INFO.DoubleClick, ICON_WHAT.DoubleClick, LBL_TIME.DoubleClick, ICON_SIZE.DoubleClick, LBL_INFO.DoubleClick,
LBL_PROGRESS.DoubleClick, PR_MAIN.DoubleClick LBL_PROGRESS.DoubleClick, PR_MAIN.DoubleClick
Controls_Click(sender, e) Controls_Click(sender, e)
If Not IgnoreDownloadState AndAlso Not MyDownloaderSettings.OnItemDoubleClick = DoubleClickBehavior.None Then If Not ContainerHasElements AndAlso Not MyDownloaderSettings.OnItemDoubleClick = DoubleClickBehavior.None Then
Dim m As New MMessage("The specified path was not found.", "Open file/folder",, vbExclamation) Dim m As New MMessage("The specified path was not found.", "Open file/folder",, vbExclamation)
If MyDownloaderSettings.OnItemDoubleClick = DoubleClickBehavior.File Then If MyDownloaderSettings.OnItemDoubleClick = DoubleClickBehavior.File Then
If FileOption = SFO.File And MyContainer.File.Exists(SFO.File, False) Then If FileOption = SFO.File And MyContainer.File.Exists(SFO.File, False) Then
@@ -405,6 +415,27 @@ Namespace DownloadObjects.STDownloader
Private Sub BTT_OPEN_FOLDER_Click(sender As Object, e As EventArgs) Handles BTT_OPEN_FOLDER.Click Private Sub BTT_OPEN_FOLDER_Click(sender As Object, e As EventArgs) Handles BTT_OPEN_FOLDER.Click
If MyContainer.File.Exists(FileOption, False) Then GlobalOpenPath(MyContainer.File) If MyContainer.File.Exists(FileOption, False) Then GlobalOpenPath(MyContainer.File)
End Sub End Sub
Private Sub BTT_OPEN_FILE_Click(sender As Object, e As EventArgs) Handles BTT_OPEN_FILE.Click
If MyContainer.File.Exists(SFO.File) Then MyContainer.File.Open(,, EDP.ShowAllMsg)
End Sub
Private Sub BTT_PLS_ITEM_EDIT_Click(sender As Object, e As EventArgs) Handles BTT_PLS_ITEM_EDIT.Click, BTT_PLS_ITEM_EDIT_FULL.Click
If ContainerHasElements Then
With DirectCast(MyContainer, YouTubeMediaContainerBase)
Dim initProtected As Boolean = .Protected
Dim isFull As Boolean = sender Is BTT_PLS_ITEM_EDIT_FULL
.Protected = False
If isFull Then
RaiseEvent BeforeOpenEditorFull(Me, MyContainer)
Else
RaiseEvent BeforeOpenEditor(Me, MyContainer)
End If
Using f As New VideoOptionsForm(MyContainer, initProtected Or isFull)
f.ShowDialog()
.Protected = IIf(f.DialogResult = DialogResult.OK, True, initProtected)
End Using
End With
End If
End Sub
Private Sub BTT_COPY_LINK_Click(sender As Object, e As EventArgs) Handles BTT_COPY_LINK.Click Private Sub BTT_COPY_LINK_Click(sender As Object, e As EventArgs) Handles BTT_COPY_LINK.Click
If Not MyContainer.URL.IsEmptyString Then If Not MyContainer.URL.IsEmptyString Then
BufferText = MyContainer.URL BufferText = MyContainer.URL

View File

@@ -32,6 +32,6 @@ Imports System.Runtime.InteropServices
' by using the '*' as shown below: ' by using the '*' as shown below:
' <Assembly: AssemblyVersion("1.0.*")> ' <Assembly: AssemblyVersion("1.0.*")>
<Assembly: AssemblyVersion("2023.12.14.0")> <Assembly: AssemblyVersion("2024.2.25.0")>
<Assembly: AssemblyFileVersion("2023.12.14.0")> <Assembly: AssemblyFileVersion("2024.2.25.0")>
<Assembly: NeutralResourcesLanguage("en")> <Assembly: NeutralResourcesLanguage("en")>

View File

@@ -139,22 +139,26 @@ Namespace API.YouTube.Objects
#End Region #End Region
#Region "Data info" #Region "Data info"
Friend ReadOnly Property MediaObjects As List(Of MediaObject) Implements IYouTubeMediaContainer.MediaObjects Friend ReadOnly Property MediaObjects As List(Of MediaObject) Implements IYouTubeMediaContainer.MediaObjects
Friend Property [Protected] As Boolean = False
Friend Property IsAudioSelected As Boolean = False
#Region "Array" #Region "Array"
''' <summary>[-10] = disabled; [-1] = max; [-2] = audio only</summary> ''' <summary>[-10] = disabled; [-1] = max; [-2] = audio only</summary>
<XMLEC> Friend Property ArrayMaxResolution As Integer = -10 <XMLEC> Friend Property ArrayMaxResolution As Integer = -10
''' <param name="Value">[-1] = max; [-2] = audio only</param> ''' <param name="Value">[-1] = max; [-2] = audio only</param>
Friend Sub SetMaxResolution(ByVal Value As Integer) Friend Sub SetMaxResolution(ByVal Value As Integer)
ArrayMaxResolution = Value If Not [Protected] Then
SelectedVideoIndex = -1 ArrayMaxResolution = Value
If MediaObjects.Count > 0 And Value <> -2 Then SelectedVideoIndex = -1
If Value = -1 Then If MediaObjects.Count > 0 And Value <> -2 Then
SelectedVideoIndex = MediaObjects.FindIndex(Function(mo) mo.Type = UMTypes.Video) If Value = -1 Then
Else SelectedVideoIndex = MediaObjects.FindIndex(Function(mo) mo.Type = UMTypes.Video)
SelectedVideoIndex = MediaObjects.FindIndex(Function(mo) mo.Type = UMTypes.Video And mo.Height <= Value) Else
If SelectedVideoIndex = -1 Then SelectedVideoIndex = MediaObjects.FindIndex(Function(mo) mo.Type = UMTypes.Video) SelectedVideoIndex = MediaObjects.FindIndex(Function(mo) mo.Type = UMTypes.Video And mo.Height <= Value)
If SelectedVideoIndex = -1 Then SelectedVideoIndex = MediaObjects.FindIndex(Function(mo) mo.Type = UMTypes.Video)
End If
End If End If
If HasElements Then Elements.ForEach(Sub(e As YouTubeMediaContainerBase) e.SetMaxResolution(Value))
End If End If
If HasElements Then Elements.ForEach(Sub(e As YouTubeMediaContainerBase) e.SetMaxResolution(Value))
End Sub End Sub
#End Region #End Region
#Region "Thumbnails" #Region "Thumbnails"
@@ -213,8 +217,22 @@ Namespace API.YouTube.Objects
Return _OutputVideoExtension Return _OutputVideoExtension
End Get End Get
Set(ByVal _OutputVideoExtension As String) Set(ByVal _OutputVideoExtension As String)
Me._OutputVideoExtension = _OutputVideoExtension If Not [Protected] Then
If HasElements Then Elements.ForEach(Sub(e) e.OutputVideoExtension = _OutputVideoExtension) Me._OutputVideoExtension = _OutputVideoExtension
If HasElements Then Elements.ForEach(Sub(e) e.OutputVideoExtension = _OutputVideoExtension)
End If
End Set
End Property
<XMLEC("OutputVideoFPS")> Protected _OutputVideoFPS As Double = -1
Friend Property OutputVideoFPS As Double
Get
Return _OutputVideoFPS
End Get
Set(ByVal fps As Double)
If Not [Protected] Then
_OutputVideoFPS = fps
If HasElements Then Elements.ForEach(Sub(elem) DirectCast(elem, YouTubeMediaContainerBase).OutputVideoFPS = fps)
End If
End Set End Set
End Property End Property
#End Region #End Region
@@ -231,8 +249,10 @@ Namespace API.YouTube.Objects
Return _OutputAudioCodec Return _OutputAudioCodec
End Get End Get
Set(ByVal _OutputAudioCodec As String) Set(ByVal _OutputAudioCodec As String)
Me._OutputAudioCodec = _OutputAudioCodec If Not [Protected] Then
If HasElements Then Elements.ForEach(Sub(e) e.OutputAudioCodec = _OutputAudioCodec) Me._OutputAudioCodec = _OutputAudioCodec
If HasElements Then Elements.ForEach(Sub(e) e.OutputAudioCodec = _OutputAudioCodec)
End If
End Set End Set
End Property End Property
<XMLEC(CollectionMode:=CollectionModes.String)> <XMLEC(CollectionMode:=CollectionModes.String)>
@@ -272,8 +292,10 @@ Namespace API.YouTube.Objects
Return _OutputSubtitlesFormat Return _OutputSubtitlesFormat
End Get End Get
Set(ByVal _OutputSubtitlesFormat As String) Set(ByVal _OutputSubtitlesFormat As String)
Me._OutputSubtitlesFormat = _OutputSubtitlesFormat If Not [Protected] Then
If HasElements Then Elements.ForEach(Sub(e) e.OutputSubtitlesFormat = _OutputSubtitlesFormat) Me._OutputSubtitlesFormat = _OutputSubtitlesFormat
If HasElements Then Elements.ForEach(Sub(e) e.OutputSubtitlesFormat = _OutputSubtitlesFormat)
End If
End Set End Set
End Property End Property
<XMLEC(CollectionMode:=CollectionModes.String)> <XMLEC(CollectionMode:=CollectionModes.String)>
@@ -555,8 +577,10 @@ Namespace API.YouTube.Objects
Return _AbsolutePath Return _AbsolutePath
End Get End Get
Set(ByVal ap As Boolean) Set(ByVal ap As Boolean)
_AbsolutePath = ap If Not [Protected] Then
If Elements.Count > 0 Then Elements.ForEach(Sub(e As YouTubeMediaContainerBase) e.AbsolutePath = ap) _AbsolutePath = ap
If Elements.Count > 0 Then Elements.ForEach(Sub(e As YouTubeMediaContainerBase) e.AbsolutePath = ap)
End If
End Set End Set
End Property End Property
Public Overridable Property File As SFile Implements IYouTubeMediaContainer.File Public Overridable Property File As SFile Implements IYouTubeMediaContainer.File
@@ -564,28 +588,30 @@ Namespace API.YouTube.Objects
Return _File Return _File
End Get End Get
Set(ByVal f As SFile) Set(ByVal f As SFile)
Select Case ObjectType If Not [Protected] Then
Case YouTubeMediaType.Channel : _File = f.Path Select Case ObjectType
Case YouTubeMediaType.PlayList Case YouTubeMediaType.Channel : _File = f.Path
If AbsolutePath Then Case YouTubeMediaType.PlayList
_File.Path = f.Path If AbsolutePath Then
Else _File.Path = f.Path
_File.Path = $"{f.PathWithSeparator}{GetPlayListTitle()}" Else
End If _File.Path = $"{f.PathWithSeparator}{GetPlayListTitle()}"
Case YouTubeMediaType.Single End If
If PlaylistCount > 0 And Not FileIgnorePlaylist Then Case YouTubeMediaType.Single
_File.Path = f.Path If PlaylistCount > 0 And Not FileIgnorePlaylist Then
Dim pls$ = If(AbsolutePath, String.Empty, GetPlayListTitle()) _File.Path = f.Path
If Not _File.Path.Contains(pls) Then _File.Path = $"{_File.PathWithSeparator(Not pls.IsEmptyString)}{pls}" Dim pls$ = If(AbsolutePath, String.Empty, GetPlayListTitle())
ElseIf Not f.Name.IsEmptyString Then If Not _File.Path.Contains(pls) Then _File.Path = $"{_File.PathWithSeparator(Not pls.IsEmptyString)}{pls}"
_File = f ElseIf Not f.Name.IsEmptyString Then
Else _File = f
_File.Path = f.Path Else
End If _File.Path = f.Path
Case Else : _File = f End If
End Select Case Else : _File = f
GenerateFileName() End Select
If HasElements Then Elements.ForEach(Sub(e) e.File = _File) GenerateFileName()
If HasElements Then Elements.ForEach(Sub(e) e.File = _File)
End If
End Set End Set
End Property End Property
Public Property FileSettings As SFile Public Property FileSettings As SFile
@@ -614,6 +640,7 @@ Namespace API.YouTube.Objects
If Not File.IsEmptyString Then If Not File.IsEmptyString Then
If File.Exists Then File = SFile.IndexReindex(File) If File.Exists Then File = SFile.IndexReindex(File)
Dim cmd$ = String.Empty, formats$ = String.Empty, subs$ = String.Empty, remux$ = String.Empty Dim cmd$ = String.Empty, formats$ = String.Empty, subs$ = String.Empty, remux$ = String.Empty
Dim embedThumbArgAdded As Boolean = False
_Size = 0 _Size = 0
Height = 0 Height = 0
Bitrate = 0 Bitrate = 0
@@ -626,6 +653,10 @@ Namespace API.YouTube.Objects
_MediaType = UMTypes.Video _MediaType = UMTypes.Video
Height = SelectedVideo.Height Height = SelectedVideo.Height
_File.Extension = OutputVideoExtension _File.Extension = OutputVideoExtension
If Not embedThumbArgAdded And MyYouTubeSettings.DefaultVideoEmbedThumbnail Then
formats.StringAppend("--embed-thumbnail", " ")
embedThumbArgAdded = True
End If
Else Else
formats.StringAppend("--extract-audio", " ") formats.StringAppend("--extract-audio", " ")
_MediaType = UMTypes.Audio _MediaType = UMTypes.Audio
@@ -643,7 +674,13 @@ Namespace API.YouTube.Objects
formats.StringAppend($"--audio-format {OutputAudioCodec.StringToLower}", " ") formats.StringAppend($"--audio-format {OutputAudioCodec.StringToLower}", " ")
atCodec = OutputAudioCodec.StringToLower atCodec = OutputAudioCodec.StringToLower
End If End If
If SelectedVideoIndex = -1 Then formats.StringAppend("--add-metadata", " ") If SelectedVideoIndex = -1 Then
formats.StringAppend("--add-metadata", " ")
If Not embedThumbArgAdded And MyYouTubeSettings.DefaultAudioEmbedThumbnail Then
formats.StringAppend("--embed-thumbnail", " ")
embedThumbArgAdded = True
End If
End If
_Size += SelectedAudio.Size _Size += SelectedAudio.Size
If _MediaType = UMTypes.Undefined Then _MediaType = UMTypes.Audio If _MediaType = UMTypes.Undefined Then _MediaType = UMTypes.Audio
Bitrate = SelectedAudio.Bitrate Bitrate = SelectedAudio.Bitrate
@@ -1026,6 +1063,16 @@ Namespace API.YouTube.Objects
If fAacAudio.Exists And Not aacRequested Then fAacAudio.Delete() If fAacAudio.Exists And Not aacRequested Then fAacAudio.Delete()
If fAc3Audio.Exists And Not ac3Requested And SelectedVideoIndex >= 0 Then fAc3Audio.Delete() If fAc3Audio.Exists And Not ac3Requested And SelectedVideoIndex >= 0 Then fAc3Audio.Delete()
End If End If
If SelectedVideoIndex >= 0 AndAlso OutputVideoFPS > 0 AndAlso SelectedVideo.Bitrate > OutputVideoFPS Then
f = File
f.Name &= "tmp00"
.Execute($"ffmpeg -i ""{File}"" -filter:v fps={OutputVideoFPS.ToString.Replace(",", ".")} -c:a copy ""{f}""")
If f.Exists Then
File.Delete()
SFile.Rename(f, File,, EDP.LogMessageValue)
End If
End If
End If End If
End If End If
End With End With

View File

@@ -32,6 +32,6 @@ Imports System.Runtime.InteropServices
' by using the '*' as shown below: ' by using the '*' as shown below:
' <Assembly: AssemblyVersion("1.0.*")> ' <Assembly: AssemblyVersion("1.0.*")>
<Assembly: AssemblyVersion("2023.12.14.0")> <Assembly: AssemblyVersion("2024.2.25.0")>
<Assembly: AssemblyFileVersion("2023.12.14.0")> <Assembly: AssemblyFileVersion("2024.2.25.0")>
<Assembly: NeutralResourcesLanguage("en")> <Assembly: NeutralResourcesLanguage("en")>

View File

@@ -47,7 +47,7 @@ Namespace API.Base
Progress.InformationTemporary = $"{HOST.Name} ({c - s}/{c}) Images: {_TotalImages}; Videos: {_TotalVideos}" Progress.InformationTemporary = $"{HOST.Name} ({c - s}/{c}) Images: {_TotalImages}; Videos: {_TotalVideos}"
End If End If
End If End If
If _FeedDataExists Then Downloader.Files.Sort() If _FeedDataExists Then Downloader.Files.Sort() : Downloader.FilesSave()
End Sub End Sub
Private Overloads Sub Download(ByVal Host As SettingsHost, ByVal Number As Integer, ByVal Count As Integer, Private Overloads Sub Download(ByVal Host As SettingsHost, ByVal Number As Integer, ByVal Count As Integer,
ByVal Token As CancellationToken, ByVal Multiple As Boolean) ByVal Token As CancellationToken, ByVal Multiple As Boolean)

View File

@@ -23,6 +23,7 @@ Imports PersonalUtilities.Tools.Web.Clients
Imports PersonalUtilities.Tools.ImageRenderer Imports PersonalUtilities.Tools.ImageRenderer
Imports UStates = SCrawler.API.Base.UserMedia.States Imports UStates = SCrawler.API.Base.UserMedia.States
Imports UTypes = SCrawler.API.Base.UserMedia.Types Imports UTypes = SCrawler.API.Base.UserMedia.Types
Imports CookieUpdateModes = PersonalUtilities.Tools.Web.Cookies.CookieKeeper.UpdateModes
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"
@@ -205,7 +206,7 @@ Namespace API.Base
If Not h Is Nothing Then _HostKey = h.Key If Not h Is Nothing Then _HostKey = h.Key
End Set End Set
End Property End Property
Private Sub ResetHost() Friend Sub ResetHost()
_HostObtained = False _HostObtained = False
End Sub End Sub
Friend Property HostStatic As Boolean = False Implements IUserData.HostStatic Friend Property HostStatic As Boolean = False Implements IUserData.HostStatic
@@ -1150,6 +1151,8 @@ BlockNullPicture:
Private _EnvirChanged As Boolean = False Private _EnvirChanged As Boolean = False
Private _PictureExists As Boolean Private _PictureExists As Boolean
Private _EnvirInvokeUserUpdated As Boolean = False Private _EnvirInvokeUserUpdated As Boolean = False
Protected _ResponserAutoUpdateCookies As Boolean = False
Protected _ResponserAddResponseReceivedHandler As Boolean = False
Protected Sub EnvirDownloadSet() Protected Sub EnvirDownloadSet()
TokenPersonal = Nothing TokenPersonal = Nothing
ProgressPre.Reset() ProgressPre.Reset()
@@ -1191,7 +1194,14 @@ BlockNullPicture:
If Not Responser Is Nothing Then Responser.Dispose() If Not Responser Is Nothing Then Responser.Dispose()
Responser = New Responser Responser = New Responser
If Not HOST.Responser Is Nothing Then Responser.Copy(HOST.Responser) If Not HOST.Responser Is Nothing Then Responser.Copy(HOST.Responser)
If Not Responser Is Nothing And _ResponserAutoUpdateCookies Then
If _ResponserAutoUpdateCookies Then
Responser.CookiesUpdateMode = CookieUpdateModes.ReplaceByNameAll
Responser.CookiesExtractMode = Responser.CookiesExtractModes.Any
Responser.CookiesExtractedAutoSave = False
End If
If _ResponserAddResponseReceivedHandler Then AddHandler Responser.ResponseReceived, AddressOf Responser_ResponseReceived
End If
Responser.DecodersError = New ErrorsDescriber(EDP.SendToLog + EDP.ReturnValue) With { Responser.DecodersError = New ErrorsDescriber(EDP.SendToLog + EDP.ReturnValue) With {
.DeclaredMessage = New MMessage($"SymbolsConverter error: [{ToStringForLog()}]", ToStringForLog())} .DeclaredMessage = New MMessage($"SymbolsConverter error: [{ToStringForLog()}]", ToStringForLog())}
@@ -1284,9 +1294,9 @@ BlockNullPicture:
Catch exit_ex As ExitException Catch exit_ex As ExitException
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 canceled (exit) ({exit_ex.Message})" MyMainLOG = $"{ToStringForLog()}: downloading interrupted (exit) ({exit_ex.Message})"
Else Else
ErrorsDescriber.Execute(EDP.SendToLog, exit_ex, $"{ToStringForLog()}: downloading canceled (exit)") ErrorsDescriber.Execute(EDP.SendToLog, exit_ex, $"{ToStringForLog()}: downloading interrupted (exit)")
End If End If
End If End If
Canceled = True Canceled = True
@@ -1311,6 +1321,7 @@ BlockNullPicture:
ProgressPre.Done() ProgressPre.Done()
__DOWNLOAD_IN_PROGRESS = False __DOWNLOAD_IN_PROGRESS = False
OnUserDownloadStateChanged(False) OnUserDownloadStateChanged(False)
If _ResponserAddResponseReceivedHandler Then Responser_ResponseReceived_RemoveHandler()
End Try End Try
End Sub End Sub
Protected Sub UpdateDataFiles() Protected Sub UpdateDataFiles()
@@ -1333,6 +1344,13 @@ BlockNullPicture:
End If End If
End Sub End Sub
Protected MustOverride Sub DownloadDataF(ByVal Token As CancellationToken) Protected MustOverride Sub DownloadDataF(ByVal Token As CancellationToken)
Protected Overridable Sub Responser_ResponseReceived(ByVal Sender As Object, ByVal e As EventArguments.WebDataResponse)
End Sub
Protected Sub Responser_ResponseReceived_RemoveHandler()
If Not Responser Is Nothing And _ResponserAddResponseReceivedHandler And Not Disposed Then
Try : RemoveHandler Responser.ResponseReceived, AddressOf Responser_ResponseReceived : Catch : End Try
End If
End Sub
Protected Function CreateCache() As CacheKeeper Protected Function CreateCache() As CacheKeeper
Dim Cache As New CacheKeeper($"{DownloadContentDefault_GetRootDir()}\_tCache\") Dim Cache As New CacheKeeper($"{DownloadContentDefault_GetRootDir()}\_tCache\")
Cache.CacheDeleteError = CacheDeletionError(Cache) Cache.CacheDeleteError = CacheDeletionError(Cache)
@@ -1403,7 +1421,7 @@ BlockNullPicture:
End If End If
ff.Name &= "_thumb" ff.Name &= "_thumb"
ff.Extension = "jpg" ff.Extension = "jpg"
f = Web.FFMPEG.TakeSnapshot(f, ff, Settings.FfmpegFile, TimeSpan.FromSeconds(1),,, EDP.LogMessageValue) f = Web.FFMPEG.TakeSnapshot(f, ff, Settings.FfmpegFile, TimeSpan.FromSeconds(1),,, EDP.SendToLog + EDP.ReturnValue)
If f.Exists Then DirectCast(Data, IDownloadableMedia).ThumbnailFile = f If f.Exists Then DirectCast(Data, IDownloadableMedia).ThumbnailFile = f
End If End If
Else Else
@@ -2057,7 +2075,7 @@ BlockNullPicture:
End Function End Function
Private Class FilesCopyingException : Inherits ErrorsDescriberException Private Class FilesCopyingException : Inherits ErrorsDescriberException
Friend Sub New(ByVal User As IUserData, ByVal Msg As String, ByVal Path As SFile) Friend Sub New(ByVal User As IUserData, ByVal Msg As String, ByVal Path As SFile)
SendInLogOnlyMessage = True SendToLogOnlyMessage = True
If User.IncludedInCollection Then _MainMessage = $"[{User.CollectionName}] - " If User.IncludedInCollection Then _MainMessage = $"[{User.CollectionName}] - "
_MainMessage &= $"[{User.Site}] - [{User.Name}]. {Msg}: {Path.Path}." _MainMessage &= $"[{User.Site}] - [{User.Name}]. {Msg}: {Path.Path}."
End Sub End Sub
@@ -2181,18 +2199,20 @@ BlockNullPicture:
End Sub End Sub
#End Region #End Region
#Region "IComparable Support" #Region "IComparable Support"
Friend Overridable Function CompareTo(ByVal Other As UserDataBase) As Integer Implements IComparable(Of UserDataBase).CompareTo Friend Overridable Overloads Function CompareTo(ByVal Other As UserDataBase) As Integer Implements IComparable(Of UserDataBase).CompareTo
If IsCollection Then If TypeOf Other Is UserDataBind Then
Return 1
ElseIf IsCollection Then
Return Name.CompareTo(Other.Name) Return Name.CompareTo(Other.Name)
Else Else
Return FriendlyName.IfNullOrEmpty(Name).StringTrim.CompareTo(Other.FriendlyName.IfNullOrEmpty(Other.Name).StringTrim) Return FriendlyName.IfNullOrEmpty(Name).StringTrim.CompareTo(Other.FriendlyName.IfNullOrEmpty(Other.Name).StringTrim)
End If End If
End Function End Function
Friend Overridable Function CompareTo(ByVal Obj As Object) As Integer Implements IComparable.CompareTo Friend Overridable Overloads Function CompareTo(ByVal Obj As Object) As Integer Implements IComparable.CompareTo
If Not Obj Is Nothing AndAlso TypeOf Obj Is UserDataBase Then If Not Obj Is Nothing AndAlso TypeOf Obj Is UserDataBase Then
Return CompareTo(DirectCast(Obj, UserDataBase)) Return CompareTo(DirectCast(Obj, UserDataBase))
Else Else
Return False Return 0
End If End If
End Function End Function
#End Region #End Region
@@ -2200,7 +2220,7 @@ BlockNullPicture:
Friend Overridable Overloads Function Equals(ByVal Other As UserDataBase) As Boolean Implements IEquatable(Of UserDataBase).Equals Friend Overridable Overloads Function Equals(ByVal Other As UserDataBase) As Boolean Implements IEquatable(Of UserDataBase).Equals
Return LVIKey = Other.LVIKey And IsSavedPosts = Other.IsSavedPosts Return LVIKey = Other.LVIKey And IsSavedPosts = Other.IsSavedPosts
End Function End Function
Public Overrides Function Equals(ByVal Obj As Object) As Boolean Public Overloads Overrides Function Equals(ByVal Obj As Object) As Boolean
If Not Obj Is Nothing AndAlso TypeOf Obj Is UserDataBase Then If Not Obj Is Nothing AndAlso TypeOf Obj Is UserDataBase Then
Return Equals(DirectCast(Obj, UserDataBase)) Return Equals(DirectCast(Obj, UserDataBase))
Else Else

View File

@@ -107,7 +107,23 @@ Namespace API.Facebook
End With End With
End Sub End Sub
#End Region #End Region
#Region "Initializer"
Friend Sub New()
_ResponserAutoUpdateCookies = True
End Sub
#End Region
#Region "Download functions" #Region "Download functions"
Private Class TokensException : Inherits Plugin.ExitException
Friend ReadOnly Property BasicTokens As Boolean
Public Sub New(ByVal Message As String, ByVal _BasicTokens As Boolean)
MyBase.New(Message)
BasicTokens = _BasicTokens
End Sub
Friend Shared Sub SendToLog(ByVal Source As UserData, ByVal ex As TokensException, ByVal f As String)
ErrorsDescriber.Execute(EDP.SendToLog, New ErrorsDescriberException($"{Source.ToStringForLog()} ({f}): {ex.Message}",,, ex) With {
.SendToLogOnlyMessage = True, .ReplaceMainMessage = True})
End Sub
End Class
Private Token_dtsg As String = String.Empty Private Token_dtsg As String = String.Empty
Private Token_lsd As String = String.Empty Private Token_lsd As String = String.Empty
Private Token_Photosby As String = String.Empty Private Token_Photosby As String = String.Empty
@@ -149,7 +165,7 @@ Namespace API.Facebook
Dim pid As PostKV Dim pid As PostKV
ValidateBaseTokens() ValidateBaseTokens()
If Token_Photosby.IsEmptyString Then Throw New ArgumentNullException("Token_Photosby", "Unable to obtain token") If Token_Photosby.IsEmptyString Then Throw New TokensException("Unable to obtain token 'Token_Photosby'", False)
URL = String.Format(Graphql_UrlPattern, Token_lsd, DocID_Photo, Header_fb_fr_name_Photo, URL = String.Format(Graphql_UrlPattern, Token_lsd, DocID_Photo, Header_fb_fr_name_Photo,
SymbolsConverter.ASCII.EncodeSymbolsOnly(Token_dtsg), SymbolsConverter.ASCII.EncodeSymbolsOnly(Token_dtsg),
@@ -199,6 +215,8 @@ Namespace API.Facebook
End If End If
If newPostsDetected And Not nextCursor.IsEmptyString Then DownloadData_Photo(nextCursor, Token) If newPostsDetected And Not nextCursor.IsEmptyString Then DownloadData_Photo(nextCursor, Token)
Catch tex As TokensException When Not tex.BasicTokens
TokensException.SendToLog(Me, tex, "data (photo)")
Catch ex As Exception Catch ex As Exception
ProcessException(ex, Token, $"data (photo) downloading error [{URL}]",, Responser) ProcessException(ex, Token, $"data (photo) downloading error [{URL}]",, Responser)
End Try End Try
@@ -212,7 +230,7 @@ Namespace API.Facebook
Dim pid As PostKV Dim pid As PostKV
If VideoPageID.IsEmptyString Then GetVideoPageID(Token) If VideoPageID.IsEmptyString Then GetVideoPageID(Token)
If VideoPageID.IsEmptyString Then Throw New ArgumentNullException("VideoPageID", "Unable to obtain VideoPageID") If VideoPageID.IsEmptyString Then Throw New TokensException("Unable to obtain 'VideoPageID'", False)
ValidateBaseTokens() ValidateBaseTokens()
URL = String.Format(Graphql_UrlPattern, Token_lsd, DocID_Video, Header_fb_fr_name_Video, URL = String.Format(Graphql_UrlPattern, Token_lsd, DocID_Video, Header_fb_fr_name_Video,
@@ -252,6 +270,8 @@ Namespace API.Facebook
End If End If
If newPostsDetected And Not nextCursor.IsEmptyString Then DownloadData_Video(nextCursor, Token) If newPostsDetected And Not nextCursor.IsEmptyString Then DownloadData_Video(nextCursor, Token)
Catch tex As TokensException When Not tex.BasicTokens
TokensException.SendToLog(Me, tex, "data (video)")
Catch ex As Exception Catch ex As Exception
ProcessException(ex, Token, $"data (video) downloading error [{URL}]",, Responser) ProcessException(ex, Token, $"data (video) downloading error [{URL}]",, Responser)
End Try End Try
@@ -266,7 +286,7 @@ Namespace API.Facebook
Dim postDate As Date? Dim postDate As Date?
ValidateBaseTokens() ValidateBaseTokens()
If StoryBucket.IsEmptyString Then Throw New ArgumentNullException("StoryBucket", "Unable to obtain StoryBucket") If StoryBucket.IsEmptyString Then Throw New TokensException("Unable to obtain 'StoryBucket'", False)
URL = String.Format(Graphql_UrlPattern, Token_lsd, DocID_Stories, Header_fb_fr_name_Stories, URL = String.Format(Graphql_UrlPattern, Token_lsd, DocID_Stories, Header_fb_fr_name_Stories,
SymbolsConverter.ASCII.EncodeSymbolsOnly(Token_dtsg), SymbolsConverter.ASCII.EncodeSymbolsOnly(Token_dtsg),
@@ -320,6 +340,8 @@ Namespace API.Facebook
End If End If
End Using End Using
End If End If
Catch tex As TokensException When Not tex.BasicTokens
TokensException.SendToLog(Me, tex, "data (stories)")
Catch ex As Exception Catch ex As Exception
ProcessException(ex, Token, $"data (stories) downloading error [{URL}]",, Responser) ProcessException(ex, Token, $"data (stories) downloading error [{URL}]",, Responser)
End Try End Try
@@ -467,8 +489,10 @@ Namespace API.Facebook
#Region "ValidateBaseTokens, GetVideoPageID, GetUserTokens" #Region "ValidateBaseTokens, GetVideoPageID, GetUserTokens"
''' <exception cref="ArgumentNullException"></exception> ''' <exception cref="ArgumentNullException"></exception>
Private Sub ValidateBaseTokens() Private Sub ValidateBaseTokens()
If Token_dtsg.IsEmptyString Then Throw New ArgumentNullException("Token_dtsg", "Unable to obtain token") Dim tokens$ = String.Empty
If Token_lsd.IsEmptyString Then Throw New ArgumentNullException("Token_lsd", "Unable to obtain token") If Token_dtsg.IsEmptyString Then tokens.StringAppend("Token_dtsg")
If Token_lsd.IsEmptyString Then tokens.StringAppend("Token_lsd")
If Not tokens.IsEmptyString Then Throw New TokensException($"Unable to obtain token(s) ({tokens}){vbCr}Your credentials may have expired.", True)
End Sub End Sub
Private Sub GetVideoPageID(ByVal Token As CancellationToken) Private Sub GetVideoPageID(ByVal Token As CancellationToken)
Dim URL$ = $"{GetProfileUrl()}\videos" Dim URL$ = $"{GetProfileUrl()}\videos"

View File

@@ -15,6 +15,9 @@ Namespace API.Instagram
Friend Const InstagramSite As String = "Instagram" Friend Const InstagramSite As String = "Instagram"
Friend Const InstagramSiteKey As String = "AndyProgram_Instagram" Friend Const InstagramSiteKey As String = "AndyProgram_Instagram"
Friend ReadOnly FilesPattern As RParams = RParams.DMS(".+?([^/\?]+?\.[\w\d]{3,4})(?=(\?|\Z))", 1, EDP.ReturnValue) Friend ReadOnly FilesPattern As RParams = RParams.DMS(".+?([^/\?]+?\.[\w\d]{3,4})(?=(\?|\Z))", 1, EDP.ReturnValue)
Friend ReadOnly ObtainMedia_SizeFuncPic_RegexP As RParams = RParams.DMS("_p(\d+)x(\d+)", 1, EDP.ReturnValue)
Friend ReadOnly ObtainMedia_SizeFuncPic_RegexS As RParams = RParams.DMS("_s(\d+)x(\d+)", 1, EDP.ReturnValue)
Friend Const PageTokenRegexPatternDefault As String = "\[\],{""token"":""(.*?)""},\d+\]"
Friend Sub UpdateResponser(ByVal Source As IResponse, ByRef Destination As Responser) Friend Sub UpdateResponser(ByVal Source As IResponse, ByRef Destination As Responser)
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

View File

@@ -11,6 +11,8 @@ Namespace API.Instagram
Friend Class EditorExchangeOptions Friend Class EditorExchangeOptions
<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
<PSetting(Caption:="Get reels", ToolTip:="Download user reels")>
Friend Property GetReels As Boolean
<PSetting(Caption:="Get stories", ToolTip:="Download user stories (pinned)")> <PSetting(Caption:="Get stories", ToolTip:="Download user stories (pinned)")>
Friend Property GetStories As Boolean Friend Property GetStories As Boolean
<PSetting(Caption:="Get stories: user", ToolTip:="Download user stories")> <PSetting(Caption:="Get stories: user", ToolTip:="Download user stories")>
@@ -20,6 +22,7 @@ Namespace API.Instagram
Friend Sub New(ByVal u As UserData) Friend Sub New(ByVal u As UserData)
With u With u
GetTimeline = .GetTimeline GetTimeline = .GetTimeline
GetReels = .GetReels
GetStories = .GetStories GetStories = .GetStories
GetStoriesUser = .GetStoriesUser GetStoriesUser = .GetStoriesUser
GetTagged = .GetTaggedData GetTagged = .GetTaggedData
@@ -28,6 +31,7 @@ Namespace API.Instagram
Friend Sub New(ByVal s As SiteSettings) Friend Sub New(ByVal s As SiteSettings)
With s With s
GetTimeline = CBool(.GetTimeline.Value) GetTimeline = CBool(.GetTimeline.Value)
GetReels = CBool(.GetReels.Value)
GetStories = CBool(.GetStories.Value) GetStories = CBool(.GetStories.Value)
GetStoriesUser = CBool(.GetStoriesUser.Value) GetStoriesUser = CBool(.GetStoriesUser.Value)
GetTagged = CBool(.GetTagged.Value) GetTagged = CBool(.GetTagged.Value)

View File

@@ -63,15 +63,14 @@ 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 As String = "Sec-Ch-Ua-Platform-Version" Friend Const Header_Platform As String = "Sec-Ch-Ua-Platform-Version"
<PropertyOption(ControlText:="Hash", ControlToolTip:="Instagram session hash for tagged posts", IsAuth:=True), PXML("InstaHash"), ControlNumber(0), PClonable(Clone:=False)> <PropertyOption(ControlText:="x-csrftoken", ControlToolTip:="Can be automatically extracted from cookies", IsAuth:=True, AllowNull:=True), ControlNumber(2), PClonable(Clone:=False)>
Friend ReadOnly Property HashTagged As PropertyValue
<PropertyOption(ControlText:="x-csrftoken", IsAuth:=True, AllowNull:=False), ControlNumber(2), PClonable(Clone:=False)>
Friend ReadOnly Property HH_CSRF_TOKEN As PropertyValue Friend ReadOnly Property HH_CSRF_TOKEN As PropertyValue
<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), ControlNumber(3), PClonable(Clone:=False)>
Friend Property HH_IG_APP_ID As PropertyValue Friend 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), ControlNumber(4), PClonable(Clone:=False)>
Friend Property HH_ASBD_ID As PropertyValue Friend Property HH_ASBD_ID As PropertyValue
<PropertyOption(ControlText:="x-ig-www-claim", IsAuth:=True, AllowNull:=True), ControlNumber(5), PClonable(Clone:=False)> 'PropertyOption(ControlText:="x-ig-www-claim", IsAuth:=True, AllowNull:=True)
<ControlNumber(5), PClonable(Clone:=False)>
Friend Property HH_IG_WWW_CLAIM As PropertyValue Friend Property HH_IG_WWW_CLAIM As PropertyValue
<PropertyOption(ControlText:="sec-ch-ua", IsAuth:=True, AllowNull:=True), ControlNumber(6), PClonable> <PropertyOption(ControlText:="sec-ch-ua", IsAuth:=True, AllowNull:=True), ControlNumber(6), PClonable>
Private Property HH_BROWSER As PropertyValue Private Property HH_BROWSER As PropertyValue
@@ -123,11 +122,13 @@ Namespace API.Instagram
Private ReadOnly Property SleepTimerOnPostsLimitProvider As IFormatProvider Private ReadOnly Property SleepTimerOnPostsLimitProvider As IFormatProvider
<PropertyOption(ControlText:="Get timeline", ControlToolTip:="Default value for new users"), PXML, ControlNumber(23), PClonable> <PropertyOption(ControlText:="Get timeline", ControlToolTip:="Default value for new users"), PXML, ControlNumber(23), PClonable>
Friend ReadOnly Property GetTimeline As PropertyValue Friend ReadOnly Property GetTimeline As PropertyValue
<PropertyOption(ControlText:="Get stories", ControlToolTip:="Default value for new users"), PXML, ControlNumber(24), PClonable> <PropertyOption(ControlText:="Get reels", ControlToolTip:="Default value for new users"), PXML, ControlNumber(24), PClonable>
Friend ReadOnly Property GetReels As PropertyValue
<PropertyOption(ControlText:="Get stories", ControlToolTip:="Default value for new users"), PXML, ControlNumber(25), PClonable>
Friend ReadOnly Property GetStories As PropertyValue Friend ReadOnly Property GetStories As PropertyValue
<PropertyOption(ControlText:="Get stories: user", ControlToolTip:="Default value for new users"), PXML, ControlNumber(25), PClonable> <PropertyOption(ControlText:="Get stories: user", ControlToolTip:="Default value for new users"), PXML, ControlNumber(26), PClonable>
Friend ReadOnly Property GetStoriesUser As PropertyValue Friend ReadOnly Property GetStoriesUser As PropertyValue
<PropertyOption(ControlText:="Get tagged photos", ControlToolTip:="Default value for new users"), PXML, ControlNumber(26), PClonable> <PropertyOption(ControlText:="Get tagged photos", ControlToolTip:="Default value for new users"), PXML, ControlNumber(27), PClonable>
Friend ReadOnly Property GetTagged As PropertyValue Friend ReadOnly Property GetTagged As PropertyValue
<PropertyOption(ControlText:="Tagged notify limit", <PropertyOption(ControlText:="Tagged notify limit",
ControlToolTip:="If the number of tagged posts exceeds this number you will be notified." & vbCr & ControlToolTip:="If the number of tagged posts exceeds this number you will be notified." & vbCr &
@@ -139,11 +140,13 @@ Namespace API.Instagram
#Region "Download ready" #Region "Download ready"
<PropertyOption(ControlText:="Download timeline", ControlToolTip:="Download timeline"), PXML, ControlNumber(10), PClonable> <PropertyOption(ControlText:="Download timeline", ControlToolTip:="Download timeline"), PXML, ControlNumber(10), PClonable>
Friend ReadOnly Property DownloadTimeline As PropertyValue Friend ReadOnly Property DownloadTimeline As PropertyValue
<PropertyOption(ControlText:="Download stories", ControlToolTip:="Download stories"), PXML, ControlNumber(11), PClonable> <PropertyOption(ControlText:="Download reels", ControlToolTip:="Download reels"), PXML, ControlNumber(11), PClonable>
Friend ReadOnly Property DownloadReels As PropertyValue
<PropertyOption(ControlText:="Download stories", ControlToolTip:="Download stories"), PXML, ControlNumber(12), PClonable>
Friend ReadOnly Property DownloadStories As PropertyValue Friend ReadOnly Property DownloadStories As PropertyValue
<PropertyOption(ControlText:="Download stories: user", ControlToolTip:="Download stories (user)"), PXML, ControlNumber(12), PClonable> <PropertyOption(ControlText:="Download stories: user", ControlToolTip:="Download stories (user)"), PXML, ControlNumber(13), PClonable>
Friend ReadOnly Property DownloadStoriesUser As PropertyValue Friend ReadOnly Property DownloadStoriesUser As PropertyValue
<PropertyOption(ControlText:="Download tagged", ControlToolTip:="Download tagged posts"), PXML, ControlNumber(13), PClonable> <PropertyOption(ControlText:="Download tagged", ControlToolTip:="Download tagged posts"), PXML, ControlNumber(14), PClonable>
Friend ReadOnly Property DownloadTagged As PropertyValue Friend ReadOnly Property DownloadTagged As PropertyValue
#End Region #End Region
#Region "429 bypass" #Region "429 bypass"
@@ -236,7 +239,6 @@ Namespace API.Instagram
.CookiesExtractedAutoSave = False .CookiesExtractedAutoSave = False
End With End With
HashTagged = New PropertyValue(String.Empty, GetType(String))
HH_CSRF_TOKEN = New PropertyValue(token, GetType(String), Sub(v) ChangeResponserFields(NameOf(HH_CSRF_TOKEN), v)) HH_CSRF_TOKEN = New PropertyValue(token, GetType(String), Sub(v) ChangeResponserFields(NameOf(HH_CSRF_TOKEN), v))
HH_IG_APP_ID = New PropertyValue(app_id, GetType(String), Sub(v) ChangeResponserFields(NameOf(HH_IG_APP_ID), v)) HH_IG_APP_ID = New PropertyValue(app_id, GetType(String), Sub(v) ChangeResponserFields(NameOf(HH_IG_APP_ID), v))
HH_ASBD_ID = New PropertyValue(asbd, GetType(String), Sub(v) ChangeResponserFields(NameOf(HH_ASBD_ID), v)) HH_ASBD_ID = New PropertyValue(asbd, GetType(String), Sub(v) ChangeResponserFields(NameOf(HH_ASBD_ID), v))
@@ -247,6 +249,7 @@ Namespace API.Instagram
HH_USER_AGENT = New PropertyValue(useragent, GetType(String), Sub(v) ChangeResponserFields(NameOf(HH_USER_AGENT), v)) HH_USER_AGENT = New PropertyValue(useragent, GetType(String), Sub(v) ChangeResponserFields(NameOf(HH_USER_AGENT), v))
DownloadTimeline = New PropertyValue(True) DownloadTimeline = New PropertyValue(True)
DownloadReels = New PropertyValue(False)
DownloadStories = New PropertyValue(True) DownloadStories = New PropertyValue(True)
DownloadStoriesUser = New PropertyValue(True) DownloadStoriesUser = New PropertyValue(True)
DownloadTagged = New PropertyValue(False) DownloadTagged = New PropertyValue(False)
@@ -259,6 +262,7 @@ Namespace API.Instagram
SleepTimerOnPostsLimitProvider = New TimersChecker(10000) SleepTimerOnPostsLimitProvider = New TimersChecker(10000)
GetTimeline = New PropertyValue(True) GetTimeline = New PropertyValue(True)
GetReels = New PropertyValue(False)
GetStories = New PropertyValue(False) GetStories = New PropertyValue(False)
GetStoriesUser = New PropertyValue(False) GetStoriesUser = New PropertyValue(False)
GetTagged = New PropertyValue(False) GetTagged = New PropertyValue(False)
@@ -273,7 +277,7 @@ Namespace API.Instagram
_AllowUserAgentUpdate = False _AllowUserAgentUpdate = False
UrlPatternUser = "https://www.instagram.com/{0}/" UrlPatternUser = "https://www.instagram.com/{0}/"
UserRegex = RParams.DMS("[htps:/]{7,8}.*?instagram.com/([^/]+)", 1) UserRegex = RParams.DMS(String.Format(UserRegexDefaultPattern, "instagram.com/"), 1)
ImageVideoContains = "instagram.com" ImageVideoContains = "instagram.com"
End Sub End Sub
#End Region #End Region
@@ -349,6 +353,50 @@ Namespace API.Instagram
SkipUntilNextSession = False SkipUntilNextSession = False
End Sub End Sub
#End Region #End Region
#Region "Settings"
Private ____HH_CSRF_TOKEN As String = String.Empty
Private ____HH_IG_APP_ID As String = String.Empty
Private ____HH_ASBD_ID As String = String.Empty
Private ____HH_BROWSER As String = String.Empty
Private ____HH_BROWSER_EXT As String = String.Empty
Private ____HH_PLATFORM As String = String.Empty
Private ____HH_USER_AGENT As String = String.Empty
Private ____Cookies As CookieKeeper = Nothing
Friend Overrides Sub BeginEdit()
____HH_CSRF_TOKEN = AConvert(Of String)(HH_CSRF_TOKEN.Value, String.Empty)
____HH_IG_APP_ID = AConvert(Of String)(HH_IG_APP_ID.Value, String.Empty)
____HH_ASBD_ID = AConvert(Of String)(HH_ASBD_ID.Value, String.Empty)
____HH_BROWSER = AConvert(Of String)(HH_BROWSER.Value, String.Empty)
____HH_BROWSER_EXT = AConvert(Of String)(HH_BROWSER_EXT.Value, String.Empty)
____HH_PLATFORM = AConvert(Of String)(HH_PLATFORM.Value, String.Empty)
____HH_USER_AGENT = AConvert(Of String)(HH_USER_AGENT.Value, String.Empty)
____Cookies = Responser.Cookies.Copy
MyBase.BeginEdit()
End Sub
Friend Overrides Sub Update()
If _SiteEditorFormOpened Then
Dim vals() = {New With {.ValueOld = ____HH_CSRF_TOKEN, .ValueNew = AConvert(Of String)(HH_CSRF_TOKEN.Value, String.Empty).ToString},
New With {.ValueOld = ____HH_IG_APP_ID, .ValueNew = AConvert(Of String)(HH_IG_APP_ID.Value, String.Empty).ToString},
New With {.ValueOld = ____HH_ASBD_ID, .ValueNew = AConvert(Of String)(HH_ASBD_ID.Value, String.Empty).ToString},
New With {.ValueOld = ____HH_BROWSER, .ValueNew = AConvert(Of String)(HH_BROWSER.Value, String.Empty).ToString},
New With {.ValueOld = ____HH_BROWSER_EXT, .ValueNew = AConvert(Of String)(HH_BROWSER_EXT.Value, String.Empty).ToString},
New With {.ValueOld = ____HH_PLATFORM, .ValueNew = AConvert(Of String)(HH_PLATFORM.Value, String.Empty).ToString},
New With {.ValueOld = ____HH_USER_AGENT, .ValueNew = AConvert(Of String)(HH_USER_AGENT.Value, String.Empty).ToString}
}
If vals.Any(Function(v) Not v.ValueOld = v.ValueNew) OrElse
Not Responser.Cookies.ListEquals(____Cookies) Then HH_IG_WWW_CLAIM.Value = 0
If Responser.CookiesExists Then
Dim csrf$ = If(Responser.Cookies.FirstOrDefault(Function(c) c.Name.StringToLower = Header_CSRF_TOKEN_COOKIE)?.Value, String.Empty)
If Not csrf.IsEmptyString Then HH_CSRF_TOKEN.Value = csrf
End If
End If
MyBase.Update()
End Sub
Friend Overrides Sub EndEdit()
If _SiteEditorFormOpened Then ____Cookies.DisposeIfReady(False) : ____Cookies = Nothing
MyBase.EndEdit()
End Sub
#End Region
#Region "UserOptions, GetUserUrl, GetUserPostUrl" #Region "UserOptions, GetUserUrl, GetUserPostUrl"
Friend Overrides Sub UserOptions(ByRef Options As Object, ByVal OpenForm As Boolean) Friend Overrides Sub UserOptions(ByRef Options As Object, ByVal OpenForm As Boolean)
If Options Is Nothing OrElse Not TypeOf Options Is EditorExchangeOptions Then Options = New EditorExchangeOptions(Me) If Options Is Nothing OrElse Not TypeOf Options Is EditorExchangeOptions Then Options = New EditorExchangeOptions(Me)

View File

@@ -15,6 +15,8 @@ Imports PersonalUtilities.Functions.XML.Base
Imports PersonalUtilities.Functions.Messaging Imports PersonalUtilities.Functions.Messaging
Imports PersonalUtilities.Functions.RegularExpressions Imports PersonalUtilities.Functions.RegularExpressions
Imports PersonalUtilities.Tools.Web.Clients Imports PersonalUtilities.Tools.Web.Clients
Imports PersonalUtilities.Tools.Web.Clients.Base
Imports PersonalUtilities.Tools.Web.Documents
Imports PersonalUtilities.Tools.Web.Documents.JSON Imports PersonalUtilities.Tools.Web.Documents.JSON
Imports UTypes = SCrawler.API.Base.UserMedia.Types Imports UTypes = SCrawler.API.Base.UserMedia.Types
Imports UStates = SCrawler.API.Base.UserMedia.States Imports UStates = SCrawler.API.Base.UserMedia.States
@@ -24,6 +26,7 @@ Namespace API.Instagram
Private Const Name_LastCursor As String = "LastCursor" Private Const Name_LastCursor As String = "LastCursor"
Private Const Name_FirstLoadingDone As String = "FirstLoadingDone" Private Const Name_FirstLoadingDone As String = "FirstLoadingDone"
Private Const Name_GetTimeline As String = "GetTimeline" Private Const Name_GetTimeline As String = "GetTimeline"
Private Const Name_GetReels As String = "GetReels"
Private Const Name_GetStories As String = "GetStories" Private Const Name_GetStories As String = "GetStories"
Private Const Name_GetStoriesUser As String = "GetStoriesUser" Private Const Name_GetStoriesUser As String = "GetStoriesUser"
Private Const Name_GetTagged As String = "GetTaggedData" Private Const Name_GetTagged As String = "GetTaggedData"
@@ -66,6 +69,7 @@ Namespace API.Instagram
Return New EContainer("Post", ID, {New EAttribute(Name_Section, CInt(Section)), New EAttribute(Name_Code, Code)}) Return New EContainer("Post", ID, {New EAttribute(Name_Section, CInt(Section)), New EAttribute(Name_Code, Code)})
End Function End Function
End Structure End Structure
Friend Const Header_FB_LSD As String = "x-fb-lsd"
Private ReadOnly Property MySiteSettings As SiteSettings Private ReadOnly Property MySiteSettings As SiteSettings
Get Get
Return DirectCast(HOST.Source, SiteSettings) Return DirectCast(HOST.Source, SiteSettings)
@@ -76,6 +80,7 @@ Namespace API.Instagram
Private LastCursor As String = String.Empty Private LastCursor As String = String.Empty
Private FirstLoadingDone As Boolean = False Private FirstLoadingDone As Boolean = False
Friend Property GetTimeline As Boolean = True Friend Property GetTimeline As Boolean = True
Friend Property GetReels As Boolean = False
Friend Property GetStories As Boolean Friend Property GetStories As Boolean
Friend Property GetStoriesUser As Boolean Friend Property GetStoriesUser As Boolean
Friend Property GetTaggedData As Boolean Friend Property GetTaggedData As Boolean
@@ -94,6 +99,7 @@ Namespace API.Instagram
LastCursor = .Value(Name_LastCursor) LastCursor = .Value(Name_LastCursor)
FirstLoadingDone = .Value(Name_FirstLoadingDone).FromXML(Of Boolean)(False) FirstLoadingDone = .Value(Name_FirstLoadingDone).FromXML(Of Boolean)(False)
GetTimeline = .Value(Name_GetTimeline).FromXML(Of Boolean)(CBool(MySiteSettings.GetTimeline.Value)) GetTimeline = .Value(Name_GetTimeline).FromXML(Of Boolean)(CBool(MySiteSettings.GetTimeline.Value))
GetReels = .Value(Name_GetReels).FromXML(Of Boolean)(MySiteSettings.GetReels.Value)
GetStories = .Value(Name_GetStories).FromXML(Of Boolean)(CBool(MySiteSettings.GetStories.Value)) GetStories = .Value(Name_GetStories).FromXML(Of Boolean)(CBool(MySiteSettings.GetStories.Value))
GetStoriesUser = .Value(Name_GetStoriesUser).FromXML(Of Boolean)(MySiteSettings.GetStoriesUser.Value) GetStoriesUser = .Value(Name_GetStoriesUser).FromXML(Of Boolean)(MySiteSettings.GetStoriesUser.Value)
GetTaggedData = .Value(Name_GetTagged).FromXML(Of Boolean)(CBool(MySiteSettings.GetTagged.Value)) GetTaggedData = .Value(Name_GetTagged).FromXML(Of Boolean)(CBool(MySiteSettings.GetTagged.Value))
@@ -103,6 +109,7 @@ Namespace API.Instagram
.Add(Name_LastCursor, LastCursor) .Add(Name_LastCursor, LastCursor)
.Add(Name_FirstLoadingDone, FirstLoadingDone.BoolToInteger) .Add(Name_FirstLoadingDone, FirstLoadingDone.BoolToInteger)
.Add(Name_GetTimeline, GetTimeline.BoolToInteger) .Add(Name_GetTimeline, GetTimeline.BoolToInteger)
.Add(Name_GetReels, GetReels.BoolToInteger)
.Add(Name_GetStories, GetStories.BoolToInteger) .Add(Name_GetStories, GetStories.BoolToInteger)
.Add(Name_GetStoriesUser, GetStoriesUser.BoolToInteger) .Add(Name_GetStoriesUser, GetStoriesUser.BoolToInteger)
.Add(Name_GetTagged, GetTaggedData.BoolToInteger) .Add(Name_GetTagged, GetTaggedData.BoolToInteger)
@@ -120,6 +127,7 @@ Namespace API.Instagram
If Not Obj Is Nothing AndAlso TypeOf Obj Is EditorExchangeOptions Then If Not Obj Is Nothing AndAlso TypeOf Obj Is EditorExchangeOptions Then
With DirectCast(Obj, EditorExchangeOptions) With DirectCast(Obj, EditorExchangeOptions)
GetTimeline = .GetTimeline GetTimeline = .GetTimeline
GetReels = .GetReels
GetStories = .GetStories GetStories = .GetStories
GetStoriesUser = .GetStoriesUser GetStoriesUser = .GetStoriesUser
GetTaggedData = .GetTagged GetTaggedData = .GetTagged
@@ -131,17 +139,20 @@ Namespace API.Instagram
Friend Sub New() Friend Sub New()
PostsKVIDs = New List(Of PostKV) PostsKVIDs = New List(Of PostKV)
PostsToReparse = New List(Of PostKV) PostsToReparse = New List(Of PostKV)
_ResponserAutoUpdateCookies = True
End Sub End Sub
#End Region #End Region
#Region "Download data" #Region "Download data"
Private E560Thrown As Boolean = False Private E560Thrown As Boolean = False
Friend Err5xx As Integer = -1
Private Class ExitException : Inherits Exception Private Class ExitException : Inherits Exception
Friend Property Is560 As Boolean = False
Friend Shared Sub Throw560(ByRef Source As UserData) Friend Shared Sub Throw560(ByRef Source As UserData)
If Not Source.E560Thrown Then If Not Source.E560Thrown Then
MyMainLOG = $"{Source.ToStringForLog}: (560) Download skipped until next session" MyMainLOG = $"{Source.ToStringForLog}: ({IIf(Source.Err5xx > 0, Source.Err5xx, 560)}) Download skipped until next session"
Source.E560Thrown = True Source.E560Thrown = True
End If End If
Throw New ExitException Throw New ExitException With {.Is560 = True}
End Sub End Sub
End Class End Class
Private ReadOnly Property MyFilePostsKV As SFile Private ReadOnly Property MyFilePostsKV As SFile
@@ -229,6 +240,7 @@ 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
Try Try
Err5xx = -1
_Limit = If(DownloadTopCount, -1) _Limit = If(DownloadTopCount, -1)
_TotalPostsParsed = 0 _TotalPostsParsed = 0
LoadSavePostsKV(True) LoadSavePostsKV(True)
@@ -253,9 +265,22 @@ Namespace API.Instagram
End If End If
If FirstLoadingDone Then LastCursor = String.Empty If FirstLoadingDone Then LastCursor = String.Empty
If Not IsSavedPosts AndAlso MySiteSettings.BaseAuthExists() Then If Not IsSavedPosts AndAlso MySiteSettings.BaseAuthExists() Then
If CBool(MySiteSettings.DownloadReels.Value) And GetReels Then
s = Sections.Reels
DefaultParser_ElemNode = {"node", "media"}
DownloadData(String.Empty, s, Token)
DefaultParser_ElemNode = Nothing
DownloadReels_SetEnvir = False
ProgressPre.Done()
End If
If CBool(MySiteSettings.DownloadStories.Value) And GetStories Then s = Sections.Stories : DownloadData(String.Empty, s, Token) : ProgressPre.Done() If CBool(MySiteSettings.DownloadStories.Value) And GetStories Then s = Sections.Stories : DownloadData(String.Empty, s, Token) : ProgressPre.Done()
If CBool(MySiteSettings.DownloadStoriesUser.Value) And GetStoriesUser Then s = Sections.UserStories : DownloadData(String.Empty, s, Token) : ProgressPre.Done() If CBool(MySiteSettings.DownloadStoriesUser.Value) And GetStoriesUser Then s = Sections.UserStories : DownloadData(String.Empty, s, Token) : ProgressPre.Done()
If CBool(MySiteSettings.DownloadTagged.Value) And ACheck(MySiteSettings.HashTagged.Value) And GetTaggedData Then s = Sections.Tagged : DownloadData(String.Empty, s, Token) : ProgressPre.Done() If CBool(MySiteSettings.DownloadTagged.Value) And GetTaggedData Then
s = Sections.Tagged
DownloadData(String.Empty, s, Token)
ProgressPre.Done()
If PostsToReparse.Count > 0 Then DownloadPosts(Token, True)
End If
End If End If
If WaitNotificationMode = WNM.SkipTemp Or WaitNotificationMode = WNM.SkipCurrent Then WaitNotificationMode = WNM.Notify If WaitNotificationMode = WNM.SkipTemp Or WaitNotificationMode = WNM.SkipCurrent Then WaitNotificationMode = WNM.Notify
Catch eex As ExitException Catch eex As ExitException
@@ -263,6 +288,8 @@ Namespace API.Instagram
errorFound = True errorFound = True
Throw ex Throw ex
Finally Finally
DefaultParser_ElemNode = Nothing
DownloadReels_SetEnvir = False
E560Thrown = False E560Thrown = False
UpdateResponser() UpdateResponser()
ValidateExtension() ValidateExtension()
@@ -287,16 +314,16 @@ Namespace API.Instagram
Try Try
If _DownloadingInProgress AndAlso Not Responser Is Nothing AndAlso Not Responser.Disposed Then If _DownloadingInProgress AndAlso Not Responser Is Nothing AndAlso Not Responser.Disposed Then
_DownloadingInProgress = False _DownloadingInProgress = False
RemoveHandler Responser.ResponseReceived, AddressOf Responser_ResponseReceived Responser_ResponseReceived_RemoveHandler()
Declarations.UpdateResponser(Responser, MySiteSettings.Responser) Declarations.UpdateResponser(Responser, MySiteSettings.Responser)
End If End If
Catch Catch
End Try End Try
End Sub End Sub
Protected Overridable 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) Declarations.UpdateResponser(e, Responser)
End Sub End Sub
Protected Enum Sections : Timeline : Tagged : Stories : UserStories : SavedPosts : End Enum Protected Enum Sections : Timeline : Reels : Tagged : Stories : UserStories : SavedPosts : 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"
@@ -436,6 +463,7 @@ Namespace API.Instagram
ReconfigureAwaiter() ReconfigureAwaiter()
Try Try
Dim r$ = String.Empty
Dim n As EContainer, nn As EContainer Dim n As EContainer, nn As EContainer
Dim HasNextPage As Boolean = False Dim HasNextPage As Boolean = False
Dim EndCursor$ = String.Empty Dim EndCursor$ = String.Empty
@@ -456,16 +484,17 @@ Namespace API.Instagram
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=50" &
If(Cursor.IsEmptyString, String.Empty, $"&max_id={Cursor}") If(Cursor.IsEmptyString, String.Empty, $"&max_id={Cursor}")
ENode = Nothing ENode = Nothing
Case Sections.Reels
r = DownloadReels(Cursor, Token)
ENode = {"data", "xdt_api__v1__clips__user__connection_v2"}
Case Sections.SavedPosts Case Sections.SavedPosts
SavedPostsDownload(String.Empty, Token) SavedPostsDownload(String.Empty, Token)
Exit Sub Exit Sub
Case Sections.Tagged Case Sections.Tagged
Dim h$ = AConvert(Of String)(MySiteSettings.HashTagged.Value, String.Empty)
If h.IsEmptyString Then Throw New ExitException
Dim vars$ = "{""id"":" & ID & ",""first"":50,""after"":""" & Cursor & """}" Dim vars$ = "{""id"":" & ID & ",""first"":50,""after"":""" & Cursor & """}"
vars = SymbolsConverter.ASCII.EncodeSymbolsOnly(vars) vars = SymbolsConverter.ASCII.EncodeSymbolsOnly(vars)
URL = $"https://www.instagram.com/graphql/query/?query_hash={h}&variables={vars}" URL = $"https://www.instagram.com/graphql/query/?doc_id=17946422347485809&variables={vars}"
ENode = {"data", "user", 0} ENode = {"data", "user", "edge_user_to_photos_of_you"}
SpecFolder = TaggedFolder SpecFolder = TaggedFolder
Case Sections.Stories Case Sections.Stories
If Not StoriesRequested Then If Not StoriesRequested Then
@@ -493,7 +522,7 @@ Namespace API.Instagram
End Select End Select
'Get response 'Get response
Dim r$ = Responser.GetResponse(URL,, EDP.ThrowException) If Not Section = Sections.Reels Then r = Responser.GetResponse(URL,, EDP.ThrowException)
MySiteSettings.TooManyRequests(False) MySiteSettings.TooManyRequests(False)
RequestsCount += 1 RequestsCount += 1
ThrowAny(Token) ThrowAny(Token)
@@ -515,6 +544,20 @@ Namespace API.Instagram
HasNextPage = False HasNextPage = False
End If End If
End With End With
Case Sections.Reels
With n
If .Contains("page_info") Then
With .Item("page_info")
HasNextPage = .Value("has_next_page").FromXML(Of Boolean)(False)
EndCursor = .Value("end_cursor")
End With
Else
HasNextPage = False
End If
If If(.Item("edges")?.Count, 0) > 0 Then
If Not DefaultParser(.Item("edges"), Section, Token, "Reels*") Then Throw New ExitException
End If
End With
Case Sections.Tagged Case Sections.Tagged
With n With n
If .Contains("page_info") Then If .Contains("page_info") Then
@@ -567,25 +610,33 @@ Namespace API.Instagram
End If End If
dValue = 0 dValue = 0
If HasNextPage And Not EndCursor.IsEmptyString Then DownloadData(EndCursor, Section, Token) If HasNextPage And Not EndCursor.IsEmptyString Then DownloadData(EndCursor, Section, Token)
Catch jsonNull As JsonDocumentException When jsonNull.State = WebDocumentEventArgs.States.Error And Section = Sections.Reels
Throw jsonNull
Catch eex As ExitException Catch eex As ExitException
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)
End Try End Try
Loop Loop
Catch jsonNull2 As JsonDocumentException When jsonNull2.State = WebDocumentEventArgs.States.Error And Section = Sections.Reels
Catch eex2 As ExitException Catch eex2 As ExitException
If (Section = Sections.Timeline Or Section = Sections.Tagged) And Not Cursor.IsEmptyString Then Throw eex2 If eex2.Is560 Then
Throw New Plugin.ExitException With {.Silent = True}
Else
If Not Section = Sections.Reels And (Section = Sections.Timeline Or Section = Sections.Tagged) And Not Cursor.IsEmptyString Then Throw eex2
End If
Catch oex2 As OperationCanceledException When Token.IsCancellationRequested Or oex2.HelpLink = InstAborted Catch oex2 As OperationCanceledException When Token.IsCancellationRequested Or oex2.HelpLink = InstAborted
If oex2.HelpLink = InstAborted Then HasError = True If oex2.HelpLink = InstAborted Then HasError = True
Catch DoEx As Exception Catch DoEx As Exception
ProcessException(DoEx, Token, $"data downloading error [{URL}]",, Section) ProcessException(DoEx, Token, $"data downloading error [{URL}]",, Section)
End Try End Try
End Sub End Sub
Private Sub DownloadPosts(ByVal Token As CancellationToken) Private Sub DownloadPosts(ByVal Token As CancellationToken, Optional ByVal IsTagged As Boolean = False)
Dim URL$ = String.Empty Dim URL$ = String.Empty
Dim dValue% = 1 Dim dValue% = 1
Dim _Index% = 0 Dim _Index% = 0
Dim before% Dim before%
Dim specFolder$ = IIf(IsTagged, "Tagged", String.Empty)
If PostsToReparse.Count > 0 Then ProgressPre.ChangeMax(PostsToReparse.Count) If PostsToReparse.Count > 0 Then ProgressPre.ChangeMax(PostsToReparse.Count)
Try Try
Do While dValue = 1 Do While dValue = 1
@@ -616,7 +667,7 @@ Namespace API.Instagram
With j("items") With j("items")
For Each jj In .Self For Each jj In .Self
before = _TempMediaList.Count before = _TempMediaList.Count
ObtainMedia(jj, PostsToReparse(i).ID) ObtainMedia(jj, PostsToReparse(i).ID, specFolder)
If Not before = _TempMediaList.Count Then _TotalPostsParsed += 1 If Not before = _TempMediaList.Count Then _TotalPostsParsed += 1
If _Limit > 0 And _TotalPostsParsed >= _Limit Then Throw New ExitException If _Limit > 0 And _TotalPostsParsed >= _Limit Then Throw New ExitException
Next Next
@@ -664,6 +715,7 @@ Namespace API.Instagram
End Sub End Sub
Protected DefaultParser_ElemNode() As Object = Nothing Protected DefaultParser_ElemNode() As Object = Nothing
Protected DefaultParser_IgnorePass As Boolean = False Protected DefaultParser_IgnorePass As Boolean = False
Private ReadOnly DefaultParser_PostUrlCreator_Default As Func(Of PostKV, String) = Function(post) $"https://www.instagram.com/p/{post.Code}/"
Protected DefaultParser_PostUrlCreator As Func(Of PostKV, String) = Function(post) $"https://www.instagram.com/p/{post.Code}/" Protected DefaultParser_PostUrlCreator As Func(Of PostKV, String) = Function(post) $"https://www.instagram.com/p/{post.Code}/"
Protected Function DefaultParser(ByVal Items As IEnumerable(Of EContainer), ByVal Section As Sections, ByVal Token As CancellationToken, Protected Function DefaultParser(ByVal Items As IEnumerable(Of EContainer), ByVal Section As Sections, ByVal Token As CancellationToken,
Optional ByVal SpecFolder As String = Nothing, Optional ByVal State As UStates = UStates.Unknown, Optional ByVal SpecFolder As String = Nothing, Optional ByVal State As UStates = UStates.Unknown,
@@ -713,6 +765,106 @@ Namespace API.Instagram
End If End If
End Function End Function
#End Region #End Region
#Region "Get reels"
Private _GetReels_LSD As String = String.Empty
Private _GetReels_dtsg As String = String.Empty
Private ReadOnly Property DownloadReels_Tokens_Valid As Boolean
Get
Return Not _GetReels_LSD.IsEmptyString And Not _GetReels_dtsg.IsEmptyString
End Get
End Property
Private WriteOnly Property DownloadReels_SetEnvir As Boolean
Set(ByVal init As Boolean)
If init Then
ObtainMedia_SetReelsFunc()
DefaultParser_PostUrlCreator = Function(post) $"{MySiteSettings.GetUserUrl(Me).TrimEnd("/")}/reel/{post.Code}"
Else
ObtainMedia_SizeFuncPic = Nothing
ObtainMedia_SizeFuncVid = Nothing
DefaultParser_PostUrlCreator = DefaultParser_PostUrlCreator_Default
End If
End Set
End Property
Private Class Responser2 : Inherits Responser
Friend Sub New(ByVal Source As Responser)
MyBase.New
Copy(Source)
ErrorProcessor = New ResponserErrorProcessor(Source)
End Sub
End Class
''' <returns>Response</returns>
Private Function DownloadReels(ByVal Cursor As String, ByVal Token As CancellationToken) As String
Const requestPattern$ = "https://www.instagram.com/api/graphql?fb_dtsg={0}&fb_api_req_friendly_name=PolarisProfileReelsTabContentQuery&lsd={1}&doc_id=7191572580905225&variables={2}"
DownloadReels_SetEnvir = True
If Cursor.IsEmptyString And Not DownloadReels_Tokens_Valid Then GetPageTokens()
If Cursor.IsEmptyString And Not DownloadReels_Tokens_Valid Then Throw New ExitException
Using resp As New Responser2(Responser)
Try
resp.Method = "POST"
AddHandler resp.ResponseReceived, AddressOf Responser_ResponseReceived
resp.Headers.Add(Header_FB_LSD, _GetReels_LSD)
Dim vars$ = """data"":{""include_feed_video"":true,""page_size"":50,""target_user_id"":""" & ID & """}"
If Not Cursor.IsEmptyString Then vars = $"""after"":""{Cursor}"",""before"":null,{vars},""first"":4,""last"":null"
vars = "{" & vars & "}"
Dim url$ = String.Format(requestPattern, _GetReels_dtsg, _GetReels_LSD, SymbolsConverter.ASCII.EncodeSymbolsOnly(vars))
Return resp.GetResponse(url,, EDP.ThrowException)
Finally
With resp
Responser.Cookies.Update(.Cookies)
With .Headers
If .Contains(SiteSettings.Header_IG_WWW_CLAIM) Then Responser.Headers.Add(SiteSettings.Header_IG_WWW_CLAIM, .Value(SiteSettings.Header_IG_WWW_CLAIM))
If .Contains(SiteSettings.Header_CSRF_TOKEN) Then Responser.Headers.Add(SiteSettings.Header_CSRF_TOKEN, .Value(SiteSettings.Header_CSRF_TOKEN))
End With
End With
End Try
End Using
End Function
Private Function GetPageTokens() As Boolean
_GetReels_LSD = String.Empty
_GetReels_dtsg = String.Empty
Try
Dim r$ = Responser.GetResponse(MySiteSettings.GetUserUrl(Me),, EDP.ThrowException)
If Not r.IsEmptyString Then
Dim rr As RParams = RParams.DM(PageTokenRegexPatternDefault, 0, RegexReturn.List, EDP.ReturnValue)
Dim tokens As List(Of String) = RegexReplace(r, rr)
Dim tt$, ttVal$
If tokens.ListExists Then
With rr
.Match = Nothing
.MatchSub = 1
.WhatGet = RegexReturn.Value
End With
For Each tt In tokens
If Not _GetReels_LSD.IsEmptyString And Not _GetReels_dtsg.IsEmptyString Then
Exit For
Else
ttVal = RegexReplace(tt, rr)
If Not ttVal.IsEmptyString Then
If ttVal.Contains(":") Then
If _GetReels_dtsg.IsEmptyString Then _GetReels_dtsg = ttVal
Else
If _GetReels_LSD.IsEmptyString Then _GetReels_LSD = ttVal
End If
End If
End If
Next
End If
End If
Catch ex As Exception
Dim notFound$ = String.Empty
If _GetReels_dtsg.IsEmptyString Then notFound.StringAppend(Header_FB_LSD)
If _GetReels_LSD.IsEmptyString Then notFound.StringAppend("lsd")
LogError(ex, $"failed to update some{IIf(notFound.IsEmptyString, String.Empty, $" ({notFound})")} credentials", EDP.SendToLog)
End Try
Return DownloadReels_Tokens_Valid
End Function
#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
Const CodeSymbols$ = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_" Const CodeSymbols$ = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
@@ -737,15 +889,38 @@ Namespace API.Instagram
Protected ObtainMedia_SizeFuncVid As Func(Of EContainer, Sizes) = Nothing Protected ObtainMedia_SizeFuncVid As Func(Of EContainer, Sizes) = Nothing
Protected ObtainMedia_SizeFuncPic As Func(Of EContainer, Sizes) = Nothing Protected ObtainMedia_SizeFuncPic As Func(Of EContainer, Sizes) = Nothing
Protected ObtainMedia_AllowAbstract As Boolean = False Protected ObtainMedia_AllowAbstract As Boolean = False
Protected Sub ObtainMedia_SetReelsFunc()
ObtainMedia_SizeFuncPic = Function(ByVal ss As EContainer) As Sizes
If ss.Value("url").IsEmptyString Then
Return New Sizes("----", "")
ElseIf Not ss.Value("width").IsEmptyString Or Not ss.Value("width").IsEmptyString Then
Return New Sizes(CInt(AConvert(Of Integer)(ss.Value("width"), 0)) +
CInt(AConvert(Of Integer)(ss.Value("height"), 0)), ss.Value("url"))
Else
Dim rval$ = RegexReplace(ss.Value("url"), ObtainMedia_SizeFuncPic_RegexP)
If Not rval.IsEmptyString Then Return New Sizes(rval, ss.Value("url"))
rval = RegexReplace(ss.Value("url"), ObtainMedia_SizeFuncPic_RegexS)
If Not rval.IsEmptyString Then Return New Sizes(AConvert(Of Integer)(rval, 1) * -1, ss.Value("url"))
Return New Sizes(10000, ss.Value("url"))
End If
End Function
ObtainMedia_SizeFuncVid = Function(ss) If(ss.Value("url").IsEmptyString, New Sizes("----", ""), New Sizes(10000, ss.Value("url")))
End Sub
Protected Sub ObtainMedia(ByVal n As EContainer, ByVal PostID As String, Optional ByVal SpecialFolder As String = Nothing, Protected Sub ObtainMedia(ByVal n As EContainer, ByVal PostID As String, Optional ByVal SpecialFolder As String = Nothing,
Optional ByVal DateObj As String = Nothing, Optional ByVal InitialType As Integer = -1, Optional ByVal DateObj As String = Nothing, Optional ByVal InitialType As Integer = -1,
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)
Try Try
Dim maxSize As Func(Of EContainer, Integer) = Function(ByVal _ss As EContainer) As Integer
Dim w% = AConvert(Of Integer)(_ss.Value("width"), 0)
Dim h% = AConvert(Of Integer)(_ss.Value("height"), 0)
'Return w + h
Return Math.Max(w, h)
End Function
Dim wrongData As Predicate(Of Sizes) = Function(_ss) _ss.HasError Or _ss.Data.IsEmptyString Dim wrongData As Predicate(Of Sizes) = Function(_ss) _ss.HasError Or _ss.Data.IsEmptyString
Dim img As Predicate(Of EContainer) = Function(_img) Not _img.Name.IsEmptyString AndAlso _img.Name.StartsWith("image_versions") AndAlso _img.Count > 0 Dim img As Predicate(Of EContainer) = Function(_img) Not _img.Name.IsEmptyString AndAlso _img.Name.StartsWith("image_versions") AndAlso _img.Count > 0
Dim vid As Predicate(Of EContainer) = Function(_vid) Not _vid.Name.IsEmptyString AndAlso _vid.Name.StartsWith("video_versions") AndAlso _vid.Count > 0 Dim vid As Predicate(Of EContainer) = Function(_vid) Not _vid.Name.IsEmptyString AndAlso _vid.Name.StartsWith("video_versions") AndAlso _vid.Count > 0
Dim ss As Func(Of EContainer, Sizes) = Function(_ss) New Sizes(_ss.Value("width"), _ss.Value("url")) Dim ss As Func(Of EContainer, Sizes) = Function(_ss) New Sizes(maxSize(_ss), _ss.Value("url"))
Dim ssVid As Func(Of EContainer, Sizes) = ss Dim ssVid As Func(Of EContainer, Sizes) = ss
Dim ssPic As Func(Of EContainer, Sizes) = ss Dim ssPic As Func(Of EContainer, Sizes) = ss
Dim mDate As Func(Of EContainer, String) = Function(ByVal elem As EContainer) As String Dim mDate As Func(Of EContainer, String) = Function(ByVal elem As EContainer) As String
@@ -1028,6 +1203,7 @@ Namespace API.Instagram
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 MySiteSettings.SkipUntilNextSession = True
Err5xx = Responser.StatusCode
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)
@@ -1041,11 +1217,12 @@ Namespace API.Instagram
Dim s As Sections = DirectCast(Section, Sections) Dim s As Sections = DirectCast(Section, Sections)
Select Case s Select Case s
Case Sections.Timeline : MySiteSettings.DownloadTimeline.Value = False Case Sections.Timeline : MySiteSettings.DownloadTimeline.Value = False
Case Sections.Reels : MySiteSettings.DownloadReels.Value = False
Case Sections.Tagged : MySiteSettings.DownloadTagged.Value = False
Case Sections.Stories, Sections.UserStories Case Sections.Stories, Sections.UserStories
MySiteSettings.DownloadTimeline.Value = False MySiteSettings.DownloadTimeline.Value = False
MySiteSettings.DownloadStories.Value = False MySiteSettings.DownloadStories.Value = False
MySiteSettings.DownloadStoriesUser.Value = False MySiteSettings.DownloadStoriesUser.Value = False
Case Else : MySiteSettings.DownloadTagged.Value = False
End Select End Select
MyMainLOG = $"[{s}] downloading is disabled until you update your credentials".ToUpper MyMainLOG = $"[{s}] downloading is disabled until you update your credentials".ToUpper
End If End If
@@ -1066,7 +1243,7 @@ Namespace API.Instagram
#End Region #End Region
#Region "Standalone downloader" #Region "Standalone downloader"
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)
Dim PID$ = RegexReplace(Data.URL, RParams.DMS(".*?instagram.com/p/([_\w\d]+)", 1)) Dim PID$ = RegexReplace(Data.URL, RParams.DMS(String.Format(UserRegexDefaultPattern, "instagram.com/p/"), 1))
If Not PID.IsEmptyString AndAlso Not ACheck(Of Long)(PID) Then PID = CodeToID(PID) If Not PID.IsEmptyString AndAlso Not ACheck(Of Long)(PID) Then PID = CodeToID(PID)
If Not PID.IsEmptyString Then If Not PID.IsEmptyString Then
PostsToReparse.Add(New PostKV With {.ID = PID}) PostsToReparse.Add(New PostKV With {.ID = PID})

View File

@@ -46,7 +46,7 @@ Namespace API.JustForFans
UserAgent = New PropertyValue(If(Responser.UserAgentExists, Responser.UserAgent, String.Empty), GetType(String), Sub(v) UpdateHeader(NameOf(UserAgent), v)) UserAgent = New PropertyValue(If(Responser.UserAgentExists, Responser.UserAgent, String.Empty), GetType(String), Sub(v) UpdateHeader(NameOf(UserAgent), v))
_AllowUserAgentUpdate = False _AllowUserAgentUpdate = False
UserRegex = RParams.DMS("https://justfor.fans/([^/\?]+)", 1, EDP.ReturnValue) UserRegex = RParams.DMS(String.Format(UserRegexDefaultPattern, "justfor.fans/"), 1, EDP.ReturnValue)
UrlPatternUser = "https://justfor.fans/{0}" UrlPatternUser = "https://justfor.fans/{0}"
ImageVideoContains = "justfor.fans" ImageVideoContains = "justfor.fans"
End Sub End Sub

View File

@@ -168,6 +168,7 @@ Namespace API.JustForFans
#Region "Initializer" #Region "Initializer"
Friend Sub New() Friend Sub New()
UseInternalM3U8Function = True UseInternalM3U8Function = True
_ResponserAutoUpdateCookies = True
End Sub End Sub
#End Region #End Region
#Region "Download functions" #Region "Download functions"
@@ -191,11 +192,11 @@ Namespace API.JustForFans
DownloadData(0, Token) DownloadData(0, Token)
Finally Finally
If DownloadTopCount.HasValue Then DownloadTopCount = Nothing If DownloadTopCount.HasValue Then DownloadTopCount = Nothing
Try : RemoveHandler Responser.ResponseReceived, AddressOf Responser_ResponseReceived : Catch : End Try Responser_ResponseReceived_RemoveHandler()
MySettings.UpdateResponser(Responser) MySettings.UpdateResponser(Responser)
End Try End Try
End Sub End Sub
Private Sub Responser_ResponseReceived(ByVal Source As Object, ByVal e As EventArguments.WebDataResponse) Protected Overrides Sub Responser_ResponseReceived(ByVal Source As Object, ByVal e As EventArguments.WebDataResponse)
If e.CookiesExists Then If e.CookiesExists Then
Dim hv$ = If(e.Cookies.FirstOrDefault(Function(cc) cc.Name.StringToLower = SiteSettings.UserHash4_CookieName)?.Value, String.Empty) Dim hv$ = If(e.Cookies.FirstOrDefault(Function(cc) cc.Name.StringToLower = SiteSettings.UserHash4_CookieName)?.Value, String.Empty)
If Not hv.IsEmptyString And Not _UserHash4 = hv Then _UserHash4 = hv If Not hv.IsEmptyString And Not _UserHash4 = hv Then _UserHash4 = hv

View File

@@ -106,9 +106,12 @@ 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 If Responser.StatusCode = Net.HttpStatusCode.ServiceUnavailable Then '503
MyMainLOG = $"{ToStringForLog()}: LPSG not available" MyMainLOG = $"{ToStringForLog()}: LPSG not available"
Return 1 Return 1
ElseIf Responser.StatusCode = Net.HttpStatusCode.NotFound Then '404
UserExists = False
Return 1
Else Else
Return 0 Return 0
End If End If

View File

@@ -0,0 +1,77 @@
'------------------------------------------------------------------------------
' <auto-generated>
' This code was generated by a tool.
' Runtime Version:4.0.30319.42000
'
' Changes to this file may cause incorrect behavior and will be lost if
' the code is regenerated.
' </auto-generated>
'------------------------------------------------------------------------------
Option Strict On
Option Explicit On
Imports System
Namespace My.Resources
'This class was auto-generated by the StronglyTypedResourceBuilder
'class via a tool like ResGen or Visual Studio.
'To add or remove a member, edit your .ResX file then rerun ResGen
'with the /str option, or rebuild your VS project.
'''<summary>
''' A strongly-typed resource class, for looking up localized strings, etc.
'''</summary>
<Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0"), _
Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute()> _
Friend Class OFResources
Private Shared resourceMan As Global.System.Resources.ResourceManager
Private Shared resourceCulture As Global.System.Globalization.CultureInfo
<Global.System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")> _
Friend Sub New()
MyBase.New
End Sub
'''<summary>
''' Returns the cached ResourceManager instance used by this class.
'''</summary>
<Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
Friend Shared ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager
Get
If Object.ReferenceEquals(resourceMan, Nothing) Then
Dim temp As Global.System.Resources.ResourceManager = New Global.System.Resources.ResourceManager("SCrawler.OFResources", GetType(OFResources).Assembly)
resourceMan = temp
End If
Return resourceMan
End Get
End Property
'''<summary>
''' Overrides the current thread's CurrentUICulture property for all
''' resource lookups using this strongly typed resource class.
'''</summary>
<Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
Friend Shared Property Culture() As Global.System.Globalization.CultureInfo
Get
Return resourceCulture
End Get
Set
resourceCulture = value
End Set
End Property
'''<summary>
''' Looks up a localized resource of type System.Byte[].
'''</summary>
Friend Shared ReadOnly Property OFScraperConfigPattern() As Byte()
Get
Dim obj As Object = ResourceManager.GetObject("OFScraperConfigPattern", resourceCulture)
Return CType(obj,Byte())
End Get
End Property
End Class
End Namespace

View File

@@ -0,0 +1,124 @@
<?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>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="OFScraperConfigPattern" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>OFScraperConfigPattern.json;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
</root>

View File

@@ -0,0 +1,61 @@
{
"config": {
"main_profile": "main_profile",
"metadata": "{configpath}/{profile}/.data/{model_username}_{model_id}",
"discord": "",
"file_options": {
"save_location": "",
"dir_format": "",
"file_format": "{filename}.{ext}",
"textlength": 0,
"space-replacer": " ",
"date": "YYYY-MM-DD"
},
"download_options": {
"file_size_limit": 0,
"file_size_min": 0,
"filter": [
"Images",
"Audios",
"Videos"
],
"auto_resume": false
},
"binary_options": {
"mp4decrypt": "",
"ffmpeg": ""
},
"cdm_options": {
"private-key": null,
"client-id": null,
"key-mode-default": "cdrm",
"keydb_api": ""
},
"performance_options": {
"download-sems": 6,
"maxfile-sem": 0,
"threads": 5
},
"advanced_options": {
"code-execution": false,
"dynamic-mode-default": "deviint",
"backend": "aio",
"downloadbars": false,
"cache-mode": "sqlite",
"appendlog": true,
"custom": null,
"sanitize_text": false,
"avatar": true
},
"responsetype": {
"timeline": "Posts",
"message": "Messages",
"archived": "Archived",
"paid": "Messages",
"stories": "Stories",
"highlights": "Stories",
"profile": "Profile",
"pinned": "Posts"
}
}
}

View File

@@ -26,8 +26,8 @@ Namespace API.OnlyFans
#Region "Headers" #Region "Headers"
Private Const HeaderBrowser As String = "sec-ch-ua" Private Const HeaderBrowser As String = "sec-ch-ua"
Private Const HeaderUserID As String = "User-Id" Private Const HeaderUserID As String = "User-Id"
Private Const HeaderXBC As String = "X-Bc" Friend Const HeaderXBC As String = "X-Bc"
Private Const HeaderAppToken As String = "App-Token" Friend Const HeaderAppToken As String = "App-Token"
<PropertyOption(ControlText:=HeaderUserID, AllowNull:=False), PClonable(Clone:=False)> <PropertyOption(ControlText:=HeaderUserID, AllowNull:=False), PClonable(Clone:=False)>
Friend ReadOnly Property HH_USER_ID As PropertyValue Friend ReadOnly Property HH_USER_ID As PropertyValue
<PropertyOption(ControlText:=HeaderXBC, AllowNull:=False), PClonable(Clone:=False)> <PropertyOption(ControlText:=HeaderXBC, AllowNull:=False), PClonable(Clone:=False)>
@@ -37,7 +37,7 @@ Namespace API.OnlyFans
<PropertyOption(ControlText:=HeaderBrowser, ControlToolTip:="Can be null", AllowNull:=True), PClonable> <PropertyOption(ControlText:=HeaderBrowser, ControlToolTip:="Can be null", AllowNull:=True), PClonable>
Private ReadOnly Property HH_BROWSER As PropertyValue Private ReadOnly Property HH_BROWSER As PropertyValue
<PropertyOption(AllowNull:=False), PClonable> <PropertyOption(AllowNull:=False), PClonable>
Private ReadOnly Property UserAgent As PropertyValue Friend ReadOnly Property UserAgent As PropertyValue
Private Sub UpdateHeader(ByVal PropertyName As String, ByVal Value As String) Private Sub UpdateHeader(ByVal PropertyName As String, ByVal Value As String)
Dim hName$ = String.Empty Dim hName$ = String.Empty
Dim isUserAgent As Boolean = False Dim isUserAgent As Boolean = False
@@ -78,6 +78,42 @@ Namespace API.OnlyFans
"Change this value only if you know what you are doing."), PXML, PClonable> "Change this value only if you know what you are doing."), PXML, PClonable>
Friend ReadOnly Property DynamicRules As PropertyValue Friend ReadOnly Property DynamicRules As PropertyValue
#End Region #End Region
#Region "OFScraper"
<PClonable, PXML("OFScraperPath")> Private ReadOnly Property OFScraperPath_XML As PropertyValue
<PropertyOption(ControlText:="OF-Scraper path", ControlToolTip:="The path to the 'ofscraper.exe'")>
Friend ReadOnly Property OFScraperPath As PropertyValue
Get
If Not DefaultInstance Is Nothing Then
Return DirectCast(DefaultInstance, SiteSettings).OFScraperPath_XML
Else
Return OFScraperPath_XML
End If
End Get
End Property
<PClonable, PXML("OFScraperMP4decrypt")> Private ReadOnly Property OFScraperMP4decrypt_XML As PropertyValue
<PropertyOption(ControlText:="mp4decrypt path", ControlToolTip:="The path to the 'mp4decrypt.exe'")>
Friend ReadOnly Property OFScraperMP4decrypt As PropertyValue
Get
If Not DefaultInstance Is Nothing Then
Return DirectCast(DefaultInstance, SiteSettings).OFScraperMP4decrypt_XML
Else
Return OFScraperMP4decrypt_XML
End If
End Get
End Property
Friend Const KeyModeDefault_Default As String = "cdrm"
<PClonable, PXML("KeyModeDefault")> Private ReadOnly Property KeyModeDefault_XML As PropertyValue
<PropertyOption(ControlText:="key-mode-default")>
Friend ReadOnly Property KeyModeDefault As PropertyValue
Get
If Not DefaultInstance Is Nothing Then
Return DirectCast(DefaultInstance, SiteSettings).KeyModeDefault_XML
Else
Return KeyModeDefault_XML
End If
End Get
End Property
#End Region
#End Region #End Region
#Region "Initializer" #Region "Initializer"
Friend Sub New(ByVal AccName As String, ByVal Temp As Boolean) Friend Sub New(ByVal AccName As String, ByVal Temp As Boolean)
@@ -112,12 +148,28 @@ Namespace API.OnlyFans
DownloadChatMedia = New PropertyValue(True) DownloadChatMedia = New PropertyValue(True)
LastDateUpdated_XML = New PropertyValue(Now.AddYears(-1), GetType(Date)) LastDateUpdated_XML = New PropertyValue(Now.AddYears(-1), GetType(Date))
UseOldAuthRules = New PropertyValue(False) 'URGENT: OF [UseOldAuthRules = True]
UseOldAuthRules = New PropertyValue(True)
DynamicRulesUpdateInterval = New PropertyValue(60 * 24) DynamicRulesUpdateInterval = New PropertyValue(60 * 24)
DynamicRulesUpdateIntervalProvider = New FieldsCheckerProviderSimple(Function(v) IIf(AConvert(Of Integer)(v, 0) > 0, v, Nothing), DynamicRulesUpdateIntervalProvider = New FieldsCheckerProviderSimple(Function(v) IIf(AConvert(Of Integer)(v, 0) > 0, v, Nothing),
"The value of [{0}] field must be greater than 0") "The value of [{0}] field must be greater than 0")
DynamicRules = New PropertyValue(String.Empty, GetType(String)) DynamicRules = New PropertyValue(String.Empty, GetType(String))
UserRegex = RParams.DMS("onlyfans.com/([\w\._]+)", 1, EDP.ReturnValue) OFScraperPath_XML = New PropertyValue(String.Empty, GetType(String))
If ACheck(OFScraperPath_XML.Value) Then
Dim f As SFile = OFScraperPath_XML.Value
If Not f.Exists AndAlso f.Exists(SFO.Path, False) Then
With SFile.GetFiles(f, "*.exe",, EDP.ReturnValue)
If .ListExists Then
f = .FirstOrDefault(Function(ff) ff.Name.StringToLower.StartsWith("ofscraper"))
If f.Exists Then OFScraperPath_XML.Value = f.ToString
End If
End With
End If
End If
OFScraperMP4decrypt_XML = New PropertyValue(String.Empty, GetType(String))
KeyModeDefault_XML = New PropertyValue(KeyModeDefault_Default)
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
@@ -151,6 +203,7 @@ Namespace API.OnlyFans
End Sub End Sub
#End Region #End Region
#Region "GetUserUrl, GetUserPostUrl, UserOptions" #Region "GetUserUrl, GetUserPostUrl, UserOptions"
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.Name, $"u{User.ID}"))
End Function End Function
@@ -168,7 +221,7 @@ Namespace API.OnlyFans
If p.IsEmptyString Then If p.IsEmptyString Then
Return GetUserUrl(User) Return GetUserUrl(User)
Else Else
Return String.Format("https://onlyfans.com/{0}/{1}", p, If(User.ID.IsEmptyString, User.Name, $"u{User.ID}")) Return String.Format(UserPostPattern, p, If(User.ID.IsEmptyString, User.Name, $"u{User.ID}"))
End If End If
Else Else
Return String.Empty Return String.Empty

View File

@@ -7,10 +7,12 @@
' This program is distributed in the hope that it will be useful, ' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY ' but WITHOUT ANY WARRANTY
Imports System.Threading Imports System.Threading
Imports System.Text.RegularExpressions
Imports SCrawler.API.Base Imports SCrawler.API.Base
Imports SCrawler.API.YouTube.Objects Imports SCrawler.API.YouTube.Objects
Imports PersonalUtilities.Functions.XML Imports PersonalUtilities.Functions.XML
Imports PersonalUtilities.Functions.RegularExpressions Imports PersonalUtilities.Functions.RegularExpressions
Imports PersonalUtilities.Tools
Imports PersonalUtilities.Tools.Web.Clients Imports PersonalUtilities.Tools.Web.Clients
Imports PersonalUtilities.Tools.Web.Clients.EventArguments Imports PersonalUtilities.Tools.Web.Clients.EventArguments
Imports PersonalUtilities.Tools.Web.Cookies Imports PersonalUtilities.Tools.Web.Cookies
@@ -65,24 +67,40 @@ Namespace API.OnlyFans
#Region "Initializer" #Region "Initializer"
Friend Sub New() Friend Sub New()
HighlightsList = New List(Of String) HighlightsList = New List(Of String)
UseInternalDownloadFileFunction = True
End Sub End Sub
#End Region #End Region
#Region "Download functions" #Region "Download functions"
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken) Private _OFScraperExists As Boolean = False
If Not MySettings.SessionAborted Then Private OFSCache As CacheKeeper = Nothing
If Not CCookie Is Nothing Then CCookie.Dispose() Private _AbsMediaIndex As Integer = 0
CCookie = Responser.Cookies.Copy Private FunctionErr As Integer = FunctionErrDef
Responser.Cookies.Clear() Private Const FunctionErrDef As Integer = -100
AddHandler Responser.ResponseReceived, AddressOf OnResponseReceived Private Sub ValidateOFScraper()
UpdateCookieHeader() _OFScraperExists = ACheck(MySettings.OFScraperPath.Value) AndAlso CStr(MySettings.OFScraperPath.Value).CSFile.Exists
DownloadTimeline(IIf(IsSavedPosts, 0, String.Empty), Token)
If Not IsSavedPosts Then
If MediaDownloadHighlights Then DownloadHighlights(Token)
If MediaDownloadChatMedia Then DownloadChatMedia(0, Token)
End If
End If
End Sub End Sub
Private Sub OnResponseReceived(ByVal Sender As Object, ByVal e As WebDataResponse) Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
Try
If Not MySettings.SessionAborted Then
ValidateOFScraper()
_AbsMediaIndex = 0
FunctionErr = FunctionErrDef
If Not CCookie Is Nothing Then CCookie.Dispose()
CCookie = Responser.Cookies.Copy
Responser.Cookies.Clear()
AddHandler Responser.ResponseReceived, AddressOf Responser_ResponseReceived
UpdateCookieHeader()
DownloadTimeline(IIf(IsSavedPosts, 0, String.Empty), Token)
If Not IsSavedPosts Then
If MediaDownloadHighlights And FunctionErr = FunctionErrDef Then DownloadHighlights(Token)
If MediaDownloadChatMedia And FunctionErr = FunctionErrDef Then DownloadChatMedia(0, Token)
End If
End If
Finally
Responser_ResponseReceived_RemoveHandler()
End Try
End Sub
Protected Overrides Sub Responser_ResponseReceived(ByVal Sender As Object, ByVal e As WebDataResponse)
If e.CookiesExists Then If e.CookiesExists Then
CCookie.Update(e.Cookies, CookieKeeper.UpdateModes.ReplaceByNameAll,, EDP.ReturnValue) CCookie.Update(e.Cookies, CookieKeeper.UpdateModes.ReplaceByNameAll,, EDP.ReturnValue)
UpdateCookieHeader() UpdateCookieHeader()
@@ -91,6 +109,10 @@ Namespace API.OnlyFans
Private Sub UpdateCookieHeader() Private Sub UpdateCookieHeader()
Responser.Headers.Add("Cookie", CCookie.ToString(False)) Responser.Headers.Add("Cookie", CCookie.ToString(False))
End Sub End Sub
Private Function ProcessFunctionErrComplete(ByVal ErrValue As Integer) As Boolean
If ErrValue <= 0 Or (ErrValue > 0 And ErrValue <> 2) Then FunctionErr = ErrValue
Return ErrValue <> 2
End Function
Friend Const A_HIGHLIGHT As String = "HL" Friend Const A_HIGHLIGHT As String = "HL"
Friend Const A_MESSAGE As String = "MSG" Friend Const A_MESSAGE As String = "MSG"
Private Const BaseUrlPattern As String = "https://onlyfans.com{0}" Private Const BaseUrlPattern As String = "https://onlyfans.com{0}"
@@ -169,7 +191,7 @@ Namespace API.OnlyFans
DownloadTimeline(tmpCursor, Token) DownloadTimeline(tmpCursor, Token)
End If End If
Catch ex As Exception Catch ex As Exception
_complete = Not ProcessException(ex, Token, $"data downloading error [{url}]") = 2 _complete = ProcessFunctionErrComplete(ProcessException(ex, Token, $"data downloading error [{url}]"))
End Try End Try
Loop While Not _complete Loop While Not _complete
End Sub End Sub
@@ -208,7 +230,7 @@ Namespace API.OnlyFans
End If End If
If hasMore Then DownloadHighlights(Cursor + 5, Token) If hasMore Then DownloadHighlights(Cursor + 5, Token)
Catch ex As Exception Catch ex As Exception
_complete = Not ProcessException(ex, Token, $"highlights downloading error [{url}]") = 2 _complete = ProcessFunctionErrComplete(ProcessException(ex, Token, $"highlights downloading error [{url}]"))
End Try End Try
Loop While Not _complete Loop While Not _complete
End Sub End Sub
@@ -253,7 +275,7 @@ Namespace API.OnlyFans
End If End If
End If End If
Catch ex As Exception Catch ex As Exception
_complete = Not ProcessException(ex, Token, $"highlights downloading error [{url}]") = 2 _complete = ProcessFunctionErrComplete(ProcessException(ex, Token, $"highlights downloading error [{url}]"))
End Try End Try
Loop While Not _complete Loop While Not _complete
End Sub End Sub
@@ -300,15 +322,15 @@ Namespace API.OnlyFans
End If End If
If hasMore Then DownloadChatMedia(Cursor + 20, Token) If hasMore Then DownloadChatMedia(Cursor + 20, Token)
Catch ex As Exception Catch ex As Exception
_complete = Not ProcessException(ex, Token, $"chats downloading error [{url}]") = 2 _complete = ProcessFunctionErrComplete(ProcessException(ex, Token, $"chats downloading error [{url}]"))
End Try End Try
Loop While Not _complete Loop While Not _complete
End Sub End Sub
#End Region #End Region
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) As List(Of UserMedia) Optional ByVal SpecFolder As String = Nothing, Optional ByVal PostUserID As String = Nothing) As List(Of UserMedia)
Dim postUrl$, 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
@@ -320,16 +342,27 @@ Namespace API.OnlyFans
Else Else
postUrl = m.Value({"source"}, "source").IfNullOrEmpty(m.Value("full")) postUrl = m.Value({"source"}, "source").IfNullOrEmpty(m.Value("full"))
End If End If
postUrlBase = String.Empty
Select Case m.Value("type") Select Case m.Value("type")
Case "photo" : t = UTypes.Picture : ext = "jpg" Case "photo" : t = UTypes.Picture : ext = "jpg"
Case "video" : t = UTypes.Video : ext = "mp4" Case "video"
t = UTypes.Video
ext = "mp4"
If postUrl.IsEmptyString And Not IsHL Then
t = UTypes.VideoPre
_AbsMediaIndex += 1
If Not PostUserID.IsEmptyString And IsSingleObjectDownload Then _
postUrlBase = String.Format(SiteSettings.UserPostPattern, PostID, $"u{PostUserID}")
End If
Case Else : t = UTypes.Undefined : ext = String.Empty Case Else : t = UTypes.Undefined : ext = String.Empty
End Select End Select
If Not t = UTypes.Undefined And Not postUrl.IsEmptyString Then If Not t = UTypes.Undefined And (Not postUrl.IsEmptyString Or t = UTypes.VideoPre) Then
Dim media As New UserMedia(postUrl, t) With { Dim media As New UserMedia(postUrl.IfNullOrEmpty(IIf(t = UTypes.VideoPre, $"{t}{_AbsMediaIndex}", String.Empty)), t) With {
.Post = New UserPost(PostID, AConvert(Of Date)(PostDate, DateProvider, Nothing)), .Post = New UserPost(PostID, AConvert(Of Date)(PostDate, DateProvider, Nothing)),
.SpecialFolder = SpecFolder .SpecialFolder = SpecFolder
} }
If postUrlBase.IsEmptyString And Not IsSingleObjectDownload Then postUrlBase = GetPostUrl(Me, media)
If Not postUrlBase.IsEmptyString Then media.URL_BASE = postUrlBase
media.File.Extension = ext media.File.Extension = ext
Result = True Result = True
mList.Add(media) mList.Add(media)
@@ -387,7 +420,7 @@ Namespace API.OnlyFans
End Function End Function
Dim mList As List(Of UserMedia) Dim mList As List(Of UserMedia)
Dim mediaResult As Boolean Dim mediaResult As Boolean
Dim r$, path$, postDate$ Dim r$, path$, postDate$, postUserID$
Dim j As EContainer Dim j As EContainer
ProgressPre.ChangeMax(_ContentList.Count) ProgressPre.ChangeMax(_ContentList.Count)
For i% = 0 To _ContentList.Count - 1 For i% = 0 To _ContentList.Count - 1
@@ -404,8 +437,9 @@ Namespace API.OnlyFans
j = JsonDocument.Parse(r) j = JsonDocument.Parse(r)
If Not j Is Nothing Then If Not j Is Nothing Then
postDate = j.Value("postedAt") postDate = j.Value("postedAt")
postUserID = j.Value({"author"}, "id")
mediaResult = False mediaResult = False
mList = TryCreateMedia(j, m.Post.ID, postDate, mediaResult) mList = TryCreateMedia(j, m.Post.ID, postDate, mediaResult,,, postUserID)
If mediaResult Then If mediaResult Then
_TempMediaList.ListAddList(mList.ListForEachCopy(stateRefill, True), LNC) _TempMediaList.ListAddList(mList.ListForEachCopy(stateRefill, True), LNC)
rList.Add(i) rList.Add(i)
@@ -531,10 +565,145 @@ Namespace API.OnlyFans
Return result Return result
End Function End Function
#End Region #End Region
#Region "OFScraper support"
Private Function OFS_DownloadFile(ByVal URL As String, ByVal Token As CancellationToken) As List(Of SFile)
Try
Const requestPattern$ = """{0}"" manual --config ""{1}"" --url {2}"
Dim conf As SFile = OFS_CreateConfig()
If conf.Exists Then
Dim command$ = String.Format(requestPattern, MySettings.OFScraperPath.Value, conf, URL)
'#If DEBUG Then
'Debug.WriteLine(command)
'#End If
Using b As New TokenBatch(Token) : b.Execute(command) : End Using
Return SFile.GetFiles(conf, "*.mp4", IO.SearchOption.AllDirectories, EDP.ReturnValue)
End If
Return Nothing
Catch ex As Exception
Return ErrorsDescriber.Execute(EDP.SendToLog, ex, "OnlyFans.UserData.OFS_DownloadFile", Nothing)
End Try
End Function
Private Function OFS_CreateConfig() As SFile
Try
Const confMainPattern$ = "{0}"": ""([^""]*)"""
If OFSCache Is Nothing Then OFSCache = If(IsSingleObjectDownload, Settings.Cache.NewInstance, CreateCache())
Dim currentCache As CacheKeeper = OFSCache.NewInstance
currentCache.Validate()
Dim cacheRoot As SFile = currentCache.NewPath
cacheRoot.Exists(SFO.Path, True, EDP.ThrowException)
Dim f As SFile = $"{SettingsFolderName}\OFScraperConfigPattern.json"
Dim configText$
If Not f.Exists Then
configText = Text.Encoding.UTF8.GetString(My.Resources.OFResources.OFScraperConfigPattern)
TextSaver.SaveTextToFile(configText, f, True)
End If
If f.Exists Then
Dim replaceValue$ = String.Empty
Dim rp As RParams = RParams.DMS(String.Empty, 1, RegexReturn.Replace, RegexOptions.IgnoreCase,
CType(Function(input) replaceValue, Func(Of String, String)), String.Empty, EDP.ReturnValue)
Dim ff As SFile
configText = f.GetText
Dim updateConf As Action(Of String, String) = Sub(ByVal patternValue As String, ByVal __replaceValue As String)
rp.Pattern = String.Format(confMainPattern, patternValue)
rp.Nothing = configText
replaceValue = __replaceValue
configText = RegexReplace(configText, rp)
End Sub
If Not configText.IsEmptyString Then
updateConf("save_location", cacheRoot.PathNoSeparator.Replace("\", "/"))
If ACheck(MySettings.OFScraperMP4decrypt.Value) Then
ff = CStr(MySettings.OFScraperMP4decrypt.Value)
If ff.Exists Then updateConf("mp4decrypt", ff.ToString.Replace("\", "/"))
End If
If Settings.FfmpegFile.Exists Then updateConf("ffmpeg", Settings.FfmpegFile.File.ToString.Replace("\", "/"))
updateConf("key-mode-default", CStr(MySettings.KeyModeDefault.Value).IfNullOrEmpty(SiteSettings.KeyModeDefault_Default))
f = currentCache
f.Name = "config"
f.Extension = "json"
If TextSaver.SaveTextToFile(configText, f, True).Exists AndAlso OFS_CreateAuth(currentCache) Then Return f
End If
End If
Return Nothing
Catch ex As Exception
Return ErrorsDescriber.Execute(EDP.SendToLog, ex, "OnlyFans.UserData.OFS_CreateConfig", Nothing)
End Try
End Function
Private Function OFS_CreateAuth(ByVal DestinationPath As SFile) As Boolean
Const authText$ = """user_agent"": ""{0}"",""app-token"": ""{1}"",""x-bc"": ""{2}"",""auth_id"": ""{3}"",""sess"": ""{4}"",""auth_uid_"": ""{3}"",""cookie"": ""{5}"""
Try
Dim sess$ = If(If(CCookie, Responser.Cookies).FirstOrDefault(Function(c) c.Name.StringToLower = "sess")?.Value, String.Empty)
Dim outText$ = "{""auth"":{" &
String.Format(authText,
MySettings.UserAgent.Value,
Responser.Headers.Value(SiteSettings.HeaderAppToken),
Responser.Headers.Value(SiteSettings.HeaderXBC),
MySettings.HH_USER_ID.Value,
sess,
If(CCookie, Responser.Cookies).ToString()) &
"}}"
If DestinationPath.Exists(SFO.Path, False) Then
Dim f As SFile = $"{DestinationPath.PathWithSeparator}main_profile\auth.json"
Return TextSaver.SaveTextToFile(outText, f, True).Exists
End If
Return False
Catch ex As Exception
Return ErrorsDescriber.Execute(EDP.SendToLog, ex, "OnlyFans.UserData.OFS_CreateAuth", False)
End Try
End Function
#End Region
#Region "DownloadContent" #Region "DownloadContent"
Private OFSPostFiles As Dictionary(Of String, List(Of SFile)) = Nothing
Protected Overrides Sub DownloadContent(ByVal Token As CancellationToken) Protected Overrides Sub DownloadContent(ByVal Token As CancellationToken)
DownloadContentDefault(Token) DownloadContentDefault(Token)
OFSCache.DisposeIfReady
OFSPostFiles.ListClearDispose
End Sub End Sub
Protected Overrides Function ValidateDownloadFile(ByVal URL As String, ByVal Media As UserMedia, ByRef Interrupt As Boolean) As Boolean
Return Media.Type = UTypes.VideoPre
End Function
Protected Overrides Function DownloadFile(ByVal URL As String, ByVal Media As UserMedia, ByVal DestinationFile As SFile,
ByVal Token As CancellationToken) As SFile
ValidateOFScraper()
If _OFScraperExists Then
If OFSPostFiles Is Nothing Then OFSPostFiles = New Dictionary(Of String, List(Of SFile))
If IsSingleObjectDownload Then
URL = Media.URL_BASE
Else
URL = GetPostUrl(Me, Media)
End If
If Not URL.IsEmptyString Then
Dim f As SFile = Nothing
If OFSPostFiles.Count > 0 AndAlso OFSPostFiles.ContainsKey(Media.Post.ID) AndAlso OFSPostFiles(Media.Post.ID).Count > 0 Then
f = OFSPostFiles(Media.Post.ID)(0)
OFSPostFiles(Media.Post.ID).RemoveAt(0)
Else
Dim files As List(Of SFile) = OFS_DownloadFile(URL, Token)
If files.ListExists Then
Dim ff As SFile
For i% = files.Count - 1 To 0 Step -1
ff = files(i)
DestinationFile.Name = ff.Name
DestinationFile.Extension = ff.Extension
If SFile.Move(ff, DestinationFile,,,, EDP.ThrowException) Then
files(i) = DestinationFile
Else
files.RemoveAt(i)
End If
Next
If files.Count > 0 Then
f = files(0)
files.RemoveAt(0)
If files.Count > 0 Then OFSPostFiles.Add(Media.Post.ID, files)
End If
End If
End If
Return f
End If
Return Nothing
Else
Throw New InvalidProgramException("OF-Scraper not found")
End If
End Function
#End Region #End Region
#Region "DownloadingException" #Region "DownloadingException"
Private _DownloadingException_AuthFileUpdate As Boolean = False Private _DownloadingException_AuthFileUpdate As Boolean = False
@@ -546,20 +715,22 @@ Namespace API.OnlyFans
Return 2 Return 2
Else Else
MySettings.SessionAborted = True MySettings.SessionAborted = True
MyMainLOG = $"{ToStringForLog()}: OnlyFans credentials expired" MyMainLOG = $"{ToStringForLog()} [{CInt(Responser.StatusCode)}]: OnlyFans credentials expired"
Return 1 Return 1
End If End If
ElseIf Responser.StatusCode = Net.HttpStatusCode.NotFound Then '404 ElseIf Responser.StatusCode = Net.HttpStatusCode.NotFound Then '404
UserExists = False UserExists = False
Return 1 Return 3
ElseIf Responser.StatusCode = Net.HttpStatusCode.GatewayTimeout Or Responser.StatusCode = 429 Then '504, 429 ElseIf Responser.StatusCode = Net.HttpStatusCode.GatewayTimeout Or Responser.StatusCode = 429 Then '504, 429
If Responser.StatusCode = 429 Then MyMainLOG = $"[429] OnlyFans too many requests ({ToStringForLog()})" If Responser.StatusCode = 429 Then MyMainLOG = $"[429] OnlyFans too many requests ({ToStringForLog()})"
MySettings.SessionAborted = True MySettings.SessionAborted = True
Return 1 Return 3
ElseIf Responser.StatusCode = Net.HttpStatusCode.Unauthorized Then '401 ElseIf Responser.StatusCode = Net.HttpStatusCode.Unauthorized Then '401
MySettings.SessionAborted = True MySettings.SessionAborted = True
MyMainLOG = $"{ToStringForLog()}: OnlyFans credentials expired" MyMainLOG = $"{ToStringForLog()} [{CInt(Responser.StatusCode)}]: OnlyFans credentials expired"
Return 1 Return 3
ElseIf Responser.StatusCode = Net.HttpStatusCode.InternalServerError Then '500
Return 3
Else Else
Return 0 Return 0
End If End If
@@ -567,7 +738,13 @@ Namespace API.OnlyFans
#End Region #End Region
#Region "IDisposable Support" #Region "IDisposable Support"
Protected Overrides Sub Dispose(ByVal disposing As Boolean) Protected Overrides Sub Dispose(ByVal disposing As Boolean)
If Not disposedValue And disposing Then CCookie.DisposeIfReady(False) : CCookie = Nothing : HighlightsList.Clear() If Not disposedValue And disposing Then
CCookie.DisposeIfReady(False)
CCookie = Nothing
HighlightsList.Clear()
OFSCache.DisposeIfReady
OFSPostFiles.ListClearDispose
End If
MyBase.Dispose(disposing) MyBase.Dispose(disposing)
End Sub End Sub
#End Region #End Region

View File

@@ -90,7 +90,7 @@ Namespace API.Reddit
UrlPatternUser = "https://www.reddit.com/{0}/{1}/" UrlPatternUser = "https://www.reddit.com/{0}/{1}/"
ImageVideoContains = "reddit.com" ImageVideoContains = "reddit.com"
UserRegex = RParams.DM("[htps:/]{7,8}.*?reddit.com/([user]{1,4})/([^/]+)", 0, RegexReturn.ListByMatch, EDP.ReturnValue) UserRegex = RParams.DM("[htps:/]{7,8}.*?reddit.com/([user]{1,4})/([^/\?&]+)", 0, RegexReturn.ListByMatch, EDP.ReturnValue)
End Sub End Sub
#End Region #End Region
#Region "GetInstance" #Region "GetInstance"

View File

@@ -49,7 +49,7 @@ Namespace API.RedGifs
TokenUpdateIntervalProvider = New TokenRefreshIntervalProvider TokenUpdateIntervalProvider = New TokenRefreshIntervalProvider
_AllowUserAgentUpdate = False _AllowUserAgentUpdate = False
UrlPatternUser = "https://www.redgifs.com/users/{0}/" UrlPatternUser = "https://www.redgifs.com/users/{0}/"
UserRegex = RParams.DMS("[htps:/]{7,8}.*?redgifs.com/users/([^/]+)", 1) UserRegex = RParams.DMS(String.Format(UserRegexDefaultPattern, "redgifs.com/users/"), 1)
ImageVideoContains = "redgifs" ImageVideoContains = "redgifs"
End Sub End Sub
#End Region #End Region

View File

@@ -55,8 +55,7 @@ Namespace API.ThisVid
#End Region #End Region
#Region "UpdateCookies" #Region "UpdateCookies"
Friend Sub UpdateCookies(ByVal Source As Responser) Friend Sub UpdateCookies(ByVal Source As Responser)
Responser.Cookies.Clear() Responser.Cookies.Update(Source.Cookies)
Responser.Cookies.AddRange(Source.Cookies)
Update_SaveCookiesNetscape(True) Update_SaveCookiesNetscape(True)
End Sub End Sub
#End Region #End Region

View File

@@ -178,6 +178,7 @@ Namespace API.ThisVid
Friend Sub New() Friend Sub New()
UseClientTokens = True UseClientTokens = True
SessionPosts = New List(Of String) SessionPosts = New List(Of String)
_ResponserAutoUpdateCookies = True
End Sub End Sub
#End Region #End Region
#Region "Validation" #Region "Validation"
@@ -225,31 +226,34 @@ Namespace API.ThisVid
Private AddedCount As Integer = 0 Private AddedCount As Integer = 0
Private _PageVideosRepeat As Integer = 0 Private _PageVideosRepeat As Integer = 0
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken) Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
SessionPosts.Clear() Try
AddedCount = 0 SessionPosts.Clear()
_PageVideosRepeat = 0 AddedCount = 0
SessionPosts.Clear() _PageVideosRepeat = 0
Responser.Cookies.ChangedAllowInternalDrop = False SessionPosts.Clear()
Responser.Cookies.Changed = False Responser.Cookies.ChangedAllowInternalDrop = False
If ID.IsEmptyString Then ID = Name Responser.Cookies.Changed = False
If Not IsUser OrElse IsValid() Then If ID.IsEmptyString Then ID = Name
If IsSavedPosts Then If Not IsUser OrElse IsValid() Then
DownloadData(1, 0, Token) If IsSavedPosts Then
DownloadData_Images(Token)
Else
If IsUser Then
If DownloadVideos Then
If DownloadPublic Then DownloadData(1, 0, Token)
If DownloadPrivate Then DownloadData(1, 1, Token)
If DownloadFavourite Then DownloadData(1, 2, Token)
End If
If DownloadImages And Not IsSubscription Then DownloadData_Images(Token)
Else
DownloadData(1, 0, Token) DownloadData(1, 0, Token)
DownloadData_Images(Token)
Else
If IsUser Then
If DownloadVideos Then
If DownloadPublic Then DownloadData(1, 0, Token)
If DownloadPrivate Then DownloadData(1, 1, Token)
If DownloadFavourite Then DownloadData(1, 2, Token)
End If
If DownloadImages And Not IsSubscription Then DownloadData_Images(Token)
Else
DownloadData(1, 0, Token)
End If
End If End If
End If End If
End If Finally
If Responser.Cookies.Changed Then MySettings.UpdateCookies(Responser) : Responser.Cookies.Changed = False If Responser.Cookies.Changed Then MySettings.UpdateCookies(Responser) : Responser.Cookies.Changed = False
End Try
End Sub End Sub
Friend Function GetNonUserUrl(ByVal Page As Integer) As String Friend Function GetNonUserUrl(ByVal Page As Integer) As String
Dim url$ = String.Empty Dim url$ = String.Empty

View File

@@ -19,7 +19,7 @@ Namespace API.ThreadsNet
#Region "Declarations" #Region "Declarations"
#Region "Authorization" #Region "Authorization"
<PClonable(Clone:=False)> Protected ReadOnly __HH_CSRF_TOKEN As PropertyValue <PClonable(Clone:=False)> Protected ReadOnly __HH_CSRF_TOKEN As PropertyValue
<PropertyOption(ControlText:="x-csrftoken", AllowNull:=False, IsAuth:=True), ControlNumber(0)> <PropertyOption(ControlText:="x-csrftoken", AllowNull:=True, IsAuth:=True), ControlNumber(0)>
Friend Overridable ReadOnly Property HH_CSRF_TOKEN As PropertyValue Friend Overridable ReadOnly Property HH_CSRF_TOKEN As PropertyValue
Get Get
Return __HH_CSRF_TOKEN Return __HH_CSRF_TOKEN
@@ -126,7 +126,7 @@ Namespace API.ThreadsNet
HH_USER_AGENT = New PropertyValue(useragent, GetType(String), Sub(v) ChangeResponserFields(NameOf(HH_USER_AGENT), v)) HH_USER_AGENT = New PropertyValue(useragent, GetType(String), Sub(v) ChangeResponserFields(NameOf(HH_USER_AGENT), v))
UrlPatternUser = "https://www.threads.net/@{0}" UrlPatternUser = "https://www.threads.net/@{0}"
UserRegex = RParams.DMS("threads.net/@([^/\?&]+)", 1) UserRegex = RParams.DMS(String.Format(UserRegexDefaultPattern, "threads.net/@"), 1)
ImageVideoContains = "threads.net" ImageVideoContains = "threads.net"
End Sub End Sub
#End Region #End Region
@@ -165,6 +165,15 @@ Namespace API.ThreadsNet
Return ErrorsDescriber.Execute(EDP.SendToLog, ex, "Can't open user's post", String.Empty) Return ErrorsDescriber.Execute(EDP.SendToLog, ex, "Can't open user's post", String.Empty)
End Try End Try
End Function End Function
#End Region
#Region "Update"
Friend Overrides Sub Update()
If _SiteEditorFormOpened And Responser.CookiesExists Then
Dim csrf$ = If(Responser.Cookies.FirstOrDefault(Function(c) c.Name.StringToLower = IG.Header_CSRF_TOKEN_COOKIE)?.Value, String.Empty)
If Not csrf.IsEmptyString Then HH_CSRF_TOKEN.Value = csrf
End If
MyBase.Update()
End Sub
#End Region #End Region
End Class End Class
End Namespace End Namespace

View File

@@ -18,14 +18,11 @@ Imports IGS = SCrawler.API.Instagram.SiteSettings
Namespace API.ThreadsNet Namespace API.ThreadsNet
Friend Class UserData : Inherits Instagram.UserData Friend Class UserData : Inherits Instagram.UserData
#Region "Declarations" #Region "Declarations"
Friend Const Header_FB_LSD As String = "x-fb-lsd"
Private ReadOnly Property MySettings As SiteSettings Private ReadOnly Property MySettings As SiteSettings
Get Get
Return HOST.Source Return HOST.Source
End Get End Get
End Property End Property
Private ReadOnly ObtainMedia_SizeFuncPic_RegexP As RParams = RParams.DMS("_p(\d+)x(\d+)", 1, EDP.ReturnValue)
Private ReadOnly ObtainMedia_SizeFuncPic_RegexS As RParams = RParams.DMS("_s(\d+)x(\d+)", 1, EDP.ReturnValue)
Private ReadOnly DefaultParser_ElemNode_Default() As Object = {"node", "thread_items", 0, "post"} Private ReadOnly DefaultParser_ElemNode_Default() As Object = {"node", "thread_items", 0, "post"}
Private OPT_LSD As String = String.Empty Private OPT_LSD As String = String.Empty
Private OPT_FB_DTSG As String = String.Empty Private OPT_FB_DTSG As String = String.Empty
@@ -48,23 +45,12 @@ Namespace API.ThreadsNet
#End Region #End Region
#Region "Initializer" #Region "Initializer"
Friend Sub New() Friend Sub New()
ObtainMedia_SizeFuncPic = Function(ByVal ss As EContainer) As Sizes ObtainMedia_SetReelsFunc()
If ss.Value("url").IsEmptyString Then
Return New Sizes("----", "")
ElseIf Not ss.Value("width").IsEmptyString Then
Return New Sizes(ss.Value("height").IfNullOrEmpty(ss.Value("width")), ss.Value("url"))
Else
Dim rval$ = RegexReplace(ss.Value("url"), ObtainMedia_SizeFuncPic_RegexP)
If Not rval.IsEmptyString Then Return New Sizes(rval, ss.Value("url"))
rval = RegexReplace(ss.Value("url"), ObtainMedia_SizeFuncPic_RegexS)
If Not rval.IsEmptyString Then Return New Sizes(AConvert(Of Integer)(rval, 1) * -1, ss.Value("url"))
Return New Sizes(10000, ss.Value("url"))
End If
End Function
ObtainMedia_SizeFuncVid = Function(ss) If(ss.Value("url").IsEmptyString, New Sizes("----", ""), New Sizes(10000, ss.Value("url")))
ObtainMedia_AllowAbstract = True ObtainMedia_AllowAbstract = True
DefaultParser_ElemNode = DefaultParser_ElemNode_Default DefaultParser_ElemNode = DefaultParser_ElemNode_Default
DefaultParser_PostUrlCreator = Function(post) $"https://www.threads.net/@{NameTrue}/post/{post.Code}" DefaultParser_PostUrlCreator = Function(post) $"https://www.threads.net/@{NameTrue}/post/{post.Code}"
_ResponserAutoUpdateCookies = True
_ResponserAddResponseReceivedHandler = True
End Sub End Sub
#End Region #End Region
#Region "Download functions" #Region "Download functions"
@@ -72,7 +58,6 @@ Namespace API.ThreadsNet
Dim errorFound As Boolean = False Dim errorFound As Boolean = False
Try Try
Responser.Method = "POST" Responser.Method = "POST"
AddHandler Responser.ResponseReceived, AddressOf Responser_ResponseReceived
LoadSavePostsKV(True) LoadSavePostsKV(True)
OPT_LSD = String.Empty OPT_LSD = String.Empty
OPT_FB_DTSG = String.Empty OPT_FB_DTSG = String.Empty
@@ -170,11 +155,11 @@ Namespace API.ThreadsNet
Responser.Method = "GET" Responser.Method = "GET"
Responser.Referer = URL Responser.Referer = URL
Responser.Headers.Remove(Header_FB_LSD) Responser.Headers.Remove(Header_FB_LSD)
Dim r$ = Responser.GetResponse(URL,, EDP.SendToLog + EDP.ThrowException) Dim r$ = Responser.GetResponse(URL,, EDP.ThrowException)
Dim rr As RParams Dim rr As RParams
Dim tt$, ttVal$ Dim tt$, ttVal$
If Not r.IsEmptyString Then If Not r.IsEmptyString Then
rr = RParams.DM("\[\],{""token"":""(.*?)""},\d+\]", 0, RegexReturn.List, EDP.ReturnValue) rr = RParams.DM(Instagram.PageTokenRegexPatternDefault, 0, RegexReturn.List, EDP.ReturnValue)
Dim tokens As List(Of String) = RegexReplace(r, rr) Dim tokens As List(Of String) = RegexReplace(r, rr)
If tokens.ListExists Then If tokens.ListExists Then
With rr With rr
@@ -205,7 +190,12 @@ Namespace API.ThreadsNet
If OPT_FB_DTSG.IsEmptyString Then notFound.StringAppend(Header_FB_LSD) If OPT_FB_DTSG.IsEmptyString Then notFound.StringAppend(Header_FB_LSD)
If OPT_LSD.IsEmptyString Then notFound.StringAppend("lsd") If OPT_LSD.IsEmptyString Then notFound.StringAppend("lsd")
If ID.IsEmptyString Then notFound.StringAppend("User ID") If ID.IsEmptyString Then notFound.StringAppend("User ID")
LogError(ex, $"failed to update some{IIf(notFound.IsEmptyString, String.Empty, $" ({notFound})")} credentials", e) Dim eex As New ErrorsDescriberException($"{ToStringForLog()}: failed to update some{IIf(notFound.IsEmptyString, String.Empty, $" ({notFound})")} credentials",,, ex) With {
.ReplaceMainMessage = True,
.SendToLogOnlyMessage = Responser.StatusCode = Net.HttpStatusCode.InternalServerError And Responser.Status = Net.WebExceptionStatus.ProtocolError
}
'LogError(ex, $"failed to update some{IIf(notFound.IsEmptyString, String.Empty, $" ({notFound})")} credentials", e)
LogError(eex, String.Empty, e)
Return False Return False
End Try End Try
End Function End Function

View File

@@ -22,6 +22,10 @@ Namespace API.TikTok
Friend ReadOnly Property TitleUseNativeSTD As PropertyValue Friend ReadOnly Property TitleUseNativeSTD As PropertyValue
<PropertyOption(ControlText:="Add video ID to video title"), PXML, PClonable> <PropertyOption(ControlText:="Add video ID to video title"), PXML, PClonable>
Friend ReadOnly Property TitleAddVideoID As PropertyValue Friend ReadOnly Property TitleAddVideoID As PropertyValue
<PropertyOption(ControlText:="Use regex to clean video title"), PXML, PClonable>
Friend ReadOnly Property TitleUseRegexForTitle As PropertyValue
<PropertyOption(ControlText:="Title regex", ControlToolTip:="Regex to clean video title"), PXML, PClonable>
Friend ReadOnly Property TitleUseRegexForTitle_Value As PropertyValue
<PropertyOption(ControlText:="Use video date as file date", <PropertyOption(ControlText:="Use video date as file date",
ControlToolTip:="Set the file date to the date the video was added (website) (if available)."), PXML, PClonable> ControlToolTip:="Set the file date to the date the video was added (website) (if available)."), PXML, PClonable>
Friend ReadOnly Property UseParsedVideoDate As PropertyValue Friend ReadOnly Property UseParsedVideoDate As PropertyValue
@@ -31,10 +35,12 @@ Namespace API.TikTok
TitleUseNative = New PropertyValue(True) TitleUseNative = New PropertyValue(True)
TitleUseNativeSTD = New PropertyValue(False) TitleUseNativeSTD = New PropertyValue(False)
TitleAddVideoID = New PropertyValue(True) TitleAddVideoID = New PropertyValue(True)
TitleUseRegexForTitle = New PropertyValue(False)
TitleUseRegexForTitle_Value = New PropertyValue(String.Empty, GetType(String))
UseParsedVideoDate = New PropertyValue(True) UseParsedVideoDate = New PropertyValue(True)
UseNetscapeCookies = True UseNetscapeCookies = True
UrlPatternUser = "https://www.tiktok.com/@{0}/" UrlPatternUser = "https://www.tiktok.com/@{0}/"
UserRegex = RParams.DMS("[htps:/]{7,8}.*?tiktok.com/@([^/]+)", 1) UserRegex = RParams.DMS(String.Format(UserRegexDefaultPattern, "tiktok.com/@"), 1)
ImageVideoContains = "tiktok.com" ImageVideoContains = "tiktok.com"
End Sub End Sub
Friend Overrides Function GetInstance(ByVal What As ISiteSettings.Download) As IPluginContentProvider Friend Overrides Function GetInstance(ByVal What As ISiteSettings.Download) As IPluginContentProvider

View File

@@ -20,6 +20,9 @@ Namespace API.TikTok
Private Const Name_TitleUseNative As String = "TitleUseNative" Private Const Name_TitleUseNative As String = "TitleUseNative"
Private Const Name_TitleAddVideoID As String = "TitleAddVideoID" Private Const Name_TitleAddVideoID As String = "TitleAddVideoID"
Private Const Name_LastDownloadDate As String = "LastDownloadDate" Private Const Name_LastDownloadDate As String = "LastDownloadDate"
Private Const Name_TitleUseRegexForTitle As String = "TitleUseRegexForTitle"
Private Const Name_TitleUseRegexForTitle_Value As String = "TitleUseRegexForTitle_Value"
Private Const Name_TitleUseGlobalRegexOptions As String = "TitleUseGlobalRegexOptions"
#End Region #End Region
#Region "Declarations" #Region "Declarations"
Private ReadOnly Property MySettings As SiteSettings Private ReadOnly Property MySettings As SiteSettings
@@ -27,26 +30,37 @@ Namespace API.TikTok
Return HOST.Source Return HOST.Source
End Get End Get
End Property End Property
Private UserCache As CacheKeeper = Nothing
Private ReadOnly Property RootCacheTikTok As ICacheKeeper Private ReadOnly Property RootCacheTikTok As ICacheKeeper
Get Get
With Settings.Cache If Not UserCache Is Nothing AndAlso Not UserCache.Disposed Then
Dim f As SFile = $"{Settings.Cache.RootDirectory.PathWithSeparator}TikTokCache\" With DirectCast(UserCache.NewInstance(Of BatchFileExchanger), BatchFileExchanger)
If .ContainsFolder(f) Then .Validate()
Return .GetInstance(f) Return .Self
Else End With
f.Exists(SFO.Path, True) Else
With .NewInstance(Of BatchFileExchanger)(f) With Settings.Cache
.DeleteCacheOnDispose = False Dim f As SFile = $"{Settings.Cache.RootDirectory.PathWithSeparator}TikTokCache\"
.DeleteRootOnDispose = False If .ContainsFolder(f) Then
Return .Self Return .GetInstance(f)
End With Else
End If f.Exists(SFO.Path, True)
End With With .NewInstance(Of BatchFileExchanger)(f)
.DeleteCacheOnDispose = False
.DeleteRootOnDispose = False
Return .Self
End With
End If
End With
End If
End Get End Get
End Property End Property
Friend Property RemoveTagsFromTitle As Boolean = False Friend Property RemoveTagsFromTitle As Boolean = False
Friend Property TitleUseNative As Boolean = True Friend Property TitleUseNative As Boolean = True
Friend Property TitleAddVideoID As Boolean = True Friend Property TitleAddVideoID As Boolean = True
Friend Property TitleUseRegexForTitle As Boolean = False
Friend Property TitleUseRegexForTitle_Value As String = String.Empty
Friend Property TitleUseGlobalRegexOptions As Boolean = True
Private Property LastDownloadDate As Date? = Nothing Private Property LastDownloadDate As Date? = Nothing
Private _TrueName As String = String.Empty Private _TrueName As String = String.Empty
Friend Property TrueName As String Friend Property TrueName As String
@@ -68,6 +82,9 @@ Namespace API.TikTok
RemoveTagsFromTitle = .RemoveTagsFromTitle RemoveTagsFromTitle = .RemoveTagsFromTitle
TitleUseNative = .TitleUseNative TitleUseNative = .TitleUseNative
TitleAddVideoID = .TitleAddVideoID TitleAddVideoID = .TitleAddVideoID
TitleUseRegexForTitle = .TitleUseRegexForTitle
TitleUseRegexForTitle_Value = .TitleUseRegexForTitle_Value
TitleUseGlobalRegexOptions = .TitleUseGlobalRegexOptions
End With End With
End If End If
End Sub End Sub
@@ -82,12 +99,18 @@ Namespace API.TikTok
LastDownloadDate = AConvert(Of Date)(.Value(Name_LastDownloadDate), ADateTime.Formats.BaseDateTime, Nothing) LastDownloadDate = AConvert(Of Date)(.Value(Name_LastDownloadDate), ADateTime.Formats.BaseDateTime, Nothing)
If Not LastDownloadDate.HasValue Then LastDownloadDate = LastUpdated If Not LastDownloadDate.HasValue Then LastDownloadDate = LastUpdated
_TrueName = .Value(Name_TrueName) _TrueName = .Value(Name_TrueName)
TitleUseRegexForTitle = .Value(Name_TitleUseRegexForTitle).FromXML(Of Boolean)(False)
TitleUseRegexForTitle_Value = .Value(Name_TitleUseRegexForTitle_Value)
TitleUseGlobalRegexOptions = .Value(Name_TitleUseGlobalRegexOptions).FromXML(Of Boolean)(True)
Else Else
.Add(Name_RemoveTagsFromTitle, RemoveTagsFromTitle.BoolToInteger) .Add(Name_RemoveTagsFromTitle, RemoveTagsFromTitle.BoolToInteger)
.Add(Name_TitleUseNative, TitleUseNative.BoolToInteger) .Add(Name_TitleUseNative, TitleUseNative.BoolToInteger)
.Add(Name_TitleAddVideoID, TitleAddVideoID.BoolToInteger) .Add(Name_TitleAddVideoID, TitleAddVideoID.BoolToInteger)
.Add(Name_LastDownloadDate, AConvert(Of String)(LastDownloadDate, AModes.XML, ADateTime.Formats.BaseDateTime, String.Empty)) .Add(Name_LastDownloadDate, AConvert(Of String)(LastDownloadDate, AModes.XML, ADateTime.Formats.BaseDateTime, String.Empty))
.Add(Name_TrueName, _TrueName) .Add(Name_TrueName, _TrueName)
.Add(Name_TitleUseRegexForTitle, TitleUseRegexForTitle.BoolToInteger)
.Add(Name_TitleUseRegexForTitle_Value, TitleUseRegexForTitle_Value)
.Add(Name_TitleUseGlobalRegexOptions, TitleUseGlobalRegexOptions.BoolToInteger)
End If End If
End With End With
End Sub End Sub
@@ -99,110 +122,146 @@ Namespace API.TikTok
End Sub End Sub
#End Region #End Region
#Region "Download functions" #Region "Download functions"
Private Function GetTitleRegex() As RParams
Dim titleRegex As RParams = Nothing
If TitleUseGlobalRegexOptions Then
If CBool(MySettings.TitleUseRegexForTitle.Value) AndAlso Not CStr(MySettings.TitleUseRegexForTitle_Value.Value).IsEmptyString Then _
titleRegex = RParams.DM(MySettings.TitleUseRegexForTitle_Value.Value, 0, RegexReturn.List, EDP.ReturnValue)
ElseIf TitleUseRegexForTitle And Not TitleUseRegexForTitle_Value.IsEmptyString Then
titleRegex = RParams.DM(TitleUseRegexForTitle_Value, 0, RegexReturn.List, EDP.ReturnValue)
End If
If Not titleRegex Is Nothing Then
titleRegex.NothingExists = True
titleRegex.Nothing = New List(Of String)
titleRegex.Converter = Function(input) input.StringTrim
End If
Return titleRegex
End Function
Private Function ChangeTitleRegex(ByVal Title As String, ByVal Regex As RParams) As String
Try
If Not Regex Is Nothing Then
With DirectCast(RegexReplace(Title, Regex), List(Of String))
If .ListExists Then
Dim newTitle$ = .ListToString(String.Empty, EDP.ReturnValue).StringTrim
If Not newTitle.IsEmptyString Then Return newTitle
End If
End With
End If
Catch ex As Exception
End Try
Return Title
End Function
Friend Overrides Sub DownloadData(ByVal Token As CancellationToken)
MyBase.DownloadData(Token)
UserCache.DisposeIfReady(False)
UserCache = Nothing
End Sub
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken) Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
Dim URL$ = $"https://www.tiktok.com/@{TrueName}" Dim URL$ = $"https://www.tiktok.com/@{TrueName}"
Using cache As CacheKeeper = CreateCache() UserCache = CreateCache()
Try Try
Dim postID$, title$, postUrl$, newName$ Dim postID$, title$, postUrl$, newName$
Dim postDate As Date? Dim postDate As Date?
Dim dateAfterC As Date? = Nothing Dim dateAfterC As Date? = Nothing
Dim dateBefore As Date? = DownloadDateTo Dim dateBefore As Date? = DownloadDateTo
Dim dateAfter As Date? = DownloadDateFrom Dim dateAfter As Date? = DownloadDateFrom
Dim baseDataObtained As Boolean = False Dim baseDataObtained As Boolean = False
Dim titleRegex As RParams = GetTitleRegex()
If _ContentList.Count > 0 Then If _ContentList.Count > 0 Then
With (From d In _ContentList Where d.Post.Date.HasValue Select d.Post.Date.Value) With (From d In _ContentList Where d.Post.Date.HasValue Select d.Post.Date.Value)
If .ListExists Then dateAfterC = .Min If .ListExists Then dateAfterC = .Min
End With
End If
With {CStr(AConvert(Of String)(dateAfter, SimpleDateConverter, String.Empty)).FromXML(Of Integer)(-1),
CStr(AConvert(Of String)(dateAfterC, SimpleDateConverter, String.Empty)).FromXML(Of Integer)(-1)}.ListWithRemove(Function(d) d = -1)
If .ListExists Then dateAfter = AConvert(Of Date)(CStr(.Min), SimpleDateConverter, Nothing)
End With End With
End If
If LastDownloadDate.HasValue Then With {CStr(AConvert(Of String)(dateAfter, SimpleDateConverter, String.Empty)).FromXML(Of Integer)(-1),
If Not DownloadDateTo.HasValue And Not DownloadDateFrom.HasValue Then CStr(AConvert(Of String)(dateAfterC, SimpleDateConverter, String.Empty)).FromXML(Of Integer)(-1)}.ListWithRemove(Function(d) d = -1)
If LastDownloadDate.Value.AddDays(1) <= Now Then If .ListExists Then dateAfter = AConvert(Of Date)(CStr(.Min), SimpleDateConverter, Nothing)
dateAfter = LastDownloadDate.Value End With
Else
dateAfter = LastDownloadDate.Value.AddDays(-1) If LastDownloadDate.HasValue Then
End If If Not DownloadDateTo.HasValue And Not DownloadDateFrom.HasValue Then
dateBefore = Nothing If LastDownloadDate.Value.AddDays(1) <= Now Then
ElseIf dateAfter.HasValue And Not DownloadDateFrom.HasValue Then dateAfter = LastDownloadDate.Value
If (LastDownloadDate.Value - dateAfter.Value).TotalDays > 1 Then dateAfter = dateAfter.Value.AddDays(1) Else
dateAfter = LastDownloadDate.Value.AddDays(-1)
End If End If
dateBefore = Nothing
ElseIf dateAfter.HasValue And Not DownloadDateFrom.HasValue Then
If (LastDownloadDate.Value - dateAfter.Value).TotalDays > 1 Then dateAfter = dateAfter.Value.AddDays(1)
End If End If
End If
Using b As New YTDLP.YTDLPBatch(Token) With {.TempPostsList = _TempPostsList} Using b As New YTDLP.YTDLPBatch(Token) With {.TempPostsList = _TempPostsList}
b.Commands.Clear() b.Commands.Clear()
b.ChangeDirectory(cache) b.ChangeDirectory(UserCache)
b.Encoding = BatchExecutor.UnicodeEncoding b.Encoding = BatchExecutor.UnicodeEncoding
b.Execute(CreateYTCommand(cache.RootDirectory, URL, False, dateBefore, dateAfter)) b.Execute(CreateYTCommand(UserCache.RootDirectory, URL, False, dateBefore, dateAfter))
End Using End Using
ThrowAny(Token) ThrowAny(Token)
Dim files As List(Of SFile) = SFile.GetFiles(cache, "*.json",, EDP.ReturnValue) Dim files As List(Of SFile) = SFile.GetFiles(UserCache, "*.json",, EDP.ReturnValue)
If files.ListExists Then If files.ListExists Then
Dim j As EContainer Dim j As EContainer
For Each file As SFile In files For Each file As SFile In files
j = JsonDocument.Parse(file.GetText, EDP.ReturnValue) j = JsonDocument.Parse(file.GetText, EDP.ReturnValue)
If j.ListExists Then If j.ListExists Then
If j.Value("_type").StringToLower = "video" Then If j.Value("_type").StringToLower = "video" Then
If Not baseDataObtained Then If Not baseDataObtained Then
baseDataObtained = True baseDataObtained = True
If ID.IsEmptyString Then If ID.IsEmptyString Then
ID = j.Value("uploader_id") ID = j.Value("uploader_id")
If Not ID.IsEmptyString Then _ForceSaveUserInfo = True If Not ID.IsEmptyString Then _ForceSaveUserInfo = True
End If
newName = j.Value("uploader")
If Not newName.IsEmptyString Then
If Not _TrueName = newName Then _ForceSaveUserInfo = True
_TrueName = newName
End If
newName = j.Value("creator")
If Not newName.IsEmptyString Then UserSiteName = newName
End If End If
postID = j.Value("id") newName = j.Value("uploader")
If Not _TempPostsList.Contains(postID) Then If Not newName.IsEmptyString Then
_TempPostsList.Add(postID) If Not _TrueName = newName Then _ForceSaveUserInfo = True
Else _TrueName = newName
Exit Sub
End If End If
title = j.Value("title").StringRemoveWinForbiddenSymbols newName = j.Value("creator")
If title.IsEmptyString Or Not TitleUseNative Then If Not newName.IsEmptyString Then UserSiteName = newName
title = postID
Else
If RemoveTagsFromTitle Then title = RegexReplace(title, RegexTagsReplacer)
title = title.StringTrim
If title.IsEmptyString Then
title = postID
ElseIf TitleAddVideoID Then
title &= $" ({postID})"
End If
End If
postDate = AConvert(Of Date)(j.Value("timestamp"), UnixDate32Provider, Nothing)
If Not postDate.HasValue Then postDate = AConvert(Of Date)(j.Value("upload_date"), SimpleDateConverter, Nothing)
Select Case CheckDatesLimit(postDate, SimpleDateConverter)
Case DateResult.Skip : Continue For
Case DateResult.Exit : Exit Sub
End Select
postUrl = j.Value("webpage_url")
If postUrl.IsEmptyString Then postUrl = $"https://www.tiktok.com/@{Name}/video/{postID}"
_TempMediaList.Add(New UserMedia(postUrl, UserMedia.Types.Video) With {
.File = $"{title}.mp4", .Post = New UserPost(postID, postDate)})
End If End If
j.Dispose() postID = j.Value("id")
If Not _TempPostsList.Contains(postID) Then
_TempPostsList.Add(postID)
Else
Exit Sub
End If
title = j.Value("title").StringRemoveWinForbiddenSymbols
If Not title.IsEmptyString Then title = Left(title, 150)
If title.IsEmptyString Or Not TitleUseNative Then
title = postID
Else
If RemoveTagsFromTitle Then title = RegexReplace(title, RegexTagsReplacer)
title = title.StringTrim
If title.IsEmptyString Then
title = postID
ElseIf TitleAddVideoID Then
title &= $" ({postID})"
End If
title = ChangeTitleRegex(title, titleRegex)
End If
postDate = AConvert(Of Date)(j.Value("timestamp"), UnixDate32Provider, Nothing)
If Not postDate.HasValue Then postDate = AConvert(Of Date)(j.Value("upload_date"), SimpleDateConverter, Nothing)
Select Case CheckDatesLimit(postDate, SimpleDateConverter)
Case DateResult.Skip : Continue For
Case DateResult.Exit : Exit Sub
End Select
postUrl = j.Value("webpage_url")
If postUrl.IsEmptyString Then postUrl = $"https://www.tiktok.com/@{Name}/video/{postID}"
_TempMediaList.Add(New UserMedia(postUrl, UserMedia.Types.Video) With {
.File = $"{title}.mp4", .Post = New UserPost(postID, postDate)})
End If End If
Next j.Dispose()
End If End If
If _TempMediaList.Count > 0 Then LastDownloadDate = Now Next
Catch ex As Exception End If
ProcessException(ex, Token, $"data downloading error [{URL}]") If _TempMediaList.Count > 0 Then LastDownloadDate = Now
End Try Catch ex As Exception
End Using ProcessException(ex, Token, $"data downloading error [{URL}]")
End Try
End Sub End Sub
#End Region #End Region
#Region "ReparseMissing" #Region "ReparseMissing"
@@ -262,7 +321,7 @@ Namespace API.TikTok
b.Encoding = BatchExecutor.UnicodeEncoding b.Encoding = BatchExecutor.UnicodeEncoding
b.Execute(CreateYTCommand(DestinationFile, URL, True)) b.Execute(CreateYTCommand(DestinationFile, URL, True))
End Using End Using
Return DestinationFile If DestinationFile.Exists Then Return DestinationFile Else Return Nothing
End Function End Function
#End Region #End Region
#Region "DownloadSingleObject" #Region "DownloadSingleObject"
@@ -292,6 +351,7 @@ Namespace API.TikTok
f = f.StringTrim f = f.StringTrim
If Not f.IsEmptyString Then If Not f.IsEmptyString Then
If CBool(MySettings.TitleAddVideoID.Value) Then f &= $" ({m.File.Name})" If CBool(MySettings.TitleAddVideoID.Value) Then f &= $" ({m.File.Name})"
f = ChangeTitleRegex(f, GetTitleRegex)
m.File.Name = f m.File.Name = f
End If End If
End If End If
@@ -303,6 +363,15 @@ Namespace API.TikTok
Optional ByVal EObj As Object = Nothing) As Integer Optional ByVal EObj As Object = Nothing) As Integer
Return 0 Return 0
End Function End Function
#End Region
#Region "IDisposable Support"
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
If Not disposedValue And disposing Then
UserCache.DisposeIfReady(False)
UserCache = Nothing
End If
MyBase.Dispose(disposing)
End Sub
#End Region #End Region
End Class End Class
End Namespace End Namespace

View File

@@ -15,18 +15,29 @@ Namespace API.TikTok
Friend Property TitleUseNative As Boolean Friend Property TitleUseNative As Boolean
<PSetting(NameOf(SiteSettings.TitleAddVideoID), NameOf(MySettings))> <PSetting(NameOf(SiteSettings.TitleAddVideoID), NameOf(MySettings))>
Friend Property TitleAddVideoID As Boolean Friend Property TitleAddVideoID As Boolean
<PSetting(NameOf(SiteSettings.TitleUseRegexForTitle), NameOf(MySettings))>
Friend Property TitleUseRegexForTitle As Boolean
<PSetting(NameOf(SiteSettings.TitleUseRegexForTitle_Value), NameOf(MySettings))>
Friend Property TitleUseRegexForTitle_Value As String
<PSetting(Caption:="Use global regex", ToolTip:="Use the global regex from the site settings to clean the video title")>
Friend Property TitleUseGlobalRegexOptions As Boolean = True
Private ReadOnly MySettings As SiteSettings Private ReadOnly MySettings As SiteSettings
Friend Sub New(ByVal u As UserData) Friend Sub New(ByVal u As UserData)
MySettings = u.HOST.Source MySettings = u.HOST.Source
RemoveTagsFromTitle = u.RemoveTagsFromTitle RemoveTagsFromTitle = u.RemoveTagsFromTitle
TitleUseNative = u.TitleUseNative TitleUseNative = u.TitleUseNative
TitleAddVideoID = u.TitleAddVideoID TitleAddVideoID = u.TitleAddVideoID
TitleUseRegexForTitle = u.TitleUseRegexForTitle
TitleUseRegexForTitle_Value = u.TitleUseRegexForTitle_Value
TitleUseGlobalRegexOptions = u.TitleUseGlobalRegexOptions
End Sub End Sub
Friend Sub New(ByVal s As SiteSettings) Friend Sub New(ByVal s As SiteSettings)
MySettings = s MySettings = s
RemoveTagsFromTitle = s.RemoveTagsFromTitle.Value RemoveTagsFromTitle = s.RemoveTagsFromTitle.Value
TitleUseNative = s.TitleUseNative.Value TitleUseNative = s.TitleUseNative.Value
TitleAddVideoID = s.TitleAddVideoID.Value TitleAddVideoID = s.TitleAddVideoID.Value
TitleUseRegexForTitle = s.TitleUseRegexForTitle.Value
TitleUseRegexForTitle_Value = s.TitleUseRegexForTitle_Value.Value
End Sub End Sub
End Class End Class
End Namespace End Namespace

View File

@@ -96,7 +96,7 @@ Namespace API.Twitter
ConcurrentDownloads = New PropertyValue(1) ConcurrentDownloads = New PropertyValue(1)
MyConcurrentDownloadsProvider = New ConcurrentDownloadsProvider MyConcurrentDownloadsProvider = New ConcurrentDownloadsProvider
UserRegex = RParams.DMS("[htps:/]{7,8}.*?twitter.com/([^/]+)", 1) UserRegex = RParams.DMS(String.Format(UserRegexDefaultPattern, "/(twitter|x).com/"), 2)
UrlPatternUser = "https://twitter.com/{0}" UrlPatternUser = "https://twitter.com/{0}"
ImageVideoContains = "twitter" ImageVideoContains = "twitter"
CheckNetscapeCookiesOnEndInit = True CheckNetscapeCookiesOnEndInit = True

View File

@@ -157,7 +157,6 @@ Namespace API.Twitter
Private Sub DownloadData_Timeline(ByVal Token As CancellationToken) Private Sub DownloadData_Timeline(ByVal Token As CancellationToken)
Dim URL$ = String.Empty Dim URL$ = String.Empty
Dim tCache As CacheKeeper = Nothing Dim tCache As CacheKeeper = Nothing
Dim jsonArgs As New WebDocumentEventArgs With {.DeclaredError = EDP.ThrowException}
Try Try
Const entry$ = "entry" Const entry$ = "entry"
Dim PostID$ = String.Empty Dim PostID$ = String.Empty
@@ -237,8 +236,7 @@ Namespace API.Twitter
For i = 0 To timelineFiles.Count - 1 : timelineFiles(i) = RenameGdlFile(timelineFiles(i), i) : Next For i = 0 To timelineFiles.Count - 1 : timelineFiles(i) = RenameGdlFile(timelineFiles(i), i) : Next
'parse files 'parse files
For i = 0 To timelineFiles.Count - 1 For i = 0 To timelineFiles.Count - 1
j = JsonDocument.Parse(timelineFiles(i).GetText, jsonArgs) j = JsonDocument.Parse(timelineFiles(i).GetText)
jsonArgs.Reset()
If Not j Is Nothing Then If Not j Is Nothing Then
If i = 0 Then If i = 0 Then
If Not userInfoParsed Then If Not userInfoParsed Then
@@ -363,15 +361,14 @@ Namespace API.Twitter
End If End If
DownloadModelForceApply = False DownloadModelForceApply = False
FirstDownloadComplete = True FirstDownloadComplete = True
Catch jsonNull_ex As ArgumentNullException When jsonArgs.State = WebDocumentEventArgs.States.Error Catch jsonNull_ex As JsonDocumentException When jsonNull_ex.State = WebDocumentEventArgs.States.Error
Throw New Plugin.ExitException($"{ToStringForLog()}: No deserialized data found") Throw New Plugin.ExitException("No deserialized data found")
Catch limit_ex As TwitterLimitException Catch limit_ex As TwitterLimitException
Throw limit_ex Throw limit_ex
Catch ex As Exception Catch ex As Exception
ProcessException(ex, Token, $"data downloading error [{URL}]") ProcessException(ex, Token, $"data downloading error [{URL}]")
Finally Finally
If Not tCache Is Nothing Then tCache.Dispose() If Not tCache Is Nothing Then tCache.Dispose()
jsonArgs.DisposeIfReady
If _TempPostsList.Count > 0 Then _TempPostsList.Sort() If _TempPostsList.Count > 0 Then _TempPostsList.Sort()
End Try End Try
End Sub End Sub

View File

@@ -741,6 +741,15 @@ Namespace API
Return GetEnumerator() Return GetEnumerator()
End Function End Function
#End Region #End Region
#Region "IComparable Support"
Friend Overrides Function CompareTo(ByVal Other As UserDataBase) As Integer
If TypeOf Other Is UserDataBind Then
Return CollectionName.CompareTo(Other.CollectionName)
Else
Return -1
End If
End Function
#End Region
#Region "IEquatable support" #Region "IEquatable support"
Friend Overrides Function Equals(ByVal Other As UserDataBase) As Boolean Friend Overrides Function Equals(ByVal Other As UserDataBase) As Boolean
If Other.IsCollection Then If Other.IsCollection Then

View File

@@ -84,10 +84,15 @@ Namespace API.Xhamster
End Function End Function
Private Shared Function ObtainUrls(ByVal URL As String, ByVal Responser As Responser, ByVal UHD As Boolean) As List(Of M3U8URL) Private Shared Function ObtainUrls(ByVal URL As String, ByVal Responser As Responser, ByVal UHD As Boolean) As List(Of M3U8URL)
Try Try
Const sk$ = "/key="
Dim file$ = ParseFirstM3U8(URL, Responser, UHD) Dim file$ = ParseFirstM3U8(URL, Responser, UHD)
If Not file.IsEmptyString Then If Not file.IsEmptyString Then
Responser.UseGZipStream = False Responser.UseGZipStream = False
Dim appender$ = URL.Replace(URL.Split("/").LastOrDefault, String.Empty) Dim appender$ = URL.Replace(URL.Split("/").LastOrDefault, String.Empty)
If file.StartsWith(sk) Then
Dim position% = InStr(URL, sk)
If position > 0 Then appender = URL.Remove(position - 1)
End If
URL = M3U8Base.CreateUrl(appender, file) URL = M3U8Base.CreateUrl(appender, file)
Dim l As List(Of M3U8URL) = ParseSecondM3U8(URL, Responser, appender) Dim l As List(Of M3U8URL) = ParseSecondM3U8(URL, Responser, appender)
If l.ListExists Then Return l If l.ListExists Then Return l

View File

@@ -46,7 +46,7 @@ Namespace API.Xhamster
_SubscriptionsAllowed = True _SubscriptionsAllowed = True
UrlPatternUser = "https://xhamster.com/{0}/{1}" UrlPatternUser = "https://xhamster.com/{0}/{1}"
UserRegex = RParams.DMS($"/({UserOption}|{ChannelOption})/([^/]+)(\Z|.*)", 0, RegexReturn.ListByMatch) UserRegex = RParams.DMS($"/({UserOption}|{ChannelOption}|{P_Creators})/([^/]+)(\Z|.*)", 0, RegexReturn.ListByMatch)
ImageVideoContains = "xhamster" ImageVideoContains = "xhamster"
End Sub End Sub
Friend Overrides Sub EndInit() Friend Overrides Sub EndInit()
@@ -96,8 +96,9 @@ Namespace API.Xhamster
Friend Const P_Search As String = "search" Friend Const P_Search As String = "search"
Friend Const P_Tags As String = "tags" Friend Const P_Tags As String = "tags"
Friend Const P_Categories As String = "categories" Friend Const P_Categories As String = "categories"
Friend Const P_Pornstars = "pornstars" Friend Const P_Pornstars As String = "pornstars"
Private ReadOnly NonUsersRegex As RParams = RParams.DM("https?://[^/]+/((gay)/|(shemale)/|)(pornstars|tags|categories|search)/([^/\?]+)[/\?]?(.*)", 0, Friend Const P_Creators As String = "creators"
Private ReadOnly NonUsersRegex As RParams = RParams.DM("https?://[^/]+/((gay)/|(shemale)/|)(pornstars|creators|tags|categories|search)/([^/\?]+)[/\?]?(.*)", 0,
RegexReturn.ListByMatch, EDP.ReturnValue) RegexReturn.ListByMatch, EDP.ReturnValue)
Private ReadOnly PageRemover_1 As RParams = RParams.DM("[\?&]?[Pp]age=\d+", 0, RegexReturn.Replace, EDP.ReturnValue, Private ReadOnly PageRemover_1 As RParams = RParams.DM("[\?&]?[Pp]age=\d+", 0, RegexReturn.Replace, EDP.ReturnValue,
CType(Function(input) String.Empty, Func(Of String, String))) CType(Function(input) String.Empty, Func(Of String, String)))
@@ -106,12 +107,23 @@ Namespace API.Xhamster
Friend Overrides Function IsMyUser(ByVal UserURL As String) As ExchangeOptions Friend Overrides Function IsMyUser(ByVal UserURL As String) As ExchangeOptions
If Not UserURL.IsEmptyString AndAlso Domains.Domains.Count > 0 AndAlso Domains.Domains.Exists(Function(d) UserURL.ToLower.Contains(d.ToLower)) Then If Not UserURL.IsEmptyString AndAlso Domains.Domains.Count > 0 AndAlso Domains.Domains.Exists(Function(d) UserURL.ToLower.Contains(d.ToLower)) Then
Dim n$, opt$ Dim n$, opt$
Dim tryNext As Boolean = False
Dim data As List(Of String) = RegexReplace(UserURL, UserRegex) Dim data As List(Of String) = RegexReplace(UserURL, UserRegex)
If data.ListExists(3) AndAlso Not data(2).IsEmptyString Then If data.ListExists(3) AndAlso Not data(2).IsEmptyString Then
n = data(2) n = data(2)
If Not data(1).IsEmptyString AndAlso data(1) = ChannelOption Then n &= $"@{data(1)}" If Not data(1).IsEmptyString Then
Return New ExchangeOptions(Site, n) If data(1) = ChannelOption Then
n &= $"@{data(1)}"
ElseIf data(1) = P_Creators Then
tryNext = True
End If
End If
If Not tryNext Then Return New ExchangeOptions(Site, n)
Else Else
tryNext = True
End If
If tryNext Then
data = RegexReplace(UserURL, NonUsersRegex) data = RegexReplace(UserURL, NonUsersRegex)
If data.ListExists(7) AndAlso Not data(5).IsEmptyString Then If data.ListExists(7) AndAlso Not data(5).IsEmptyString Then
n = data(5).StringRemoveWinForbiddenSymbols n = data(5).StringRemoveWinForbiddenSymbols
@@ -122,6 +134,7 @@ Namespace API.Xhamster
Case P_Tags : mode = SiteModes.Tags Case P_Tags : mode = SiteModes.Tags
Case P_Categories : mode = SiteModes.Categories Case P_Categories : mode = SiteModes.Categories
Case P_Pornstars : mode = SiteModes.Pornstars Case P_Pornstars : mode = SiteModes.Pornstars
Case P_Creators : mode = SiteModes.User
Case Else : Return Nothing Case Else : Return Nothing
End Select End Select
n = $"{CInt(mode)}@{n}" n = $"{CInt(mode)}@{n}"

View File

@@ -19,6 +19,7 @@ Namespace API.Xhamster
Friend Class UserData : Inherits UserDataBase Friend Class UserData : Inherits UserDataBase
#Region "XML names" #Region "XML names"
Private Const Name_Gender As String = "Gender" Private Const Name_Gender As String = "Gender"
Private Const Name_IsCreator As String = "IsCreator"
#End Region #End Region
#Region "Declarations" #Region "Declarations"
Friend Overrides ReadOnly Property FeedIsUser As Boolean Friend Overrides ReadOnly Property FeedIsUser As Boolean
@@ -27,6 +28,7 @@ Namespace API.Xhamster
End Get End Get
End Property End Property
Friend Property IsChannel As Boolean = False Friend Property IsChannel As Boolean = False
Friend Property IsCreator As Boolean = False
Friend Property TrueName As String = String.Empty Friend Property TrueName As String = String.Empty
Friend Property Gender As String = String.Empty Friend Property Gender As String = String.Empty
Friend Property SiteMode As SiteModes = SiteModes.User Friend Property SiteMode As SiteModes = SiteModes.User
@@ -77,7 +79,8 @@ Namespace API.Xhamster
If n.Length = 2 And If(Force, eObj.Options, Options).IsEmptyString Then If n.Length = 2 And If(Force, eObj.Options, Options).IsEmptyString Then
If Force Then Return False If Force Then Return False
TrueName = n(0) TrueName = n(0)
IsChannel = True IsChannel = n(1) = SiteSettings.ChannelOption
IsCreator = n(1) = SiteSettings.P_Creators
ElseIf IsChannel Then ElseIf IsChannel Then
If Force Then Return False If Force Then Return False
TrueName = Name TrueName = Name
@@ -89,6 +92,7 @@ Namespace API.Xhamster
If n2.ListExists Then If n2.ListExists Then
IsChannel = False IsChannel = False
__Mode = CInt(n2(0)) __Mode = CInt(n2(0))
IsCreator = __Mode = SiteModes.User
__Gender = n2(1) __Gender = n2(1)
__Arguments = n2(3) __Arguments = n2(3)
__TrueName = n2.ListTake(3, 100, EDP.ReturnValue).ListToString(String.Empty) __TrueName = n2.ListTake(3, 100, EDP.ReturnValue).ListToString(String.Empty)
@@ -139,6 +143,7 @@ Namespace API.Xhamster
With Container With Container
If Loading Then If Loading Then
IsChannel = .Value(Name_IsChannel).FromXML(Of Boolean)(False) IsChannel = .Value(Name_IsChannel).FromXML(Of Boolean)(False)
IsCreator = .Value(Name_IsCreator).FromXML(Of Boolean)(False)
TrueName = .Value(Name_TrueName) TrueName = .Value(Name_TrueName)
Gender = .Value(Name_Gender) Gender = .Value(Name_Gender)
SiteMode = .Value(Name_SiteMode).FromXML(Of Integer)(SiteModes.User) SiteMode = .Value(Name_SiteMode).FromXML(Of Integer)(SiteModes.User)
@@ -151,6 +156,7 @@ Namespace API.Xhamster
.Value(Name_FriendlyName) = FriendlyName .Value(Name_FriendlyName) = FriendlyName
End If End If
.Add(Name_IsChannel, IsChannel.BoolToInteger) .Add(Name_IsChannel, IsChannel.BoolToInteger)
.Add(Name_IsCreator, IsCreator.BoolToInteger)
.Add(Name_TrueName, TrueName) .Add(Name_TrueName, TrueName)
.Add(Name_Gender, Gender) .Add(Name_Gender, Gender)
.Add(Name_SiteMode, CInt(SiteMode)) .Add(Name_SiteMode, CInt(SiteMode))
@@ -178,7 +184,7 @@ Namespace API.Xhamster
#End Region #End Region
#Region "Download functions" #Region "Download functions"
Friend Function GetNonUserUrl(ByVal Page As Integer) As String Friend Function GetNonUserUrl(ByVal Page As Integer) As String
If SiteMode = SiteModes.User Then If SiteMode = SiteModes.User And Not IsCreator Then
Return String.Empty Return String.Empty
Else Else
Dim url$ = "https://xhamster.com/" Dim url$ = "https://xhamster.com/"
@@ -188,6 +194,7 @@ Namespace API.Xhamster
Case SiteModes.Categories : url &= SiteSettings.P_Categories Case SiteModes.Categories : url &= SiteSettings.P_Categories
Case SiteModes.Search : url &= SiteSettings.P_Search Case SiteModes.Search : url &= SiteSettings.P_Search
Case SiteModes.Pornstars : url &= SiteSettings.P_Pornstars Case SiteModes.Pornstars : url &= SiteSettings.P_Pornstars
Case SiteModes.User : url &= SiteSettings.P_Creators
Case Else : Return String.Empty Case Else : Return String.Empty
End Select End Select
url &= $"/{TrueName}" url &= $"/{TrueName}"
@@ -224,15 +231,20 @@ Namespace API.Xhamster
Private ReadOnly SessionPosts As List(Of String) Private ReadOnly SessionPosts As List(Of String)
Private _PageVideosRepeat As Integer = 0 Private _PageVideosRepeat As Integer = 0
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken) Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
_TempPhotoData.Clear() Try
SearchPostsCount = 0 _TempPhotoData.Clear()
_PageVideosRepeat = 0 SearchPostsCount = 0
SessionPosts.Clear() _PageVideosRepeat = 0
If DownloadVideos Then DownloadData(1, True, Token) SessionPosts.Clear()
If Not IsChannel And DownloadImages And Not IsSubscription Then Responser.CookiesAsHeader = True
DownloadData(1, False, Token) If DownloadVideos Then DownloadData(1, True, Token)
ReparsePhoto(Token) If Not IsChannel And Not IsCreator And DownloadImages And Not IsSubscription Then
End If DownloadData(1, False, Token)
ReparsePhoto(Token)
End If
Finally
Responser.CookiesAsHeader = False
End Try
End Sub End Sub
Private Overloads Sub DownloadData(ByVal Page As Integer, ByVal IsVideo As Boolean, ByVal Token As CancellationToken) Private Overloads Sub DownloadData(ByVal Page As Integer, ByVal IsVideo As Boolean, ByVal Token As CancellationToken)
Dim URL$ = String.Empty Dim URL$ = String.Empty
@@ -260,7 +272,7 @@ Namespace API.Xhamster
ElseIf SiteMode = SiteModes.Search Then ElseIf SiteMode = SiteModes.Search Then
URL = GetNonUserUrl(Page) URL = GetNonUserUrl(Page)
containerNodes.Add({"searchResult", "models"}) containerNodes.Add({"searchResult", "models"})
ElseIf SiteMode = SiteModes.Tags Or SiteMode = SiteModes.Categories Or SiteMode = SiteModes.Pornstars Then ElseIf IsCreator Or SiteMode = SiteModes.Tags Or SiteMode = SiteModes.Categories Or SiteMode = SiteModes.Pornstars Then
URL = GetNonUserUrl(Page) URL = GetNonUserUrl(Page)
If SiteMode = SiteModes.Pornstars Then If SiteMode = SiteModes.Pornstars Then
containerNodes.Add({"trendingVideoListComponent", "models"}) containerNodes.Add({"trendingVideoListComponent", "models"})
@@ -269,9 +281,11 @@ Namespace API.Xhamster
containerNodes.Add({"pagesCategoryComponent", "trendingVideoListProps", "models"}) containerNodes.Add({"pagesCategoryComponent", "trendingVideoListProps", "models"})
containerNodes.Add({"trendingVideoListComponent", "models"}) containerNodes.Add({"trendingVideoListComponent", "models"})
End If End If
containerNodes.Add({"trendingVideoSectionComponent", "videoModels"})
Else Else
URL = $"https://xhamster.com/users/{TrueName}/{IIf(IsVideo, "videos", "photos")}{IIf(Page = 1, String.Empty, $"/{Page}")}" URL = $"https://xhamster.com/users/{TrueName}/{IIf(IsVideo, "videos", "photos")}{IIf(Page = 1, String.Empty, $"/{Page}")}"
containerNodes.Add({If(IsVideo, "userVideoCollection", "userGalleriesCollection")}) containerNodes.Add({If(IsVideo, "userVideoCollection", "userGalleriesCollection")})
containerNodes.Add(If(IsVideo, {"videoListComponent", "models"}, {"userGalleriesCollection"}))
End If End If
ThrowAny(Token) ThrowAny(Token)

View File

@@ -24,6 +24,8 @@ Namespace API.YouTube
Friend ReadOnly Property DownloadCommunityImages As PropertyValue Friend ReadOnly Property DownloadCommunityImages As PropertyValue
<PXML, PropertyOption(ControlText:="Download user community: videos"), PClonable> <PXML, PropertyOption(ControlText:="Download user community: videos"), PClonable>
Friend ReadOnly Property DownloadCommunityVideos As PropertyValue Friend ReadOnly Property DownloadCommunityVideos As PropertyValue
<PXML, PropertyOption(ControlText:="Ignore community errors", ControlToolTip:="If true, community errors will not be added to the log."), PClonable>
Friend ReadOnly Property IgnoreCommunityErrors As PropertyValue
<PXML, PropertyOption(ControlText:="Use cookies", ControlToolTip:="Default value for new users." & vbCr & "Use cookies when downloading data."), PClonable> <PXML, PropertyOption(ControlText:="Use cookies", ControlToolTip:="Default value for new users." & vbCr & "Use cookies when downloading data."), PClonable>
Friend ReadOnly Property UseCookies As PropertyValue Friend ReadOnly Property UseCookies As PropertyValue
#End Region #End Region
@@ -36,6 +38,7 @@ Namespace API.YouTube
DownloadPlaylists = New PropertyValue(False) DownloadPlaylists = New PropertyValue(False)
DownloadCommunityImages = New PropertyValue(False) DownloadCommunityImages = New PropertyValue(False)
DownloadCommunityVideos = New PropertyValue(False) DownloadCommunityVideos = New PropertyValue(False)
IgnoreCommunityErrors = New PropertyValue(False)
UseCookies = New PropertyValue(False) UseCookies = New PropertyValue(False)
_SubscriptionsAllowed = True _SubscriptionsAllowed = True
UseNetscapeCookies = True UseNetscapeCookies = True
@@ -90,7 +93,11 @@ Namespace API.YouTube
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 User Is Nothing AndAlso TypeOf User Is UserData Then If Not User Is Nothing AndAlso TypeOf User Is UserData Then
Return $"https://{IIf(DirectCast(User, UserData).IsMusic, "music", "www")}.youtube.com/watch?v={Media.Post.ID}" If DirectCast(User, UserData).IsMusic Or Media.URL_BASE.IsEmptyString Then
Return $"https://{IIf(DirectCast(User, UserData).IsMusic, "music", "www")}.youtube.com/watch?v={Media.Post.ID}"
Else
Return Media.URL_BASE
End If
Else Else
Return String.Empty Return String.Empty
End If End If

View File

@@ -137,6 +137,26 @@ Namespace API.YouTube
Dim list As New List(Of IYouTubeMediaContainer) Dim list As New List(Of IYouTubeMediaContainer)
Dim url$ = String.Empty Dim url$ = String.Empty
Dim maxDate As Date? = Nothing Dim maxDate As Date? = Nothing
Dim __minDate As Date? = DownloadDateFrom
Dim __maxDate As Date? = DownloadDateTo
Dim __getMinDate As Func(Of Date?, Date?) = Function(ByVal dInput As Date?) As Date?
If dInput.HasValue Then
If __minDate.HasValue Then
Return {__minDate.Value, dInput.Value}.Min
Else
Return dInput
End If
ElseIf __minDate.HasValue Then
Return __minDate
Else
Return Nothing
End If
End Function
Dim shortsUrlStandardize As Action(Of IYouTubeMediaContainer, Integer) = Sub(ByVal c As IYouTubeMediaContainer, ByVal ii As Integer)
Dim sUrl$ = $"https://www.youtube.com/shorts/{c.ID}"
'c.URL = sUrl
c.URL_BASE = sUrl
End Sub
Dim nDate As Func(Of Date?, Date?) = Function(ByVal dInput As Date?) As Date? Dim nDate As Func(Of Date?, Date?) = Function(ByVal dInput As Date?) As Date?
If dInput.HasValue Then If dInput.HasValue Then
If dInput.Value.AddDays(3) < Now Then Return dInput.Value.AddDays(1) Else Return dInput If dInput.Value.AddDays(3) < Now Then Return dInput.Value.AddDays(1) Else Return dInput
@@ -144,22 +164,23 @@ Namespace API.YouTube
Return Nothing Return Nothing
End If End If
End Function End Function
Dim fillList As Func(Of Date?, Boolean) = Function(ByVal lDate As Date?) As Boolean Dim fillList As Func(Of Date?, Boolean, Boolean) = Function(ByVal lDate As Date?, ByVal ___isShorts As Boolean) As Boolean
If Not container Is Nothing AndAlso container.HasElements Then If Not container Is Nothing AndAlso container.HasElements Then
Dim ce As IEnumerable(Of IYouTubeMediaContainer) Dim ce As IEnumerable(Of IYouTubeMediaContainer)
ce = container.Elements ce = container.Elements
If ce.ListExists Then ce = ce.Where(Function(e) e.ObjectType = YouTubeMediaType.Single) If ce.ListExists Then ce = ce.Where(Function(e) e.ObjectType = YouTubeMediaType.Single)
If ce.ListExists AndAlso lDate.HasValue Then _ If ce.ListExists AndAlso lDate.HasValue Then _
ce = ce.Where(Function(e) e.DateAdded <= lDate.Value AndAlso ce = ce.Where(Function(e) e.DateAdded >= lDate.Value AndAlso
Not e.ID.IsEmptyString AndAlso Not _TempPostsList.Contains(e.ID)) Not e.ID.IsEmptyString AndAlso Not _TempPostsList.Contains(e.ID))
If ce.ListExists Then If ce.ListExists Then
maxDate = ce.Max(Function(e) e.DateAdded) maxDate = ce.Max(Function(e) e.DateAdded)
list.AddRange(ce) If ___isShorts Then ce.ListForEach(shortsUrlStandardize, EDP.None)
Return True list.AddRange(ce)
End If Return True
End If End If
Return False End If
End Function Return False
End Function
Dim applySpecFolder As Action(Of String, Boolean) = Sub(ByVal fName As String, ByVal isPls As Boolean) Dim applySpecFolder As Action(Of String, Boolean) = Sub(ByVal fName As String, ByVal isPls As Boolean)
If If(container?.Count, 0) > 0 Then _ If If(container?.Count, 0) > 0 Then _
container.Elements.ForEach(Sub(ByVal el As YouTubeMediaContainerBase) container.Elements.ForEach(Sub(ByVal el As YouTubeMediaContainerBase)
@@ -175,33 +196,33 @@ Namespace API.YouTube
maxDate = Nothing maxDate = Nothing
LastDownloadDatePlaylist = nDate(LastDownloadDatePlaylist) LastDownloadDatePlaylist = nDate(LastDownloadDatePlaylist)
url = $"https://{IIf(IsMusic, "music", "www")}.youtube.com/playlist?list={ID}" url = $"https://{IIf(IsMusic, "music", "www")}.youtube.com/playlist?list={ID}"
container = YouTubeFunctions.Parse(url, YTUseCookies, Token, pr,, LastDownloadDatePlaylist,, True) container = YouTubeFunctions.Parse(url, YTUseCookies, Token, pr, __getMinDate(LastDownloadDatePlaylist), __maxDate,, True)
applySpecFolder.Invoke(String.Empty, False) applySpecFolder.Invoke(String.Empty, False)
If fillList.Invoke(LastDownloadDatePlaylist) Then LastDownloadDatePlaylist = If(maxDate, Now) If fillList.Invoke(LastDownloadDatePlaylist, False) Then LastDownloadDatePlaylist = If(maxDate, Now)
ElseIf YTMediaType = YouTubeMediaType.Channel Then ElseIf YTMediaType = YouTubeMediaType.Channel Then
If IsMusic Or DownloadYTVideos Then If IsMusic Or DownloadYTVideos Then
maxDate = Nothing maxDate = Nothing
LastDownloadDateVideos = nDate(LastDownloadDateVideos) LastDownloadDateVideos = nDate(LastDownloadDateVideos)
url = $"https://{IIf(IsMusic, "music", "www")}.youtube.com/{IIf(IsMusic Or IsChannelUser, $"{YouTubeFunctions.UserChannelOption}/", "@")}{ID}" url = $"https://{IIf(IsMusic, "music", "www")}.youtube.com/{IIf(IsMusic Or IsChannelUser, $"{YouTubeFunctions.UserChannelOption}/", "@")}{ID}"
container = YouTubeFunctions.Parse(url, YTUseCookies, Token, pr,, LastDownloadDateVideos,, True) container = YouTubeFunctions.Parse(url, YTUseCookies, Token, pr, __getMinDate(LastDownloadDateVideos), __maxDate,, True)
applySpecFolder.Invoke(IIf(IsMusic, String.Empty, "Videos"), False) applySpecFolder.Invoke(IIf(IsMusic, String.Empty, "Videos"), False)
If fillList.Invoke(LastDownloadDateVideos) Then LastDownloadDateVideos = If(maxDate, Now) If fillList.Invoke(LastDownloadDateVideos, False) Then LastDownloadDateVideos = If(maxDate, Now)
End If End If
If Not IsMusic And DownloadYTShorts Then If Not IsMusic And DownloadYTShorts Then
maxDate = Nothing maxDate = Nothing
LastDownloadDateShorts = nDate(LastDownloadDateShorts) LastDownloadDateShorts = nDate(LastDownloadDateShorts)
url = $"https://www.youtube.com/{IIf(IsChannelUser, $"{YouTubeFunctions.UserChannelOption}/", "@")}{ID}/shorts" url = $"https://www.youtube.com/{IIf(IsChannelUser, $"{YouTubeFunctions.UserChannelOption}/", "@")}{ID}/shorts"
container = YouTubeFunctions.Parse(url, YTUseCookies, Token, pr,, LastDownloadDateShorts,, True) container = YouTubeFunctions.Parse(url, YTUseCookies, Token, pr, __getMinDate(LastDownloadDateShorts), __maxDate,, True)
applySpecFolder.Invoke("Shorts", False) applySpecFolder.Invoke("Shorts", False)
If fillList.Invoke(LastDownloadDateShorts) Then LastDownloadDateShorts = If(maxDate, Now) If fillList.Invoke(LastDownloadDateShorts, True) Then LastDownloadDateShorts = If(maxDate, Now)
End If End If
If Not IsMusic And DownloadYTPlaylists Then If Not IsMusic And DownloadYTPlaylists Then
maxDate = Nothing maxDate = Nothing
LastDownloadDatePlaylist = nDate(LastDownloadDatePlaylist) LastDownloadDatePlaylist = nDate(LastDownloadDatePlaylist)
url = $"https://www.youtube.com/{IIf(IsChannelUser, $"{YouTubeFunctions.UserChannelOption}/", "@")}{ID}/playlists" url = $"https://www.youtube.com/{IIf(IsChannelUser, $"{YouTubeFunctions.UserChannelOption}/", "@")}{ID}/playlists"
container = YouTubeFunctions.Parse(url, YTUseCookies, Token, pr,, LastDownloadDatePlaylist,, True) container = YouTubeFunctions.Parse(url, YTUseCookies, Token, pr, __getMinDate(LastDownloadDatePlaylist), __maxDate,, True)
applySpecFolder.Invoke("Playlists", True) applySpecFolder.Invoke("Playlists", True)
If fillList.Invoke(LastDownloadDatePlaylist) Then LastDownloadDatePlaylist = If(maxDate, Now) If fillList.Invoke(LastDownloadDatePlaylist, False) Then LastDownloadDatePlaylist = If(maxDate, Now)
End If End If
If Not IsMusic And (DownloadYTCommunityImages Or DownloadYTCommunityVideos) Then DownloadCommunity(String.Empty, Token) If Not IsMusic And (DownloadYTCommunityImages Or DownloadYTCommunityVideos) Then DownloadCommunity(String.Empty, Token)
Else Else
@@ -225,6 +246,7 @@ Namespace API.YouTube
End Sub End Sub
Private Sub DownloadCommunity(ByVal Cursor As String, ByVal Token As CancellationToken, Optional ByVal Round As Integer = 0) Private Sub DownloadCommunity(ByVal Cursor As String, ByVal Token As CancellationToken, Optional ByVal Round As Integer = 0)
Dim URL$ = String.Empty Dim URL$ = String.Empty
Const errMsg$ = "community data downloading error"
Try Try
Const postIdTemp$ = "Community_{0}" Const postIdTemp$ = "Community_{0}"
Const specFolder$ = "Community" Const specFolder$ = "Community"
@@ -311,6 +333,10 @@ Namespace API.YouTube
Next Next
End If End If
End With End With
ElseIf Not CBool(DirectCast(HOST.Source, SiteSettings).IgnoreCommunityErrors.Value) Then
With j({"error"})
If .ListExists Then MyMainLOG = $"{ToStringForLog()} {errMsg} [{ .Value("code")}]: { .Value("message")}"
End With
End If End If
End With End With
End If End If
@@ -327,7 +353,7 @@ Namespace API.YouTube
If Not nextToken.IsEmptyString Then DownloadCommunity(nextToken, Token) If Not nextToken.IsEmptyString Then DownloadCommunity(nextToken, Token)
Catch ex As Exception Catch ex As Exception
ProcessException(ex, Token, "community data downloading error") ProcessException(ex, Token, errMsg)
End Try End Try
End Sub End Sub
Private Sub GetChannelID() Private Sub GetChannelID()

View File

@@ -20,7 +20,7 @@ Imports ADB = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons
Imports RButton = PersonalUtilities.Forms.Toolbars.RangeSwitcherToolbar.ControlItem Imports RButton = PersonalUtilities.Forms.Toolbars.RangeSwitcherToolbar.ControlItem
Friend Class ChannelViewForm : Implements IChannelLimits Friend Class ChannelViewForm : Implements IChannelLimits
#Region "Events" #Region "Events"
Friend Event OnUsersAdded(ByVal StartIndex As Integer) Friend Event OnUsersAdded As UsersAddedEventHandler
Friend Event OnDownloadDone As NotificationEventHandler Friend Event OnDownloadDone As NotificationEventHandler
#End Region #End Region
#Region "Appended user structure" #Region "Appended user structure"

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@@ -14,7 +14,7 @@ Imports PersonalUtilities.Functions.XML.Base
Imports PersonalUtilities.Tools Imports PersonalUtilities.Tools
Imports PersonalUtilities.Tools.Notifications Imports PersonalUtilities.Tools.Notifications
Namespace DownloadObjects Namespace DownloadObjects
Friend Class AutoDownloader : Inherits GroupParameters : Implements IIndexable, IEContainerProvider Friend Class AutoDownloader : Inherits GroupParameters : Implements IIndexable, IEContainerProvider, IComparable(Of AutoDownloader)
Friend Event PauseChanged(ByVal Value As PauseModes) Friend Event PauseChanged(ByVal Value As PauseModes)
Friend Enum Modes As Integer Friend Enum Modes As Integer
None = 0 None = 0
@@ -39,6 +39,7 @@ Namespace DownloadObjects
#Region "Notifications" #Region "Notifications"
Private Const KeyOpenFolder As String = "_____OPEN_FOLDER_SCRAWLER_AUTOMATION" Private Const KeyOpenFolder As String = "_____OPEN_FOLDER_SCRAWLER_AUTOMATION"
Private Const KeyOpenSite As String = "_____OPEN_SITE_SCRAWLER_AUTOMATION" Private Const KeyOpenSite As String = "_____OPEN_SITE_SCRAWLER_AUTOMATION"
Private Const KeyOpenFeed As String = "_____OPEN_FEED_SCRAWLER_AUTOMATION"
Private Const KeyBttDismiss As String = "_____DISMISS_SCRAWLER_AUTOMATION" Private Const KeyBttDismiss As String = "_____DISMISS_SCRAWLER_AUTOMATION"
Private Const KeyBttPhoto As String = "_____PHOTO_SCRAWLER_AUTOMATION" Private Const KeyBttPhoto As String = "_____PHOTO_SCRAWLER_AUTOMATION"
Private ReadOnly UserKeys As List(Of NotifiedUser) Private ReadOnly UserKeys As List(Of NotifiedUser)
@@ -48,6 +49,7 @@ Namespace DownloadObjects
Private ReadOnly Property Key As String Private ReadOnly Property Key As String
Private ReadOnly Property KeyFolder As String Private ReadOnly Property KeyFolder As String
Private ReadOnly Property KeySite As String Private ReadOnly Property KeySite As String
Private ReadOnly Property KeyFeed As String
Private ReadOnly Property KeyDismiss As String Private ReadOnly Property KeyDismiss As String
Private ReadOnly Property Images As Dictionary(Of String, SFile) Private ReadOnly Property Images As Dictionary(Of String, SFile)
Private ReadOnly Property AutoDownloaderSource As AutoDownloader Private ReadOnly Property AutoDownloaderSource As AutoDownloader
@@ -59,6 +61,7 @@ Namespace DownloadObjects
Key = _Key Key = _Key
KeyFolder = $"{Key}{KeyOpenFolder}" KeyFolder = $"{Key}{KeyOpenFolder}"
KeySite = $"{Key}{KeyOpenSite}" KeySite = $"{Key}{KeyOpenSite}"
KeyFeed = $"{Key}{KeyOpenFeed}"
KeyDismiss = $"{Key}{KeyBttDismiss}" KeyDismiss = $"{Key}{KeyBttDismiss}"
End Sub End Sub
Friend Sub New(ByVal _Key As String, ByRef _User As IUserData, ByRef Source As AutoDownloader) Friend Sub New(ByVal _Key As String, ByRef _User As IUserData, ByRef Source As AutoDownloader)
@@ -116,7 +119,8 @@ Namespace DownloadObjects
End If End If
Notify.Buttons = { Notify.Buttons = {
New ToastButton(KeyFolder, "Folder"), New ToastButton(KeyFolder, "Folder"),
New ToastButton(KeySite, "Site") New ToastButton(KeySite, "Site"),
New ToastButton(KeyFeed, "Feed")
} }
If Not uifKey.IsEmptyString Then Notify.Buttons = {New ToastButton(uifKey, "Photo")} If Not uifKey.IsEmptyString Then Notify.Buttons = {New ToastButton(uifKey, "Photo")}
Notify.Buttons = {New ToastButton(KeyDismiss, "Dismiss")} Notify.Buttons = {New ToastButton(KeyDismiss, "Dismiss")}
@@ -149,6 +153,8 @@ Namespace DownloadObjects
End If End If
ElseIf KeySite = _Key Then ElseIf KeySite = _Key Then
User.OpenSite() User.OpenSite()
ElseIf KeyFeed = _Key Then
With MainFrameObj : ControlInvokeFast(.MF, AddressOf .MF.ShowFeed, EDP.LogMessageValue) : End With
ElseIf Images.ContainsKey(_Key) Then ElseIf Images.ContainsKey(_Key) Then
Images(_Key).Open() Images(_Key).Open()
End If End If
@@ -159,7 +165,7 @@ Namespace DownloadObjects
End Function End Function
Public Overrides Function Equals(ByVal Obj As Object) As Boolean Public Overrides Function Equals(ByVal Obj As Object) As Boolean
With CType(Obj, NotifiedUser) With CType(Obj, NotifiedUser)
Return .Key = Key Or .Key = KeyFolder Or .Key = KeySite Or .Key = KeyDismiss Or Images.ContainsKey(.Key) Return .Key = Key Or .Key = KeyFolder Or .Key = KeySite Or .Key = KeyFeed Or .Key = KeyDismiss Or Images.ContainsKey(.Key)
End With End With
End Function End Function
#Region "IDisposable Support" #Region "IDisposable Support"
@@ -213,7 +219,7 @@ Namespace DownloadObjects
Friend Property ShowPictureDownloaded As Boolean = True Friend Property ShowPictureDownloaded As Boolean = True
Friend Property ShowPictureUser As Boolean = True Friend Property ShowPictureUser As Boolean = True
Friend Property ShowSimpleNotification As Boolean = False Friend Property ShowSimpleNotification As Boolean = False
Private Property Index As Integer = -1 Implements IIndexable.Index Friend Property Index As Integer = -1 Implements IIndexable.Index
Private Function SetIndex(ByVal Obj As Object, ByVal Index As Integer) As Object Implements IIndexable.SetIndex Private Function SetIndex(ByVal Obj As Object, ByVal Index As Integer) As Object Implements IIndexable.SetIndex
DirectCast(Obj, AutoDownloader).Index = Index DirectCast(Obj, AutoDownloader).Index = Index
Return Obj Return Obj
@@ -519,6 +525,7 @@ Namespace DownloadObjects
Dim users As New List(Of IUserData) Dim users As New List(Of IUserData)
Dim GName$ Dim GName$
Dim i% Dim i%
Dim doRound% = -1, doLim% = Settings.Plugins.Count
Dim DownloadedUsersCount% = 0 Dim DownloadedUsersCount% = 0
Dim DownloadedSubscriptionsCount% = 0 Dim DownloadedSubscriptionsCount% = 0
Dim simple As Boolean = ShowSimpleNotification And ShowNotifications Dim simple As Boolean = ShowSimpleNotification And ShowNotifications
@@ -594,7 +601,7 @@ Namespace DownloadObjects
With Downloader With Downloader
.AutoDownloaderWorking = True .AutoDownloaderWorking = True
If .Downloaded.Count > 0 Then .Downloaded.RemoveAll(Function(u) Keys.Contains(u.Key)) : .InvokeDownloadsChangeEvent() If .Downloaded.Count > 0 Then .Downloaded.RemoveAll(Function(u) Keys.Contains(u.Key)) : .InvokeDownloadsChangeEvent()
.AddRange(users, True) Do : Try : doRound += 1 : .AddRange(users, True) : Exit Do : Catch iex As IndexOutOfRangeException : Thread.Sleep(200) : End Try : Loop While doRound < doLim
While .Working Or .Count > 0 : notify.Invoke() : Thread.Sleep(200) : End While While .Working Or .Count > 0 : notify.Invoke() : Thread.Sleep(200) : End While
.AutoDownloaderWorking = False .AutoDownloaderWorking = False
notify.Invoke notify.Invoke
@@ -640,6 +647,11 @@ Namespace DownloadObjects
End If End If
End Function End Function
#End Region #End Region
#Region "IComparable Support"
Private Function CompareTo(ByVal Other As AutoDownloader) As Integer Implements IComparable(Of AutoDownloader).CompareTo
Return Index.CompareTo(Other.Index)
End Function
#End Region
#Region "IDisposable Support" #Region "IDisposable Support"
Protected Overrides Sub Dispose(ByVal disposing As Boolean) Protected Overrides Sub Dispose(ByVal disposing As Boolean)
If Not disposedValue And disposing Then If Not disposedValue And disposing Then

View File

@@ -38,7 +38,13 @@ Namespace DownloadObjects
End Property End Property
Friend Sub New() Friend Sub New()
Plans = New List(Of AutoDownloader) Plans = New List(Of AutoDownloader)
File = Settings.AutomationFile.Value.IfNullOrEmpty(FileDefault) Dim sFolder As SFile = SettingsFolderName.CSFileP
File = New SFile(Settings.AutomationFile.Value.IfNullOrEmpty(FileDefault.ToString))
If File.Path.IsEmptyString OrElse Not File.Path.StartsWith(sFolder.Path) Then
Dim updateSetting As Boolean = File.Path.IsEmptyString OrElse Not File.Path.StartsWith(sFolder.CutPath.Path)
File.Path = sFolder.Path
If File.Exists And updateSetting Then Settings.AutomationFile.Value = File.File
End If
If Not File.Exists Then File = FileDefault If Not File.Exists Then File = FileDefault
Reset(File, True) Reset(File, True)
End Sub End Sub
@@ -129,6 +135,25 @@ Namespace DownloadObjects
End If End If
Return True Return True
End Function End Function
Friend Function Move(ByVal Index As Integer, ByVal Up As Boolean) As Integer
Try
If Index.ValueBetween(0, Count - 1) Then
Plans.ListReindex
Dim v% = IIf(Up, -1, 1)
Dim newIndx%
Item(Index).Index += v
newIndx = Item(Index).Index
If newIndx.ValueBetween(0, Count - 1) Then Item(newIndx).Index += v * -1
Plans.Sort()
Plans.ListReindex
Update()
Return newIndx
End If
Catch ex As Exception
ErrorsDescriber.Execute(EDP.SendToLog, ex, "[Scheduler.Move]")
End Try
Return -1
End Function
#Region "Groups Support" #Region "Groups Support"
Friend Sub GROUPS_Updated(ByVal Sender As DownloadGroup) Friend Sub GROUPS_Updated(ByVal Sender As DownloadGroup)
If Count > 0 Then Plans.ForEach(Sub(p) p.GROUPS_Updated(Sender)) If Count > 0 Then Plans.ForEach(Sub(p) p.GROUPS_Updated(Sender))

View File

@@ -27,6 +27,8 @@ Namespace DownloadObjects
Private WithEvents BTT_START_FORCE As ToolStripButton Private WithEvents BTT_START_FORCE As ToolStripButton
Private WithEvents BTT_PAUSE As ToolStripDropDownButton Private WithEvents BTT_PAUSE As ToolStripDropDownButton
Private WithEvents PauseArr As AutoDownloaderPauseButtons Private WithEvents PauseArr As AutoDownloaderPauseButtons
Private WithEvents BTT_MOVE_UP As ToolStripButton
Private WithEvents BTT_MOVE_DOWN As ToolStripButton
#End Region #End Region
#Region "Initializer" #Region "Initializer"
Friend Sub New() Friend Sub New()
@@ -98,6 +100,18 @@ Namespace DownloadObjects
.ToolTipText = "Pause task", .ToolTipText = "Pause task",
.AutoToolTip = True .AutoToolTip = True
} }
BTT_MOVE_UP = New ToolStripButton With {
.Text = String.Empty,
.Image = PersonalUtilities.My.Resources.ArrowUpPic_Blue_32,
.ToolTipText = "Move the selected task higher in the list",
.AutoToolTip = True
}
BTT_MOVE_DOWN = New ToolStripButton With {
.Text = String.Empty,
.Image = PersonalUtilities.My.Resources.ArrowDownPic_Blue_32,
.ToolTipText = "Move the selected task lower in the list",
.AutoToolTip = True
}
PauseArr = New AutoDownloaderPauseButtons(AutoDownloaderPauseButtons.ButtonsPlace.Scheduler) With { PauseArr = New AutoDownloaderPauseButtons(AutoDownloaderPauseButtons.ButtonsPlace.Scheduler) With {
.MainFrameButtonsInstance = MainFrameObj.PauseButtons} .MainFrameButtonsInstance = MainFrameObj.PauseButtons}
Icon = ImageRenderer.GetIcon(My.Resources.ScriptPic_32, EDP.ReturnValue) Icon = ImageRenderer.GetIcon(My.Resources.ScriptPic_32, EDP.ReturnValue)
@@ -108,6 +122,7 @@ Namespace DownloadObjects
With MyDefs With MyDefs
.MyViewInitialize() .MyViewInitialize()
.AddEditToolbar({BTT_SETTINGS, ECI.Separator, ECI.Add, BTT_CLONE, ECI.Edit, ECI.Delete, ECI.Update, ECI.Separator, .AddEditToolbar({BTT_SETTINGS, ECI.Separator, ECI.Add, BTT_CLONE, ECI.Edit, ECI.Delete, ECI.Update, ECI.Separator,
BTT_MOVE_UP, BTT_MOVE_DOWN, ECI.Separator,
BTT_START, BTT_START_FORCE, MENU_SKIP, BTT_PAUSE}) BTT_START, BTT_START_FORCE, MENU_SKIP, BTT_PAUSE})
PauseArr.AddButtons(BTT_PAUSE, .MyEditToolbar.ToolStrip) PauseArr.AddButtons(BTT_PAUSE, .MyEditToolbar.ToolStrip)
Refill() Refill()
@@ -264,9 +279,9 @@ Namespace DownloadObjects
If Not Settings.Automation.File = f AndAlso Settings.Automation.Reset(f, False) Then If Not Settings.Automation.File = f AndAlso Settings.Automation.Reset(f, False) Then
Settings.Automation.File = f Settings.Automation.File = f
If selectedName = defName Then If selectedName = defName Then
Settings.AutomationFile.Value = Nothing Settings.AutomationFile.Value = String.Empty
Else Else
Settings.AutomationFile.Value = f Settings.AutomationFile.Value = f.File
End If End If
PauseArr.UpdatePauseButtons() PauseArr.UpdatePauseButtons()
Refill() Refill()
@@ -332,6 +347,15 @@ Namespace DownloadObjects
Private Sub PauseArr_Updating() Handles PauseArr.Updating Private Sub PauseArr_Updating() Handles PauseArr.Updating
Refill() Refill()
End Sub End Sub
#End Region
#Region "Move"
Private Sub BTT_MOVE_UP_DOWN_Click(sender As Object, e As EventArgs) Handles BTT_MOVE_UP.Click, BTT_MOVE_DOWN.Click
If _LatestSelected.ValueBetween(0, LIST_PLANS.Items.Count - 1) Then
Dim v% = Settings.Automation.Move(_LatestSelected, sender Is BTT_MOVE_UP)
If v >= 0 Then _LatestSelected = v
Refill()
End If
End Sub
#End Region #End Region
End Class End Class
End Namespace End Namespace

View File

@@ -30,6 +30,10 @@ Namespace DownloadObjects
Dim MENU_LOAD_SEP_2 As System.Windows.Forms.ToolStripSeparator Dim MENU_LOAD_SEP_2 As System.Windows.Forms.ToolStripSeparator
Dim MENU_LOAD_SEP_3 As System.Windows.Forms.ToolStripSeparator Dim MENU_LOAD_SEP_3 As System.Windows.Forms.ToolStripSeparator
Dim MENU_LOAD_SEP_4 As System.Windows.Forms.ToolStripSeparator Dim MENU_LOAD_SEP_4 As System.Windows.Forms.ToolStripSeparator
Dim MENU_LOAD_SEP_5 As System.Windows.Forms.ToolStripSeparator
Dim MENU_LOAD_SEP_6 As System.Windows.Forms.ToolStripSeparator
Dim MENU_LOAD_SEP_7 As System.Windows.Forms.ToolStripSeparator
Dim MENU_LOAD_SEP_0 As System.Windows.Forms.ToolStripSeparator
Me.OPT_DEFAULT = New System.Windows.Forms.ToolStripMenuItem() Me.OPT_DEFAULT = New System.Windows.Forms.ToolStripMenuItem()
Me.OPT_SUBSCRIPTIONS = New System.Windows.Forms.ToolStripMenuItem() Me.OPT_SUBSCRIPTIONS = New System.Windows.Forms.ToolStripMenuItem()
Me.ToolbarTOP = New System.Windows.Forms.ToolStrip() Me.ToolbarTOP = New System.Windows.Forms.ToolStrip()
@@ -37,24 +41,32 @@ Namespace DownloadObjects
Me.BTT_LOAD_SESSION_CURRENT = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_LOAD_SESSION_CURRENT = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_LOAD_SESSION_LAST = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_LOAD_SESSION_LAST = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_LOAD_SESSION_CHOOSE = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_LOAD_SESSION_CHOOSE = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_COPY_TO = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_MOVE_TO = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_LOAD_FAV = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_LOAD_FAV = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_LOAD_SPEC = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_LOAD_SPEC = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_FEED_ADD_FAV = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_FEED_ADD_FAV = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_FEED_ADD_FAV_REMOVE = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_FEED_REMOVE_FAV = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_FEED_REMOVE_FAV = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_FEED_ADD_SPEC = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_FEED_ADD_SPEC = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_FEED_ADD_SPEC_REMOVE = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_FEED_REMOVE_SPEC = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_FEED_REMOVE_SPEC = New System.Windows.Forms.ToolStripMenuItem()
Me.SEP_0 = New System.Windows.Forms.ToolStripSeparator()
Me.MENU_DOWN = New System.Windows.Forms.ToolStripDropDownButton()
Me.BTT_DOWN_ALL = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_DOWN_SELECTED = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_REFRESH = New System.Windows.Forms.ToolStripButton()
Me.BTT_CLEAR = New System.Windows.Forms.ToolStripButton()
Me.TP_DATA = New System.Windows.Forms.TableLayoutPanel()
Me.BTT_FEED_CLEAR_FAV = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_FEED_CLEAR_FAV = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_FEED_CLEAR_SPEC = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_FEED_CLEAR_SPEC = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_FEED_DELETE_SPEC = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_FEED_DELETE_SPEC = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_FEED_DELETE_DAILY_LIST = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_FEED_DELETE_DAILY_LIST = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_FEED_DELETE_DAILY_DATE = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_FEED_DELETE_DAILY_DATE = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_MERGE_SESSIONS = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_CLEAR_DAILY = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_MERGE_FEEDS = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_CHECK_ALL = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_CHECK_NONE = New System.Windows.Forms.ToolStripMenuItem()
Me.SEP_0 = New System.Windows.Forms.ToolStripSeparator()
Me.MENU_DOWN = New System.Windows.Forms.ToolStripDropDownButton()
Me.BTT_DOWN_ALL = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_DOWN_SELECTED = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_REFRESH = New System.Windows.Forms.ToolStripButton()
Me.TP_DATA = New System.Windows.Forms.TableLayoutPanel()
SEP_1 = New System.Windows.Forms.ToolStripSeparator() SEP_1 = New System.Windows.Forms.ToolStripSeparator()
SEP_2 = New System.Windows.Forms.ToolStripSeparator() SEP_2 = New System.Windows.Forms.ToolStripSeparator()
MENU_VIEW = New System.Windows.Forms.ToolStripDropDownButton() MENU_VIEW = New System.Windows.Forms.ToolStripDropDownButton()
@@ -62,6 +74,10 @@ Namespace DownloadObjects
MENU_LOAD_SEP_2 = New System.Windows.Forms.ToolStripSeparator() MENU_LOAD_SEP_2 = New System.Windows.Forms.ToolStripSeparator()
MENU_LOAD_SEP_3 = New System.Windows.Forms.ToolStripSeparator() MENU_LOAD_SEP_3 = New System.Windows.Forms.ToolStripSeparator()
MENU_LOAD_SEP_4 = New System.Windows.Forms.ToolStripSeparator() MENU_LOAD_SEP_4 = New System.Windows.Forms.ToolStripSeparator()
MENU_LOAD_SEP_5 = New System.Windows.Forms.ToolStripSeparator()
MENU_LOAD_SEP_6 = New System.Windows.Forms.ToolStripSeparator()
MENU_LOAD_SEP_7 = New System.Windows.Forms.ToolStripSeparator()
MENU_LOAD_SEP_0 = New System.Windows.Forms.ToolStripSeparator()
Me.ToolbarTOP.SuspendLayout() Me.ToolbarTOP.SuspendLayout()
Me.SuspendLayout() Me.SuspendLayout()
' '
@@ -100,22 +116,47 @@ Namespace DownloadObjects
'MENU_LOAD_SEP_1 'MENU_LOAD_SEP_1
' '
MENU_LOAD_SEP_1.Name = "MENU_LOAD_SEP_1" MENU_LOAD_SEP_1.Name = "MENU_LOAD_SEP_1"
MENU_LOAD_SEP_1.Size = New System.Drawing.Size(264, 6) MENU_LOAD_SEP_1.Size = New System.Drawing.Size(349, 6)
' '
'MENU_LOAD_SEP_2 'MENU_LOAD_SEP_2
' '
MENU_LOAD_SEP_2.Name = "MENU_LOAD_SEP_2" MENU_LOAD_SEP_2.Name = "MENU_LOAD_SEP_2"
MENU_LOAD_SEP_2.Size = New System.Drawing.Size(264, 6) MENU_LOAD_SEP_2.Size = New System.Drawing.Size(349, 6)
' '
'MENU_LOAD_SEP_3 'MENU_LOAD_SEP_3
' '
MENU_LOAD_SEP_3.Name = "MENU_LOAD_SEP_3" MENU_LOAD_SEP_3.Name = "MENU_LOAD_SEP_3"
MENU_LOAD_SEP_3.Size = New System.Drawing.Size(264, 6) MENU_LOAD_SEP_3.Size = New System.Drawing.Size(349, 6)
'
'MENU_LOAD_SEP_4
'
MENU_LOAD_SEP_4.Name = "MENU_LOAD_SEP_4"
MENU_LOAD_SEP_4.Size = New System.Drawing.Size(349, 6)
'
'MENU_LOAD_SEP_5
'
MENU_LOAD_SEP_5.Name = "MENU_LOAD_SEP_5"
MENU_LOAD_SEP_5.Size = New System.Drawing.Size(349, 6)
'
'MENU_LOAD_SEP_6
'
MENU_LOAD_SEP_6.Name = "MENU_LOAD_SEP_6"
MENU_LOAD_SEP_6.Size = New System.Drawing.Size(349, 6)
'
'MENU_LOAD_SEP_7
'
MENU_LOAD_SEP_7.Name = "MENU_LOAD_SEP_7"
MENU_LOAD_SEP_7.Size = New System.Drawing.Size(349, 6)
'
'MENU_LOAD_SEP_0
'
MENU_LOAD_SEP_0.Name = "MENU_LOAD_SEP_0"
MENU_LOAD_SEP_0.Size = New System.Drawing.Size(349, 6)
' '
'ToolbarTOP 'ToolbarTOP
' '
Me.ToolbarTOP.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden Me.ToolbarTOP.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden
Me.ToolbarTOP.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.MENU_LOAD_SESSION, Me.SEP_0, MENU_VIEW, SEP_1, Me.MENU_DOWN, Me.BTT_REFRESH, Me.BTT_CLEAR, SEP_2}) Me.ToolbarTOP.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.MENU_LOAD_SESSION, Me.SEP_0, MENU_VIEW, SEP_1, Me.MENU_DOWN, Me.BTT_REFRESH, SEP_2})
Me.ToolbarTOP.Location = New System.Drawing.Point(0, 0) Me.ToolbarTOP.Location = New System.Drawing.Point(0, 0)
Me.ToolbarTOP.Name = "ToolbarTOP" Me.ToolbarTOP.Name = "ToolbarTOP"
Me.ToolbarTOP.Size = New System.Drawing.Size(484, 25) Me.ToolbarTOP.Size = New System.Drawing.Size(484, 25)
@@ -123,8 +164,9 @@ Namespace DownloadObjects
' '
'MENU_LOAD_SESSION 'MENU_LOAD_SESSION
' '
Me.MENU_LOAD_SESSION.AutoToolTip = False
Me.MENU_LOAD_SESSION.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image Me.MENU_LOAD_SESSION.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image
Me.MENU_LOAD_SESSION.DropDownItems.AddRange(New System.Windows.Forms.ToolStripItem() {Me.BTT_LOAD_SESSION_CURRENT, Me.BTT_LOAD_SESSION_LAST, Me.BTT_LOAD_SESSION_CHOOSE, MENU_LOAD_SEP_1, Me.BTT_LOAD_FAV, Me.BTT_LOAD_SPEC, MENU_LOAD_SEP_2, Me.BTT_FEED_ADD_FAV, Me.BTT_FEED_REMOVE_FAV, MENU_LOAD_SEP_3, Me.BTT_FEED_ADD_SPEC, Me.BTT_FEED_REMOVE_SPEC, MENU_LOAD_SEP_4, Me.BTT_FEED_CLEAR_FAV, Me.BTT_FEED_CLEAR_SPEC, Me.BTT_FEED_DELETE_SPEC, Me.BTT_FEED_DELETE_DAILY_LIST, Me.BTT_FEED_DELETE_DAILY_DATE}) Me.MENU_LOAD_SESSION.DropDownItems.AddRange(New System.Windows.Forms.ToolStripItem() {Me.BTT_LOAD_SESSION_CURRENT, Me.BTT_LOAD_SESSION_LAST, Me.BTT_LOAD_SESSION_CHOOSE, MENU_LOAD_SEP_0, Me.BTT_COPY_TO, Me.BTT_MOVE_TO, MENU_LOAD_SEP_1, Me.BTT_LOAD_FAV, Me.BTT_LOAD_SPEC, MENU_LOAD_SEP_2, Me.BTT_FEED_ADD_FAV, Me.BTT_FEED_ADD_FAV_REMOVE, Me.BTT_FEED_REMOVE_FAV, MENU_LOAD_SEP_3, Me.BTT_FEED_ADD_SPEC, Me.BTT_FEED_ADD_SPEC_REMOVE, Me.BTT_FEED_REMOVE_SPEC, MENU_LOAD_SEP_4, Me.BTT_FEED_CLEAR_FAV, Me.BTT_FEED_CLEAR_SPEC, Me.BTT_FEED_DELETE_SPEC, Me.BTT_FEED_DELETE_DAILY_LIST, Me.BTT_FEED_DELETE_DAILY_DATE, MENU_LOAD_SEP_5, Me.BTT_MERGE_SESSIONS, Me.BTT_CLEAR_DAILY, MENU_LOAD_SEP_6, Me.BTT_MERGE_FEEDS, MENU_LOAD_SEP_7, Me.BTT_CHECK_ALL, Me.BTT_CHECK_NONE})
Me.MENU_LOAD_SESSION.Image = Global.SCrawler.My.Resources.Resources.ArrowDownPic_Blue_24 Me.MENU_LOAD_SESSION.Image = Global.SCrawler.My.Resources.Resources.ArrowDownPic_Blue_24
Me.MENU_LOAD_SESSION.ImageTransparentColor = System.Drawing.Color.Magenta Me.MENU_LOAD_SESSION.ImageTransparentColor = System.Drawing.Color.Magenta
Me.MENU_LOAD_SESSION.Name = "MENU_LOAD_SESSION" Me.MENU_LOAD_SESSION.Name = "MENU_LOAD_SESSION"
@@ -135,65 +177,168 @@ Namespace DownloadObjects
' '
Me.BTT_LOAD_SESSION_CURRENT.Image = Global.SCrawler.My.Resources.Resources.ArrowDownPic_Blue_24 Me.BTT_LOAD_SESSION_CURRENT.Image = Global.SCrawler.My.Resources.Resources.ArrowDownPic_Blue_24
Me.BTT_LOAD_SESSION_CURRENT.Name = "BTT_LOAD_SESSION_CURRENT" Me.BTT_LOAD_SESSION_CURRENT.Name = "BTT_LOAD_SESSION_CURRENT"
Me.BTT_LOAD_SESSION_CURRENT.Size = New System.Drawing.Size(267, 22) Me.BTT_LOAD_SESSION_CURRENT.Size = New System.Drawing.Size(352, 22)
Me.BTT_LOAD_SESSION_CURRENT.Text = "Load current session" Me.BTT_LOAD_SESSION_CURRENT.Text = "Load current session"
' '
'BTT_LOAD_SESSION_LAST 'BTT_LOAD_SESSION_LAST
' '
Me.BTT_LOAD_SESSION_LAST.Image = Global.SCrawler.My.Resources.Resources.ArrowDownPic_Blue_24 Me.BTT_LOAD_SESSION_LAST.Image = Global.SCrawler.My.Resources.Resources.ArrowDownPic_Blue_24
Me.BTT_LOAD_SESSION_LAST.Name = "BTT_LOAD_SESSION_LAST" Me.BTT_LOAD_SESSION_LAST.Name = "BTT_LOAD_SESSION_LAST"
Me.BTT_LOAD_SESSION_LAST.Size = New System.Drawing.Size(267, 22) Me.BTT_LOAD_SESSION_LAST.Size = New System.Drawing.Size(352, 22)
Me.BTT_LOAD_SESSION_LAST.Text = "Load last session" Me.BTT_LOAD_SESSION_LAST.Text = "Load last session"
' '
'BTT_LOAD_SESSION_CHOOSE 'BTT_LOAD_SESSION_CHOOSE
' '
Me.BTT_LOAD_SESSION_CHOOSE.Image = Global.SCrawler.My.Resources.Resources.ArrowDownPic_Blue_24 Me.BTT_LOAD_SESSION_CHOOSE.Image = Global.SCrawler.My.Resources.Resources.ArrowDownPic_Blue_24
Me.BTT_LOAD_SESSION_CHOOSE.Name = "BTT_LOAD_SESSION_CHOOSE" Me.BTT_LOAD_SESSION_CHOOSE.Name = "BTT_LOAD_SESSION_CHOOSE"
Me.BTT_LOAD_SESSION_CHOOSE.Size = New System.Drawing.Size(267, 22) Me.BTT_LOAD_SESSION_CHOOSE.Size = New System.Drawing.Size(352, 22)
Me.BTT_LOAD_SESSION_CHOOSE.Text = "Select loading session" Me.BTT_LOAD_SESSION_CHOOSE.Text = "Select loading session"
' '
'BTT_COPY_TO
'
Me.BTT_COPY_TO.Image = Global.SCrawler.My.Resources.Resources.PastePic_32
Me.BTT_COPY_TO.Name = "BTT_COPY_TO"
Me.BTT_COPY_TO.Size = New System.Drawing.Size(352, 22)
Me.BTT_COPY_TO.Text = "Copy checked to..."
'
'BTT_MOVE_TO
'
Me.BTT_MOVE_TO.Image = Global.SCrawler.My.Resources.Resources.CutPic_48
Me.BTT_MOVE_TO.Name = "BTT_MOVE_TO"
Me.BTT_MOVE_TO.Size = New System.Drawing.Size(352, 22)
Me.BTT_MOVE_TO.Text = "Move checked to..."
'
'BTT_LOAD_FAV 'BTT_LOAD_FAV
' '
Me.BTT_LOAD_FAV.Image = Global.SCrawler.My.Resources.Resources.HeartPic_32 Me.BTT_LOAD_FAV.Image = Global.SCrawler.My.Resources.Resources.HeartPic_32
Me.BTT_LOAD_FAV.Name = "BTT_LOAD_FAV" Me.BTT_LOAD_FAV.Name = "BTT_LOAD_FAV"
Me.BTT_LOAD_FAV.Size = New System.Drawing.Size(267, 22) Me.BTT_LOAD_FAV.Size = New System.Drawing.Size(352, 22)
Me.BTT_LOAD_FAV.Text = "Load Favorite" Me.BTT_LOAD_FAV.Text = "Load Favorite"
' '
'BTT_LOAD_SPEC 'BTT_LOAD_SPEC
' '
Me.BTT_LOAD_SPEC.Image = Global.SCrawler.My.Resources.Resources.RSSPic_512 Me.BTT_LOAD_SPEC.Image = Global.SCrawler.My.Resources.Resources.RSSPic_512
Me.BTT_LOAD_SPEC.Name = "BTT_LOAD_SPEC" Me.BTT_LOAD_SPEC.Name = "BTT_LOAD_SPEC"
Me.BTT_LOAD_SPEC.Size = New System.Drawing.Size(267, 22) Me.BTT_LOAD_SPEC.Size = New System.Drawing.Size(352, 22)
Me.BTT_LOAD_SPEC.Text = "Load special feed" Me.BTT_LOAD_SPEC.Text = "Load special feed"
' '
'BTT_FEED_ADD_FAV 'BTT_FEED_ADD_FAV
' '
Me.BTT_FEED_ADD_FAV.Image = Global.SCrawler.My.Resources.Resources.HeartPic_32 Me.BTT_FEED_ADD_FAV.Image = Global.SCrawler.My.Resources.Resources.HeartPic_32
Me.BTT_FEED_ADD_FAV.Name = "BTT_FEED_ADD_FAV" Me.BTT_FEED_ADD_FAV.Name = "BTT_FEED_ADD_FAV"
Me.BTT_FEED_ADD_FAV.Size = New System.Drawing.Size(267, 22) Me.BTT_FEED_ADD_FAV.Size = New System.Drawing.Size(352, 22)
Me.BTT_FEED_ADD_FAV.Text = "Add checked to Favorite" Me.BTT_FEED_ADD_FAV.Text = "Add checked to Favorite"
' '
'BTT_FEED_ADD_FAV_REMOVE
'
Me.BTT_FEED_ADD_FAV_REMOVE.Image = Global.SCrawler.My.Resources.Resources.HeartPic_32
Me.BTT_FEED_ADD_FAV_REMOVE.Name = "BTT_FEED_ADD_FAV_REMOVE"
Me.BTT_FEED_ADD_FAV_REMOVE.Size = New System.Drawing.Size(352, 22)
Me.BTT_FEED_ADD_FAV_REMOVE.Text = "Add checked to Favorite (remove from current)"
'
'BTT_FEED_REMOVE_FAV 'BTT_FEED_REMOVE_FAV
' '
Me.BTT_FEED_REMOVE_FAV.Image = Global.SCrawler.My.Resources.Resources.DeletePic_24 Me.BTT_FEED_REMOVE_FAV.Image = Global.SCrawler.My.Resources.Resources.DeletePic_24
Me.BTT_FEED_REMOVE_FAV.Name = "BTT_FEED_REMOVE_FAV" Me.BTT_FEED_REMOVE_FAV.Name = "BTT_FEED_REMOVE_FAV"
Me.BTT_FEED_REMOVE_FAV.Size = New System.Drawing.Size(267, 22) Me.BTT_FEED_REMOVE_FAV.Size = New System.Drawing.Size(352, 22)
Me.BTT_FEED_REMOVE_FAV.Text = "Remove checked from Favorite" Me.BTT_FEED_REMOVE_FAV.Text = "Remove checked from Favorite"
' '
'BTT_FEED_ADD_SPEC 'BTT_FEED_ADD_SPEC
' '
Me.BTT_FEED_ADD_SPEC.Image = Global.SCrawler.My.Resources.Resources.RSSPic_512 Me.BTT_FEED_ADD_SPEC.Image = Global.SCrawler.My.Resources.Resources.RSSPic_512
Me.BTT_FEED_ADD_SPEC.Name = "BTT_FEED_ADD_SPEC" Me.BTT_FEED_ADD_SPEC.Name = "BTT_FEED_ADD_SPEC"
Me.BTT_FEED_ADD_SPEC.Size = New System.Drawing.Size(267, 22) Me.BTT_FEED_ADD_SPEC.Size = New System.Drawing.Size(352, 22)
Me.BTT_FEED_ADD_SPEC.Text = "Add checked to special feed..." Me.BTT_FEED_ADD_SPEC.Text = "Add checked to special feed..."
' '
'BTT_FEED_ADD_SPEC_REMOVE
'
Me.BTT_FEED_ADD_SPEC_REMOVE.Image = Global.SCrawler.My.Resources.Resources.RSSPic_512
Me.BTT_FEED_ADD_SPEC_REMOVE.Name = "BTT_FEED_ADD_SPEC_REMOVE"
Me.BTT_FEED_ADD_SPEC_REMOVE.Size = New System.Drawing.Size(352, 22)
Me.BTT_FEED_ADD_SPEC_REMOVE.Text = "Add checked to special feed (remove from current)..."
'
'BTT_FEED_REMOVE_SPEC 'BTT_FEED_REMOVE_SPEC
' '
Me.BTT_FEED_REMOVE_SPEC.Image = Global.SCrawler.My.Resources.Resources.DeletePic_24 Me.BTT_FEED_REMOVE_SPEC.Image = Global.SCrawler.My.Resources.Resources.DeletePic_24
Me.BTT_FEED_REMOVE_SPEC.Name = "BTT_FEED_REMOVE_SPEC" Me.BTT_FEED_REMOVE_SPEC.Name = "BTT_FEED_REMOVE_SPEC"
Me.BTT_FEED_REMOVE_SPEC.Size = New System.Drawing.Size(267, 22) Me.BTT_FEED_REMOVE_SPEC.Size = New System.Drawing.Size(352, 22)
Me.BTT_FEED_REMOVE_SPEC.Text = "Remove checked from special feed..." Me.BTT_FEED_REMOVE_SPEC.Text = "Remove checked from special feed..."
' '
'BTT_FEED_CLEAR_FAV
'
Me.BTT_FEED_CLEAR_FAV.Image = Global.SCrawler.My.Resources.Resources.BrushToolPic_16
Me.BTT_FEED_CLEAR_FAV.Name = "BTT_FEED_CLEAR_FAV"
Me.BTT_FEED_CLEAR_FAV.Size = New System.Drawing.Size(352, 22)
Me.BTT_FEED_CLEAR_FAV.Text = "Clear Favorite"
'
'BTT_FEED_CLEAR_SPEC
'
Me.BTT_FEED_CLEAR_SPEC.Image = Global.SCrawler.My.Resources.Resources.BrushToolPic_16
Me.BTT_FEED_CLEAR_SPEC.Name = "BTT_FEED_CLEAR_SPEC"
Me.BTT_FEED_CLEAR_SPEC.Size = New System.Drawing.Size(352, 22)
Me.BTT_FEED_CLEAR_SPEC.Text = "Clear special feed..."
'
'BTT_FEED_DELETE_SPEC
'
Me.BTT_FEED_DELETE_SPEC.Image = Global.SCrawler.My.Resources.Resources.DeletePic_24
Me.BTT_FEED_DELETE_SPEC.Name = "BTT_FEED_DELETE_SPEC"
Me.BTT_FEED_DELETE_SPEC.Size = New System.Drawing.Size(352, 22)
Me.BTT_FEED_DELETE_SPEC.Text = "Delete special feed..."
'
'BTT_FEED_DELETE_DAILY_LIST
'
Me.BTT_FEED_DELETE_DAILY_LIST.Image = Global.SCrawler.My.Resources.Resources.DeletePic_24
Me.BTT_FEED_DELETE_DAILY_LIST.Name = "BTT_FEED_DELETE_DAILY_LIST"
Me.BTT_FEED_DELETE_DAILY_LIST.Size = New System.Drawing.Size(352, 22)
Me.BTT_FEED_DELETE_DAILY_LIST.Text = "Delete daily feed (by list)"
'
'BTT_FEED_DELETE_DAILY_DATE
'
Me.BTT_FEED_DELETE_DAILY_DATE.Image = Global.SCrawler.My.Resources.Resources.DeletePic_24
Me.BTT_FEED_DELETE_DAILY_DATE.Name = "BTT_FEED_DELETE_DAILY_DATE"
Me.BTT_FEED_DELETE_DAILY_DATE.Size = New System.Drawing.Size(352, 22)
Me.BTT_FEED_DELETE_DAILY_DATE.Text = "Delete daily feed (by date)"
'
'BTT_MERGE_SESSIONS
'
Me.BTT_MERGE_SESSIONS.AutoToolTip = True
Me.BTT_MERGE_SESSIONS.Image = Global.SCrawler.My.Resources.Resources.DBPic_32
Me.BTT_MERGE_SESSIONS.Name = "BTT_MERGE_SESSIONS"
Me.BTT_MERGE_SESSIONS.Size = New System.Drawing.Size(352, 22)
Me.BTT_MERGE_SESSIONS.Text = "Merge sessions"
Me.BTT_MERGE_SESSIONS.ToolTipText = "Merge multiple session feeds into one"
'
'BTT_CLEAR_DAILY
'
Me.BTT_CLEAR_DAILY.AutoToolTip = True
Me.BTT_CLEAR_DAILY.Image = Global.SCrawler.My.Resources.Resources.DeletePic_24
Me.BTT_CLEAR_DAILY.ImageTransparentColor = System.Drawing.Color.Magenta
Me.BTT_CLEAR_DAILY.Name = "BTT_CLEAR_DAILY"
Me.BTT_CLEAR_DAILY.Size = New System.Drawing.Size(352, 22)
Me.BTT_CLEAR_DAILY.Text = "Clear session"
Me.BTT_CLEAR_DAILY.ToolTipText = "Clear current session"
'
'BTT_MERGE_FEEDS
'
Me.BTT_MERGE_FEEDS.AutoToolTip = True
Me.BTT_MERGE_FEEDS.Image = Global.SCrawler.My.Resources.Resources.DBPic_32
Me.BTT_MERGE_FEEDS.Name = "BTT_MERGE_FEEDS"
Me.BTT_MERGE_FEEDS.Size = New System.Drawing.Size(352, 22)
Me.BTT_MERGE_FEEDS.Text = "Merge special feeds"
Me.BTT_MERGE_FEEDS.ToolTipText = "Merge multiple special feeds into one"
'
'BTT_CHECK_ALL
'
Me.BTT_CHECK_ALL.Name = "BTT_CHECK_ALL"
Me.BTT_CHECK_ALL.Size = New System.Drawing.Size(352, 22)
Me.BTT_CHECK_ALL.Text = "Select all"
'
'BTT_CHECK_NONE
'
Me.BTT_CHECK_NONE.Name = "BTT_CHECK_NONE"
Me.BTT_CHECK_NONE.Size = New System.Drawing.Size(352, 22)
Me.BTT_CHECK_NONE.Text = "Select none"
'
'SEP_0 'SEP_0
' '
Me.SEP_0.Name = "SEP_0" Me.SEP_0.Name = "SEP_0"
@@ -235,15 +380,6 @@ Namespace DownloadObjects
Me.BTT_REFRESH.Text = "Refresh" Me.BTT_REFRESH.Text = "Refresh"
Me.BTT_REFRESH.ToolTipText = "Refresh data list" Me.BTT_REFRESH.ToolTipText = "Refresh data list"
' '
'BTT_CLEAR
'
Me.BTT_CLEAR.Image = Global.SCrawler.My.Resources.Resources.DeletePic_24
Me.BTT_CLEAR.ImageTransparentColor = System.Drawing.Color.Magenta
Me.BTT_CLEAR.Name = "BTT_CLEAR"
Me.BTT_CLEAR.Size = New System.Drawing.Size(54, 22)
Me.BTT_CLEAR.Text = "Clear"
Me.BTT_CLEAR.ToolTipText = "Clear data list"
'
'TP_DATA 'TP_DATA
' '
Me.TP_DATA.AutoScroll = True Me.TP_DATA.AutoScroll = True
@@ -269,46 +405,6 @@ Namespace DownloadObjects
Me.TP_DATA.Size = New System.Drawing.Size(484, 436) Me.TP_DATA.Size = New System.Drawing.Size(484, 436)
Me.TP_DATA.TabIndex = 1 Me.TP_DATA.TabIndex = 1
' '
'MENU_LOAD_SEP_4
'
MENU_LOAD_SEP_4.Name = "MENU_LOAD_SEP_4"
MENU_LOAD_SEP_4.Size = New System.Drawing.Size(264, 6)
'
'BTT_FEED_CLEAR_FAV
'
Me.BTT_FEED_CLEAR_FAV.Image = Global.SCrawler.My.Resources.Resources.BrushToolPic_16
Me.BTT_FEED_CLEAR_FAV.Name = "BTT_FEED_CLEAR_FAV"
Me.BTT_FEED_CLEAR_FAV.Size = New System.Drawing.Size(267, 22)
Me.BTT_FEED_CLEAR_FAV.Text = "Clear Favorite"
'
'BTT_FEED_CLEAR_SPEC
'
Me.BTT_FEED_CLEAR_SPEC.Image = Global.SCrawler.My.Resources.Resources.BrushToolPic_16
Me.BTT_FEED_CLEAR_SPEC.Name = "BTT_FEED_CLEAR_SPEC"
Me.BTT_FEED_CLEAR_SPEC.Size = New System.Drawing.Size(267, 22)
Me.BTT_FEED_CLEAR_SPEC.Text = "Clear special feed..."
'
'BTT_FEED_DELETE_SPEC
'
Me.BTT_FEED_DELETE_SPEC.Image = Global.SCrawler.My.Resources.Resources.DeletePic_24
Me.BTT_FEED_DELETE_SPEC.Name = "BTT_FEED_DELETE_SPEC"
Me.BTT_FEED_DELETE_SPEC.Size = New System.Drawing.Size(267, 22)
Me.BTT_FEED_DELETE_SPEC.Text = "Delete special feed..."
'
'BTT_FEED_DELETE_DAILY_LIST
'
Me.BTT_FEED_DELETE_DAILY_LIST.Image = Global.SCrawler.My.Resources.Resources.DeletePic_24
Me.BTT_FEED_DELETE_DAILY_LIST.Name = "BTT_FEED_DELETE_DAILY_LIST"
Me.BTT_FEED_DELETE_DAILY_LIST.Size = New System.Drawing.Size(267, 22)
Me.BTT_FEED_DELETE_DAILY_LIST.Text = "Delete daily feed (by list)"
'
'BTT_FEED_DELETE_DAILY_DATE
'
Me.BTT_FEED_DELETE_DAILY_DATE.Image = Global.SCrawler.My.Resources.Resources.DeletePic_24
Me.BTT_FEED_DELETE_DAILY_DATE.Name = "BTT_FEED_DELETE_DAILY_DATE"
Me.BTT_FEED_DELETE_DAILY_DATE.Size = New System.Drawing.Size(267, 22)
Me.BTT_FEED_DELETE_DAILY_DATE.Text = "Delete daily feed (by date)"
'
'DownloadFeedForm 'DownloadFeedForm
' '
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!) Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
@@ -322,7 +418,7 @@ Namespace DownloadObjects
Me.KeyPreview = True Me.KeyPreview = True
Me.MinimumSize = New System.Drawing.Size(300, 300) Me.MinimumSize = New System.Drawing.Size(300, 300)
Me.Name = "DownloadFeedForm" Me.Name = "DownloadFeedForm"
Me.Text = "Download Feed" Me.Text = "Feed"
Me.ToolbarTOP.ResumeLayout(False) Me.ToolbarTOP.ResumeLayout(False)
Me.ToolbarTOP.PerformLayout() Me.ToolbarTOP.PerformLayout()
Me.ResumeLayout(False) Me.ResumeLayout(False)
@@ -330,7 +426,7 @@ Namespace DownloadObjects
End Sub End Sub
Private WithEvents BTT_REFRESH As ToolStripButton Private WithEvents BTT_REFRESH As ToolStripButton
Private WithEvents BTT_CLEAR As ToolStripButton Private WithEvents BTT_CLEAR_DAILY As ToolStripMenuItem
Private WithEvents MENU_LOAD_SESSION As ToolStripDropDownButton Private WithEvents MENU_LOAD_SESSION As ToolStripDropDownButton
Private WithEvents BTT_LOAD_SESSION_LAST As ToolStripMenuItem Private WithEvents BTT_LOAD_SESSION_LAST As ToolStripMenuItem
Private WithEvents BTT_LOAD_SESSION_CHOOSE As ToolStripMenuItem Private WithEvents BTT_LOAD_SESSION_CHOOSE As ToolStripMenuItem
@@ -354,5 +450,13 @@ Namespace DownloadObjects
Private WithEvents BTT_FEED_DELETE_SPEC As ToolStripMenuItem Private WithEvents BTT_FEED_DELETE_SPEC As ToolStripMenuItem
Private WithEvents BTT_FEED_DELETE_DAILY_LIST As ToolStripMenuItem Private WithEvents BTT_FEED_DELETE_DAILY_LIST As ToolStripMenuItem
Private WithEvents BTT_FEED_DELETE_DAILY_DATE As ToolStripMenuItem Private WithEvents BTT_FEED_DELETE_DAILY_DATE As ToolStripMenuItem
Private WithEvents BTT_MERGE_SESSIONS As ToolStripMenuItem
Private WithEvents BTT_MERGE_FEEDS As ToolStripMenuItem
Private WithEvents BTT_FEED_ADD_FAV_REMOVE As ToolStripMenuItem
Private WithEvents BTT_FEED_ADD_SPEC_REMOVE As ToolStripMenuItem
Private WithEvents BTT_CHECK_ALL As ToolStripMenuItem
Private WithEvents BTT_CHECK_NONE As ToolStripMenuItem
Private WithEvents BTT_COPY_TO As ToolStripMenuItem
Private WithEvents BTT_MOVE_TO As ToolStripMenuItem
End Class End Class
End Namespace End Namespace

View File

@@ -144,10 +144,22 @@
<metadata name="MENU_LOAD_SEP_3.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <metadata name="MENU_LOAD_SEP_3.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value> <value>False</value>
</metadata> </metadata>
<metadata name="ToolbarTOP.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="MENU_LOAD_SEP_4.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <metadata name="MENU_LOAD_SEP_4.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value> <value>False</value>
</metadata> </metadata>
<metadata name="MENU_LOAD_SEP_5.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="MENU_LOAD_SEP_6.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="MENU_LOAD_SEP_7.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="MENU_LOAD_SEP_0.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="ToolbarTOP.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root> </root>

View File

@@ -16,7 +16,11 @@ Imports UserMediaD = SCrawler.DownloadObjects.TDownloader.UserMediaD
Imports DTSModes = PersonalUtilities.Forms.DateTimeSelectionForm.Modes Imports DTSModes = PersonalUtilities.Forms.DateTimeSelectionForm.Modes
Namespace DownloadObjects Namespace DownloadObjects
Friend Class DownloadFeedForm Friend Class DownloadFeedForm
#Region "Events"
Friend Event UsersAdded As UsersAddedEventHandler
#End Region
#Region "Declarations" #Region "Declarations"
Private Const FeedTitleDefault As String = "Feed"
Private WithEvents MyDefs As DefaultFormOptions Private WithEvents MyDefs As DefaultFormOptions
Private WithEvents MyRange As RangeSwitcherToolbar(Of UserMediaD) Private WithEvents MyRange As RangeSwitcherToolbar(Of UserMediaD)
Private ReadOnly DataList As List(Of UserMediaD) Private ReadOnly DataList As List(Of UserMediaD)
@@ -37,6 +41,72 @@ Namespace DownloadObjects
Return OPT_SUBSCRIPTIONS.Checked Return OPT_SUBSCRIPTIONS.Checked
End Get End Get
End Property End Property
#Region "Feeds options"
Private Enum FeedModes : Current : Saved : Special : End Enum
Private FeedMode As FeedModes = FeedModes.Current
Private LoadedSessionName As String = String.Empty
Private ReadOnly Property IsSession As Boolean
Get
Return FeedMode = FeedModes.Current Or FeedMode = FeedModes.Saved
End Get
End Property
Private ReadOnly LoadedFeedNames As List(Of String)
Private Sub FeedChangeMode(ByVal Mode As FeedModes, Optional ByVal fNames As IEnumerable(Of String) = Nothing)
FeedMode = Mode
LoadedFeedNames.Clear()
If fNames.ListExists Then LoadedFeedNames.AddRange(fNames)
Try : ControlInvokeFast(Me, Sub()
Select Case FeedMode
Case FeedModes.Current : Text = $"{FeedTitleDefault}: current session"
Case FeedModes.Saved : Text = $"{FeedTitleDefault}: saved session {LoadedSessionName.IfNullOrEmpty("(multiple)")}"
Case FeedModes.Special : Text = $"{FeedTitleDefault}: {IIf(LoadedFeedNames.Count > 1, "multiple special feeds", LoadedFeedNames.FirstOrDefault.IfNullOrEmpty("?"))}"
Case Else : Text = FeedTitleDefault
End Select
End Sub, EDP.None) : Catch : End Try
End Sub
Private Sub FeedRemoveCheckedMedia(ByVal MediaList As IEnumerable(Of UserMediaD), Optional ByVal OverriddenNames As List(Of String) = Nothing,
Optional ByVal RemoveChecked As Boolean = True, Optional ByVal ExcludingNames As IEnumerable(Of String) = Nothing,
Optional ByVal RemoveFromDataListOnly As Boolean = False)
Try
If FeedMode = FeedModes.Special Then
If LoadedFeedNames.Count > 0 Then
Dim dataRemoved As Boolean = False
If OverriddenNames.ListExists And Not LoadedFeedNames.ListContains(OverriddenNames) Then Exit Sub
If Not RemoveFromDataListOnly Then
Dim eNames As IEnumerable(Of String) = If(ExcludingNames, New String() {})
With If(OverriddenNames, LoadedFeedNames)
.ForEach(Sub(ByVal feedName As String)
If Not eNames.Contains(feedName) Then
Dim indx% = Settings.Feeds.IndexOf(feedName)
If indx >= 0 Then
If Settings.Feeds(indx).Remove(MediaList) > 0 Then dataRemoved = True
End If
End If
End Sub)
End With
End If
If RemoveFromDataListOnly Then
RefillSpecialFeedsData()
ElseIf dataRemoved Then
DataList.ListDisposeRemove(MediaList)
If RemoveChecked Then
If RemoveCheckedMedia(False) Then RefillAfterDelete()
Else
RefillSpecialFeedsData()
End If
End If
End If
ElseIf FeedMode = FeedModes.Current Then
If OverriddenNames Is Nothing AndAlso Downloader.Files.ListDisposeRemove(MediaList) > 0 AndAlso RemoveCheckedMedia(False) Then
DataList.ListDisposeRemove(MediaList)
RefillAfterDelete()
End If
End If
Catch ex As Exception
ErrorsDescriber.Execute(EDP.SendToLog, ex, "[DownloadFeedForm.FeedRemoveCheckedMedia]")
End Try
End Sub
#End Region
#End Region #End Region
#Region "Initializer" #Region "Initializer"
Friend Sub New() Friend Sub New()
@@ -44,6 +114,7 @@ Namespace DownloadObjects
MyDefs = New DefaultFormOptions(Me, Settings.Design) MyDefs = New DefaultFormOptions(Me, Settings.Design)
MyRange = New RangeSwitcherToolbar(Of UserMediaD)(ToolbarTOP) MyRange = New RangeSwitcherToolbar(Of UserMediaD)(ToolbarTOP)
DataList = New List(Of UserMediaD) DataList = New List(Of UserMediaD)
LoadedFeedNames = New List(Of String)
BTT_DELETE_SELECTED = New ToolStripButton With { BTT_DELETE_SELECTED = New ToolStripButton With {
.Text = "Delete selected", .Text = "Delete selected",
.AutoToolTip = True, .AutoToolTip = True,
@@ -78,6 +149,7 @@ Namespace DownloadObjects
If Not feed.IsFavorite Then If Not feed.IsFavorite Then
AddNewFeedItem(BTT_LOAD_SPEC, feed, My.Resources.RSSPic_512, AddressOf Feed_SPEC_LOAD) AddNewFeedItem(BTT_LOAD_SPEC, feed, My.Resources.RSSPic_512, AddressOf Feed_SPEC_LOAD)
AddNewFeedItem(BTT_FEED_ADD_SPEC, feed, My.Resources.RSSPic_512, AddressOf Feed_SPEC_ADD) AddNewFeedItem(BTT_FEED_ADD_SPEC, feed, My.Resources.RSSPic_512, AddressOf Feed_SPEC_ADD)
AddNewFeedItem(BTT_FEED_ADD_SPEC_REMOVE, feed, My.Resources.RSSPic_512, AddressOf Feed_SPEC_ADD_REMOVE)
AddNewFeedItem(BTT_FEED_REMOVE_SPEC, feed, My.Resources.RSSPic_512, AddressOf Feed_SPEC_REMOVE) AddNewFeedItem(BTT_FEED_REMOVE_SPEC, feed, My.Resources.RSSPic_512, AddressOf Feed_SPEC_REMOVE)
AddNewFeedItem(BTT_FEED_DELETE_SPEC, feed, My.Resources.DeletePic_24, AddressOf Feed_SPEC_DELETE) AddNewFeedItem(BTT_FEED_DELETE_SPEC, feed, My.Resources.DeletePic_24, AddressOf Feed_SPEC_DELETE)
AddNewFeedItem(BTT_FEED_CLEAR_SPEC, feed, My.Resources.BrushToolPic_16, AddressOf Feed_SPEC_CLEAR) AddNewFeedItem(BTT_FEED_CLEAR_SPEC, feed, My.Resources.BrushToolPic_16, AddressOf Feed_SPEC_CLEAR)
@@ -94,7 +166,8 @@ Namespace DownloadObjects
End With End With
MENU_DOWN.Visible = OPT_SUBSCRIPTIONS.Checked MENU_DOWN.Visible = OPT_SUBSCRIPTIONS.Checked
UpdateSettings() UpdateSettings()
RefillList() FeedChangeMode(FeedModes.Current)
RefillList(True, False)
.EndLoaderOperations(False) .EndLoaderOperations(False)
End With End With
End Sub End Sub
@@ -105,7 +178,8 @@ Namespace DownloadObjects
Private Sub DownloadFeedForm_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed Private Sub DownloadFeedForm_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed
ClearTable() ClearTable()
MyRange.Dispose() MyRange.Dispose()
BTT_CLEAR.Dispose() LoadedFeedNames.Clear()
BTT_CLEAR_DAILY.Dispose()
DataList.Clear() DataList.Clear()
End Sub End Sub
Private Sub DownloadFeedForm_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown Private Sub DownloadFeedForm_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
@@ -134,6 +208,7 @@ Namespace DownloadObjects
Private Sub Feed_FeedAdded(ByVal Source As FeedSpecialCollection, ByVal Feed As FeedSpecial) Private Sub Feed_FeedAdded(ByVal Source As FeedSpecialCollection, ByVal Feed As FeedSpecial)
AddNewFeedItem(BTT_LOAD_SPEC, Feed, My.Resources.RSSPic_512, AddressOf Feed_SPEC_LOAD, True) AddNewFeedItem(BTT_LOAD_SPEC, Feed, My.Resources.RSSPic_512, AddressOf Feed_SPEC_LOAD, True)
AddNewFeedItem(BTT_FEED_ADD_SPEC, Feed, My.Resources.RSSPic_512, AddressOf Feed_SPEC_ADD, True) AddNewFeedItem(BTT_FEED_ADD_SPEC, Feed, My.Resources.RSSPic_512, AddressOf Feed_SPEC_ADD, True)
AddNewFeedItem(BTT_FEED_ADD_SPEC_REMOVE, Feed, My.Resources.RSSPic_512, AddressOf Feed_SPEC_ADD_REMOVE, True)
AddNewFeedItem(BTT_FEED_REMOVE_SPEC, Feed, My.Resources.RSSPic_512, AddressOf Feed_SPEC_REMOVE, True) AddNewFeedItem(BTT_FEED_REMOVE_SPEC, Feed, My.Resources.RSSPic_512, AddressOf Feed_SPEC_REMOVE, True)
AddNewFeedItem(BTT_FEED_DELETE_SPEC, Feed, My.Resources.DeletePic_24, AddressOf Feed_SPEC_DELETE, True) AddNewFeedItem(BTT_FEED_DELETE_SPEC, Feed, My.Resources.DeletePic_24, AddressOf Feed_SPEC_DELETE, True)
AddNewFeedItem(BTT_FEED_CLEAR_SPEC, Feed, My.Resources.BrushToolPic_16, AddressOf Feed_SPEC_CLEAR, True) AddNewFeedItem(BTT_FEED_CLEAR_SPEC, Feed, My.Resources.BrushToolPic_16, AddressOf Feed_SPEC_CLEAR, True)
@@ -159,7 +234,6 @@ Namespace DownloadObjects
item = .DropDownItems(i) item = .DropDownItems(i)
If TypeOf item Is ToolStripMenuItem AndAlso Feed.Equals(DirectCast(item, ToolStripMenuItem).Tag) Then If TypeOf item Is ToolStripMenuItem AndAlso Feed.Equals(DirectCast(item, ToolStripMenuItem).Tag) Then
With DirectCast(item, ToolStripMenuItem) : .Tag = Nothing : .Dispose() : End With With DirectCast(item, ToolStripMenuItem) : .Tag = Nothing : .Dispose() : End With
'.DropDownItems.RemoveAt(i)
End If End If
Next Next
End If End If
@@ -173,30 +247,51 @@ Namespace DownloadObjects
Private Sub Feed_SPEC_LOAD(ByVal Source As ToolStripMenuItem, ByVal e As EventArgs) Private Sub Feed_SPEC_LOAD(ByVal Source As ToolStripMenuItem, ByVal e As EventArgs)
Dim f As FeedSpecial = Source.Tag Dim f As FeedSpecial = Source.Tag
If Not f Is Nothing AndAlso Not f.Disposed Then If Not f Is Nothing AndAlso Not f.Disposed Then
DataList.Clear() FeedChangeMode(FeedModes.Special, {f.Name})
If f.Count > 0 Then DataList.ListAddList(f) : CleanDataList() RefillSpecialFeedsData(False)
RefillList(False)
End If End If
End Sub End Sub
Private Sub Feed_SPEC_ADD(ByVal Source As ToolStripMenuItem, ByVal e As EventArgs) Private Sub Feed_SPEC_ADD(ByVal Source As ToolStripMenuItem, ByVal e As EventArgs)
Dim f As FeedSpecial = Source.Tag Dim f As FeedSpecial = Source.Tag
If Not f Is Nothing AndAlso Not f.Disposed Then f.Add(GetCheckedMedia()) If Not f Is Nothing AndAlso Not f.Disposed Then f.Add(GetCheckedMedia())
End Sub End Sub
Private Sub Feed_SPEC_ADD_REMOVE(ByVal Source As ToolStripMenuItem, ByVal e As EventArgs)
Dim f As FeedSpecial = Source.Tag
If Not f Is Nothing AndAlso Not f.Disposed Then
Dim c As IEnumerable(Of UserMediaD) = GetCheckedMedia()
If c.ListExists Then
f.Add(c)
FeedRemoveCheckedMedia(c,,, {f.Name})
End If
End If
End Sub
Private Sub Feed_SPEC_CLEAR(ByVal Source As ToolStripMenuItem, ByVal e As EventArgs) Private Sub Feed_SPEC_CLEAR(ByVal Source As ToolStripMenuItem, ByVal e As EventArgs)
Dim f As FeedSpecial = Source.Tag Dim f As FeedSpecial = Source.Tag
If Not f Is Nothing AndAlso Not f.Disposed Then If Not f Is Nothing AndAlso Not f.Disposed Then
If MsgBoxE({$"Are you sure you want to clear the '{f.Name}' feed?", "Clear feed"}, vbExclamation,,, {"Process", "Cancel"}) = 0 Then f.Clear() If MsgBoxE({$"Are you sure you want to clear the '{f.Name}' feed?", "Clear feed"}, vbExclamation,,, {"Process", "Cancel"}) = 0 Then
f.Clear()
If FeedMode = FeedModes.Special Then RefillSpecialFeedsData()
End If
End If End If
End Sub End Sub
Private Sub Feed_SPEC_REMOVE(ByVal Source As ToolStripMenuItem, ByVal e As EventArgs) Private Sub Feed_SPEC_REMOVE(ByVal Source As ToolStripMenuItem, ByVal e As EventArgs)
Dim f As FeedSpecial = Source.Tag Dim f As FeedSpecial = Source.Tag
If Not f Is Nothing AndAlso Not f.Disposed Then f.Remove(GetCheckedMedia()) If Not f Is Nothing AndAlso Not f.Disposed Then
Dim m As IEnumerable(Of UserMediaD) = GetCheckedMedia()
If m.ListExists Then
f.Remove(m)
FeedRemoveCheckedMedia(m, {f.Name}.ToList)
End If
End If
End Sub End Sub
Private Sub Feed_SPEC_DELETE(ByVal Source As ToolStripMenuItem, ByVal e As EventArgs) Private Sub Feed_SPEC_DELETE(ByVal Source As ToolStripMenuItem, ByVal e As EventArgs)
Dim f As FeedSpecial = Source.Tag Dim f As FeedSpecial = Source.Tag
If Not f Is Nothing AndAlso Not f.Disposed Then If Not f Is Nothing AndAlso Not f.Disposed Then
If MsgBoxE({$"Are you sure you want to delete the '{f.Name}' feed?", "Delete feed"}, vbExclamation,,, {"Process", "Cancel"}) = 0 AndAlso Dim name$ = f.Name
f.Delete() Then Feed_FeedRemoved(Settings.Feeds, f) If MsgBoxE({$"Are you sure you want to delete the '{name}' feed?", "Delete feed"}, vbExclamation,,, {"Process", "Cancel"}) = 0 AndAlso f.Delete() Then
Feed_FeedRemoved(Settings.Feeds, f)
If LoadedFeedNames.Count > 0 AndAlso LoadedFeedNames.Contains(name) Then LoadedFeedNames.Remove(name) : RefillSpecialFeedsData()
End If
End If End If
End Sub End Sub
#End Region #End Region
@@ -227,11 +322,6 @@ Namespace DownloadObjects
ForeColor = SystemColors.WindowText ForeColor = SystemColors.WindowText
End If End If
Dim fsd As Boolean = .FeedStoreSessionsData
ControlInvoke(ToolbarTOP, MENU_LOAD_SESSION, Sub()
MENU_LOAD_SESSION.Visible = fsd
SEP_0.Visible = fsd
End Sub)
If rangeChanged Then If rangeChanged Then
ClearTable() ClearTable()
ControlInvoke(TP_DATA, Sub() ControlInvoke(TP_DATA, Sub()
@@ -253,13 +343,22 @@ Namespace DownloadObjects
MyRange.HandlersSuspended = True MyRange.HandlersSuspended = True
MyRange.Limit = c MyRange.Limit = c
MyRange.HandlersSuspended = False MyRange.HandlersSuspended = False
If Not MyDefs.Initializing Then RefillList(False) If Not MyDefs.Initializing Then RefillList()
End With End With
End Sub End Sub
#End Region #End Region
#Region "Refill" #Region "Refill"
Private Sub RefillList(Optional ByVal RefillDataList As Boolean = True) Private Overloads Sub RefillList(Optional ByVal RememberPosition As Boolean? = Nothing)
If IsSession Then
RefillList(FeedMode = FeedModes.Current, If(RememberPosition, True))
Else
RefillSpecialFeedsData()
End If
End Sub
Private Overloads Sub RefillList(ByVal RefillDataList As Boolean, ByVal RememberPosition As Boolean)
DataPopulated = False DataPopulated = False
Dim rIndx% = -1
If RememberPosition Then rIndx = MyRange.CurrentIndex
If RefillDataList Then If RefillDataList Then
If Not IsSubscription Then If Not IsSubscription Then
Try : Downloader.Files.RemoveAll(FileNotExist) : Catch : End Try Try : Downloader.Files.RemoveAll(FileNotExist) : Catch : End Try
@@ -268,6 +367,10 @@ Namespace DownloadObjects
DataList.ListAddList(Downloader.Files.Where(If(IsSubscription, FilterSubscriptions, FilterUsers)), LAP.NotContainsOnly) DataList.ListAddList(Downloader.Files.Where(If(IsSubscription, FilterSubscriptions, FilterUsers)), LAP.NotContainsOnly)
End If End If
MyRange.Source = DataList MyRange.Source = DataList
If rIndx >= 0 Then
If Not rIndx.ValueBetween(0, MyRange.Count - 1) Then rIndx -= 1
If rIndx.ValueBetween(0, MyRange.Count - 1) Then MyRange.CurrentIndex = rIndx
End If
ControlInvokeFast(ToolbarTOP, BTT_REFRESH, Sub() BTT_REFRESH.ToolTipText = BttRefreshToolTipText) ControlInvokeFast(ToolbarTOP, BTT_REFRESH, Sub() BTT_REFRESH.ToolTipText = BttRefreshToolTipText)
BTT_REFRESH.ControlDropColor(ToolbarTOP) BTT_REFRESH.ControlDropColor(ToolbarTOP)
If DataList.Count = 0 Then If DataList.Count = 0 Then
@@ -291,17 +394,20 @@ Namespace DownloadObjects
#Region "Feed" #Region "Feed"
#Region "Load" #Region "Load"
Private Sub BTT_LOAD_SESSION_CURRENT_Click(sender As Object, e As EventArgs) Handles BTT_LOAD_SESSION_CURRENT.Click Private Sub BTT_LOAD_SESSION_CURRENT_Click(sender As Object, e As EventArgs) Handles BTT_LOAD_SESSION_CURRENT.Click
RefillList() FeedChangeMode(FeedModes.Current)
RefillList(True, False)
End Sub End Sub
Private Sub BTT_LOAD_SESSION_LAST_Click(sender As Object, e As EventArgs) Handles BTT_LOAD_SESSION_LAST.Click Private Sub BTT_LOAD_SESSION_LAST_Click(sender As Object, e As EventArgs) Handles BTT_LOAD_SESSION_LAST.Click
SessionChooser(True) SessionChooser(True,,, FeedModes.Saved)
End Sub End Sub
Private Sub BTT_LOAD_SESSION_CHOOSE_Click(sender As Object, e As EventArgs) Handles BTT_LOAD_SESSION_CHOOSE.Click Private Sub BTT_LOAD_SESSION_CHOOSE_Click(sender As Object, e As EventArgs) Handles BTT_LOAD_SESSION_CHOOSE.Click
SessionChooser(False) SessionChooser(False,,, FeedModes.Saved)
End Sub End Sub
Private Sub SessionChooser(ByVal GetLast As Boolean, Optional ByVal GetFilesOnly As Boolean = False, Private Sub SessionChooser(ByVal GetLast As Boolean, Optional ByVal GetFilesOnly As Boolean = False,
Optional ByRef ResultFilesList As List(Of SFile) = Nothing) Optional ByRef ResultFilesList As List(Of SFile) = Nothing,
Optional ByVal SelectedMode As FeedModes = -1)
Try Try
LoadedSessionName = String.Empty
Downloader.ClearSessions() Downloader.ClearSessions()
Dim f As SFile = TDownloader.SessionsPath.CSFileP Dim f As SFile = TDownloader.SessionsPath.CSFileP
Dim fList As List(Of SFile) = Nothing Dim fList As List(Of SFile) = Nothing
@@ -318,7 +424,7 @@ Namespace DownloadObjects
Return False Return False
End If End If
End Function End Function
If Not GetLast Then __getFiles.Invoke __getFiles.Invoke
If Not GetLast And GetFilesOnly And Not fList.ListExists Then If Not GetLast And GetFilesOnly And Not fList.ListExists Then
MsgBoxE({"No session files found", "Get session files"}, vbExclamation) MsgBoxE({"No session files found", "Get session files"}, vbExclamation)
ElseIf Not GetLast AndAlso fList.ListExists Then ElseIf Not GetLast AndAlso fList.ListExists Then
@@ -336,6 +442,10 @@ Namespace DownloadObjects
ResultFilesList.AddRange(fList) ResultFilesList.AddRange(fList)
Else Else
DataList.Clear() DataList.Clear()
If SelectedMode >= 0 Then
If SelectedMode = FeedModes.Saved And fList.Count = 1 Then LoadedSessionName = fList(0).Name
FeedChangeMode(SelectedMode)
End If
For Each f In fList For Each f In fList
x = New XmlFile(f,, False) With {.AllowSameNames = True, .XmlReadOnly = True} x = New XmlFile(f,, False) With {.AllowSameNames = True, .XmlReadOnly = True}
x.LoadData() x.LoadData()
@@ -343,7 +453,7 @@ Namespace DownloadObjects
x.Dispose() x.Dispose()
Next Next
CleanDataList() CleanDataList()
RefillList(False) RefillList(False, False)
End If End If
Else Else
MsgBoxE(m) MsgBoxE(m)
@@ -352,18 +462,29 @@ Namespace DownloadObjects
MsgBoxE(m) MsgBoxE(m)
End If End If
End Using End Using
ElseIf Downloader.FilesSessionActual(False).Exists OrElse __getFiles.Invoke Then ElseIf Downloader.FilesSessionActual(False).Exists OrElse fList.ListExists Then
If Downloader.FilesSessionActual(False).Exists Then If GetLast Then
f = Downloader.FilesSessionActual(False) If fList.ListExists Then
f = fList(IIf(fList.Count > 1 And Downloader.FilesSessionActual(False).Exists, 1, 0))
Else
f = Downloader.FilesSessionActual(False)
End If
Else Else
f = fList(0) f = Downloader.FilesSessionActual(False)
End If
If f.Exists Then
If SelectedMode >= 0 Then
If SelectedMode = FeedModes.Saved Then LoadedSessionName = f.Name
FeedChangeMode(SelectedMode)
End If
DataList.Clear()
x = New XmlFile(f,, False) With {.AllowSameNames = True, .XmlReadOnly = True}
x.LoadData()
If x.Count > 0 Then DataList.ListAddList(x, lcr)
x.Dispose()
CleanDataList()
RefillList(False, False)
End If End If
x = New XmlFile(f,, False) With {.AllowSameNames = True, .XmlReadOnly = True}
x.LoadData()
If x.Count > 0 Then DataList.Clear() : DataList.ListAddList(x, lcr)
x.Dispose()
CleanDataList()
RefillList(False)
Else Else
m.Text = "Saved sessions not found" m.Text = "Saved sessions not found"
MsgBoxE(m) MsgBoxE(m)
@@ -374,43 +495,256 @@ Namespace DownloadObjects
End Try End Try
End Sub End Sub
#End Region #End Region
Private Sub BTT_COPY_MOVE_TO_Click(sender As Object, e As EventArgs) Handles BTT_COPY_TO.Click, BTT_MOVE_TO.Click
MoveCopyFiles(True, sender, Nothing, Nothing)
End Sub
Private Function MoveCopyFiles(ByVal IsInternal As Boolean, ByVal Sender As Object, ByVal MCTOptions As FeedMoveCopyTo, ByVal FeedMediaData As FeedMedia) As Boolean
Const MsgTitle$ = "Copy/Move checked files"
Try
Dim isCopy As Boolean = Not Sender Is Nothing AndAlso Sender Is BTT_COPY_TO
Dim moveOptions As FeedMoveCopyTo = Nothing
Dim ff As SFile = Nothing, df As SFile
Dim data As IEnumerable(Of UserMediaD) = Nothing
Dim dd As UserMediaD
Dim data_files As IEnumerable(Of SFile) = Nothing
Dim mm As UserMediaD
Dim mm_data As API.Base.UserMedia
Dim indx%
Dim renameExisting As Boolean = False
Dim downloaderFilesUpdated As Boolean = False
Dim eFiles As IEnumerable(Of SFile)
Dim finder As Predicate(Of UserMediaD) = Function(media) media.Data.File = ff
Dim x As XmlFile
Dim sessionData As New List(Of UserMediaD)
Dim sesFile As SFile
Dim sesFilesReplaced As Boolean = False
Dim filesReplace As New List(Of KeyValuePair(Of SFile, SFile))
Dim updateFileLocations As Boolean = Settings.FeedMoveCopyUpdateFileLocationOnMove
Dim result As Boolean = False
If FeedMediaData Is Nothing Then
data = GetCheckedMedia()
With data
If .ListExists Then data_files = .Select(Function(m) m.Data.File)
End With
Else
data = {FeedMediaData.Media}
data_files = {FeedMediaData.File}
End If
If data.ListExists Then
If MCTOptions.Destination.IsEmptyString Then
Using f As New FeedCopyToForm(data_files, isCopy)
f.ShowDialog()
If f.DialogResult = DialogResult.OK Then moveOptions = f.Result
End Using
Else
moveOptions = MCTOptions
End If
With moveOptions
If Not .Destination.IsEmptyString And .ReplaceUserProfile And .ReplaceUserProfile_CreateIfNull And .ReplaceUserProfile_Profile Is Nothing Then
Dim existingPathInstances As IEnumerable(Of String) = Nothing
Dim __user As UserInfo
Dim __host As Plugin.Hosts.SettingsHost = Settings(API.PathPlugin.PluginKey).Default
Dim __userName$ = .Destination.Segments.LastOrDefault
If Settings.UsersList.Count > 0 Then _
existingPathInstances = (From __uu As UserInfo In Settings.UsersList
Where __uu.Plugin = API.PathPlugin.PluginKey
Select __uu.Name.ToLower)
Do
__userName = InputBoxE("Enter a new username for the 'path' plugin:", MsgTitle, __userName)
If __userName.IsEmptyString Then
Return False
Else
If Not existingPathInstances.ListExists OrElse Not existingPathInstances.Contains(__userName.ToLower) Then
Exit Do
ElseIf MsgBoxE({$"The name you entered ({__userName}) already exists", MsgTitle}, vbCritical,,, {"Retry", "Cancel"}) = 1 Then
Return False
End If
End If
Loop
__user = New UserInfo(__userName, __host) With {.SpecialPath = moveOptions.Destination.CSFilePS}
__user.UpdateUserFile()
If Settings.UsersList.Count = 0 OrElse Not Settings.UsersList.Contains(__user) Then
Settings.UpdateUsersList(__user)
With Settings.Users
Dim startIndx% = .Count
.Add(API.Base.UserDataBase.GetInstance(__user))
With .Last
If Not .FileExists Then .UpdateUserInformation()
End With
RaiseEvent UsersAdded(startIndx)
moveOptions.ReplaceUserProfile_Profile = .Last
End With
Else
MsgBoxE({$"The user list already contains the user you want to add.{vbCr}Operation canceled.", MsgTitle}, vbCritical)
Return False
End If
End If
End With
If Not moveOptions.Destination.IsEmptyString Then
If Not isCopy Then
Dim eFileResult As Func(Of UserMediaD, SFile) = Function(ByVal fff As UserMediaD) As SFile
Dim _fff As SFile = fff.Data.File
_fff.Path = moveOptions.DestinationTrue(fff).Path
Return _fff
End Function
eFiles = (From ef As UserMediaD In data Where eFileResult.Invoke(ef).Exists Select eFileResult.Invoke(ef))
If eFiles.ListExists Then _
renameExisting = MsgBoxE(New MMessage("The following files already exist at the destination. " &
"Do you still want to move them? These files will be renamed and moved." & vbCr &
$"Destination: {moveOptions.Destination.PathWithSeparator}{vbCr}{vbCr}" &
eFiles.ListToString(vbCr), MsgTitle, {"Move", "Cancel"}, vbExclamation) With {.Editable = True}) = 0
End If
For Each dd In data
If Not dd.Data.File.IsEmptyString Then
ff = dd.Data.File
df = ff
df.Path = moveOptions.DestinationTrue(dd).Path
If isCopy Then
If ff.Copy(df) Then result = True
Else
If df.Exists And renameExisting Then df = SFile.IndexReindex(df,,,, New ErrorsDescriber(False, False, False, df))
If SFile.Move(ff, df) Then
result = True
If updateFileLocations Then
filesReplace.Add(New KeyValuePair(Of SFile, SFile)(ff, df))
indx = Downloader.Files.FindIndex(finder)
If indx >= 0 Then
mm = Downloader.Files(indx)
mm_data = mm.Data
mm_data.File = df
mm = New UserMediaD(mm_data, If(moveOptions.ReplaceUserProfile_Profile, mm.User), mm.Session, mm.Date)
Downloader.Files(indx) = mm
downloaderFilesUpdated = True
End If
End If
End If
End If
End If
Next
If Not isCopy And updateFileLocations Then
If downloaderFilesUpdated Then Downloader.FilesSave()
If FeedMode = FeedModes.Saved And Not LoadedSessionName.IsEmptyString And filesReplace.Count > 0 Then
sesFile = $"{TDownloader.SessionsPath.CSFilePS}{LoadedSessionName}.xml"
If sesFile.Exists Then
sessionData.Clear()
x = New XmlFile(sesFile, Protector.Modes.All, False) With {.AllowSameNames = True}
x.LoadData()
If x.Count > 0 Then sessionData.ListAddList(x, LAP.IgnoreICopier)
x.Dispose()
If sessionData.Count > 0 Then
For Each rfile As KeyValuePair(Of SFile, SFile) In filesReplace
ff = rfile.Key
df = rfile.Value
indx = sessionData.FindIndex(finder)
If indx >= 0 Then
mm = sessionData(indx)
mm_data = mm.Data
mm_data.File = df
mm = New UserMediaD(mm_data, If(moveOptions.ReplaceUserProfile_Profile, mm.User), mm.Session, mm.Date)
sessionData(indx) = mm
sesFilesReplaced = True
If DataList.Count > 0 Then
indx = DataList.FindIndex(finder)
If indx >= 0 Then DataList(indx) = mm
End If
End If
Next
If sesFilesReplaced Then
x = New XmlFile With {.AllowSameNames = True}
x.AddRange(sessionData)
x.Name = TDownloader.Name_SessionXML
x.Save(sesFile, EDP.SendToLog)
x.Dispose()
End If
sessionData.Clear()
End If
End If
End If
If filesReplace.Count > 0 Then filesReplace.ForEach(Sub(fr) Settings.Feeds.UpdateDataByFile(fr.Key, fr.Value, moveOptions))
filesReplace.Clear()
End If
If IsInternal Then MsgBoxE(New MMessage($"The following files were {IIf(isCopy, "copied", "moved")} to{vbCr}{moveOptions.Destination}{vbCr}{vbCr}{data_files.ListToString(vbCr)}", MsgTitle) With {.Editable = True})
If Not isCopy And updateFileLocations Then RefillList()
End If
Else
MsgBoxE({"No files selected", MsgTitle}, vbExclamation)
End If
Return result
Catch ex As Exception
Return ErrorsDescriber.Execute(EDP.LogMessageValue, ex, MsgTitle, False)
Finally
Settings.Feeds.UpdateWhereDataReplaced()
End Try
End Function
#Region "Load fav, spec" #Region "Load fav, spec"
Private Sub BTT_LOAD_FAV_Click(sender As Object, e As EventArgs) Handles BTT_LOAD_FAV.Click Private Sub BTT_LOAD_FAV_Click(sender As Object, e As EventArgs) Handles BTT_LOAD_FAV.Click
DataList.Clear() FeedChangeMode(FeedModes.Special, {FeedSpecial.FavoriteName})
With Settings.Feeds.Favorite RefillSpecialFeedsData(False)
.RemoveNotExist(FileNotExist)
If .Count > 0 Then DataList.AddRange(.Self) : CleanDataList() : RefillList(False)
End With
End Sub End Sub
Private Sub BTT_LOAD_SPEC_Click(sender As Object, e As EventArgs) Handles BTT_LOAD_SPEC.Click Private Sub BTT_LOAD_SPEC_Click(sender As Object, e As EventArgs) Handles BTT_LOAD_SPEC.Click
With FeedSpecialCollection.ChooseFeeds(False) With FeedSpecialCollection.ChooseFeeds(False)
If .ListExists Then If .ListExists Then
DataList.Clear() FeedChangeMode(FeedModes.Special, .Select(Function(f) f.Name))
Dim d As New List(Of UserMediaD) RefillSpecialFeedsData(False)
.ForEach(Sub(ByVal f As FeedSpecial)
f.RemoveNotExist(FileNotExist)
If f.Count > 0 Then d.AddRange(f)
End Sub)
If d.Count > 0 Then DataList.ListAddList(d.Distinct)
CleanDataList()
RefillList(False)
End If End If
End With End With
End Sub End Sub
Private Sub RefillSpecialFeedsData(Optional ByVal RememberPosition As Boolean = True)
If LoadedFeedNames.Count > 0 Then
Dim d As New List(Of UserMediaD)
Dim lp As New ListAddParams(LAP.NotContainsOnly)
LoadedFeedNames.ForEach(Sub(ByVal fName As String)
Dim indx% = Settings.Feeds.IndexOf(fName)
If indx >= 0 Then
With Settings.Feeds(indx)
.RemoveNotExist(FileNotExist)
d.ListAddList(.Self, lp)
End With
End If
End Sub)
DataList.Clear()
If d.Count > 0 Then
d.Sort(New FeedSpecial.SEComparer)
DataList.AddRange(d)
CleanDataList()
d.Clear()
End If
RefillList(False, RememberPosition)
End If
End Sub
#End Region #End Region
#Region "Add remove fav spec" #Region "Add remove fav spec"
Private Sub BTT_FEED_ADD_FAV_Click(sender As Object, e As EventArgs) Handles BTT_FEED_ADD_FAV.Click Private Sub BTT_FEED_ADD_FAV_Click(sender As Object, e As EventArgs) Handles BTT_FEED_ADD_FAV.Click, BTT_FEED_ADD_FAV_REMOVE.Click
Settings.Feeds.Favorite.Add(GetCheckedMedia()) Dim m As IEnumerable(Of UserMediaD) = GetCheckedMedia()
If m.ListExists Then
Settings.Feeds.Favorite.Add(m)
If sender Is BTT_FEED_ADD_FAV_REMOVE Then FeedRemoveCheckedMedia(m,,, {FeedSpecial.FavoriteName})
End If
End Sub End Sub
Private Sub BTT_FEED_REMOVE_FAV_Click(sender As Object, e As EventArgs) Handles BTT_FEED_REMOVE_FAV.Click Private Sub BTT_FEED_REMOVE_FAV_Click(sender As Object, e As EventArgs) Handles BTT_FEED_REMOVE_FAV.Click
Settings.Feeds.Favorite.Remove(GetCheckedMedia()) Dim m As IEnumerable(Of UserMediaD) = GetCheckedMedia()
If m.ListExists Then
Settings.Feeds.Favorite.Remove(m)
If FeedMode = FeedModes.Special Then FeedRemoveCheckedMedia(m, {FeedSpecial.FavoriteName}.ToList)
End If
End Sub End Sub
Private Sub BTT_FEED_ADD_SPEC_Click(sender As Object, e As EventArgs) Handles BTT_FEED_ADD_SPEC.Click Private Sub BTT_FEED_ADD_SPEC_Click(sender As Object, e As EventArgs) Handles BTT_FEED_ADD_SPEC.Click, BTT_FEED_ADD_SPEC_REMOVE.Click
Dim c As IEnumerable(Of UserMediaD) = GetCheckedMedia() Dim c As IEnumerable(Of UserMediaD) = GetCheckedMedia()
If c.ListExists Then If c.ListExists Then
With FeedSpecialCollection.ChooseFeeds(False) Dim names As New List(Of String)
If .ListExists Then .ForEach(Sub(f) f.Add(c)) With FeedSpecialCollection.ChooseFeeds(True)
If .ListExists Then .ForEach(Sub(ByVal f As FeedSpecial)
names.Add(f.Name)
f.Add(c)
End Sub)
End With End With
If sender Is BTT_FEED_ADD_SPEC_REMOVE Then FeedRemoveCheckedMedia(c,,, names)
names.Clear()
Else Else
MsgBoxE({"You haven't selected media to add to your feed(s)", "Add to feed(s)"}, vbExclamation) MsgBoxE({"You haven't selected media to add to your feed(s)", "Add to feed(s)"}, vbExclamation)
End If End If
@@ -418,9 +752,14 @@ Namespace DownloadObjects
Private Sub BTT_FEED_REMOVE_SPEC_Click(sender As Object, e As EventArgs) Handles BTT_FEED_REMOVE_SPEC.Click Private Sub BTT_FEED_REMOVE_SPEC_Click(sender As Object, e As EventArgs) Handles BTT_FEED_REMOVE_SPEC.Click
Dim c As IEnumerable(Of UserMediaD) = GetCheckedMedia() Dim c As IEnumerable(Of UserMediaD) = GetCheckedMedia()
If c.ListExists Then If c.ListExists Then
Dim names As New List(Of String)
With FeedSpecialCollection.ChooseFeeds(False) With FeedSpecialCollection.ChooseFeeds(False)
If .ListExists Then .ForEach(Sub(f) f.Remove(c)) If .ListExists Then .ForEach(Sub(ByVal f As FeedSpecial)
names.Add(f.Name)
f.Remove(c)
End Sub)
End With End With
If FeedMode = FeedModes.Special Then FeedRemoveCheckedMedia(c, names)
Else Else
MsgBoxE({"You haven't selected media to remove from your feed(s)", "Remove from feed(s)"}, vbExclamation) MsgBoxE({"You haven't selected media to remove from your feed(s)", "Remove from feed(s)"}, vbExclamation)
End If End If
@@ -444,16 +783,28 @@ Namespace DownloadObjects
Private Sub BTT_FEED_CLEAR_SPEC_Click(sender As Object, e As EventArgs) Handles BTT_FEED_CLEAR_SPEC.Click Private Sub BTT_FEED_CLEAR_SPEC_Click(sender As Object, e As EventArgs) Handles BTT_FEED_CLEAR_SPEC.Click
With FeedSpecialCollection.ChooseFeeds(False) With FeedSpecialCollection.ChooseFeeds(False)
If .ListExists Then If .ListExists Then
If MsgBoxE({$"Are you sure you want to clear the following feeds?{vbCr}{vbCr}{ .ListToString(vbCr)}", "Clear feed"}, vbExclamation,,, If MsgBoxE({$"Are you sure you want to clear the following feeds?{vbCr}{vbCr}{ .ListToString(vbCr)}", "Clear feed"}, vbExclamation,,, {"Process", "Cancel"}) = 0 Then
{"Process", "Cancel"}) = 0 Then .ForEach(Sub(f) f.Clear()) Dim names As IEnumerable(Of String) = .Select(Function(f) f.Name)
.ForEach(Sub(f) f.Clear())
If FeedMode = FeedModes.Special Then
LoadedFeedNames.ListDisposeRemove(names)
RefillSpecialFeedsData()
End If
End If
End If End If
End With End With
End Sub End Sub
Private Sub BTT_FEED_DELETE_SPEC_Click(sender As Object, e As EventArgs) Handles BTT_FEED_DELETE_SPEC.Click Private Sub BTT_FEED_DELETE_SPEC_Click(sender As Object, e As EventArgs) Handles BTT_FEED_DELETE_SPEC.Click
With FeedSpecialCollection.ChooseFeeds(False) With FeedSpecialCollection.ChooseFeeds(False)
If .ListExists Then If .ListExists Then
If MsgBoxE({$"Are you sure you want to delete the following feeds?{vbCr}{vbCr}{ .ListToString(vbCr)}", "Delete feed"}, vbExclamation,,, If MsgBoxE({$"Are you sure you want to delete the following feeds?{vbCr}{vbCr}{ .ListToString(vbCr)}", "Delete feed"}, vbExclamation,,, {"Process", "Cancel"}) = 0 Then
{"Process", "Cancel"}) = 0 Then .ForEach(Sub(f) f.Delete()) Dim names As IEnumerable(Of String) = .Select(Function(f) f.Name)
.ForEach(Sub(f) f.Delete())
If FeedMode = FeedModes.Special Then
LoadedFeedNames.ListDisposeRemove(names)
RefillSpecialFeedsData()
End If
End If
End If End If
End With End With
End Sub End Sub
@@ -512,6 +863,128 @@ Namespace DownloadObjects
End Try End Try
End Sub End Sub
#End Region #End Region
#Region "Clear session"
Private Sub BTT_CLEAR_DAILY_Click(sender As Object, e As EventArgs) Handles BTT_CLEAR_DAILY.Click
If MsgBoxE({"Are you sure you want to clear this session data?", "Clear session"}, vbExclamation,,, {"Process", "Cancel"}) = 0 Then
Downloader.Files.Clear()
ClearTable()
RefillList()
End If
End Sub
#End Region
#Region "Merge feeds"
Private Sub BTT_MERGE_SESSIONS_Click(sender As Object, e As EventArgs) Handles BTT_MERGE_SESSIONS.Click
Try
Const msgTitle$ = "Merge feeds"
Dim files As New List(Of SFile)
Dim abs% = 0, prev% = 0, curr%, i%
Dim x As XmlFile
Dim f As SFile
Dim um As UserMediaD
Dim data As New List(Of UserMediaD)
Dim tmpData As New List(Of UserMediaD)
Dim lrc As New ListAddParams(LAP.NotContainsOnly + LAP.IgnoreICopier)
SessionChooser(False, True, files)
If files.ListExists(2) Then
files.Sort()
For Each f In files
x = New XmlFile(f,, False) With {.AllowSameNames = True, .XmlReadOnly = True}
x.LoadData(EDP.None)
If x.Count > 0 Then tmpData.ListAddList(x, lrc)
If tmpData.Count > 0 Then tmpData.Reverse() : data.AddRange(tmpData) : tmpData.Clear()
x.Dispose()
Next
If data.Count > 0 Then
For i = 0 To data.Count - 1
um = data(i)
curr = um.Session
If i = 0 Then
abs = curr
Else
If curr < abs And prev <> curr Then
abs += 1
ElseIf curr >= abs Then
abs = curr
End If
End If
prev = curr
um.Session = abs
data(i) = um
Next
data.Reverse()
x = New XmlFile With {.Name = TDownloader.Name_SessionXML, .AllowSameNames = True}
x.AddRange(data)
x.Save(files(0))
x.Dispose()
For i = 1 To files.Count - 1 : files(i).Delete(SFO.File, SFODelete.DeleteToRecycleBin, EDP.ReturnValue) : Next
MsgBoxE({$"Session data was combined into '{files(0).Name}'.{vbCr}{vbCr}" &
files.ListToStringE(vbCr, New CustomProvider(Function(ff As SFile) ff.Name),,, EDP.ReturnValue), msgTitle})
files.Clear()
data.Clear()
Else
MsgBoxE({"There is no session data in the selected files", msgTitle}, vbExclamation)
End If
ElseIf files.ListExists(1) Then
MsgBoxE({"You must select two or more files to merge feeds", msgTitle}, vbExclamation)
Else
MsgBoxE({"You haven't selected any feeds", msgTitle}, vbExclamation)
End If
Catch ex As Exception
ErrorsDescriber.Execute(EDP.SendToLog, ex, "[DownloadFeedForm.MergeSessions]")
End Try
End Sub
Private Sub BTT_MERGE_FEEDS_Click(sender As Object, e As EventArgs) Handles BTT_MERGE_FEEDS.Click
Try
Const msgTitle$ = "Merge feeds"
If Settings.Feeds.Count > 1 Then
Dim mFrom As List(Of FeedSpecial) = FeedSpecialCollection.ChooseFeeds(False, "[SOURCE]", True)
Dim mTo As FeedSpecial
If mFrom.ListExists(2) Then
mTo = FeedSpecialCollection.ChooseFeeds(True, "[DESTINATION]", True).FirstOrDefault
If Not mTo Is Nothing Then
Dim names$() = mFrom.Select(Function(f) f.Name).ToArray
If MsgBoxE({$"Are you sure you want to merge the following feeds into '{mTo.Name}'?{vbCr}{vbCr}" &
names.ListToString(vbCr), msgTitle}, vbQuestion + vbYesNo) = vbYes Then
mFrom.ForEach(Sub(f) mTo.Add(f, False))
mTo.Save()
mFrom.ForEach(Sub(f) If Not f.Equals(mTo) Then Settings.Feeds.Delete(f))
MsgBoxE({$"Feeds' data was combined into '{mTo.Name}'.{vbCr}It is highly recommended to restart SCrawler!{vbCr}{vbCr}" &
names.ListToStringE(vbCr), msgTitle})
Else
ShowOperationCanceledMsg(msgTitle)
End If
mFrom.Clear()
Else
MsgBoxE({"No destination selected", msgTitle}, vbExclamation)
End If
ElseIf mFrom.ListExists(1) Then
MsgBoxE({"You must select two or more files to merge feeds", msgTitle}, vbExclamation)
Else
MsgBoxE({"You haven't selected any feeds", msgTitle}, vbExclamation)
End If
ElseIf Settings.Feeds.Count = 1 Then
MsgBoxE({"You must have two or more files to merge feeds", msgTitle}, vbExclamation)
Else
MsgBoxE({"No feeds found", msgTitle}, vbExclamation)
End If
Catch ex As Exception
ErrorsDescriber.Execute(EDP.SendToLog, ex, "[DownloadFeedForm.MergeFeeds]")
End Try
End Sub
#End Region
Private Sub BTT_CHECK_ALL_NONE_Click(sender As Object, e As EventArgs) Handles BTT_CHECK_ALL.Click, BTT_CHECK_NONE.Click
Try
Dim checked As Boolean = sender Is BTT_CHECK_ALL
ControlInvokeFast(TP_DATA, Sub()
With TP_DATA
If .Controls.Count > 0 Then
For Each cnt As FeedMedia In .Controls : cnt.Checked = checked : Next
End If
End With
End Sub, EDP.None)
Catch
End Try
End Sub
#End Region #End Region
#Region "View modes" #Region "View modes"
Private Sub OPT_Click(ByVal Sender As ToolStripMenuItem, ByVal e As EventArgs) Handles OPT_DEFAULT.Click, OPT_SUBSCRIPTIONS.Click Private Sub OPT_Click(ByVal Sender As ToolStripMenuItem, ByVal e As EventArgs) Handles OPT_DEFAULT.Click, OPT_SUBSCRIPTIONS.Click
@@ -540,13 +1013,19 @@ Namespace DownloadObjects
Private Sub BTT_REFRESH_Click(sender As Object, e As EventArgs) Handles BTT_REFRESH.Click Private Sub BTT_REFRESH_Click(sender As Object, e As EventArgs) Handles BTT_REFRESH.Click
RefillList() RefillList()
End Sub End Sub
Private Sub BTT_CLEAR_Click(sender As Object, e As EventArgs) Handles BTT_CLEAR.Click
Downloader.Files.Clear()
ClearTable()
RefillList()
End Sub
#End Region #End Region
#Region "Download" #Region "FeedMedia handlers"
Private Sub FeedMedia_MediaMove(ByVal Sender As FeedMedia, ByVal MCTOptions As FeedMoveCopyTo, ByRef Result As Boolean)
Result = MoveCopyFiles(False, Nothing, MCTOptions, Sender)
End Sub
Private Sub FeedMedia_MediaDeleted(ByVal Sender As FeedMedia)
Try
ControlInvoke(TP_DATA, Sub() TPRemoveControl(Sender, True))
DataList.RemoveAll(Function(dd) dd.Data.File = Sender.File)
RefillAfterDelete()
Catch
End Try
End Sub
Private Sub FeedMedia_Download(ByVal Sender As Object, ByVal e As EventArgs) Handles BTT_DOWN_ALL.Click, BTT_DOWN_SELECTED.Click Private Sub FeedMedia_Download(ByVal Sender As Object, ByVal e As EventArgs) Handles BTT_DOWN_ALL.Click, BTT_DOWN_SELECTED.Click
Try Try
Dim urls As New List(Of String) Dim urls As New List(Of String)
@@ -570,38 +1049,19 @@ Namespace DownloadObjects
ErrorsDescriber.Execute(EDP.LogMessageValue, ex, "Download subscription media") ErrorsDescriber.Execute(EDP.LogMessageValue, ex, "Download subscription media")
End Try End Try
End Sub End Sub
Private Sub FeedMedia_FeedAddWithRemove(ByVal Sender As FeedMedia, ByVal Feeds As IEnumerable(Of String), ByVal Media As UserMediaD, ByVal RemoveOperation As Boolean)
FeedRemoveCheckedMedia({Media},, False, Feeds, RemoveOperation)
End Sub
#End Region #End Region
#Region "Delete" #Region "Delete / Remove"
Private Sub BTT_DELETE_SELECTED_Click(sender As Object, e As EventArgs) Handles BTT_DELETE_SELECTED.Click Private Sub BTT_DELETE_SELECTED_Click(sender As Object, e As EventArgs) Handles BTT_DELETE_SELECTED.Click
Const MsgTitle$ = "Deleting marked files" Const MsgTitle$ = "Deleting marked files"
Try Try
Dim c As IEnumerable(Of FeedMedia) = ControlInvoke(TP_DATA, Function() If(TP_DATA.Controls.Count > 0, TP_DATA.Controls.ToObjectsList.Cast(Of FeedMedia)().Where(Function(f) f.Checked), New FeedMedia() {})) Dim c As IEnumerable(Of FeedMedia) = GetCheckedMediaControls()
If c.ListExists Then If c.ListExists Then
If MsgBoxE({$"Are you sure you want to delete {c.Count} file(s)?", MsgTitle}, vbExclamation,,, {"Process", "Cancel"}) = 0 Then If MsgBoxE({$"Are you sure you want to delete {c.Count} file(s)?", MsgTitle}, vbExclamation,,, {"Process", "Cancel"}) = 0 Then
Dim indx% = MyRange.CurrentIndex Dim indx% = MyRange.CurrentIndex
Dim d% = 0 Dim d% = RemoveCheckedMedia(True, c)
ControlInvoke(TP_DATA, Sub()
With TP_DATA
.SuspendLayout()
LatestScrollValueDisabled = True
For Each fm As FeedMedia In c
If fm.DeleteFile(True) Then
d += 1
DataList.RemoveAll(Function(dd) dd.Data.File = fm.File)
TPRemoveControl(fm, False)
End If
Next
If d = 0 Then LatestScrollValueDisabled = False
.ResumeLayout(d = 0)
If d > 0 Then
.AutoScroll = False
.AutoScroll = True
SetScrollValue(False)
.PerformLayout()
LatestScrollValueDisabled = False
End If
End With
End Sub)
If d > 0 Then RefillAfterDelete() If d > 0 Then RefillAfterDelete()
MsgBoxE({$"{d}/{c.Count} file(s) deleted", MsgTitle}) MsgBoxE({$"{d}/{c.Count} file(s) deleted", MsgTitle})
Else Else
@@ -614,14 +1074,42 @@ Namespace DownloadObjects
ErrorsDescriber.Execute(EDP.LogMessageValue, ex, MsgTitle) ErrorsDescriber.Execute(EDP.LogMessageValue, ex, MsgTitle)
End Try End Try
End Sub End Sub
Private Sub FeedMedia_MediaDeleted(ByVal Sender As FeedMedia) Private Function GetCheckedMediaControls() As IEnumerable(Of FeedMedia)
Return ControlInvoke(TP_DATA, Function() If(TP_DATA.Controls.Count > 0, TP_DATA.Controls.ToObjectsList.Cast(Of FeedMedia)().Where(Function(f) f.Checked), New FeedMedia() {}))
End Function
Private Function RemoveCheckedMedia(ByVal DeleteFiles As Boolean, Optional ByVal Controls As IEnumerable(Of FeedMedia) = Nothing) As Integer
Try Try
ControlInvoke(TP_DATA, Sub() TPRemoveControl(Sender, True)) Dim d% = 0
DataList.RemoveAll(Function(dd) dd.Data.File = Sender.File) If Not Controls.ListExists Then Controls = GetCheckedMediaControls()
RefillAfterDelete() If Controls.ListExists Then
Catch ControlInvoke(TP_DATA, Sub()
With TP_DATA
.SuspendLayout()
LatestScrollValueDisabled = True
For Each fm As FeedMedia In Controls
If Not DeleteFiles OrElse fm.DeleteFile(True) Then
d += 1
DataList.RemoveAll(Function(dd) dd.Data.File = fm.File)
TPRemoveControl(fm, False)
End If
Next
If d = 0 Then LatestScrollValueDisabled = False
.ResumeLayout(d = 0)
If d > 0 Then
.AutoScroll = False
.AutoScroll = True
SetScrollValue(False)
.PerformLayout()
LatestScrollValueDisabled = False
End If
End With
End Sub)
End If
Return d
Catch ex As Exception
Return ErrorsDescriber.Execute(EDP.SendToLog, ex, "[DownloadFeedForm.RemoveCheckedMedia]", 0)
End Try End Try
End Sub End Function
Private Sub TPRemoveControl(ByVal CNT As FeedMedia, ByVal Suspend As Boolean) Private Sub TPRemoveControl(ByVal CNT As FeedMedia, ByVal Suspend As Boolean)
Dim HeightChanged As Boolean = False Dim HeightChanged As Boolean = False
Try Try
@@ -731,7 +1219,7 @@ Namespace DownloadObjects
If d.ListExists AndAlso Not IsSubscription AndAlso d.All(FileNotExist) Then If d.ListExists AndAlso Not IsSubscription AndAlso d.All(FileNotExist) Then
i = Sender.CurrentIndex i = Sender.CurrentIndex
Sender.HandlersSuspended = True Sender.HandlersSuspended = True
RefillList() RefillList(False)
If Sender.Count > 0 Then If Sender.Count > 0 Then
If i.ValueBetween(0, Sender.Count - 1) Then Sender.CurrentIndex = i If i.ValueBetween(0, Sender.Count - 1) Then Sender.CurrentIndex = i
Sender.HandlersSuspended = False Sender.HandlersSuspended = False
@@ -753,10 +1241,12 @@ Namespace DownloadObjects
Dim p As New TPCELL(DataRows, DataColumns) Dim p As New TPCELL(DataRows, DataColumns)
Dim fmList As New List(Of FeedMedia) Dim fmList As New List(Of FeedMedia)
d.ForEach(Sub(ByVal de As UserMediaD) d.ForEach(Sub(ByVal de As UserMediaD)
fmList.Add(New FeedMedia(de, w, h)) fmList.Add(New FeedMedia(de, w, h, IsSession))
With fmList.Last With fmList.Last
AddHandler .MediaDeleted, AddressOf FeedMedia_MediaDeleted AddHandler .MediaDeleted, AddressOf FeedMedia_MediaDeleted
AddHandler .MediaDownload, AddressOf FeedMedia_Download AddHandler .MediaDownload, AddressOf FeedMedia_Download
AddHandler .MediaMove, AddressOf FeedMedia_MediaMove
AddHandler .FeedAddWithRemove, AddressOf FeedMedia_FeedAddWithRemove
End With End With
End Sub) End Sub)
If fmList.Count > 0 Then fmList.ListDisposeRemoveAll(Function(fm) fm Is Nothing OrElse fm.HasError) If fmList.Count > 0 Then fmList.ListDisposeRemoveAll(Function(fm) fm Is Nothing OrElse fm.HasError)

View File

@@ -0,0 +1,312 @@
' 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 DownloadObjects
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
Partial Friend Class FeedCopyToForm : 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 ActionButton1 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(FeedCopyToForm))
Dim ActionButton2 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton3 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton4 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim FRM_FILES As System.Windows.Forms.GroupBox
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 ListColumn1 As PersonalUtilities.Forms.Controls.Base.ListColumn = New PersonalUtilities.Forms.Controls.Base.ListColumn()
Dim ListColumn2 As PersonalUtilities.Forms.Controls.Base.ListColumn = New PersonalUtilities.Forms.Controls.Base.ListColumn()
Dim ActionButton7 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton8 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ListColumn3 As PersonalUtilities.Forms.Controls.Base.ListColumn = New PersonalUtilities.Forms.Controls.Base.ListColumn()
Dim ListColumn4 As PersonalUtilities.Forms.Controls.Base.ListColumn = New PersonalUtilities.Forms.Controls.Base.ListColumn()
Dim TP_PROFILES As System.Windows.Forms.TableLayoutPanel
Dim TT_MAIN As System.Windows.Forms.ToolTip
Me.CMB_DEST = New PersonalUtilities.Forms.Controls.ComboBoxExtended()
Me.TXT_FILES = New System.Windows.Forms.RichTextBox()
Me.CH_VIDEO_SEP = New System.Windows.Forms.CheckBox()
Me.CMB_PROFILE = New PersonalUtilities.Forms.Controls.ComboBoxExtended()
Me.CMB_PROFILE_PATH = New PersonalUtilities.Forms.Controls.ComboBoxExtended()
Me.CH_PROFILE_REPLACE = New System.Windows.Forms.CheckBox()
Me.CH_PROFILE_CREATE = New System.Windows.Forms.CheckBox()
CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer()
TP_MAIN = New System.Windows.Forms.TableLayoutPanel()
FRM_FILES = New System.Windows.Forms.GroupBox()
TP_PROFILES = New System.Windows.Forms.TableLayoutPanel()
TT_MAIN = New System.Windows.Forms.ToolTip(Me.components)
CONTAINER_MAIN.ContentPanel.SuspendLayout()
CONTAINER_MAIN.SuspendLayout()
TP_MAIN.SuspendLayout()
CType(Me.CMB_DEST, System.ComponentModel.ISupportInitialize).BeginInit()
FRM_FILES.SuspendLayout()
CType(Me.CMB_PROFILE, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.CMB_PROFILE_PATH, System.ComponentModel.ISupportInitialize).BeginInit()
TP_PROFILES.SuspendLayout()
Me.SuspendLayout()
'
'CONTAINER_MAIN
'
'
'CONTAINER_MAIN.ContentPanel
'
CONTAINER_MAIN.ContentPanel.Controls.Add(TP_MAIN)
CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(534, 266)
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(534, 266)
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(Me.CMB_DEST, 0, 0)
TP_MAIN.Controls.Add(FRM_FILES, 0, 5)
TP_MAIN.Controls.Add(Me.CH_VIDEO_SEP, 0, 1)
TP_MAIN.Controls.Add(Me.CMB_PROFILE, 0, 3)
TP_MAIN.Controls.Add(Me.CMB_PROFILE_PATH, 0, 4)
TP_MAIN.Controls.Add(TP_PROFILES, 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 = 6
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.Absolute, 25.0!))
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
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(534, 266)
TP_MAIN.TabIndex = 0
'
'CMB_DEST
'
ActionButton1.BackgroundImage = CType(resources.GetObject("ActionButton1.BackgroundImage"), System.Drawing.Image)
ActionButton1.Name = "Open"
ActionButton1.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Open
ActionButton1.ToolTipText = "Choose a new location (Ctrl+O)"
ActionButton2.BackgroundImage = CType(resources.GetObject("ActionButton2.BackgroundImage"), System.Drawing.Image)
ActionButton2.Name = "Add"
ActionButton2.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Add
ActionButton2.ToolTipText = "Choose a new location and add it to the list (Alt+O)"
ActionButton3.BackgroundImage = CType(resources.GetObject("ActionButton3.BackgroundImage"), System.Drawing.Image)
ActionButton3.Name = "Clear"
ActionButton3.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
ActionButton4.BackgroundImage = CType(resources.GetObject("ActionButton4.BackgroundImage"), System.Drawing.Image)
ActionButton4.Name = "ArrowDown"
ActionButton4.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.ArrowDown
Me.CMB_DEST.Buttons.Add(ActionButton1)
Me.CMB_DEST.Buttons.Add(ActionButton2)
Me.CMB_DEST.Buttons.Add(ActionButton3)
Me.CMB_DEST.Buttons.Add(ActionButton4)
Me.CMB_DEST.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.CheckBox
Me.CMB_DEST.CaptionText = "Destination"
Me.CMB_DEST.CaptionToolTipEnabled = True
Me.CMB_DEST.CaptionToolTipText = "If checked, the profile path will be ignored"
Me.CMB_DEST.CaptionVisible = True
Me.CMB_DEST.CaptionWidth = 90.0R
Me.CMB_DEST.ChangeControlsEnableOnCheckedChange = False
Me.CMB_DEST.Dock = System.Windows.Forms.DockStyle.Fill
Me.CMB_DEST.Location = New System.Drawing.Point(3, 3)
Me.CMB_DEST.Name = "CMB_DEST"
Me.CMB_DEST.Size = New System.Drawing.Size(528, 22)
Me.CMB_DEST.TabIndex = 0
Me.CMB_DEST.TextBoxBorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
'
'FRM_FILES
'
FRM_FILES.Controls.Add(Me.TXT_FILES)
FRM_FILES.Dock = System.Windows.Forms.DockStyle.Fill
FRM_FILES.Location = New System.Drawing.Point(3, 137)
FRM_FILES.Name = "FRM_FILES"
FRM_FILES.Size = New System.Drawing.Size(528, 126)
FRM_FILES.TabIndex = 5
FRM_FILES.TabStop = False
FRM_FILES.Text = "Files:"
'
'TXT_FILES
'
Me.TXT_FILES.Dock = System.Windows.Forms.DockStyle.Fill
Me.TXT_FILES.Location = New System.Drawing.Point(3, 16)
Me.TXT_FILES.Name = "TXT_FILES"
Me.TXT_FILES.ReadOnly = True
Me.TXT_FILES.Size = New System.Drawing.Size(522, 107)
Me.TXT_FILES.TabIndex = 0
Me.TXT_FILES.Text = ""
'
'CH_VIDEO_SEP
'
Me.CH_VIDEO_SEP.AutoSize = True
Me.CH_VIDEO_SEP.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_VIDEO_SEP.Location = New System.Drawing.Point(3, 31)
Me.CH_VIDEO_SEP.Name = "CH_VIDEO_SEP"
Me.CH_VIDEO_SEP.Size = New System.Drawing.Size(528, 19)
Me.CH_VIDEO_SEP.TabIndex = 1
Me.CH_VIDEO_SEP.Text = "Place videos in a separate video folder"
Me.CH_VIDEO_SEP.UseVisualStyleBackColor = True
'
'CMB_PROFILE
'
ActionButton5.BackgroundImage = CType(resources.GetObject("ActionButton5.BackgroundImage"), System.Drawing.Image)
ActionButton5.Enabled = False
ActionButton5.Name = "Clear"
ActionButton5.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
ActionButton6.BackgroundImage = CType(resources.GetObject("ActionButton6.BackgroundImage"), System.Drawing.Image)
ActionButton6.Enabled = False
ActionButton6.Name = "ArrowDown"
ActionButton6.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.ArrowDown
Me.CMB_PROFILE.Buttons.Add(ActionButton5)
Me.CMB_PROFILE.Buttons.Add(ActionButton6)
Me.CMB_PROFILE.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.RadioButton
Me.CMB_PROFILE.CaptionPadding = New System.Windows.Forms.Padding(0, 0, 1, 0)
Me.CMB_PROFILE.CaptionText = "Profile"
Me.CMB_PROFILE.CaptionVisible = True
ListColumn1.DisplayMember = True
ListColumn1.Name = "COL_NAME"
ListColumn1.Text = "Name"
ListColumn1.Width = -1
ListColumn2.Name = "COL_VALUE"
ListColumn2.Text = "Value"
ListColumn2.ValueMember = True
ListColumn2.Visible = False
Me.CMB_PROFILE.Columns.Add(ListColumn1)
Me.CMB_PROFILE.Columns.Add(ListColumn2)
Me.CMB_PROFILE.Dock = System.Windows.Forms.DockStyle.Fill
Me.CMB_PROFILE.Location = New System.Drawing.Point(3, 81)
Me.CMB_PROFILE.Name = "CMB_PROFILE"
Me.CMB_PROFILE.Size = New System.Drawing.Size(528, 22)
Me.CMB_PROFILE.TabIndex = 3
Me.CMB_PROFILE.TextBoxBorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
'
'CMB_PROFILE_PATH
'
ActionButton7.BackgroundImage = CType(resources.GetObject("ActionButton7.BackgroundImage"), System.Drawing.Image)
ActionButton7.Enabled = False
ActionButton7.Name = "Clear"
ActionButton7.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
ActionButton8.BackgroundImage = CType(resources.GetObject("ActionButton8.BackgroundImage"), System.Drawing.Image)
ActionButton8.Enabled = False
ActionButton8.Name = "ArrowDown"
ActionButton8.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.ArrowDown
Me.CMB_PROFILE_PATH.Buttons.Add(ActionButton7)
Me.CMB_PROFILE_PATH.Buttons.Add(ActionButton8)
Me.CMB_PROFILE_PATH.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.RadioButton
Me.CMB_PROFILE_PATH.CaptionPadding = New System.Windows.Forms.Padding(0, 0, 1, 0)
Me.CMB_PROFILE_PATH.CaptionText = "Profile (path)"
Me.CMB_PROFILE_PATH.CaptionVisible = True
ListColumn3.DisplayMember = True
ListColumn3.Name = "COL_NAME"
ListColumn3.Text = "Name"
ListColumn3.Width = -1
ListColumn4.Name = "COL_VALUE"
ListColumn4.Text = "Value"
ListColumn4.ValueMember = True
ListColumn4.Visible = False
Me.CMB_PROFILE_PATH.Columns.Add(ListColumn3)
Me.CMB_PROFILE_PATH.Columns.Add(ListColumn4)
Me.CMB_PROFILE_PATH.Dock = System.Windows.Forms.DockStyle.Fill
Me.CMB_PROFILE_PATH.Location = New System.Drawing.Point(3, 109)
Me.CMB_PROFILE_PATH.Name = "CMB_PROFILE_PATH"
Me.CMB_PROFILE_PATH.Size = New System.Drawing.Size(528, 22)
Me.CMB_PROFILE_PATH.TabIndex = 4
Me.CMB_PROFILE_PATH.TextBoxBorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
'
'TP_PROFILES
'
TP_PROFILES.ColumnCount = 2
TP_PROFILES.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
TP_PROFILES.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
TP_PROFILES.Controls.Add(Me.CH_PROFILE_REPLACE, 0, 0)
TP_PROFILES.Controls.Add(Me.CH_PROFILE_CREATE, 1, 0)
TP_PROFILES.Dock = System.Windows.Forms.DockStyle.Fill
TP_PROFILES.Location = New System.Drawing.Point(0, 53)
TP_PROFILES.Margin = New System.Windows.Forms.Padding(0)
TP_PROFILES.Name = "TP_PROFILES"
TP_PROFILES.RowCount = 1
TP_PROFILES.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_PROFILES.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
TP_PROFILES.Size = New System.Drawing.Size(534, 25)
TP_PROFILES.TabIndex = 2
'
'CH_PROFILE_REPLACE
'
Me.CH_PROFILE_REPLACE.AutoSize = True
Me.CH_PROFILE_REPLACE.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_PROFILE_REPLACE.Location = New System.Drawing.Point(3, 3)
Me.CH_PROFILE_REPLACE.Name = "CH_PROFILE_REPLACE"
Me.CH_PROFILE_REPLACE.Size = New System.Drawing.Size(261, 19)
Me.CH_PROFILE_REPLACE.TabIndex = 0
Me.CH_PROFILE_REPLACE.Text = "Replace user profile"
TT_MAIN.SetToolTip(Me.CH_PROFILE_REPLACE, "The user profile will be replaced with the selected one")
Me.CH_PROFILE_REPLACE.UseVisualStyleBackColor = True
'
'CH_PROFILE_CREATE
'
Me.CH_PROFILE_CREATE.AutoSize = True
Me.CH_PROFILE_CREATE.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_PROFILE_CREATE.Location = New System.Drawing.Point(270, 3)
Me.CH_PROFILE_CREATE.Name = "CH_PROFILE_CREATE"
Me.CH_PROFILE_CREATE.Size = New System.Drawing.Size(261, 19)
Me.CH_PROFILE_CREATE.TabIndex = 1
Me.CH_PROFILE_CREATE.Text = "Create path profile"
TT_MAIN.SetToolTip(Me.CH_PROFILE_CREATE, "Create a path profile if it doesn't exist")
Me.CH_PROFILE_CREATE.UseVisualStyleBackColor = True
'
'FeedCopyToForm
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(534, 266)
Me.Controls.Add(CONTAINER_MAIN)
Me.KeyPreview = True
Me.MinimizeBox = False
Me.MinimumSize = New System.Drawing.Size(550, 305)
Me.Name = "FeedCopyToForm"
Me.ShowInTaskbar = False
Me.Text = "Copy to..."
CONTAINER_MAIN.ContentPanel.ResumeLayout(False)
CONTAINER_MAIN.ResumeLayout(False)
CONTAINER_MAIN.PerformLayout()
TP_MAIN.ResumeLayout(False)
TP_MAIN.PerformLayout()
CType(Me.CMB_DEST, System.ComponentModel.ISupportInitialize).EndInit()
FRM_FILES.ResumeLayout(False)
CType(Me.CMB_PROFILE, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.CMB_PROFILE_PATH, System.ComponentModel.ISupportInitialize).EndInit()
TP_PROFILES.ResumeLayout(False)
TP_PROFILES.PerformLayout()
Me.ResumeLayout(False)
End Sub
Private WithEvents CMB_DEST As PersonalUtilities.Forms.Controls.ComboBoxExtended
Private WithEvents TXT_FILES As RichTextBox
Private WithEvents CH_VIDEO_SEP As CheckBox
Private WithEvents CMB_PROFILE As PersonalUtilities.Forms.Controls.ComboBoxExtended
Private WithEvents CMB_PROFILE_PATH As PersonalUtilities.Forms.Controls.ComboBoxExtended
Private WithEvents CH_PROFILE_REPLACE As CheckBox
Private WithEvents CH_PROFILE_CREATE As CheckBox
End Class
End Namespace

View File

@@ -0,0 +1,466 @@
<?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
wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP
WQwhyWIyJIUW5NqyPb7oCVtIlhVTwYf8nv7/t2zJagel9KmqKsIACYL9RjI8UHz5zshougZr/AEvbxEP
aZCDBY3VslixaJvX3wzkkDiOwbZtDRGA5vdNAg+TL27qgmt5XkBG/gTdAG7Gt+3PP9oOaEGFCVEC6rp+
5g9MfM/c5e4OsEZMZkQEtGL5H2DdZ5JRArDwPA+iKII0TfkC9vroC9j5vq8JTWw3WzWgLMtZGIaa0MR8
vlAD8PYlSaIJTTiOowY0p0Bc19XEJo6HE59FAPuMzyAINKGJ1XLFZxHALtMrnkBXOIQIIIQ8YvF/KrgB
cMaRN0UdBBkAAAAASUVORK5CYII=
</value>
</data>
<data name="ActionButton2.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAADmUlE
QVRIS62WWWxMURjHL220JW1HausmlFrDFKUhnUGH6bRFzJ2idImlC0Vp2mlji1A8iNhCPIjIRES8EU+W
h2oEtbSDTk3HNNM7S01VKsXjkb/vXBo3k1Ee7sMvmZzzzf//ne/+z50RAAxL1MUIG4G/YAv3HSVhF5Vw
IYNdz3LadVj9RgdTB+HQYYPHIJuE1ocSdlEJFzG+1bPRLQLinglIeCkg+XUkKvz56hnkOfQs/rmA8S9H
YEp7FDI64tAQtKhnsMapZ7zzNHsUFnbGY4VzIk70l6hnIH4wsDR7NBZ3apDrSqL5T8eFgUr1DLZ78lim
Q4N8VzK29MxEpZSBa4M16hnU+c3M9CEFpdJsVHsXos63DDcHrf9nQEXD5VymwW/5USLNwl5vJhp7dTgW
NML2pR7jbsUMS+KdMTa5Q8NQxinfBU4dRFcOyjy52OtbhwOBDTgZLKPPmTgY0ON4MBdNfSbYBupxY8Aq
G10dqMG5/nIc7ytGQ6CQRliAamkTN/g1Ai4e95Qy3iogpX0UtBRDnhRzdxq2SXOxz5eFQ70rScCEU335
ssGxj0YS06HSm4GN3ekwdE2C1hGH1LZR0JDOJof5jwHvnIvzTa0jlooTYfktvt+fhcOBHDQFTWRgxJGP
ObAGsulZLMLWnjlY756K5c4JmNcRi6T2SGheCIihS2l5ozAo6NRhMolnUAcGV6IcwwqvFrX+JTjYuwKH
SfRAYDms/mzs9y1GFe2VSnOw1j0FejqpLN4WCX4ZufiIBwLMLxQGm12rsLQzgWKYgmLPLNTQw6ynpDSS
IBet8y+TqaVRVdFIeJrWuCcj+/0EzH43BomvIhBLI45uFiDcJ+6QwROFwa6+Amb9bGFNg6Xs9Ncd7Oy3
Knb2eyU7/20nu9y/m136tIvEl6BC0qKoZwby3alo9JVhj7T5R7m/kJVIIityi8zyXmTiW+I10SqyIQNb
uIgNwYuuf25kFd75KPKkI49OmUWnrfYWyXv/wBb2cijhhVf6a9lGei65XclYRDd6mj0GWz2iLBJaH0rY
RSVc5Eywmhm7kuQXHX+bJlBStrh+zTi0PpSwi0q4yNFAOVvgiEcKJWUsxZn/NhT+znlofShhF5VwkRpv
MUtti4KGYjj6sYCIh5QSu4oG27stjItHU+cjeQzvkcFzFQ2KnSKLoc4FukDCXeI2GbSoaFD4ziyPxNxK
0AUyNxOP1DOwcaG/8I+/LRB+At7psBnyDBG0AAAAAElFTkSuQmCC
</value>
</data>
<data name="ActionButton3.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value>
</data>
<data name="ActionButton4.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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
AAAASUVORK5CYII=
</value>
</data>
<metadata name="FRM_FILES.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<data name="ActionButton5.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value>
</data>
<data name="ActionButton6.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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
AAAASUVORK5CYII=
</value>
</data>
<data name="ActionButton7.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value>
</data>
<data name="ActionButton8.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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
AAAASUVORK5CYII=
</value>
</data>
<metadata name="TP_PROFILES.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>

View File

@@ -0,0 +1,278 @@
' 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
Imports SCrawler.API.Base
Imports PersonalUtilities.Tools
Imports PersonalUtilities.Forms
Imports PersonalUtilities.Forms.Controls
Imports PersonalUtilities.Forms.Controls.Base
Imports ADB = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons
Namespace DownloadObjects
Friend Class FeedCopyToForm
#Region "Declarations"
Private WithEvents MyDefs As DefaultFormOptions
Private _Result As FeedMoveCopyTo
Friend ReadOnly Property Result As FeedMoveCopyTo
Get
Return _Result
End Get
End Property
Private ReadOnly Profiles As List(Of IUserData)
#End Region
#Region "Initializer"
Friend Sub New(ByVal Files As IEnumerable(Of SFile), ByVal IsCopy As Boolean)
InitializeComponent()
MyDefs = New DefaultFormOptions(Me, Settings.Design)
If Files.ListExists Then TXT_FILES.Text = Files.ListToString(vbNewLine)
Profiles = New List(Of IUserData)
Text = $"{IIf(IsCopy, "Copy", "Move")} files to..."
Try
If IsCopy Then
Icon = ImageRenderer.GetIcon(My.Resources.PastePic_32, EDP.ThrowException)
Else
Icon = ImageRenderer.GetIcon(My.Resources.CutPic_48, EDP.ThrowException)
End If
Catch
ShowIcon = False
End Try
End Sub
#End Region
#Region "Form handlers"
Private Sub FeedCopyToForm_Load(sender As Object, e As EventArgs) Handles Me.Load
Try
With MyDefs
.MyViewInitialize()
.AddOkCancelToolbar()
.MyFieldsCheckerE = New FieldsChecker
With .MyFieldsCheckerE
.AddControl(Of String)(CMB_DEST, "Destination")
.EndLoaderOperations()
End With
Settings.DownloadLocations.PopulateComboBox(CMB_DEST)
With Settings
CMB_DEST.Text = .FeedMoveCopyLastLocation.Value
CH_VIDEO_SEP.Checked = .FeedMoveCopySeparateVideo
CH_PROFILE_REPLACE.Checked = .FeedMoveCopyReplaceUserProfile
CH_PROFILE_CREATE.Checked = .FeedMoveCopyCreatePathProfile
End With
If Settings.Users.Count > 0 Then _
Profiles.AddRange(Settings.Users.SelectMany(Of IUserData)(Function(ByVal p As IUserData) As IEnumerable(Of IUserData)
If p.IsCollection Then
Return DirectCast(p, UserDataBind).Collections
Else
Return {p}
End If
End Function))
If Profiles.Count > 0 Then
CMB_PROFILE.BeginUpdate()
CMB_PROFILE_PATH.BeginUpdate()
For i% = 0 To Profiles.Count - 1
With DirectCast(Profiles(i), UserDataBase)
If If(.HOST?.Key, String.Empty) = PathPlugin.PluginKey Then
CMB_PROFILE_PATH.Items.Add(New ListItem({ .Self.ToStringForLog, i}))
Else
CMB_PROFILE.Items.Add(New ListItem({ .Self.ToStringForLog, i}))
End If
End With
Next
CMB_PROFILE.EndUpdate()
CMB_PROFILE_PATH.EndUpdate()
End If
UpdateCombo()
If Not CMB_DEST.Text.IsEmptyString Then
_ComboChangingByDest = True
UpdateComboIndex(CMB_PROFILE)
UpdateComboIndex(CMB_PROFILE_PATH)
_ComboChangingByDest = False
End If
UpdateComboCheck()
.EndLoaderOperations()
.MyOkCancel.EnableOK = True
End With
Catch ex As Exception
MyDefs.InvokeLoaderError(ex)
End Try
End Sub
Private Sub FeedCopyToForm_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
Dim b As Boolean = True
If e.KeyCode = Keys.O And e.Control Then
Settings.DownloadLocations.ChooseNewLocation(CMB_DEST, False, False)
ElseIf e.KeyCode = Keys.O And e.Alt Then
Settings.DownloadLocations.ChooseNewLocation(CMB_DEST, True, True)
Else
b = False
End If
If b Then e.Handled = True
End Sub
Private Sub FeedCopyToForm_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed
Profiles.Clear()
End Sub
#End Region
#Region "Ok, Cancel"
Private Sub MyDefs_ButtonOkClick(ByVal Sender As Object, ByVal e As KeyHandleEventArgs) Handles MyDefs.ButtonOkClick
Try
If MyDefs.MyFieldsChecker.AllParamsOK Then
_Result = New FeedMoveCopyTo With {
.Destination = CMB_DEST.Text,
.SeparateVideoFolder = CH_VIDEO_SEP.Checked,
.ReplaceUserProfile = CH_PROFILE_REPLACE.Checked,
.ReplaceUserProfile_CreateIfNull = CH_PROFILE_CREATE.Checked
}
If CH_PROFILE_REPLACE.Checked Then
If CMB_PROFILE.Enabled And CMB_PROFILE.Checked Then
With CMB_PROFILE
If .SelectedIndex >= 0 Then _
_Result.ReplaceUserProfile_Profile = Settings.GetUser(GetComboProfile(.Self), False)
End With
ElseIf CMB_PROFILE_PATH.Enabled And CMB_PROFILE_PATH.Checked Then
With CMB_PROFILE_PATH
If .SelectedIndex >= 0 Then _
_Result.ReplaceUserProfile_Profile = Settings.GetUser(GetComboProfile(.Self), False)
End With
End If
End If
With Settings
.BeginUpdate()
.FeedMoveCopyLastLocation.Value = CMB_DEST.Text
.FeedMoveCopyIsProfileChecked.Value = CMB_PROFILE.Checked
.FeedMoveCopySeparateVideo.Value = CH_VIDEO_SEP.Checked
.FeedMoveCopyReplaceUserProfile.Value = CH_PROFILE_REPLACE.Checked
.FeedMoveCopyCreatePathProfile.Value = CH_PROFILE_CREATE.Checked
.EndUpdate()
End With
MyDefs.CloseForm()
End If
Catch ex As Exception
ErrorsDescriber.Execute(EDP.LogMessageValue, ex, "[FeedCopyToForm.OK]")
End Try
End Sub
#End Region
#Region "Controls"
Private _TextChangingByCombo As Boolean = False
Private _ComboChangingByDest As Boolean = False
Private Sub CMB_DEST_ActionOnButtonClick(ByVal Sender As Object, ByVal e As ActionButtonEventArgs) Handles CMB_DEST.ActionOnButtonClick
If Sender.DefaultButton = ADB.Open Or Sender.DefaultButton = ADB.Add Then _
Settings.DownloadLocations.ChooseNewLocation(CMB_DEST, Sender.DefaultButton = ADB.Add, Sender.DefaultButton = ADB.Add)
End Sub
Private Sub CMB_DEST_ActionOnTextChanged(ByVal Sender As Object, ByVal e As EventArgs) Handles CMB_DEST.ActionOnTextChanged
If Not _TextChangingByCombo And Not CMB_DEST.Checked And Not CMB_DEST.Text.IsEmptyString Then
_ComboChangingByDest = True
UpdateComboIndex(CMB_PROFILE)
UpdateComboIndex(CMB_PROFILE_PATH)
UpdateComboCheck()
_ComboChangingByDest = False
End If
End Sub
Private Sub UpdateComboIndex(ByVal CMB As ComboBoxExtended)
Try
With CMB
If .Count > 0 Then
Dim t$ = CMB_DEST.Text.CSFilePSN.StringToLower
Dim lvi_check As Func(Of ListItem, Boolean, Boolean) =
Function(ByVal lvi As ListItem, ByVal exact As Boolean) As Boolean
Dim ii% = lvi.Value(1)
If ii.ValueBetween(0, Profiles.Count - 1) Then
With DirectCast(Profiles(ii), UserDataBase)
If exact Then
Return t = .MyFile.CutPath.PathNoSeparator.StringToLower
Else
Return t.StartsWith(.MyFile.CutPath.PathNoSeparator.StringToLower)
End If
End With
End If
Return False
End Function
Dim i% = CMB.Items.ListIndexOf(Function(lvi) lvi_check.Invoke(lvi, True))
If i = -1 Then i = CMB.Items.ListIndexOf(Function(lvi) lvi_check.Invoke(lvi, False))
CMB.SelectedIndex = i
End If
End With
Catch ex As Exception
CMB.SelectedIndex = -1
End Try
End Sub
Private Sub UpdateComboCheck()
Try
Dim isProfile As Boolean
If CMB_PROFILE.SelectedIndex >= 0 And CMB_PROFILE_PATH.SelectedIndex >= 0 Then
isProfile = Settings.FeedMoveCopyIsProfileChecked
ElseIf CMB_PROFILE.SelectedIndex >= 0 Then
isProfile = True
ElseIf CMB_PROFILE_PATH.SelectedIndex >= 0 Then
isProfile = False
Else
isProfile = Settings.FeedMoveCopyIsProfileChecked
End If
If isProfile Then
CMB_PROFILE.Checked = True
Else
CMB_PROFILE_PATH.Checked = True
End If
Catch ex As Exception
ErrorsDescriber.Execute(EDP.SendToLog, ex, "[FeedCopyToForm.UpdateComboCheck]")
End Try
End Sub
Private Sub CH_PROFILE_REPLACE_CheckedChanged(sender As Object, e As EventArgs) Handles CH_PROFILE_REPLACE.CheckedChanged
UpdateCombo()
End Sub
Private Sub UpdateCombo()
Dim e As Boolean = CH_PROFILE_REPLACE.Checked
CH_PROFILE_CREATE.Enabled = e
CMB_PROFILE.Enabled(True) = e And CMB_PROFILE.Count > 0
CMB_PROFILE_PATH.Enabled(True) = e And CMB_PROFILE_PATH.Count > 0
End Sub
#Region "Comboboxes"
Private Sub CMB_PROFILE_ActionSelectedItemChanged(ByVal Sender As Object, ByVal e As EventArgs, ByVal Item As ListViewItem) Handles CMB_PROFILE.ActionSelectedItemChanged
If Not MyDefs.Initializing Then SetDestinationByCombo(CMB_PROFILE)
End Sub
Private Sub CMB_PROFILE_ActionOnCheckedChange(ByVal Sender As Object, ByVal e As EventArgs, ByVal Checked As Boolean) Handles CMB_PROFILE.ActionOnCheckedChange
If Checked And Not MyDefs.Initializing And Not _ComboChangingByDest Then SetDestinationByCombo(CMB_PROFILE)
End Sub
Private Sub CMB_PROFILE_ActionOnButtonClick(ByVal Sender As Object, ByVal e As ActionButtonEventArgs) Handles CMB_PROFILE.ActionOnButtonClick
If e.DefaultButton = ADB.Clear Then CMB_PROFILE.SelectedIndex = -1
End Sub
Private Sub CMB_PROFILE_PATH_ActionSelectedItemChanged(ByVal Sender As Object, ByVal e As EventArgs, ByVal Item As ListViewItem) Handles CMB_PROFILE_PATH.ActionSelectedItemChanged
If Not MyDefs.Initializing Then SetDestinationByCombo(CMB_PROFILE_PATH)
End Sub
Private Sub CMB_PROFILE_PATH_ActionOnButtonClick(ByVal Sender As Object, ByVal e As ActionButtonEventArgs) Handles CMB_PROFILE_PATH.ActionOnButtonClick
If e.DefaultButton = ADB.Clear Then CMB_PROFILE_PATH.SelectedIndex = -1
End Sub
Private Sub CMB_PROFILE_PATH_ActionOnCheckedChange(ByVal Sender As Object, ByVal e As EventArgs, ByVal Checked As Boolean) Handles CMB_PROFILE_PATH.ActionOnCheckedChange
If Checked And Not MyDefs.Initializing And Not _ComboChangingByDest Then SetDestinationByCombo(CMB_PROFILE_PATH)
End Sub
Private Sub SetDestinationByCombo(ByVal CMB As ComboBoxExtended)
Try
With CMB
If .Checked And .Enabled And Not CMB_DEST.Checked And Not _ComboChangingByDest And .SelectedIndex >= 0 Then
_TextChangingByCombo = True
CMB_DEST.Text = GetComboProfile(.Self).MyFile.CutPath.PathWithSeparator
_TextChangingByCombo = False
End If
End With
Catch ex As Exception
ErrorsDescriber.Execute(EDP.SendToLog, ex, "[FeedCopyToForm.SetDestinationByCombo]")
End Try
End Sub
Private Function GetComboProfile(ByVal CMB As ComboBoxExtended) As UserDataBase
Try
With CMB
If .SelectedIndex >= 0 Then
Dim i% = .Items(.SelectedIndex).Value(1)
If i.ValueBetween(0, Profiles.Count - 1) Then Return Profiles(i)
End If
End With
Return Nothing
Catch ex As Exception
Return ErrorsDescriber.Execute(EDP.SendToLog + EDP.ReturnValue, ex, "[FeedCopyToForm.GetComboProfile]")
End Try
End Function
#End Region
#End Region
End Class
End Namespace

View File

@@ -24,8 +24,10 @@ Namespace DownloadObjects
Private Sub InitializeComponent() Private Sub InitializeComponent()
Me.components = New System.ComponentModel.Container() Me.components = New System.ComponentModel.Container()
Dim CONTEXT_SEP_1 As System.Windows.Forms.ToolStripSeparator Dim CONTEXT_SEP_1 As System.Windows.Forms.ToolStripSeparator
Dim CONTEXT_SEP_2 As System.Windows.Forms.ToolStripSeparator
Dim TP_LBL As System.Windows.Forms.TableLayoutPanel Dim TP_LBL As System.Windows.Forms.TableLayoutPanel
Dim CONTEXT_SEP_3 As System.Windows.Forms.ToolStripSeparator
Dim CONTEXT_SEP_4 As System.Windows.Forms.ToolStripSeparator
Me.CONTEXT_SEP_2 = New System.Windows.Forms.ToolStripSeparator()
Me.CH_CHECKED = New System.Windows.Forms.CheckBox() Me.CH_CHECKED = New System.Windows.Forms.CheckBox()
Me.LBL_INFO = New System.Windows.Forms.Label() Me.LBL_INFO = New System.Windows.Forms.Label()
Me.CONTEXT_DATA = New System.Windows.Forms.ContextMenuStrip(Me.components) Me.CONTEXT_DATA = New System.Windows.Forms.ContextMenuStrip(Me.components)
@@ -35,21 +37,25 @@ Namespace DownloadObjects
Me.BTT_CONTEXT_OPEN_USER = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_CONTEXT_OPEN_USER = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_CONTEXT_OPEN_USER_URL = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_CONTEXT_OPEN_USER_URL = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_CONTEXT_OPEN_USER_POST = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_CONTEXT_OPEN_USER_POST = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_COPY_TO = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_MOVE_TO = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_FEED_ADD_FAV = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_FEED_ADD_FAV_REMOVE = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_FEED_ADD_SPEC = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_FEED_ADD_SPEC_REMOVE = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_FEED_REMOVE_FAV = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_FEED_REMOVE_SPEC = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_CONTEXT_FIND_USER = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_CONTEXT_FIND_USER = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_CONTEXT_INFO = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_CONTEXT_INFO = New System.Windows.Forms.ToolStripMenuItem()
Me.CONTEXT_SEP_3 = New System.Windows.Forms.ToolStripSeparator() Me.CONTEXT_SEP_5 = New System.Windows.Forms.ToolStripSeparator()
Me.BTT_CONTEXT_DELETE = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_CONTEXT_DELETE = New System.Windows.Forms.ToolStripMenuItem()
Me.ICON_SITE = New System.Windows.Forms.PictureBox() Me.ICON_SITE = New System.Windows.Forms.PictureBox()
Me.TP_MAIN = New System.Windows.Forms.TableLayoutPanel() Me.TP_MAIN = New System.Windows.Forms.TableLayoutPanel()
Me.LBL_TITLE = New System.Windows.Forms.Label() Me.LBL_TITLE = New System.Windows.Forms.Label()
Me.CONTEXT_SEP_4 = New System.Windows.Forms.ToolStripSeparator()
Me.BTT_FEED_ADD_FAV = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_FEED_ADD_SPEC = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_FEED_REMOVE_FAV = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_FEED_REMOVE_SPEC = New System.Windows.Forms.ToolStripMenuItem()
CONTEXT_SEP_1 = New System.Windows.Forms.ToolStripSeparator() CONTEXT_SEP_1 = New System.Windows.Forms.ToolStripSeparator()
CONTEXT_SEP_2 = New System.Windows.Forms.ToolStripSeparator()
TP_LBL = New System.Windows.Forms.TableLayoutPanel() TP_LBL = New System.Windows.Forms.TableLayoutPanel()
CONTEXT_SEP_3 = New System.Windows.Forms.ToolStripSeparator()
CONTEXT_SEP_4 = New System.Windows.Forms.ToolStripSeparator()
TP_LBL.SuspendLayout() TP_LBL.SuspendLayout()
Me.CONTEXT_DATA.SuspendLayout() Me.CONTEXT_DATA.SuspendLayout()
CType(Me.ICON_SITE, System.ComponentModel.ISupportInitialize).BeginInit() CType(Me.ICON_SITE, System.ComponentModel.ISupportInitialize).BeginInit()
@@ -59,12 +65,12 @@ Namespace DownloadObjects
'CONTEXT_SEP_1 'CONTEXT_SEP_1
' '
CONTEXT_SEP_1.Name = "CONTEXT_SEP_1" CONTEXT_SEP_1.Name = "CONTEXT_SEP_1"
CONTEXT_SEP_1.Size = New System.Drawing.Size(217, 6) CONTEXT_SEP_1.Size = New System.Drawing.Size(302, 6)
' '
'CONTEXT_SEP_2 'CONTEXT_SEP_2
' '
CONTEXT_SEP_2.Name = "CONTEXT_SEP_2" Me.CONTEXT_SEP_2.Name = "CONTEXT_SEP_2"
CONTEXT_SEP_2.Size = New System.Drawing.Size(217, 6) Me.CONTEXT_SEP_2.Size = New System.Drawing.Size(302, 6)
' '
'TP_LBL 'TP_LBL
' '
@@ -108,76 +114,142 @@ Namespace DownloadObjects
' '
'CONTEXT_DATA 'CONTEXT_DATA
' '
Me.CONTEXT_DATA.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.BTT_CONTEXT_DOWN, Me.CONTEXT_SEP_0, Me.BTT_CONTEXT_OPEN_MEDIA, Me.BTT_CONTEXT_OPEN_USER, CONTEXT_SEP_1, Me.BTT_CONTEXT_OPEN_USER_URL, Me.BTT_CONTEXT_OPEN_USER_POST, CONTEXT_SEP_2, Me.BTT_FEED_ADD_FAV, Me.BTT_FEED_ADD_SPEC, Me.BTT_FEED_REMOVE_FAV, Me.BTT_FEED_REMOVE_SPEC, Me.CONTEXT_SEP_3, Me.BTT_CONTEXT_FIND_USER, Me.BTT_CONTEXT_INFO, Me.CONTEXT_SEP_4, Me.BTT_CONTEXT_DELETE}) Me.CONTEXT_DATA.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.BTT_CONTEXT_DOWN, Me.CONTEXT_SEP_0, Me.BTT_CONTEXT_OPEN_MEDIA, Me.BTT_CONTEXT_OPEN_USER, CONTEXT_SEP_1, Me.BTT_CONTEXT_OPEN_USER_URL, Me.BTT_CONTEXT_OPEN_USER_POST, Me.CONTEXT_SEP_2, Me.BTT_COPY_TO, Me.BTT_MOVE_TO, CONTEXT_SEP_3, Me.BTT_FEED_ADD_FAV, Me.BTT_FEED_ADD_FAV_REMOVE, Me.BTT_FEED_ADD_SPEC, Me.BTT_FEED_ADD_SPEC_REMOVE, Me.BTT_FEED_REMOVE_FAV, Me.BTT_FEED_REMOVE_SPEC, CONTEXT_SEP_4, Me.BTT_CONTEXT_FIND_USER, Me.BTT_CONTEXT_INFO, Me.CONTEXT_SEP_5, Me.BTT_CONTEXT_DELETE})
Me.CONTEXT_DATA.Name = "CONTEXT_PIC" Me.CONTEXT_DATA.Name = "CONTEXT_PIC"
Me.CONTEXT_DATA.Size = New System.Drawing.Size(221, 320) Me.CONTEXT_DATA.Size = New System.Drawing.Size(306, 414)
' '
'BTT_CONTEXT_DOWN 'BTT_CONTEXT_DOWN
' '
Me.BTT_CONTEXT_DOWN.Image = Global.SCrawler.My.Resources.Resources.StartPic_Green_16 Me.BTT_CONTEXT_DOWN.Image = Global.SCrawler.My.Resources.Resources.StartPic_Green_16
Me.BTT_CONTEXT_DOWN.Name = "BTT_CONTEXT_DOWN" Me.BTT_CONTEXT_DOWN.Name = "BTT_CONTEXT_DOWN"
Me.BTT_CONTEXT_DOWN.Size = New System.Drawing.Size(220, 22) Me.BTT_CONTEXT_DOWN.Size = New System.Drawing.Size(305, 22)
Me.BTT_CONTEXT_DOWN.Text = "Download" Me.BTT_CONTEXT_DOWN.Text = "Download"
Me.BTT_CONTEXT_DOWN.Visible = False Me.BTT_CONTEXT_DOWN.Visible = False
' '
'CONTEXT_SEP_0 'CONTEXT_SEP_0
' '
Me.CONTEXT_SEP_0.Name = "CONTEXT_SEP_0" Me.CONTEXT_SEP_0.Name = "CONTEXT_SEP_0"
Me.CONTEXT_SEP_0.Size = New System.Drawing.Size(217, 6) Me.CONTEXT_SEP_0.Size = New System.Drawing.Size(302, 6)
Me.CONTEXT_SEP_0.Visible = False Me.CONTEXT_SEP_0.Visible = False
' '
'BTT_CONTEXT_OPEN_MEDIA 'BTT_CONTEXT_OPEN_MEDIA
' '
Me.BTT_CONTEXT_OPEN_MEDIA.Image = Global.SCrawler.My.Resources.Resources.FolderPic_32 Me.BTT_CONTEXT_OPEN_MEDIA.Image = Global.SCrawler.My.Resources.Resources.FolderPic_32
Me.BTT_CONTEXT_OPEN_MEDIA.Name = "BTT_CONTEXT_OPEN_MEDIA" Me.BTT_CONTEXT_OPEN_MEDIA.Name = "BTT_CONTEXT_OPEN_MEDIA"
Me.BTT_CONTEXT_OPEN_MEDIA.Size = New System.Drawing.Size(220, 22) Me.BTT_CONTEXT_OPEN_MEDIA.Size = New System.Drawing.Size(305, 22)
Me.BTT_CONTEXT_OPEN_MEDIA.Text = "Open" Me.BTT_CONTEXT_OPEN_MEDIA.Text = "Open"
' '
'BTT_CONTEXT_OPEN_USER 'BTT_CONTEXT_OPEN_USER
' '
Me.BTT_CONTEXT_OPEN_USER.Image = Global.SCrawler.My.Resources.Resources.FolderPic_32 Me.BTT_CONTEXT_OPEN_USER.Image = Global.SCrawler.My.Resources.Resources.FolderPic_32
Me.BTT_CONTEXT_OPEN_USER.Name = "BTT_CONTEXT_OPEN_USER" Me.BTT_CONTEXT_OPEN_USER.Name = "BTT_CONTEXT_OPEN_USER"
Me.BTT_CONTEXT_OPEN_USER.Size = New System.Drawing.Size(220, 22) Me.BTT_CONTEXT_OPEN_USER.Size = New System.Drawing.Size(305, 22)
Me.BTT_CONTEXT_OPEN_USER.Text = "Open user" Me.BTT_CONTEXT_OPEN_USER.Text = "Open user"
' '
'BTT_CONTEXT_OPEN_USER_URL 'BTT_CONTEXT_OPEN_USER_URL
' '
Me.BTT_CONTEXT_OPEN_USER_URL.Image = Global.SCrawler.My.Resources.Resources.GlobePic_32 Me.BTT_CONTEXT_OPEN_USER_URL.Image = Global.SCrawler.My.Resources.Resources.GlobePic_32
Me.BTT_CONTEXT_OPEN_USER_URL.Name = "BTT_CONTEXT_OPEN_USER_URL" Me.BTT_CONTEXT_OPEN_USER_URL.Name = "BTT_CONTEXT_OPEN_USER_URL"
Me.BTT_CONTEXT_OPEN_USER_URL.Size = New System.Drawing.Size(220, 22) Me.BTT_CONTEXT_OPEN_USER_URL.Size = New System.Drawing.Size(305, 22)
Me.BTT_CONTEXT_OPEN_USER_URL.Text = "Open user" Me.BTT_CONTEXT_OPEN_USER_URL.Text = "Open user"
' '
'BTT_CONTEXT_OPEN_USER_POST 'BTT_CONTEXT_OPEN_USER_POST
' '
Me.BTT_CONTEXT_OPEN_USER_POST.Image = Global.SCrawler.My.Resources.Resources.GlobePic_32 Me.BTT_CONTEXT_OPEN_USER_POST.Image = Global.SCrawler.My.Resources.Resources.GlobePic_32
Me.BTT_CONTEXT_OPEN_USER_POST.Name = "BTT_CONTEXT_OPEN_USER_POST" Me.BTT_CONTEXT_OPEN_USER_POST.Name = "BTT_CONTEXT_OPEN_USER_POST"
Me.BTT_CONTEXT_OPEN_USER_POST.Size = New System.Drawing.Size(220, 22) Me.BTT_CONTEXT_OPEN_USER_POST.Size = New System.Drawing.Size(305, 22)
Me.BTT_CONTEXT_OPEN_USER_POST.Text = "Open post" Me.BTT_CONTEXT_OPEN_USER_POST.Text = "Open post"
' '
'BTT_COPY_TO
'
Me.BTT_COPY_TO.Image = Global.SCrawler.My.Resources.Resources.PastePic_32
Me.BTT_COPY_TO.Name = "BTT_COPY_TO"
Me.BTT_COPY_TO.Size = New System.Drawing.Size(305, 22)
Me.BTT_COPY_TO.Text = "Copy to..."
'
'BTT_MOVE_TO
'
Me.BTT_MOVE_TO.Image = Global.SCrawler.My.Resources.Resources.CutPic_48
Me.BTT_MOVE_TO.Name = "BTT_MOVE_TO"
Me.BTT_MOVE_TO.Size = New System.Drawing.Size(305, 22)
Me.BTT_MOVE_TO.Text = "Move to..."
'
'CONTEXT_SEP_3
'
CONTEXT_SEP_3.Name = "CONTEXT_SEP_3"
CONTEXT_SEP_3.Size = New System.Drawing.Size(302, 6)
'
'BTT_FEED_ADD_FAV
'
Me.BTT_FEED_ADD_FAV.Image = Global.SCrawler.My.Resources.Resources.HeartPic_32
Me.BTT_FEED_ADD_FAV.Name = "BTT_FEED_ADD_FAV"
Me.BTT_FEED_ADD_FAV.Size = New System.Drawing.Size(305, 22)
Me.BTT_FEED_ADD_FAV.Text = "Add to Favorite"
'
'BTT_FEED_ADD_FAV_REMOVE
'
Me.BTT_FEED_ADD_FAV_REMOVE.Image = Global.SCrawler.My.Resources.Resources.HeartPic_32
Me.BTT_FEED_ADD_FAV_REMOVE.Name = "BTT_FEED_ADD_FAV_REMOVE"
Me.BTT_FEED_ADD_FAV_REMOVE.Size = New System.Drawing.Size(305, 22)
Me.BTT_FEED_ADD_FAV_REMOVE.Text = "Add to Favorite (remove from current)"
'
'BTT_FEED_ADD_SPEC
'
Me.BTT_FEED_ADD_SPEC.Image = Global.SCrawler.My.Resources.Resources.RSSPic_512
Me.BTT_FEED_ADD_SPEC.Name = "BTT_FEED_ADD_SPEC"
Me.BTT_FEED_ADD_SPEC.Size = New System.Drawing.Size(305, 22)
Me.BTT_FEED_ADD_SPEC.Text = "Add to special feed..."
'
'BTT_FEED_ADD_SPEC_REMOVE
'
Me.BTT_FEED_ADD_SPEC_REMOVE.Image = Global.SCrawler.My.Resources.Resources.RSSPic_512
Me.BTT_FEED_ADD_SPEC_REMOVE.Name = "BTT_FEED_ADD_SPEC_REMOVE"
Me.BTT_FEED_ADD_SPEC_REMOVE.Size = New System.Drawing.Size(305, 22)
Me.BTT_FEED_ADD_SPEC_REMOVE.Text = "Add to special feed (remove from current)..."
'
'BTT_FEED_REMOVE_FAV
'
Me.BTT_FEED_REMOVE_FAV.Image = Global.SCrawler.My.Resources.Resources.DeletePic_24
Me.BTT_FEED_REMOVE_FAV.Name = "BTT_FEED_REMOVE_FAV"
Me.BTT_FEED_REMOVE_FAV.Size = New System.Drawing.Size(305, 22)
Me.BTT_FEED_REMOVE_FAV.Text = "Remove from Favorite"
'
'BTT_FEED_REMOVE_SPEC
'
Me.BTT_FEED_REMOVE_SPEC.Image = Global.SCrawler.My.Resources.Resources.DeletePic_24
Me.BTT_FEED_REMOVE_SPEC.Name = "BTT_FEED_REMOVE_SPEC"
Me.BTT_FEED_REMOVE_SPEC.Size = New System.Drawing.Size(305, 22)
Me.BTT_FEED_REMOVE_SPEC.Text = "Remove from special feed..."
'
'CONTEXT_SEP_4
'
CONTEXT_SEP_4.Name = "CONTEXT_SEP_4"
CONTEXT_SEP_4.Size = New System.Drawing.Size(302, 6)
'
'BTT_CONTEXT_FIND_USER 'BTT_CONTEXT_FIND_USER
' '
Me.BTT_CONTEXT_FIND_USER.Image = Global.SCrawler.My.Resources.Resources.InfoPic_32 Me.BTT_CONTEXT_FIND_USER.Image = Global.SCrawler.My.Resources.Resources.InfoPic_32
Me.BTT_CONTEXT_FIND_USER.Name = "BTT_CONTEXT_FIND_USER" Me.BTT_CONTEXT_FIND_USER.Name = "BTT_CONTEXT_FIND_USER"
Me.BTT_CONTEXT_FIND_USER.Size = New System.Drawing.Size(220, 22) Me.BTT_CONTEXT_FIND_USER.Size = New System.Drawing.Size(305, 22)
Me.BTT_CONTEXT_FIND_USER.Text = "Find user" Me.BTT_CONTEXT_FIND_USER.Text = "Find user"
' '
'BTT_CONTEXT_INFO 'BTT_CONTEXT_INFO
' '
Me.BTT_CONTEXT_INFO.Image = Global.SCrawler.My.Resources.Resources.InfoPic_32 Me.BTT_CONTEXT_INFO.Image = Global.SCrawler.My.Resources.Resources.InfoPic_32
Me.BTT_CONTEXT_INFO.Name = "BTT_CONTEXT_INFO" Me.BTT_CONTEXT_INFO.Name = "BTT_CONTEXT_INFO"
Me.BTT_CONTEXT_INFO.Size = New System.Drawing.Size(220, 22) Me.BTT_CONTEXT_INFO.Size = New System.Drawing.Size(305, 22)
Me.BTT_CONTEXT_INFO.Text = "Information" Me.BTT_CONTEXT_INFO.Text = "Information"
' '
'CONTEXT_SEP_3 'CONTEXT_SEP_5
' '
Me.CONTEXT_SEP_3.Name = "CONTEXT_SEP_3" Me.CONTEXT_SEP_5.Name = "CONTEXT_SEP_5"
Me.CONTEXT_SEP_3.Size = New System.Drawing.Size(217, 6) Me.CONTEXT_SEP_5.Size = New System.Drawing.Size(302, 6)
' '
'BTT_CONTEXT_DELETE 'BTT_CONTEXT_DELETE
' '
Me.BTT_CONTEXT_DELETE.Image = Global.SCrawler.My.Resources.Resources.DeletePic_24 Me.BTT_CONTEXT_DELETE.Image = Global.SCrawler.My.Resources.Resources.DeletePic_24
Me.BTT_CONTEXT_DELETE.Name = "BTT_CONTEXT_DELETE" Me.BTT_CONTEXT_DELETE.Name = "BTT_CONTEXT_DELETE"
Me.BTT_CONTEXT_DELETE.Size = New System.Drawing.Size(220, 22) Me.BTT_CONTEXT_DELETE.Size = New System.Drawing.Size(305, 22)
Me.BTT_CONTEXT_DELETE.Text = "Delete" Me.BTT_CONTEXT_DELETE.Text = "Delete"
' '
'ICON_SITE 'ICON_SITE
@@ -217,39 +289,6 @@ Namespace DownloadObjects
Me.LBL_TITLE.Size = New System.Drawing.Size(140, 25) Me.LBL_TITLE.Size = New System.Drawing.Size(140, 25)
Me.LBL_TITLE.TabIndex = 1 Me.LBL_TITLE.TabIndex = 1
' '
'CONTEXT_SEP_4
'
Me.CONTEXT_SEP_4.Name = "CONTEXT_SEP_4"
Me.CONTEXT_SEP_4.Size = New System.Drawing.Size(217, 6)
'
'BTT_FEED_ADD_FAV
'
Me.BTT_FEED_ADD_FAV.Image = Global.SCrawler.My.Resources.Resources.HeartPic_32
Me.BTT_FEED_ADD_FAV.Name = "BTT_FEED_ADD_FAV"
Me.BTT_FEED_ADD_FAV.Size = New System.Drawing.Size(220, 22)
Me.BTT_FEED_ADD_FAV.Text = "Add to Favorite"
'
'BTT_FEED_ADD_SPEC
'
Me.BTT_FEED_ADD_SPEC.Image = Global.SCrawler.My.Resources.Resources.RSSPic_512
Me.BTT_FEED_ADD_SPEC.Name = "BTT_FEED_ADD_SPEC"
Me.BTT_FEED_ADD_SPEC.Size = New System.Drawing.Size(220, 22)
Me.BTT_FEED_ADD_SPEC.Text = "Add to special feed..."
'
'BTT_FEED_REMOVE_FAV
'
Me.BTT_FEED_REMOVE_FAV.Image = Global.SCrawler.My.Resources.Resources.DeletePic_24
Me.BTT_FEED_REMOVE_FAV.Name = "BTT_FEED_REMOVE_FAV"
Me.BTT_FEED_REMOVE_FAV.Size = New System.Drawing.Size(220, 22)
Me.BTT_FEED_REMOVE_FAV.Text = "Remove from Favorite"
'
'BTT_FEED_REMOVE_SPEC
'
Me.BTT_FEED_REMOVE_SPEC.Image = Global.SCrawler.My.Resources.Resources.DeletePic_24
Me.BTT_FEED_REMOVE_SPEC.Name = "BTT_FEED_REMOVE_SPEC"
Me.BTT_FEED_REMOVE_SPEC.Size = New System.Drawing.Size(220, 22)
Me.BTT_FEED_REMOVE_SPEC.Text = "Remove from special feed..."
'
'FeedMedia 'FeedMedia
' '
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!) Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
@@ -283,7 +322,6 @@ Namespace DownloadObjects
Private WithEvents LBL_INFO As Label Private WithEvents LBL_INFO As Label
Private WithEvents BTT_CONTEXT_INFO As ToolStripMenuItem Private WithEvents BTT_CONTEXT_INFO As ToolStripMenuItem
Private WithEvents ICON_SITE As PictureBox Private WithEvents ICON_SITE As PictureBox
Private WithEvents CONTEXT_SEP_3 As ToolStripSeparator
Private WithEvents BTT_CONTEXT_DOWN As ToolStripMenuItem Private WithEvents BTT_CONTEXT_DOWN As ToolStripMenuItem
Private WithEvents CONTEXT_SEP_0 As ToolStripSeparator Private WithEvents CONTEXT_SEP_0 As ToolStripSeparator
Private WithEvents LBL_TITLE As Label Private WithEvents LBL_TITLE As Label
@@ -291,6 +329,11 @@ Namespace DownloadObjects
Private WithEvents BTT_FEED_ADD_SPEC As ToolStripMenuItem Private WithEvents BTT_FEED_ADD_SPEC As ToolStripMenuItem
Private WithEvents BTT_FEED_REMOVE_FAV As ToolStripMenuItem Private WithEvents BTT_FEED_REMOVE_FAV As ToolStripMenuItem
Private WithEvents BTT_FEED_REMOVE_SPEC As ToolStripMenuItem Private WithEvents BTT_FEED_REMOVE_SPEC As ToolStripMenuItem
Private WithEvents CONTEXT_SEP_4 As ToolStripSeparator Private WithEvents BTT_FEED_ADD_FAV_REMOVE As ToolStripMenuItem
Private WithEvents BTT_FEED_ADD_SPEC_REMOVE As ToolStripMenuItem
Private WithEvents BTT_COPY_TO As ToolStripMenuItem
Private WithEvents BTT_MOVE_TO As ToolStripMenuItem
Private WithEvents CONTEXT_SEP_5 As ToolStripSeparator
Private WithEvents CONTEXT_SEP_2 As ToolStripSeparator
End Class End Class
End Namespace End Namespace

View File

@@ -120,13 +120,16 @@
<metadata name="CONTEXT_SEP_1.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <metadata name="CONTEXT_SEP_1.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value> <value>False</value>
</metadata> </metadata>
<metadata name="CONTEXT_SEP_2.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="TP_LBL.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <metadata name="TP_LBL.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value> <value>False</value>
</metadata> </metadata>
<metadata name="CONTEXT_DATA.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> <metadata name="CONTEXT_DATA.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value> <value>17, 17</value>
</metadata> </metadata>
<metadata name="CONTEXT_SEP_3.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="CONTEXT_SEP_4.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
</root> </root>

View File

@@ -17,6 +17,8 @@ Namespace DownloadObjects
#Region "Events" #Region "Events"
Friend Event MediaDeleted(ByVal Sender As Object) Friend Event MediaDeleted(ByVal Sender As Object)
Friend Event MediaDownload As EventHandler Friend Event MediaDownload As EventHandler
Friend Event FeedAddWithRemove(ByVal Sender As FeedMedia, ByVal Feeds As IEnumerable(Of String), ByVal Media As UserMediaD, ByVal RemoveOperation As Boolean)
Friend Event MediaMove(ByVal Sender As FeedMedia, ByVal MCTOptions As FeedMoveCopyTo, ByRef Result As Boolean)
#End Region #End Region
#Region "Declarations" #Region "Declarations"
Private Const VideoHeight As Integer = 450 Private Const VideoHeight As Integer = 450
@@ -74,7 +76,7 @@ Namespace DownloadObjects
Private ReadOnly Property IsSubscription As Boolean = False Private ReadOnly Property IsSubscription As Boolean = False
Private Function GetImageResize(ByVal Width As Integer, ByVal Height As Integer) As Size Private Function GetImageResize(ByVal Width As Integer, ByVal Height As Integer) As Size
If Height > 0 Then If Height > 0 Then
Dim h% = Height = ObjectsPaddingHeight Dim h% = Height - ObjectsPaddingHeight
If h <= 0 Then h = Height If h <= 0 Then h = Height
Dim s As Size = MyImage.FitToHeightF(h) Dim s As Size = MyImage.FitToHeightF(h)
s = MyImage.FitToWidthF(s, Width, False) s = MyImage.FitToWidthF(s, Width, False)
@@ -159,7 +161,7 @@ Namespace DownloadObjects
Public Sub New() Public Sub New()
InitializeComponent() InitializeComponent()
End Sub End Sub
Friend Sub New(ByVal Media As UserMediaD, ByVal Width As Integer, ByVal Height As Integer) Friend Sub New(ByVal Media As UserMediaD, ByVal Width As Integer, ByVal Height As Integer, ByVal IsSession As Boolean)
Try Try
InitializeComponent() InitializeComponent()
Me.Media = Media Me.Media = Media
@@ -176,9 +178,13 @@ Namespace DownloadObjects
BTT_CONTEXT_DOWN.Visible = True BTT_CONTEXT_DOWN.Visible = True
CONTEXT_SEP_0.Visible = True CONTEXT_SEP_0.Visible = True
BTT_CONTEXT_OPEN_USER.Visible = False BTT_CONTEXT_OPEN_USER.Visible = False
CONTEXT_SEP_4.Visible = False CONTEXT_SEP_5.Visible = False
BTT_CONTEXT_DELETE.Visible = False BTT_CONTEXT_DELETE.Visible = False
CONTEXT_SEP_2.Visible = False
BTT_COPY_TO.Visible = False
BTT_MOVE_TO.Visible = False
If Not Media.Data.URL.IsEmptyString Then If Not Media.Data.URL.IsEmptyString Then
Dim ext$ = Media.Data.URL.CSFile.Extension Dim ext$ = Media.Data.URL.CSFile.Extension
Dim imgFile As New SFile With {.Path = Settings.Cache.RootDirectory.Path} Dim imgFile As New SFile With {.Path = Settings.Cache.RootDirectory.Path}
@@ -191,8 +197,7 @@ Namespace DownloadObjects
End With End With
If Not imgFile.Exists Then If Not imgFile.Exists Then
Settings.Cache.Validate() Settings.Cache.Validate()
GetWebFile(Media.Data.URL, imgFile, EDP.None) If GetWebFile(Media.Data.URL, imgFile, EDP.None) AndAlso imgFile.Exists Then File = ConvertWebp(imgFile)
If imgFile.Exists Then File = ConvertWebp(imgFile)
Else Else
File = imgFile File = imgFile
End If End If
@@ -228,7 +233,12 @@ Namespace DownloadObjects
Case UserMedia.Types.Picture, UserMedia.Types.GIF Case UserMedia.Types.Picture, UserMedia.Types.GIF
Dim tmpMediaFile As SFile = ConvertWebp(File, True) Dim tmpMediaFile As SFile = ConvertWebp(File, True)
If tmpMediaFile.IsEmptyString Then Throw New ArgumentNullException With {.HelpLink = 1} If tmpMediaFile.IsEmptyString Then Throw New ArgumentNullException With {.HelpLink = 1}
MyImage = New ImageRenderer(tmpMediaFile) Try
MyImage = New ImageRenderer(tmpMediaFile, EDP.ThrowException)
Catch
MyImage.DisposeIfReady
MyImage = New ImageRenderer(New Bitmap(10, 10))
End Try
Dim a As AnchorStyles = AnchorStyles.Top + If(Height > 0, 0, AnchorStyles.Left) Dim a As AnchorStyles = AnchorStyles.Top + If(Height > 0, 0, AnchorStyles.Left)
s = GetImageResize(Width, Height) s = GetImageResize(Width, Height)
h = s.Height h = s.Height
@@ -278,7 +288,7 @@ Namespace DownloadObjects
End With End With
End If End If
If Settings.FeedAddSessionToCaption Then info = $"[{Media.Session}] {info}" If Settings.FeedAddSessionToCaption And IsSession Then info = $"[{Media.Session}] {info}"
If Settings.FeedAddDateToCaption Then info &= $" ({Media.Date.ToStringDate(ADateTime.Formats.BaseDateTime)})" If Settings.FeedAddDateToCaption Then info &= $" ({Media.Date.ToStringDate(ADateTime.Formats.BaseDateTime)})"
LBL_INFO.Text = info LBL_INFO.Text = info
If Not Media.User Is Nothing AndAlso Not Media.User.HOST Is Nothing Then If Not Media.User Is Nothing AndAlso Not Media.User.HOST Is Nothing Then
@@ -314,6 +324,7 @@ Namespace DownloadObjects
For Each fItem As FeedSpecial In .Self For Each fItem As FeedSpecial In .Self
If Not fItem.IsFavorite Then If Not fItem.IsFavorite Then
DownloadFeedForm.AddNewFeedItem(BTT_FEED_ADD_SPEC, CONTEXT_DATA, fItem, Nothing, AddressOf Feed_SPEC_ADD) DownloadFeedForm.AddNewFeedItem(BTT_FEED_ADD_SPEC, CONTEXT_DATA, fItem, Nothing, AddressOf Feed_SPEC_ADD)
DownloadFeedForm.AddNewFeedItem(BTT_FEED_ADD_SPEC_REMOVE, CONTEXT_DATA, fItem, Nothing, AddressOf Feed_SPEC_ADD_REMOVE)
DownloadFeedForm.AddNewFeedItem(BTT_FEED_REMOVE_SPEC, CONTEXT_DATA, fItem, Nothing, AddressOf Feed_SPEC_REMOVE) DownloadFeedForm.AddNewFeedItem(BTT_FEED_REMOVE_SPEC, CONTEXT_DATA, fItem, Nothing, AddressOf Feed_SPEC_REMOVE)
End If End If
Next Next
@@ -333,6 +344,7 @@ Namespace DownloadObjects
#Region "Feed handlers" #Region "Feed handlers"
Private Sub Feed_FeedAdded(ByVal Source As FeedSpecialCollection, ByVal Feed As FeedSpecial) Private Sub Feed_FeedAdded(ByVal Source As FeedSpecialCollection, ByVal Feed As FeedSpecial)
DownloadFeedForm.AddNewFeedItem(BTT_FEED_ADD_SPEC, CONTEXT_DATA, Feed, My.Resources.RSSPic_512, AddressOf Feed_SPEC_ADD, True) DownloadFeedForm.AddNewFeedItem(BTT_FEED_ADD_SPEC, CONTEXT_DATA, Feed, My.Resources.RSSPic_512, AddressOf Feed_SPEC_ADD, True)
DownloadFeedForm.AddNewFeedItem(BTT_FEED_ADD_SPEC_REMOVE, CONTEXT_DATA, Feed, My.Resources.RSSPic_512, AddressOf Feed_SPEC_ADD_REMOVE, True)
DownloadFeedForm.AddNewFeedItem(BTT_FEED_REMOVE_SPEC, CONTEXT_DATA, Feed, My.Resources.RSSPic_512, AddressOf Feed_SPEC_REMOVE, True) DownloadFeedForm.AddNewFeedItem(BTT_FEED_REMOVE_SPEC, CONTEXT_DATA, Feed, My.Resources.RSSPic_512, AddressOf Feed_SPEC_REMOVE, True)
End Sub End Sub
Private Sub Feed_FeedRemoved(ByVal Source As FeedSpecialCollection, ByVal Feed As FeedSpecial) Private Sub Feed_FeedRemoved(ByVal Source As FeedSpecialCollection, ByVal Feed As FeedSpecial)
@@ -340,12 +352,20 @@ Namespace DownloadObjects
DownloadFeedForm.Feed_FeedRemoved(BTT_FEED_REMOVE_SPEC, CONTEXT_DATA, Feed) DownloadFeedForm.Feed_FeedRemoved(BTT_FEED_REMOVE_SPEC, CONTEXT_DATA, Feed)
End Sub End Sub
Private Sub Feed_SPEC_ADD(ByVal Source As ToolStripMenuItem, ByVal e As EventArgs) Private Sub Feed_SPEC_ADD(ByVal Source As ToolStripMenuItem, ByVal e As EventArgs)
Feed_SPEC_ADD_Impl(Source)
End Sub
Private Function Feed_SPEC_ADD_Impl(ByVal Source As ToolStripMenuItem) As FeedSpecial
Dim f As FeedSpecial = Source.Tag Dim f As FeedSpecial = Source.Tag
If Not f Is Nothing AndAlso Not f.Disposed Then f.Add(Media) If Not f Is Nothing AndAlso Not f.Disposed Then f.Add(Media) : Return f
Return Nothing
End Function
Private Sub Feed_SPEC_ADD_REMOVE(ByVal Source As ToolStripMenuItem, ByVal e As EventArgs)
Dim f As FeedSpecial = Feed_SPEC_ADD_Impl(Source)
If Not f Is Nothing Then RaiseEvent FeedAddWithRemove(Me, {f.Name}, Media, False)
End Sub End Sub
Private Sub Feed_SPEC_REMOVE(ByVal Source As ToolStripMenuItem, ByVal e As EventArgs) Private Sub Feed_SPEC_REMOVE(ByVal Source As ToolStripMenuItem, ByVal e As EventArgs)
Dim f As FeedSpecial = Source.Tag Dim f As FeedSpecial = Source.Tag
If Not f Is Nothing AndAlso Not f.Disposed Then f.Remove(Media) If Not f Is Nothing AndAlso Not f.Disposed Then f.Remove(Media) : RaiseEvent FeedAddWithRemove(Me, {f.Name}, Media, True)
End Sub End Sub
#End Region #End Region
#Region "Dispose" #Region "Dispose"
@@ -463,27 +483,64 @@ Namespace DownloadObjects
End Try End Try
End Sub End Sub
#End Region #End Region
#Region "Copy, Move"
Private Sub BTT_COPY_MOVE_TO_Click(sender As Object, e As EventArgs) Handles BTT_COPY_TO.Click, BTT_MOVE_TO.Click
Const MsgTitle$ = "Copy/Move checked files"
Try
If Not File.IsEmptyString Then
Dim isCopy As Boolean = sender Is BTT_COPY_TO
Dim moveOptions As FeedMoveCopyTo = Nothing
Dim ff As SFile = File
Dim result As Boolean = False
Using f As New FeedCopyToForm({File}, isCopy)
f.ShowDialog()
If f.DialogResult = DialogResult.OK Then moveOptions = f.Result
End Using
If Not moveOptions.Destination.IsEmptyString Then
ff.Path = moveOptions.Destination.Path
If isCopy Then
result = File.Copy(ff)
Else
RaiseEvent MediaMove(Me, moveOptions, result)
End If
If result Then MsgBoxE({$"File {IIf(isCopy, "copied", "moved")}{vbCr}Source: '{File}'{vbCr}Destination: '{ff}'", MsgTitle})
End If
End If
Catch ex As Exception
ErrorsDescriber.Execute(EDP.LogMessageValue, ex, MsgTitle)
End Try
End Sub
#End Region
#Region "Feed" #Region "Feed"
Private Sub BTT_FEED_ADD_FAV_Click(sender As Object, e As EventArgs) Handles BTT_FEED_ADD_FAV.Click Private Sub BTT_FEED_ADD_FAV_Click(sender As Object, e As EventArgs) Handles BTT_FEED_ADD_FAV.Click, BTT_FEED_ADD_FAV_REMOVE.Click
With Settings.Feeds.Favorite With Settings.Feeds.Favorite
If Not .Contains(Media) Then .Add(Media) If Not .Contains(Media) Then .Add(Media)
BTT_FEED_ADD_FAV.ControlChangeColor(True, False) BTT_FEED_ADD_FAV.ControlChangeColor(True, False)
If sender Is BTT_FEED_ADD_FAV_REMOVE Then RaiseEvent FeedAddWithRemove(Me, {FeedSpecial.FavoriteName}, Media, False)
End With End With
End Sub End Sub
Private Sub BTT_FEED_ADD_SPEC_Click(sender As Object, e As EventArgs) Handles BTT_FEED_ADD_SPEC.Click Private Sub BTT_FEED_ADD_SPEC_Click(sender As Object, e As EventArgs) Handles BTT_FEED_ADD_SPEC.Click, BTT_FEED_ADD_SPEC_REMOVE.Click
With FeedSpecialCollection.ChooseFeeds(True) With FeedSpecialCollection.ChooseFeeds(True)
If .ListExists Then .ForEach(Sub(f) f.Add(Media)) If .ListExists Then
.ForEach(Sub(f) f.Add(Media))
If sender Is BTT_FEED_ADD_SPEC_REMOVE Then RaiseEvent FeedAddWithRemove(Me, .Select(Function(f) f.Name), Media, False)
End If
End With End With
End Sub End Sub
Private Sub BTT_FEED_REMOVE_FAV_Click(sender As Object, e As EventArgs) Handles BTT_FEED_REMOVE_FAV.Click Private Sub BTT_FEED_REMOVE_FAV_Click(sender As Object, e As EventArgs) Handles BTT_FEED_REMOVE_FAV.Click
With Settings.Feeds.Favorite With Settings.Feeds.Favorite
If .Contains(Media) Then .Remove(Media) If .Contains(Media) Then .Remove(Media)
BTT_FEED_ADD_FAV.ControlChangeColor(True) BTT_FEED_ADD_FAV.ControlChangeColor(True)
RaiseEvent FeedAddWithRemove(Me, {FeedSpecial.FavoriteName}, Media, True)
End With End With
End Sub End Sub
Private Sub BTT_FEED_REMOVE_SPEC_Click(sender As Object, e As EventArgs) Handles BTT_FEED_REMOVE_SPEC.Click Private Sub BTT_FEED_REMOVE_SPEC_Click(sender As Object, e As EventArgs) Handles BTT_FEED_REMOVE_SPEC.Click
With FeedSpecialCollection.ChooseFeeds(False) With FeedSpecialCollection.ChooseFeeds(False)
If .ListExists Then .ForEach(Sub(f) f.Remove(Media)) If .ListExists Then
.ForEach(Sub(f) f.Remove(Media))
RaiseEvent FeedAddWithRemove(Me, .Select(Function(f) f.Name), Media, True)
End If
End With End With
End Sub End Sub
#End Region #End Region

View File

@@ -0,0 +1,31 @@
' 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 UTypes = SCrawler.API.Base.UserMedia.Types
Namespace DownloadObjects
Friend Structure FeedMoveCopyTo
Friend Destination As SFile
Friend SeparateVideoFolder As Boolean
Friend ReplaceUserProfile As Boolean
Friend ReplaceUserProfile_CreateIfNull As Boolean
Friend ReplaceUserProfile_Profile As API.Base.IUserData
Friend ReadOnly Property DestinationTrue(ByVal Media As TDownloader.UserMediaD) As SFile
Get
If SeparateVideoFolder Then
Dim f$ = Destination.PathWithSeparator
With Media.Data
If Not (.Type = UTypes.Picture Or .Type = UTypes.GIF) Then f &= "Video\"
End With
Return f
Else
Return Destination
End If
End Get
End Property
End Structure
End Namespace

View File

@@ -30,6 +30,7 @@ Namespace DownloadObjects
Friend Const FavoriteName As String = "Favorite" Friend Const FavoriteName As String = "Favorite"
Friend Const SpecialName As String = "Special" Friend Const SpecialName As String = "Special"
Private ReadOnly Items As List(Of UserMediaD) Private ReadOnly Items As List(Of UserMediaD)
Private _FilesUpdated As Boolean = False
Private _File As SFile Private _File As SFile
Friend ReadOnly Property File As SFile Friend ReadOnly Property File As SFile
Get Get
@@ -167,6 +168,26 @@ Namespace DownloadObjects
Return Item Return Item
End Function End Function
#End Region #End Region
#Region "UpdateDataByFile"
Friend Sub UpdateDataByFile(ByVal InitialFile As SFile, ByVal NewFile As SFile, ByVal MCTOptions As FeedMoveCopyTo)
Try
Dim indx% = Items.FindIndex(Function(ii) ii.Data.File = InitialFile)
If indx >= 0 Then
Dim m As UserMediaD = Items(indx)
Dim mm As UserMedia = m.Data
mm.File = NewFile
m = New UserMediaD(mm, If(MCTOptions.ReplaceUserProfile_Profile, m.User), m.Session, m.Date)
Items(indx) = m
_FilesUpdated = True
End If
Catch ex As Exception
ErrorsDescriber.Execute(EDP.SendToLog, ex, "[FeedSpecial.UpdateDataByFile]")
End Try
End Sub
Friend Sub UpdateIfRequired()
If _FilesUpdated Then Save() : _FilesUpdated = False
End Sub
#End Region
#Region "Add" #Region "Add"
Friend Overloads Function Add(ByVal Item As UserMediaD, Optional ByVal AutoSave As Boolean = True) As Boolean Friend Overloads Function Add(ByVal Item As UserMediaD, Optional ByVal AutoSave As Boolean = True) As Boolean
If Not Items.Contains(Item) Then If Not Items.Contains(Item) Then

View File

@@ -8,6 +8,7 @@
' but WITHOUT ANY WARRANTY ' but WITHOUT ANY WARRANTY
Imports PersonalUtilities.Tools Imports PersonalUtilities.Tools
Imports PersonalUtilities.Forms Imports PersonalUtilities.Forms
Imports ADB = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons
Namespace DownloadObjects Namespace DownloadObjects
Friend Class FeedSpecialCollection : Implements IEnumerable(Of FeedSpecial), IMyEnumerator(Of FeedSpecial) Friend Class FeedSpecialCollection : Implements IEnumerable(Of FeedSpecial), IMyEnumerator(Of FeedSpecial)
#Region "Events" #Region "Events"
@@ -115,33 +116,41 @@ Namespace DownloadObjects
End Sub End Sub
Private Sub Feeds_FeedDeleted(ByVal Source As FeedSpecialCollection, ByVal Feed As FeedSpecial) Private Sub Feeds_FeedDeleted(ByVal Source As FeedSpecialCollection, ByVal Feed As FeedSpecial)
RaiseEvent FeedRemoved(Me, Feed) RaiseEvent FeedRemoved(Me, Feed)
If Count > 0 Then Feeds.Remove(Feed) If Count > 0 And Not Feed Is Nothing Then Feeds.Remove(Feed)
End Sub End Sub
#End Region #End Region
#Region "ChooseFeeds" #Region "ChooseFeeds"
Friend Shared Function ChooseFeeds(ByVal AllowAdd As Boolean) As List(Of FeedSpecial) Friend Shared Function ChooseFeeds(ByVal AllowAdd As Boolean, Optional ByVal AdditText As String = Nothing,
Optional ByVal ReplaceOriginalText As Boolean = False) As List(Of FeedSpecial)
Try Try
Dim newFeed$ = String.Empty Dim newFeed$ = String.Empty
If Not AdditText.IsEmptyString And Not ReplaceOriginalText Then AdditText = $" {AdditText}"
Using f As New SimpleListForm(Of String)(Settings.Feeds.Select(Function(ff) ff.Name), Settings.Design) With { Using f As New SimpleListForm(Of String)(Settings.Feeds.Select(Function(ff) ff.Name), Settings.Design) With {
.DesignXMLNodeName = "FeedsChooserForm", .DesignXMLNodeName = "FeedsChooserForm",
.Icon = My.Resources.RSSIcon_32, .Icon = My.Resources.RSSIcon_32,
.FormText = "Feeds" .FormText = $"{IIf(ReplaceOriginalText, String.Empty, "Feeds")}{AdditText}"
} }
If AllowAdd Then f.AddFunction = Sub(ByVal sender As Object, ByVal e As SimpleListFormEventArgs) If AllowAdd Then
If newFeed.IsEmptyString Then f.Buttons = {ADB.Add, ADB.Clear}
Dim nf$ = InputBoxE("Enter a new feed name:", "New feed") f.AddFunction = Sub(ByVal sender As Object, ByVal e As SimpleListFormEventArgs)
If Not nf.IsEmptyString Then If newFeed.IsEmptyString Then
If Settings.Feeds.ListExists(Function(ff) ff.Name.StringToLower = nf.ToLower) Then Dim nf$ = InputBoxE("Enter a new feed name:", "New feed")
MsgBoxE({$"A feed named '{nf}' already exists", "New feed"}, vbCritical) If Not nf.IsEmptyString Then
Else If Settings.Feeds.ListExists(Function(ff) ff.Name.StringToLower = nf.ToLower) Then
newFeed = nf MsgBoxE({$"A feed named '{nf}' already exists", "New feed"}, vbCritical)
e.Item = nf e.Result = False
End If Else
Else newFeed = nf
MsgBoxE({"You can only create one feed at a time", "New feed"}, vbCritical) e.Item = nf
End If End If
End If Else
End Sub e.Result = False
End If
Else
MsgBoxE({"You can only create one feed at a time", "New feed"}, vbCritical)
End If
End Sub
End If
If f.ShowDialog = DialogResult.OK AndAlso f.DataResult.Count > 0 Then If f.ShowDialog = DialogResult.OK AndAlso f.DataResult.Count > 0 Then
If Not newFeed.IsEmptyString AndAlso f.DataResult.Contains(newFeed) Then Settings.Feeds.Add(newFeed) If Not newFeed.IsEmptyString AndAlso f.DataResult.Contains(newFeed) Then Settings.Feeds.Add(newFeed)
Return Settings.Feeds.Where(Function(ff) f.DataResult.Contains(ff.Name)).ToList Return Settings.Feeds.Where(Function(ff) f.DataResult.Contains(ff.Name)).ToList
@@ -165,7 +174,7 @@ Namespace DownloadObjects
End Get End Get
End Property End Property
#End Region #End Region
#Region "Add, Delete" #Region "Add, Delete, UpdateDataByFile, UpdateWhereDataReplaced"
Friend Function Add(ByVal Name As String) As Integer Friend Function Add(ByVal Name As String) As Integer
Dim i% = -1 Dim i% = -1
If Not Name.IsEmptyString Then If Not Name.IsEmptyString Then
@@ -174,7 +183,7 @@ Namespace DownloadObjects
Feeds.Last.Save() Feeds.Last.Save()
i = Count - 1 i = Count - 1
Else Else
i = Feeds.FindIndex(Function(f) f.Name = Name) i = IndexOf(Name)
If i = -1 Then If i = -1 Then
Feeds.Add(FeedSpecial.CreateSpecial(Name)) Feeds.Add(FeedSpecial.CreateSpecial(Name))
Feeds.Last.Save() Feeds.Last.Save()
@@ -184,7 +193,7 @@ Namespace DownloadObjects
End If End If
If i >= 0 Then If i >= 0 Then
Feeds.Sort(ComparerFeeds) Feeds.Sort(ComparerFeeds)
i = Feeds.FindIndex(Function(f) f.Name = Name) i = IndexOf(Name)
If i >= 0 Then RaiseEvent FeedAdded(Me, Feeds(i)) If i >= 0 Then RaiseEvent FeedAdded(Me, Feeds(i))
End If End If
Return i Return i
@@ -194,11 +203,14 @@ Namespace DownloadObjects
Dim i% = Feeds.IndexOf(Item) Dim i% = Feeds.IndexOf(Item)
If i >= 0 Then If i >= 0 Then
With Feeds(i) With Feeds(i)
Dim name$ = .Name
If .IsFavorite Then If .IsFavorite Then
result = .Clear result = .Clear
Else Else
result = .Delete result = .Delete
If result Then i = -1
If Feeds.Count > 0 Then i = Feeds.FindIndex(Function(f) f.Name = name And Not f.IsFavorite)
If result And i >= 0 Then
.Dispose() .Dispose()
Feeds.RemoveAt(i) Feeds.RemoveAt(i)
End If End If
@@ -207,6 +219,18 @@ Namespace DownloadObjects
End If End If
Return result Return result
End Function End Function
Friend Sub UpdateDataByFile(ByVal InitialFile As SFile, ByVal NewFile As SFile, ByVal MCTOptions As FeedMoveCopyTo)
If Count > 0 Then Feeds.ForEach(Sub(f) f.UpdateDataByFile(InitialFile, NewFile, MCTOptions))
End Sub
Friend Sub UpdateWhereDataReplaced()
If Count > 0 Then Feeds.ForEach(Sub(f) f.UpdateIfRequired())
End Sub
#End Region
#Region "IndexOf"
Friend Function IndexOf(ByVal Name As String) As Integer
If Feeds.Count > 0 Then Return Feeds.FindIndex(Function(f) f.Name = Name)
Return -1
End Function
#End Region #End Region
#Region "UpdateUsers" #Region "UpdateUsers"
Friend Sub UpdateUsers(ByVal InitialUser As UserInfo, ByVal NewUser As UserInfo) Friend Sub UpdateUsers(ByVal InitialUser As UserInfo, ByVal NewUser As UserInfo)

View File

@@ -138,6 +138,7 @@ Namespace DownloadObjects.STDownloader
Me.TXT_URLS.MaxLength = 2147483647 Me.TXT_URLS.MaxLength = 2147483647
Me.TXT_URLS.Multiline = True Me.TXT_URLS.Multiline = True
Me.TXT_URLS.Name = "TXT_URLS" Me.TXT_URLS.Name = "TXT_URLS"
Me.TXT_URLS.ScrollBars = System.Windows.Forms.ScrollBars.Both
Me.TXT_URLS.Size = New System.Drawing.Size(372, 180) Me.TXT_URLS.Size = New System.Drawing.Size(372, 180)
Me.TXT_URLS.TabIndex = 0 Me.TXT_URLS.TabIndex = 0
' '

View File

@@ -26,6 +26,7 @@ Namespace DownloadObjects
#End Region #End Region
#Region "Declarations" #Region "Declarations"
#Region "Files" #Region "Files"
Friend Const Name_SessionXML As String = "Session"
Friend Structure UserMediaD : Implements IComparable(Of UserMediaD), IEquatable(Of UserMediaD), IEContainerProvider Friend Structure UserMediaD : Implements IComparable(Of UserMediaD), IEquatable(Of UserMediaD), IEContainerProvider
#Region "XML Names" #Region "XML Names"
Private Const Name_Data As String = "Data" Private Const Name_Data As String = "Data"
@@ -40,7 +41,7 @@ Namespace DownloadObjects
Friend ReadOnly Data As UserMedia Friend ReadOnly Data As UserMedia
Friend ReadOnly UserInfo As UserInfo Friend ReadOnly UserInfo As UserInfo
Friend ReadOnly [Date] As Date Friend ReadOnly [Date] As Date
Friend ReadOnly Session As Integer Friend Session As Integer
Friend IsSavedPosts As Boolean Friend IsSavedPosts As Boolean
Friend Sub New(ByVal Data As UserMedia, ByVal User As IUserData, ByVal Session As Integer) Friend Sub New(ByVal Data As UserMedia, ByVal User As IUserData, ByVal Session As Integer)
Me.Data = Data Me.Data = Data
@@ -122,19 +123,29 @@ Namespace DownloadObjects
Return _FilesSessionActual Return _FilesSessionActual
End Get End Get
End Property End Property
Private _FilesSaving As Boolean = False
Friend Sub FilesSave() Friend Sub FilesSave()
While _FilesSaving Or _FilesUpdating : Thread.Sleep(100) : End While
Dim i% = 0
While Not FilesSaveImpl() And i < 10 : i += 1 : End While
End Sub
Private Function FilesSaveImpl() As Boolean
_FilesSaving = True
Try Try
If Settings.FeedStoreSessionsData And Files.Count > 0 Then If Settings.FeedStoreSessionsData And Files.Count > 0 Then
ClearSessions() ClearSessions()
Using x As New XmlFile With {.Name = "Session", .AllowSameNames = True} Using x As New XmlFile With {.Name = Name_SessionXML, .AllowSameNames = True}
x.AddRange(Files) x.AddRange(Files)
x.Save(FilesSessionActual) x.Save(FilesSessionActual)
End Using End Using
End If End If
Return True
Catch ex As Exception Catch ex As Exception
ErrorsDescriber.Execute(EDP.SendToLog, ex, "[DownloadObjects.TDownloader.FilesSave]") Return ErrorsDescriber.Execute(EDP.SendToLog, ex, "[DownloadObjects.TDownloader.FilesSave]", False)
Finally
_FilesSaving = False
End Try End Try
End Sub End Function
Private _FilesUpdating As Boolean = False Private _FilesUpdating As Boolean = False
Friend Sub FilesUpdatePendingUsers() Friend Sub FilesUpdatePendingUsers()
_FilesUpdating = True _FilesUpdating = True

View File

@@ -133,6 +133,7 @@ Namespace Editors
Me.CH_STD_SNAP_CACHE_PERMANENT = New System.Windows.Forms.CheckBox() Me.CH_STD_SNAP_CACHE_PERMANENT = New System.Windows.Forms.CheckBox()
Me.CH_STD_YT_CREATE_URL = New System.Windows.Forms.CheckBox() Me.CH_STD_YT_CREATE_URL = New System.Windows.Forms.CheckBox()
Me.CH_USE_DEF_ACC = New System.Windows.Forms.CheckBox() Me.CH_USE_DEF_ACC = New System.Windows.Forms.CheckBox()
Me.CH_NOTIFY_LOG = New System.Windows.Forms.CheckBox()
Me.TXT_CHANNELS_ROWS = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.TXT_CHANNELS_ROWS = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.TXT_CHANNELS_COLUMNS = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.TXT_CHANNELS_COLUMNS = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.CH_DOWN_IMAGES_NATIVE = New System.Windows.Forms.CheckBox() Me.CH_DOWN_IMAGES_NATIVE = New System.Windows.Forms.CheckBox()
@@ -157,6 +158,7 @@ Namespace Editors
Me.TXT_FEED_CENTER_IMAGE = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.TXT_FEED_CENTER_IMAGE = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.COLORS_FEED = New SCrawler.Editors.ColorPicker() Me.COLORS_FEED = New SCrawler.Editors.ColorPicker()
Me.CH_FEED_SHOW_FRIENDLY = New System.Windows.Forms.CheckBox() Me.CH_FEED_SHOW_FRIENDLY = New System.Windows.Forms.CheckBox()
Me.CH_FEED_SHOW_SPEC_MEDIAITEM = New System.Windows.Forms.CheckBox()
Me.TXT_YTDLP = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.TXT_YTDLP = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.TXT_FFMPEG = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.TXT_FFMPEG = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.TXT_CURL = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.TXT_CURL = New PersonalUtilities.Forms.Controls.TextBoxExtended()
@@ -177,7 +179,7 @@ Namespace Editors
Me.TAB_MAIN = New System.Windows.Forms.TabControl() Me.TAB_MAIN = New System.Windows.Forms.TabControl()
Me.TAB_ENVIR = New System.Windows.Forms.TabPage() Me.TAB_ENVIR = New System.Windows.Forms.TabPage()
Me.CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer() Me.CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer()
Me.CH_FEED_SHOW_SPEC_MEDIAITEM = New System.Windows.Forms.CheckBox() Me.CH_FEED_UP_FILE_LOC_MOVE = New System.Windows.Forms.CheckBox()
TP_BASIS = New System.Windows.Forms.TableLayoutPanel() TP_BASIS = New System.Windows.Forms.TableLayoutPanel()
TP_IMAGES = New System.Windows.Forms.TableLayoutPanel() TP_IMAGES = New System.Windows.Forms.TableLayoutPanel()
TP_FILE_NAME = New System.Windows.Forms.TableLayoutPanel() TP_FILE_NAME = New System.Windows.Forms.TableLayoutPanel()
@@ -1036,6 +1038,18 @@ Namespace Editors
TT_MAIN.SetToolTip(Me.CH_USE_DEF_ACC, "Use the default account if you deleted an account that you used for some users") TT_MAIN.SetToolTip(Me.CH_USE_DEF_ACC, "Use the default account if you deleted an account that you used for some users")
Me.CH_USE_DEF_ACC.UseVisualStyleBackColor = True Me.CH_USE_DEF_ACC.UseVisualStyleBackColor = True
' '
'CH_NOTIFY_LOG
'
Me.CH_NOTIFY_LOG.AutoSize = True
Me.CH_NOTIFY_LOG.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_NOTIFY_LOG.Location = New System.Drawing.Point(4, 212)
Me.CH_NOTIFY_LOG.Name = "CH_NOTIFY_LOG"
Me.CH_NOTIFY_LOG.Size = New System.Drawing.Size(568, 19)
Me.CH_NOTIFY_LOG.TabIndex = 8
Me.CH_NOTIFY_LOG.Text = "The log contains new data"
TT_MAIN.SetToolTip(Me.CH_NOTIFY_LOG, "Show a notification when the new data is added to the log.")
Me.CH_NOTIFY_LOG.UseVisualStyleBackColor = True
'
'TP_CHANNELS_IMGS 'TP_CHANNELS_IMGS
' '
TP_CHANNELS_IMGS.ColumnCount = 2 TP_CHANNELS_IMGS.ColumnCount = 2
@@ -1506,10 +1520,11 @@ Namespace Editors
TP_FEED.Controls.Add(Me.CH_FEED_OPEN_LAST_MODE, 0, 7) TP_FEED.Controls.Add(Me.CH_FEED_OPEN_LAST_MODE, 0, 7)
TP_FEED.Controls.Add(Me.CH_FEED_SHOW_FRIENDLY, 0, 8) TP_FEED.Controls.Add(Me.CH_FEED_SHOW_FRIENDLY, 0, 8)
TP_FEED.Controls.Add(Me.CH_FEED_SHOW_SPEC_MEDIAITEM, 0, 9) TP_FEED.Controls.Add(Me.CH_FEED_SHOW_SPEC_MEDIAITEM, 0, 9)
TP_FEED.Controls.Add(Me.CH_FEED_UP_FILE_LOC_MOVE, 0, 10)
TP_FEED.Dock = System.Windows.Forms.DockStyle.Fill TP_FEED.Dock = System.Windows.Forms.DockStyle.Fill
TP_FEED.Location = New System.Drawing.Point(0, 0) TP_FEED.Location = New System.Drawing.Point(0, 0)
TP_FEED.Name = "TP_FEED" TP_FEED.Name = "TP_FEED"
TP_FEED.RowCount = 11 TP_FEED.RowCount = 12
TP_FEED.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!)) TP_FEED.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
TP_FEED.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!)) TP_FEED.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
TP_FEED.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) TP_FEED.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
@@ -1520,6 +1535,7 @@ Namespace Editors
TP_FEED.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) TP_FEED.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
TP_FEED.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) TP_FEED.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
TP_FEED.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) TP_FEED.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
TP_FEED.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
TP_FEED.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) TP_FEED.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_FEED.Size = New System.Drawing.Size(576, 399) TP_FEED.Size = New System.Drawing.Size(576, 399)
TP_FEED.TabIndex = 0 TP_FEED.TabIndex = 0
@@ -1670,6 +1686,17 @@ Namespace Editors
Me.CH_FEED_SHOW_FRIENDLY.Text = "Show friendly names instead of usernames" Me.CH_FEED_SHOW_FRIENDLY.Text = "Show friendly names instead of usernames"
Me.CH_FEED_SHOW_FRIENDLY.UseVisualStyleBackColor = True Me.CH_FEED_SHOW_FRIENDLY.UseVisualStyleBackColor = True
' '
'CH_FEED_SHOW_SPEC_MEDIAITEM
'
Me.CH_FEED_SHOW_SPEC_MEDIAITEM.AutoSize = True
Me.CH_FEED_SHOW_SPEC_MEDIAITEM.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_FEED_SHOW_SPEC_MEDIAITEM.Location = New System.Drawing.Point(4, 247)
Me.CH_FEED_SHOW_SPEC_MEDIAITEM.Name = "CH_FEED_SHOW_SPEC_MEDIAITEM"
Me.CH_FEED_SHOW_SPEC_MEDIAITEM.Size = New System.Drawing.Size(568, 19)
Me.CH_FEED_SHOW_SPEC_MEDIAITEM.TabIndex = 9
Me.CH_FEED_SHOW_SPEC_MEDIAITEM.Text = "Show special feeds in media items"
Me.CH_FEED_SHOW_SPEC_MEDIAITEM.UseVisualStyleBackColor = True
'
'TAB_NOTIFY 'TAB_NOTIFY
' '
TAB_NOTIFY.Controls.Add(TP_NOTIFY_MAIN) TAB_NOTIFY.Controls.Add(TP_NOTIFY_MAIN)
@@ -1692,10 +1719,12 @@ Namespace Editors
TP_NOTIFY_MAIN.Controls.Add(Me.CH_NOTIFY_SAVED_POSTS, 0, 5) TP_NOTIFY_MAIN.Controls.Add(Me.CH_NOTIFY_SAVED_POSTS, 0, 5)
TP_NOTIFY_MAIN.Controls.Add(Me.CH_STD, 0, 6) TP_NOTIFY_MAIN.Controls.Add(Me.CH_STD, 0, 6)
TP_NOTIFY_MAIN.Controls.Add(Me.CH_STD_EVERY, 0, 7) TP_NOTIFY_MAIN.Controls.Add(Me.CH_STD_EVERY, 0, 7)
TP_NOTIFY_MAIN.Controls.Add(Me.CH_NOTIFY_LOG, 0, 8)
TP_NOTIFY_MAIN.Dock = System.Windows.Forms.DockStyle.Fill TP_NOTIFY_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
TP_NOTIFY_MAIN.Location = New System.Drawing.Point(0, 0) TP_NOTIFY_MAIN.Location = New System.Drawing.Point(0, 0)
TP_NOTIFY_MAIN.Name = "TP_NOTIFY_MAIN" TP_NOTIFY_MAIN.Name = "TP_NOTIFY_MAIN"
TP_NOTIFY_MAIN.RowCount = 9 TP_NOTIFY_MAIN.RowCount = 10
TP_NOTIFY_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
TP_NOTIFY_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) TP_NOTIFY_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
TP_NOTIFY_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) TP_NOTIFY_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
TP_NOTIFY_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) TP_NOTIFY_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
@@ -2140,16 +2169,17 @@ Namespace Editors
Me.CONTAINER_MAIN.TabIndex = 0 Me.CONTAINER_MAIN.TabIndex = 0
Me.CONTAINER_MAIN.TopToolStripPanelVisible = False Me.CONTAINER_MAIN.TopToolStripPanelVisible = False
' '
'CH_FEED_SHOW_SPEC_MEDIAITEM 'CH_FEED_UP_FILE_LOC_MOVE
' '
Me.CH_FEED_SHOW_SPEC_MEDIAITEM.AutoSize = True Me.CH_FEED_UP_FILE_LOC_MOVE.AutoSize = True
Me.CH_FEED_SHOW_SPEC_MEDIAITEM.Dock = System.Windows.Forms.DockStyle.Fill Me.CH_FEED_UP_FILE_LOC_MOVE.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_FEED_SHOW_SPEC_MEDIAITEM.Location = New System.Drawing.Point(4, 247) Me.CH_FEED_UP_FILE_LOC_MOVE.Location = New System.Drawing.Point(4, 273)
Me.CH_FEED_SHOW_SPEC_MEDIAITEM.Name = "CH_FEED_SHOW_SPEC_MEDIAITEM" Me.CH_FEED_UP_FILE_LOC_MOVE.Name = "CH_FEED_UP_FILE_LOC_MOVE"
Me.CH_FEED_SHOW_SPEC_MEDIAITEM.Size = New System.Drawing.Size(568, 19) Me.CH_FEED_UP_FILE_LOC_MOVE.Size = New System.Drawing.Size(568, 19)
Me.CH_FEED_SHOW_SPEC_MEDIAITEM.TabIndex = 9 Me.CH_FEED_UP_FILE_LOC_MOVE.TabIndex = 10
Me.CH_FEED_SHOW_SPEC_MEDIAITEM.Text = "Show special feeds in media items" Me.CH_FEED_UP_FILE_LOC_MOVE.Text = "Update file location when moved"
Me.CH_FEED_SHOW_SPEC_MEDIAITEM.UseVisualStyleBackColor = True TT_MAIN.SetToolTip(Me.CH_FEED_UP_FILE_LOC_MOVE, "The file location will be updated in the session data and in the feeds data")
Me.CH_FEED_UP_FILE_LOC_MOVE.UseVisualStyleBackColor = True
' '
'GlobalSettingsForm 'GlobalSettingsForm
' '
@@ -2341,5 +2371,7 @@ Namespace Editors
Private WithEvents CH_STD_YT_CREATE_URL As CheckBox Private WithEvents CH_STD_YT_CREATE_URL As CheckBox
Private WithEvents CH_USE_DEF_ACC As CheckBox Private WithEvents CH_USE_DEF_ACC As CheckBox
Private WithEvents CH_FEED_SHOW_SPEC_MEDIAITEM As CheckBox Private WithEvents CH_FEED_SHOW_SPEC_MEDIAITEM As CheckBox
Private WithEvents CH_NOTIFY_LOG As CheckBox
Private WithEvents CH_FEED_UP_FILE_LOC_MOVE As CheckBox
End Class End Class
End Namespace End Namespace

View File

@@ -74,6 +74,7 @@ Namespace Editors
CH_NOTIFY_SAVED_POSTS.Checked = .ShowNotificationsDownSavedPosts CH_NOTIFY_SAVED_POSTS.Checked = .ShowNotificationsDownSavedPosts
CH_STD.Checked = .ShowNotificationsSTDownloader CH_STD.Checked = .ShowNotificationsSTDownloader
CH_STD_EVERY.Checked = .ShowNotificationsSTDownloaderEveryDownload CH_STD_EVERY.Checked = .ShowNotificationsSTDownloaderEveryDownload
CH_NOTIFY_LOG.Checked = .ShowNotificationsLOG
'Defaults 'Defaults
CH_SEPARATE_VIDEO_FOLDER.Checked = .SeparateVideoFolder.Value CH_SEPARATE_VIDEO_FOLDER.Checked = .SeparateVideoFolder.Value
CH_DEF_TEMP.Checked = .DefaultTemporary CH_DEF_TEMP.Checked = .DefaultTemporary
@@ -142,6 +143,7 @@ Namespace Editors
CH_FEED_OPEN_LAST_MODE.Checked = .FeedOpenLastMode CH_FEED_OPEN_LAST_MODE.Checked = .FeedOpenLastMode
CH_FEED_SHOW_FRIENDLY.Checked = .FeedShowFriendlyNames CH_FEED_SHOW_FRIENDLY.Checked = .FeedShowFriendlyNames
CH_FEED_SHOW_SPEC_MEDIAITEM.Checked = .FeedShowSpecialFeedsMediaItem CH_FEED_SHOW_SPEC_MEDIAITEM.Checked = .FeedShowSpecialFeedsMediaItem
CH_FEED_UP_FILE_LOC_MOVE.Checked = .FeedMoveCopyUpdateFileLocationOnMove
End With End With
.MyFieldsChecker = New FieldsChecker .MyFieldsChecker = New FieldsChecker
With .MyFieldsCheckerE With .MyFieldsCheckerE
@@ -248,6 +250,7 @@ Namespace Editors
.ShowNotificationsDownSavedPosts.Value = CH_NOTIFY_SAVED_POSTS.Checked .ShowNotificationsDownSavedPosts.Value = CH_NOTIFY_SAVED_POSTS.Checked
.ShowNotificationsSTDownloader.Value = CH_STD.Checked .ShowNotificationsSTDownloader.Value = CH_STD.Checked
.ShowNotificationsSTDownloaderEveryDownload.Value = CH_STD_EVERY.Checked .ShowNotificationsSTDownloaderEveryDownload.Value = CH_STD_EVERY.Checked
.ShowNotificationsLOG.Value = CH_NOTIFY_LOG.Checked
'Defaults 'Defaults
.SeparateVideoFolder.Value = CH_SEPARATE_VIDEO_FOLDER.Checked .SeparateVideoFolder.Value = CH_SEPARATE_VIDEO_FOLDER.Checked
.DefaultTemporary.Value = CH_DEF_TEMP.Checked .DefaultTemporary.Value = CH_DEF_TEMP.Checked
@@ -314,10 +317,10 @@ Namespace Editors
.FeedOpenLastMode.Value = CH_FEED_OPEN_LAST_MODE.Checked .FeedOpenLastMode.Value = CH_FEED_OPEN_LAST_MODE.Checked
.FeedShowFriendlyNames.Value = CH_FEED_SHOW_FRIENDLY.Checked .FeedShowFriendlyNames.Value = CH_FEED_SHOW_FRIENDLY.Checked
.FeedShowSpecialFeedsMediaItem.Value = CH_FEED_SHOW_SPEC_MEDIAITEM.Checked .FeedShowSpecialFeedsMediaItem.Value = CH_FEED_SHOW_SPEC_MEDIAITEM.Checked
.FeedMoveCopyUpdateFileLocationOnMove.Value = CH_FEED_UP_FILE_LOC_MOVE.Checked
FeedParametersChanged = .FeedDataRows.ChangesDetected Or .FeedDataColumns.ChangesDetected Or FeedParametersChanged = .FeedDataRows.ChangesDetected Or .FeedDataColumns.ChangesDetected Or
.FeedEndless.ChangesDetected Or .FeedStoreSessionsData.ChangesDetected Or .FeedEndless.ChangesDetected Or .FeedBackColor.ChangesDetected Or
.FeedBackColor.ChangesDetected Or .FeedForeColor.ChangesDetected Or .FeedForeColor.ChangesDetected Or .FeedCenterImage.ChangesDetected
.FeedCenterImage.ChangesDetected
.EndUpdate() .EndUpdate()
End With End With

View File

@@ -213,7 +213,7 @@ Namespace Editors
Dim loAdded As Boolean = False Dim loAdded As Boolean = False
Dim pArr() As Boolean Dim pArr() As Boolean
If .PropList.Exists(Function(p) If(p.Options?.IsAuth, False)) Then pArr = {True, False} Else pArr = {False} If .PropList.Exists(Function(p) If(p.Options?.IsAuth, False)) Then pArr = {True, False} Else pArr = {False}
.PropList.Sort() If .PropList.Exists(Function(p) p.ControlNumber >= 0) Then .PropList.Sort()
For Each pAuth As Boolean In pArr For Each pAuth As Boolean In pArr
For Each prop As PropertyValueHost In .PropList For Each prop As PropertyValueHost In .PropList
If Not prop.Options Is Nothing Then If Not prop.Options Is Nothing Then

View File

@@ -430,6 +430,7 @@ Namespace Editors
If Not UserInstance Is Nothing Then If Not UserInstance Is Nothing Then
With DirectCast(UserInstance, UserDataBase) With DirectCast(UserInstance, UserDataBase)
.User = User .User = User
.ResetHost()
Dim setFriendly As Boolean = True Dim setFriendly As Boolean = True
If FriendlyNameIsSiteName Then If FriendlyNameIsSiteName Then
If Not FriendlyNameChanged Then If Not FriendlyNameChanged Then
@@ -590,7 +591,7 @@ CloseForm:
End Sub End Sub
Private _AccountsRefilling As Boolean = False Private _AccountsRefilling As Boolean = False
Private Sub CMB_ACCOUNT_ActionSelectedItemChanged(ByVal Sender As Object, ByVal e As EventArgs, ByVal Item As ListViewItem) Handles CMB_ACCOUNT.ActionSelectedItemChanged Private Sub CMB_ACCOUNT_ActionSelectedItemChanged(ByVal Sender As Object, ByVal e As EventArgs, ByVal Item As ListViewItem) Handles CMB_ACCOUNT.ActionSelectedItemChanged
If Not _AccountsRefilling Then SetParamsBySite(False) If Not _AccountsRefilling And UserInstance Is Nothing Then SetParamsBySite(False)
End Sub End Sub
Private Sub CH_TEMP_CheckedChanged(sender As Object, e As EventArgs) Handles CH_TEMP.CheckedChanged Private Sub CH_TEMP_CheckedChanged(sender As Object, e As EventArgs) Handles CH_TEMP.CheckedChanged
If CH_TEMP.Checked Then CH_FAV.Checked = False : CH_READY_FOR_DOWN.Checked = False If CH_TEMP.Checked Then CH_FAV.Checked = False : CH_READY_FOR_DOWN.Checked = False

View File

@@ -139,6 +139,7 @@ Partial Public Class MainFrame : Inherits System.Windows.Forms.Form
Me.BTT_TRAY_FEED_SHOW = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_TRAY_FEED_SHOW = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_TRAY_CHANNELS = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_TRAY_CHANNELS = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_TRAY_DOWNLOADER = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_TRAY_DOWNLOADER = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_TRAY_SCHEDULER = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_TRAY_SHOW_HIDE = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_TRAY_SHOW_HIDE = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_TRAY_CLOSE = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_TRAY_CLOSE = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_TRAY_CLOSE_NO_SCRIPT = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_TRAY_CLOSE_NO_SCRIPT = New System.Windows.Forms.ToolStripMenuItem()
@@ -987,9 +988,9 @@ Partial Public Class MainFrame : Inherits System.Windows.Forms.Form
' '
'TRAY_CONTEXT 'TRAY_CONTEXT
' '
Me.TRAY_CONTEXT.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.BTT_TRAY_PAUSE_AUTOMATION, Me.BTT_TRAY_SILENT_MODE, Me.BTT_TRAY_FEED_SHOW, Me.BTT_TRAY_CHANNELS, Me.BTT_TRAY_DOWNLOADER, TRAY_SEP_1, Me.BTT_TRAY_SHOW_HIDE, TRAY_SEP_2, Me.BTT_TRAY_CLOSE, Me.BTT_TRAY_CLOSE_NO_SCRIPT}) Me.TRAY_CONTEXT.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.BTT_TRAY_PAUSE_AUTOMATION, Me.BTT_TRAY_SILENT_MODE, Me.BTT_TRAY_FEED_SHOW, Me.BTT_TRAY_CHANNELS, Me.BTT_TRAY_DOWNLOADER, Me.BTT_TRAY_SCHEDULER, TRAY_SEP_1, Me.BTT_TRAY_SHOW_HIDE, TRAY_SEP_2, Me.BTT_TRAY_CLOSE, Me.BTT_TRAY_CLOSE_NO_SCRIPT})
Me.TRAY_CONTEXT.Name = "TRAY_CONTEXT" Me.TRAY_CONTEXT.Name = "TRAY_CONTEXT"
Me.TRAY_CONTEXT.Size = New System.Drawing.Size(171, 192) Me.TRAY_CONTEXT.Size = New System.Drawing.Size(171, 214)
' '
'BTT_TRAY_PAUSE_AUTOMATION 'BTT_TRAY_PAUSE_AUTOMATION
' '
@@ -1032,6 +1033,13 @@ Partial Public Class MainFrame : Inherits System.Windows.Forms.Form
Me.BTT_TRAY_DOWNLOADER.Size = New System.Drawing.Size(170, 22) Me.BTT_TRAY_DOWNLOADER.Size = New System.Drawing.Size(170, 22)
Me.BTT_TRAY_DOWNLOADER.Text = "Downloader" Me.BTT_TRAY_DOWNLOADER.Text = "Downloader"
' '
'BTT_TRAY_SCHEDULER
'
Me.BTT_TRAY_SCHEDULER.Image = Global.SCrawler.My.Resources.Resources.ScriptPic_32
Me.BTT_TRAY_SCHEDULER.Name = "BTT_TRAY_SCHEDULER"
Me.BTT_TRAY_SCHEDULER.Size = New System.Drawing.Size(170, 22)
Me.BTT_TRAY_SCHEDULER.Text = "Scheduler"
'
'BTT_TRAY_SHOW_HIDE 'BTT_TRAY_SHOW_HIDE
' '
Me.BTT_TRAY_SHOW_HIDE.Image = Global.SCrawler.My.Resources.Resources.ApplicationPic_16 Me.BTT_TRAY_SHOW_HIDE.Image = Global.SCrawler.My.Resources.Resources.ApplicationPic_16
@@ -1181,4 +1189,5 @@ Partial Public Class MainFrame : Inherits System.Windows.Forms.Form
Private WithEvents MENU_INFO_SHOW_QUEUE As ToolStripMenuItem Private WithEvents MENU_INFO_SHOW_QUEUE As ToolStripMenuItem
Private WithEvents BTT_DOWN_SPEC As ToolStripKeyMenuItem Private WithEvents BTT_DOWN_SPEC As ToolStripKeyMenuItem
Private WithEvents BTT_SHOW_FILTER_ADV As ToolStripMenuItem Private WithEvents BTT_SHOW_FILTER_ADV As ToolStripMenuItem
Private WithEvents BTT_TRAY_SCHEDULER As ToolStripMenuItem
End Class End Class

View File

@@ -484,10 +484,11 @@ CloseResume:
MyUserMetrics.FormShow(EDP.LogMessageValue) MyUserMetrics.FormShow(EDP.LogMessageValue)
End Sub End Sub
#End Region #End Region
Private Sub ShowFeed() Handles BTT_FEED.Click, BTT_TRAY_FEED_SHOW.Click Friend Sub ShowFeed() Handles BTT_FEED.Click, BTT_TRAY_FEED_SHOW.Click
If MyFeed Is Nothing Then If MyFeed Is Nothing Then
MyFeed = New DownloadFeedForm MyFeed = New DownloadFeedForm
AddHandler Downloader.FeedFilesChanged, AddressOf MyFeed.Downloader_FilesChanged AddHandler Downloader.FeedFilesChanged, AddressOf MyFeed.Downloader_FilesChanged
AddHandler MyFeed.UsersAdded, AddressOf OnUsersAddedHandler
If Not MySavedPosts Is Nothing Then AddHandler MySavedPosts.FeedFilesChanged, AddressOf MyFeed.Downloader_FilesChanged If Not MySavedPosts Is Nothing Then AddHandler MySavedPosts.FeedFilesChanged, AddressOf MyFeed.Downloader_FilesChanged
End If End If
If MyFeed.Visible Then MyFeed.BringToFront() Else MyFeed.Show() If MyFeed.Visible Then MyFeed.BringToFront() Else MyFeed.Show()
@@ -603,7 +604,7 @@ CloseResume:
ControlInvokeFast(Toolbar_TOP, BTT_DOWN_AUTOMATION_PAUSE, Sub() BTT_DOWN_AUTOMATION_PAUSE.Visible = b) ControlInvokeFast(Toolbar_TOP, BTT_DOWN_AUTOMATION_PAUSE, Sub() BTT_DOWN_AUTOMATION_PAUSE.Visible = b)
ControlInvokeFast(Me, Sub() BTT_TRAY_PAUSE_AUTOMATION.Visible = b) ControlInvokeFast(Me, Sub() BTT_TRAY_PAUSE_AUTOMATION.Visible = b)
End Sub End Sub
Private Async Sub BTT_DOWN_AUTOMATION_Click(sender As Object, e As EventArgs) Handles BTT_DOWN_AUTOMATION.Click Private Async Sub BTT_DOWN_AUTOMATION_Click(sender As Object, e As EventArgs) Handles BTT_DOWN_AUTOMATION.Click, BTT_TRAY_SCHEDULER.Click
Try Try
Using f As New SchedulerEditorForm : f.ShowDialog() : End Using Using f As New SchedulerEditorForm : f.ShowDialog() : End Using
Await Settings.Automation.Start(False) Await Settings.Automation.Start(False)
@@ -842,7 +843,7 @@ CloseResume:
#End Region #End Region
#End Region #End Region
Private Sub BTT_LOG_Click(sender As Object, e As EventArgs) Handles BTT_LOG.Click Private Sub BTT_LOG_Click(sender As Object, e As EventArgs) Handles BTT_LOG.Click
MyMainLOG_ShowForm(Settings.Design,,,, Sub() MainFrameObj.UpdateLogButton()) MainFrameObj.ShowLog()
End Sub End Sub
Private Sub BTT_VERSION_INFO_Click(sender As Object, e As EventArgs) Handles BTT_VERSION_INFO.Click Private Sub BTT_VERSION_INFO_Click(sender As Object, e As EventArgs) Handles BTT_VERSION_INFO.Click
CheckVersion(True) CheckVersion(True)

View File

@@ -19,6 +19,11 @@ Friend Class MainFrameObjects : Implements INotificator
MF = f MF = f
Notificator = New NotificationsManager Notificator = New NotificationsManager
PauseButtons = New DownloadObjects.AutoDownloaderPauseButtons(DownloadObjects.AutoDownloaderPauseButtons.ButtonsPlace.MainFrame) PauseButtons = New DownloadObjects.AutoDownloaderPauseButtons(DownloadObjects.AutoDownloaderPauseButtons.ButtonsPlace.MainFrame)
ProgramLogInitialize()
With ProgramLog
AddHandler .TextAdded, AddressOf ProgramLog_TextAdded
AddHandler .TextCleared, AddressOf ProgramLog_TextCleared
End With
End Sub End Sub
#Region "Users" #Region "Users"
Friend Sub FocusUser(ByVal Key As String, Optional ByVal ActivateForm As Boolean = False) Friend Sub FocusUser(ByVal Key As String, Optional ByVal ActivateForm As Boolean = False)
@@ -65,15 +70,26 @@ Friend Class MainFrameObjects : Implements INotificator
Friend Function GetUserListProvider(ByVal WithCollections As Boolean) As IFormatProvider Friend Function GetUserListProvider(ByVal WithCollections As Boolean) As IFormatProvider
Return MF.GetUserListProvider(WithCollections) Return MF.GetUserListProvider(WithCollections)
End Function End Function
Friend Sub ShowLog()
MyMainLOG_ShowForm(Settings.Design,,,, Sub()
UpdateLogButton()
LogFormClosed()
End Sub)
End Sub
#End Region #End Region
#Region "Notifications" #Region "Notifications"
Private Sub INotificator_ShowNotification(ByVal Text As String, ByVal Image As SFile) Implements INotificator.ShowNotification Private Sub INotificator_ShowNotification(ByVal Text As String, ByVal Image As SFile) Implements INotificator.ShowNotification
If Settings.ProcessNotification(NotifyObj.STDownloader) Then Notification.ShowNotification(Text,, $"{NotificationInternalKey}_{NotifyObj.STDownloader}", Image) If Settings.ProcessNotification(NotifyObj.STDownloader) Then Notification.ShowNotification(Text,, $"{NotificationInternalKey}_{NotifyObj.STDownloader}", Image)
End Sub End Sub
Private Const NotificationInternalKey As String = "NotificationInternalKey" Private Const NotificationInternalKey As String = "NotificationInternalKey"
Private Const DEF_BTT_FEED As String = "DEF_BTT_FEED"
Private Const DEF_BTT_DISABLE As String = "DEF_BTT_DISABLE"
Friend Sub ShowNotification(ByVal Sender As NotifyObj, ByVal Message As String) Friend Sub ShowNotification(ByVal Sender As NotifyObj, ByVal Message As String)
If Settings.ProcessNotification(Sender) Then If Settings.ProcessNotification(Sender) Then
Using n As New Notification(Message) With {.Key = $"{NotificationInternalKey}_{Sender}"} : n.Show() : End Using Dim b As List(Of IButton) = Nothing
If Sender = NotifyObj.Profiles Or Sender = NotifyObj.AutoDownloader Or Sender = NotifyObj.SavedPosts Then _
b = New List(Of IButton) From {New ToastButton(DEF_BTT_FEED, "Feed"), New ToastButton(DEF_BTT_DISABLE, "Disable")}
Using n As New Notification(Message) With {.Key = $"{NotificationInternalKey}_{Sender}", .Buttons = b} : n.Show() : End Using
End If End If
End Sub End Sub
Friend Sub ClearNotifications() Implements INotificator.Clear Friend Sub ClearNotifications() Implements INotificator.Clear
@@ -83,11 +99,16 @@ Friend Class MainFrameObjects : Implements INotificator
If Not Key.IsEmptyString Then If Not Key.IsEmptyString Then
Dim found As Boolean = False Dim found As Boolean = False
Dim activateForm As Boolean = False Dim activateForm As Boolean = False
If Key.StartsWith(NotificationInternalKey) Then If Key = DEF_BTT_FEED Then
ControlInvokeFast(MF, AddressOf MF.ShowFeed, EDP.LogMessageValue)
ElseIf Key = DEF_BTT_DISABLE Then
Exit Sub
ElseIf Key.StartsWith(NotificationInternalKey) Then
Select Case Key Select Case Key
Case $"{NotificationInternalKey}_{NotifyObj.Channels}" : MF.MyChannels.FormShowS() Case $"{NotificationInternalKey}_{NotifyObj.Channels}" : MF.MyChannels.FormShowS()
Case $"{NotificationInternalKey}_{NotifyObj.SavedPosts}" : MF.MySavedPosts.FormShowS() Case $"{NotificationInternalKey}_{NotifyObj.SavedPosts}" : MF.MySavedPosts.FormShowS()
Case $"{NotificationInternalKey}_{NotifyObj.STDownloader}" : VideoDownloader.FormShowS() Case $"{NotificationInternalKey}_{NotifyObj.STDownloader}" : VideoDownloader.FormShowS()
Case $"{NotificationInternalKey}_{NotifyObj.LOG}" : ControlInvokeFast(MF, AddressOf ShowLog, EDP.LogMessageValue)
Case Else : Focus(True) Case Else : Focus(True)
End Select End Select
ElseIf Settings.Automation Is Nothing OrElse Not Settings.Automation.NotificationClicked(Key, found, activateForm) Then ElseIf Settings.Automation Is Nothing OrElse Not Settings.Automation.NotificationClicked(Key, found, activateForm) Then
@@ -100,4 +121,16 @@ Friend Class MainFrameObjects : Implements INotificator
End If End If
End Sub End Sub
#End Region #End Region
#Region "LOG events support"
Private _LogNotificationsEnabled As Boolean = True
Private Sub ProgramLog_TextAdded(ByVal Sender As Object, ByVal e As EventArgs)
If _LogNotificationsEnabled Then _LogNotificationsEnabled = False : ShowNotification(NotifyObj.LOG, "There is new data in the log")
End Sub
Private Sub ProgramLog_TextCleared(ByVal Sender As Object, ByVal e As EventArgs)
_LogNotificationsEnabled = True
End Sub
Friend Sub LogFormClosed()
_LogNotificationsEnabled = True
End Sub
#End Region
End Class End Class

View File

@@ -16,10 +16,12 @@ Imports SCrawler.DownloadObjects
Friend Module MainMod Friend Module MainMod
Friend Settings As SettingsCLS Friend Settings As SettingsCLS
Friend Const SettingsFolderName As String = XML.XmlFile.SettingsFolder Friend Const SettingsFolderName As String = XML.XmlFile.SettingsFolder
Friend Const UserRegexDefaultPattern As String = "{0}([^/\?&]+)"
Friend ReadOnly LinkPattern As RParams = RParams.DMS("[htps:]{0,6}[/]{0,2}(.+)", 1) Friend ReadOnly LinkPattern As RParams = RParams.DMS("[htps:]{0,6}[/]{0,2}(.+)", 1)
Friend ReadOnly FilesPattern As RParams = RParams.DM("[^\./]+?\.\w+", 1, EDP.ReturnValue) Friend ReadOnly FilesPattern As RParams = RParams.DM("[^\./]+?\.\w+", 1, EDP.ReturnValue)
Friend Delegate Sub NotificationEventHandler(ByVal Sender As SettingsCLS.NotificationObjects, ByVal Message As String) Friend Delegate Sub NotificationEventHandler(ByVal Sender As SettingsCLS.NotificationObjects, ByVal Message As String)
Friend Delegate Sub UserDownloadStateChangedEventHandler(ByVal User As IUserData, ByVal IsDownloading As Boolean) Friend Delegate Sub UserDownloadStateChangedEventHandler(ByVal User As IUserData, ByVal IsDownloading As Boolean)
Friend Delegate Sub UsersAddedEventHandler(ByVal StartIndex As Integer)
Friend Delegate Function PathMoverHandler(ByVal User As UserInfo, ByVal DestinationPattern As SFile) As SFile Friend Delegate Function PathMoverHandler(ByVal User As UserInfo, ByVal DestinationPattern As SFile) As SFile
Friend Const LVI_TempOption As String = "Temp" Friend Const LVI_TempOption As String = "Temp"
Friend Const LVI_FavOption As String = "Favorite" Friend Const LVI_FavOption As String = "Favorite"

View File

@@ -32,6 +32,6 @@ Imports System.Runtime.InteropServices
' by using the '*' as shown below: ' by using the '*' as shown below:
' <Assembly: AssemblyVersion("1.0.*")> ' <Assembly: AssemblyVersion("1.0.*")>
<Assembly: AssemblyVersion("2023.12.15.0")> <Assembly: AssemblyVersion("2024.2.25.0")>
<Assembly: AssemblyFileVersion("2023.12.15.0")> <Assembly: AssemblyFileVersion("2024.2.25.0")>
<Assembly: NeutralResourcesLanguage("en")> <Assembly: NeutralResourcesLanguage("en")>

View File

@@ -120,6 +120,16 @@ Namespace My.Resources
End Get End Get
End Property End Property
'''<summary>
''' Looks up a localized resource of type System.Drawing.Bitmap.
'''</summary>
Friend ReadOnly Property CutPic_48() As System.Drawing.Bitmap
Get
Dim obj As Object = ResourceManager.GetObject("CutPic_48", resourceCulture)
Return CType(obj,System.Drawing.Bitmap)
End Get
End Property
'''<summary> '''<summary>
''' Looks up a localized resource of type System.Drawing.Bitmap. ''' Looks up a localized resource of type System.Drawing.Bitmap.
'''</summary> '''</summary>

View File

@@ -220,4 +220,7 @@
<data name="BrushToolPic_16" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="BrushToolPic_16" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Content\Pictures\BrushToolPic_16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> <value>..\Content\Pictures\BrushToolPic_16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data> </data>
<data name="CutPic_48" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Content\Pictures\CutPic_48.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root> </root>

View File

@@ -12,7 +12,7 @@ Imports PersonalUtilities.Functions.XML
Imports PersonalUtilities.Functions.XML.Objects Imports PersonalUtilities.Functions.XML.Objects
Imports PersonalUtilities.Tools.WEB.GitHub Imports PersonalUtilities.Tools.WEB.GitHub
Namespace Plugin.Hosts Namespace Plugin.Hosts
Friend Class PluginHost Friend Class PluginHost : Implements IDisposable
Friend Const PluginsPath As String = "Plugins\" Friend Const PluginsPath As String = "Plugins\"
Friend ReadOnly Property Settings As SettingsHostCollection Friend ReadOnly Property Settings As SettingsHostCollection
Friend ReadOnly Property Name As String Friend ReadOnly Property Name As String
@@ -25,6 +25,16 @@ Namespace Plugin.Hosts
Return Settings.Key Return Settings.Key
End Get End Get
End Property End Property
Friend ReadOnly Property Replacer As ReplaceInternalPluginAttribute
Get
Return Settings.Default.Replacer
End Get
End Property
Friend ReadOnly Property IsReplacer As Boolean
Get
Return Settings.Default.IsReplacer
End Get
End Property
Friend ReadOnly Property Exists As Boolean Friend ReadOnly Property Exists As Boolean
Get Get
Return Not Settings Is Nothing Return Not Settings Is Nothing
@@ -113,5 +123,22 @@ Namespace Plugin.Hosts
Return Nothing Return Nothing
End Try End Try
End Function End Function
#Region "IDisposable Support"
Private disposedValue As Boolean = False
Protected Overridable Overloads Sub Dispose(ByVal disposing As Boolean)
If Not disposedValue Then
If disposing Then Settings.Dispose()
disposedValue = True
End If
End Sub
Protected Overrides Sub Finalize()
Dispose(False)
MyBase.Finalize()
End Sub
Friend Overloads Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region
End Class End Class
End Namespace End Namespace

View File

@@ -23,6 +23,7 @@ Namespace Plugin.Hosts
Private ReadOnly Keeper As SettingsHost Private ReadOnly Keeper As SettingsHost
Protected Source As Object 'ReadOnly Protected Source As Object 'ReadOnly
Protected Member As MemberInfo Protected Member As MemberInfo
Private ReadOnly MemberRef As MemberInfo
Friend ReadOnly Options As PropertyOption Friend ReadOnly Options As PropertyOption
Friend Overridable ReadOnly Property Name As String Friend Overridable ReadOnly Property Name As String
Protected _Type As Type Protected _Type As Type
@@ -41,7 +42,7 @@ Namespace Plugin.Hosts
#End Region #End Region
#Region "Control" #Region "Control"
Friend Property Control As Control Friend Property Control As Control
Protected ControlNumber As Integer = -1 Friend Property ControlNumber As Integer = -1
Friend ReadOnly Property ControlHeight As Integer Friend ReadOnly Property ControlHeight As Integer
Get Get
If Not Control Is Nothing Then If Not Control Is Nothing Then
@@ -245,13 +246,12 @@ Namespace Plugin.Hosts
Me.Keeper = Keeper Me.Keeper = Keeper
Source = PropertySource Source = PropertySource
Name = Member.Name Name = Member.Name
MemberRef = Member
ControlNumber = If(Member.GetCustomAttribute(Of ControlNumber)()?.PropertyNumber, -1) ControlNumber = If(Member.GetCustomAttribute(Of ControlNumber)()?.PropertyNumber, -1)
If DirectCast(Member, PropertyInfo).PropertyType Is GetType(PropertyValue) Then If DirectCast(Member, PropertyInfo).PropertyType Is GetType(PropertyValue) Then
ExternalValue = DirectCast(DirectCast(Member, PropertyInfo).GetValue(Source), PropertyValue) UpdateMember()
_Value = ExternalValue.Value
AddHandler ExternalValue.ValueChanged, AddressOf ExternalValueChanged
Options = Member.GetCustomAttribute(Of PropertyOption)() Options = Member.GetCustomAttribute(Of PropertyOption)()
IsTaskCounter = Not Member.GetCustomAttribute(Of TaskCounter)() Is Nothing IsTaskCounter = Not Member.GetCustomAttribute(Of TaskCounter)() Is Nothing
_XmlName = If(Member.GetCustomAttribute(Of PXML)()?.ElementName, String.Empty) _XmlName = If(Member.GetCustomAttribute(Of PXML)()?.ElementName, String.Empty)
@@ -274,9 +274,22 @@ Namespace Plugin.Hosts
Next Next
End If End If
End Sub End Sub
Friend Sub UpdateMember()
If Not ExternalValue Is Nothing Then
Try : RemoveHandler ExternalValue.ValueChanged, AddressOf ExternalValueChanged : Catch : End Try
End If
_ExternalValue = DirectCast(DirectCast(MemberRef, PropertyInfo).GetValue(Source), PropertyValue)
_Value = ExternalValue.Value
AddHandler ExternalValue.ValueChanged, AddressOf ExternalValueChanged
End Sub
#End Region #End Region
#Region "Value" #Region "Value"
Protected ReadOnly Property ExternalValue As PropertyValue Private _ExternalValue As PropertyValue = Nothing
Private ReadOnly Property ExternalValue As PropertyValue
Get
Return _ExternalValue
End Get
End Property
Friend ReadOnly Property XValue As IXMLValue Friend ReadOnly Property XValue As IXMLValue
Protected _Value As Object Protected _Value As Object
Friend Overloads Property Value As Object Implements IPropertyValue.Value Friend Overloads Property Value As Object Implements IPropertyValue.Value

View File

@@ -107,6 +107,12 @@ Namespace Plugin.Hosts
#End Region #End Region
#Region "Host declarations" #Region "Host declarations"
Friend ReadOnly Property Source As ISiteSettings Friend ReadOnly Property Source As ISiteSettings
Friend Property Replacer As ReplaceInternalPluginAttribute = Nothing
Friend ReadOnly Property IsReplacer As Boolean
Get
Return Not Replacer Is Nothing AndAlso (Not Replacer.PluginKey.IsEmptyString Or Not Replacer.SiteName.IsEmptyString)
End Get
End Property
Friend ReadOnly Property PropList As List(Of PropertyValueHost) Friend ReadOnly Property PropList As List(Of PropertyValueHost)
Friend ReadOnly Property Name As String Friend ReadOnly Property Name As String
Get Get
@@ -143,6 +149,9 @@ Namespace Plugin.Hosts
End Set End Set
End Property End Property
Friend ReadOnly Property [Default] As Boolean Friend ReadOnly Property [Default] As Boolean
Friend Sub DefaultInstanceChanged()
If PropList.Count > 0 Then PropList.ForEach(Sub(p) p.UpdateMember())
End Sub
Friend ReadOnly Property IsSeparatedTasks As Boolean = False Friend ReadOnly Property IsSeparatedTasks As Boolean = False
Friend ReadOnly Property IsSavedPostsCompatible As Boolean = False Friend ReadOnly Property IsSavedPostsCompatible As Boolean = False
Private ReadOnly _TaskCountDefined As Integer? = Nothing Private ReadOnly _TaskCountDefined As Integer? = Nothing
@@ -248,6 +257,8 @@ Namespace Plugin.Hosts
HasSpecialOptions = True HasSpecialOptions = True
End If End If
End With End With
ElseIf TypeOf a Is ReplaceInternalPluginAttribute Then
Replacer = a
End If End If
Next Next
End If End If

View File

@@ -17,7 +17,7 @@ Imports Download = SCrawler.Plugin.ISiteSettings.Download
Imports PauseModes = SCrawler.DownloadObjects.AutoDownloader.PauseModes Imports PauseModes = SCrawler.DownloadObjects.AutoDownloader.PauseModes
Imports MsgBoxButton = PersonalUtilities.Functions.Messaging.MsgBoxButton Imports MsgBoxButton = PersonalUtilities.Functions.Messaging.MsgBoxButton
Namespace Plugin.Hosts Namespace Plugin.Hosts
Friend Class SettingsHostCollection : Implements IEnumerable(Of SettingsHost), IMyEnumerator(Of SettingsHost) Friend Class SettingsHostCollection : Implements IEnumerable(Of SettingsHost), IMyEnumerator(Of SettingsHost), IDisposable
#Region "Declarations" #Region "Declarations"
Private Const FileNamePrefix As String = "Host_" Private Const FileNamePrefix As String = "Host_"
Private Const FileNamePattern As String = FileNamePrefix & "{0}_{1}_" Private Const FileNamePattern As String = FileNamePrefix & "{0}_{1}_"
@@ -122,7 +122,7 @@ Namespace Plugin.Hosts
AddHandler Host.OkClick, AddressOf Hosts_OkClick AddHandler Host.OkClick, AddressOf Hosts_OkClick
AddHandler Host.Deleted, AddressOf Hosts_Deleted AddHandler Host.Deleted, AddressOf Hosts_Deleted
AddHandler Host.CloneClick, AddressOf Hosts_CloneClick AddHandler Host.CloneClick, AddressOf Hosts_CloneClick
If Host.Index > 0 Then Host.Source.DefaultInstance = [Default].Source If Host.Index > 0 Then Host.Source.DefaultInstance = [Default].Source : Host.DefaultInstanceChanged()
End Sub End Sub
Private Sub Hosts_OkClick(ByVal Obj As SettingsHost) Private Sub Hosts_OkClick(ByVal Obj As SettingsHost)
If Obj.Index = -1 Then If Obj.Index = -1 Then
@@ -437,6 +437,33 @@ Namespace Plugin.Hosts
Private Function IEnumerable_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator Private Function IEnumerable_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
Return GetEnumerator() Return GetEnumerator()
End Function End Function
#End Region
#Region "IDisposable Support"
Private disposedValue As Boolean = False
Protected Overridable Overloads Sub Dispose(ByVal disposing As Boolean)
If Not disposedValue Then
If disposing Then
Hosts.ListClearDispose(, False, EDP.SendToLog)
HostsUnavailableIndexes.Clear()
HostsXml.ListClearDispose(, False, EDP.SendToLog)
BTT_SETTINGS.DisposeIfReady
BTT_SETTINGS_SEP_1.DisposeIfReady
BTT_SETTINGS_ACTIONS_ADD.DisposeIfReady
End If
BTT_SETTINGS = Nothing
BTT_SETTINGS_SEP_1 = Nothing
BTT_SETTINGS_ACTIONS_ADD = Nothing
disposedValue = True
End If
End Sub
Protected Overrides Sub Finalize()
Dispose(False)
MyBase.Finalize()
End Sub
Friend Overloads Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region #End Region
End Class End Class
End Namespace End Namespace

View File

@@ -194,6 +194,11 @@
<Compile Include="API\Mastodon\SiteSettings.vb" /> <Compile Include="API\Mastodon\SiteSettings.vb" />
<Compile Include="API\Mastodon\UserData.vb" /> <Compile Include="API\Mastodon\UserData.vb" />
<Compile Include="API\OnlyFans\Declarations.vb" /> <Compile Include="API\OnlyFans\Declarations.vb" />
<Compile Include="API\OnlyFans\OFResources.Designer.vb">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>OFResources.resx</DependentUpon>
</Compile>
<Compile Include="API\OnlyFans\SiteSettings.vb" /> <Compile Include="API\OnlyFans\SiteSettings.vb" />
<Compile Include="API\OnlyFans\UserData.vb" /> <Compile Include="API\OnlyFans\UserData.vb" />
<Compile Include="API\OnlyFans\UserExchangeOptions.vb" /> <Compile Include="API\OnlyFans\UserExchangeOptions.vb" />
@@ -262,12 +267,19 @@
<Compile Include="Download\Feed\DownloadFeedForm.vb"> <Compile Include="Download\Feed\DownloadFeedForm.vb">
<SubType>Form</SubType> <SubType>Form</SubType>
</Compile> </Compile>
<Compile Include="Download\Feed\FeedCopyToForm.Designer.vb">
<DependentUpon>FeedCopyToForm.vb</DependentUpon>
</Compile>
<Compile Include="Download\Feed\FeedCopyToForm.vb">
<SubType>Form</SubType>
</Compile>
<Compile Include="Download\Feed\FeedMedia.Designer.vb"> <Compile Include="Download\Feed\FeedMedia.Designer.vb">
<DependentUpon>FeedMedia.vb</DependentUpon> <DependentUpon>FeedMedia.vb</DependentUpon>
</Compile> </Compile>
<Compile Include="Download\Feed\FeedMedia.vb"> <Compile Include="Download\Feed\FeedMedia.vb">
<SubType>UserControl</SubType> <SubType>UserControl</SubType>
</Compile> </Compile>
<Compile Include="Download\Feed\FeedMoveCopyTo.vb" />
<Compile Include="Download\Feed\FeedSpecial.vb" /> <Compile Include="Download\Feed\FeedSpecial.vb" />
<Compile Include="Download\Feed\FeedSpecialCollection.vb" /> <Compile Include="Download\Feed\FeedSpecialCollection.vb" />
<Compile Include="Download\Feed\FeedVideo.Designer.vb"> <Compile Include="Download\Feed\FeedVideo.Designer.vb">
@@ -490,6 +502,11 @@
<EmbeddedResource Include="API\BaseObjects\InternalSettingsForm.resx"> <EmbeddedResource Include="API\BaseObjects\InternalSettingsForm.resx">
<DependentUpon>InternalSettingsForm.vb</DependentUpon> <DependentUpon>InternalSettingsForm.vb</DependentUpon>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Include="API\OnlyFans\OFResources.resx">
<CustomToolNamespace>My.Resources</CustomToolNamespace>
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>OFResources.Designer.vb</LastGenOutput>
</EmbeddedResource>
<EmbeddedResource Include="API\Reddit\RedditViewSettingsForm.resx"> <EmbeddedResource Include="API\Reddit\RedditViewSettingsForm.resx">
<DependentUpon>RedditViewSettingsForm.vb</DependentUpon> <DependentUpon>RedditViewSettingsForm.vb</DependentUpon>
</EmbeddedResource> </EmbeddedResource>
@@ -514,6 +531,9 @@
<EmbeddedResource Include="Download\DownloadSavedPostsForm.resx"> <EmbeddedResource Include="Download\DownloadSavedPostsForm.resx">
<DependentUpon>DownloadSavedPostsForm.vb</DependentUpon> <DependentUpon>DownloadSavedPostsForm.vb</DependentUpon>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Include="Download\Feed\FeedCopyToForm.resx">
<DependentUpon>FeedCopyToForm.vb</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Download\Feed\FeedMedia.resx"> <EmbeddedResource Include="Download\Feed\FeedMedia.resx">
<DependentUpon>FeedMedia.vb</DependentUpon> <DependentUpon>FeedMedia.vb</DependentUpon>
</EmbeddedResource> </EmbeddedResource>
@@ -588,6 +608,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include=".editorconfig" /> <None Include=".editorconfig" />
<None Include="API\OnlyFans\OFScraperConfigPattern.json" />
<None Include="Content\Pictures\ApplicationPic_16.png" /> <None Include="Content\Pictures\ApplicationPic_16.png" />
<None Include="Content\Pictures\BookmarkBlack_16.png" /> <None Include="Content\Pictures\BookmarkBlack_16.png" />
<None Include="Content\Pictures\DBPic_32.png" /> <None Include="Content\Pictures\DBPic_32.png" />
@@ -721,6 +742,9 @@
<ItemGroup> <ItemGroup>
<None Include="Content\Pictures\SitePictures\FacebookPic_37.png" /> <None Include="Content\Pictures\SitePictures\FacebookPic_37.png" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Content Include="Content\Pictures\CutPic_48.png" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup> <PropertyGroup>

View File

@@ -27,6 +27,7 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
Friend Const CookieEncryptKey As String = "SCrawlerCookiesEncryptKeyword" Friend Const CookieEncryptKey As String = "SCrawlerCookiesEncryptKeyword"
Private Const EnvironmentPath As String = "Environment\" Private Const EnvironmentPath As String = "Environment\"
Friend Const CollectionsFolderName As String = "Collections" Friend Const CollectionsFolderName As String = "Collections"
Private Const PermanentCacheSnapshotsPath As String = "_CacheSnapshots\"
Friend Const DefaultCmdEncoding As Integer = BatchExecutor.UnicodeEncoding Friend Const DefaultCmdEncoding As Integer = BatchExecutor.UnicodeEncoding
Friend ReadOnly Design As XmlFile Friend ReadOnly Design As XmlFile
Private ReadOnly MyXML As XmlFile Private ReadOnly MyXML As XmlFile
@@ -113,7 +114,7 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
Friend ReadOnly Property CacheSnapshots(ByVal Permanent As Boolean) As CacheKeeper Friend ReadOnly Property CacheSnapshots(ByVal Permanent As Boolean) As CacheKeeper
Get Get
If Permanent Then If Permanent Then
If _CacheSnapshots Is Nothing Then _CacheSnapshots = New CacheKeeper("_CacheSnapshots\") With {.DeleteCacheOnDispose = False, .DeleteRootOnDispose = False} If _CacheSnapshots Is Nothing Then _CacheSnapshots = New CacheKeeper(PermanentCacheSnapshotsPath) With {.DeleteCacheOnDispose = False, .DeleteRootOnDispose = False}
Return _CacheSnapshots Return _CacheSnapshots
Else Else
Dim dir As SFile = $"{Cache.RootDirectory.PathWithSeparator}Snapshots\" Dim dir As SFile = $"{Cache.RootDirectory.PathWithSeparator}Snapshots\"
@@ -133,7 +134,7 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
Friend ReadOnly Property DownloadLocations As STDownloader.DownloadLocationsCollection Friend ReadOnly Property DownloadLocations As STDownloader.DownloadLocationsCollection
Friend ReadOnly Property GlobalLocations As STDownloader.DownloadLocationsCollection Friend ReadOnly Property GlobalLocations As STDownloader.DownloadLocationsCollection
Friend Property Automation As Scheduler Friend Property Automation As Scheduler
Friend ReadOnly Property AutomationFile As XMLValue(Of SFile) Friend ReadOnly Property AutomationFile As XMLValue(Of String)
Friend ReadOnly Property Feeds As FeedSpecialCollection Friend ReadOnly Property Feeds As FeedSpecialCollection
Friend ReadOnly Property BlackList As List(Of UserBan) Friend ReadOnly Property BlackList As List(Of UserBan)
Private ReadOnly BlackListFile As SFile = $"{SettingsFolderName}\BlackList.txt" Private ReadOnly BlackListFile As SFile = $"{SettingsFolderName}\BlackList.txt"
@@ -178,7 +179,7 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
SeparateVideoFolder = New XMLValue(Of Boolean)("SeparateVideoFolder", True, MyXML) SeparateVideoFolder = New XMLValue(Of Boolean)("SeparateVideoFolder", True, MyXML)
CollectionsPath = New XMLValue(Of String)("CollectionsPath", CollectionsFolderName, MyXML) CollectionsPath = New XMLValue(Of String)("CollectionsPath", CollectionsFolderName, MyXML)
AutomationFile = New XMLValue(Of SFile)("AutomationFile",, MyXML) AutomationFile = New XMLValue(Of String)("AutomationFile",, MyXML)
UserAgent = New XMLValue(Of String)("UserAgent",, MyXML) UserAgent = New XMLValue(Of String)("UserAgent",, MyXML)
If Not UserAgent.IsEmptyString Then DefaultUserAgent = UserAgent If Not UserAgent.IsEmptyString Then DefaultUserAgent = UserAgent
@@ -209,7 +210,21 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
Plugins.AddRange(PluginHost.GetMyHosts(MyXML, GlobalPath.Value, DefaultTemporary, DefaultDownloadImages, DefaultDownloadVideos)) Plugins.AddRange(PluginHost.GetMyHosts(MyXML, GlobalPath.Value, DefaultTemporary, DefaultDownloadImages, DefaultDownloadVideos))
Dim tmpPluginList As IEnumerable(Of PluginHost) = PluginHost.GetPluginsHosts(MyXML, GlobalPath.Value, DefaultTemporary, Dim tmpPluginList As IEnumerable(Of PluginHost) = PluginHost.GetPluginsHosts(MyXML, GlobalPath.Value, DefaultTemporary,
DefaultDownloadImages, DefaultDownloadVideos) DefaultDownloadImages, DefaultDownloadVideos)
If tmpPluginList.ListExists Then Plugins.AddRange(tmpPluginList) If tmpPluginList.ListExists Then
Dim tplIndx% = -1
For Each tpl As PluginHost In tmpPluginList
If tpl.IsReplacer Then
tplIndx = Plugins.FindIndex(Function(pl) pl.Key.StringToLower = tpl.Replacer.PluginKey.StringToLower Or
pl.Name.StringToLower = tpl.Replacer.SiteName.StringToLower)
If tplIndx >= 0 Then
Plugins(tplIndx).Dispose()
Plugins.RemoveAt(tplIndx)
If Plugins.Count = 0 Then Exit For
End If
End If
Next
Plugins.AddRange(tmpPluginList)
End If
MainFrameUsersShowDefaults = New XMLValue(Of Boolean)("UsersShowDefaults", True, MyXML) MainFrameUsersShowDefaults = New XMLValue(Of Boolean)("UsersShowDefaults", True, MyXML)
MainFrameUsersShowSubscriptions = New XMLValue(Of Boolean)("UsersShowSubscriptions", True, MyXML) MainFrameUsersShowSubscriptions = New XMLValue(Of Boolean)("UsersShowSubscriptions", True, MyXML)
@@ -305,6 +320,13 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
FeedLastModeSubscriptions = New XMLValue(Of Boolean)("LastModeSubscriptions", False, MyXML, n) FeedLastModeSubscriptions = New XMLValue(Of Boolean)("LastModeSubscriptions", False, MyXML, n)
FeedShowFriendlyNames = New XMLValue(Of Boolean)("ShowFriendlyNames", True, MyXML, n) FeedShowFriendlyNames = New XMLValue(Of Boolean)("ShowFriendlyNames", True, MyXML, n)
FeedShowSpecialFeedsMediaItem = New XMLValue(Of Boolean)("ShowSpecialFeedsMediaItem", False, MyXML, n) FeedShowSpecialFeedsMediaItem = New XMLValue(Of Boolean)("ShowSpecialFeedsMediaItem", False, MyXML, n)
n = {"Feed", "MoveCopy"}
FeedMoveCopyLastLocation = New XMLValue(Of SFile)("LastLocation",, MyXML, n)
FeedMoveCopyUpdateFileLocationOnMove = New XMLValue(Of Boolean)("UpdateFileLocationOnMove", True, MyXML, n)
FeedMoveCopyIsProfileChecked = New XMLValue(Of Boolean)("IsProfileChecked", True, MyXML, n)
FeedMoveCopySeparateVideo = New XMLValue(Of Boolean)("SeparateVideo",, MyXML, n)
FeedMoveCopyReplaceUserProfile = New XMLValue(Of Boolean)("ReplaceUserProfile",, MyXML, n)
FeedMoveCopyCreatePathProfile = New XMLValue(Of Boolean)("CreatePathProfile",, MyXML, n)
n = {"Users"} n = {"Users"}
FromChannelDownloadTop = New XMLValue(Of Integer)("FromChannelDownloadTop", 10, MyXML, n) FromChannelDownloadTop = New XMLValue(Of Integer)("FromChannelDownloadTop", 10, MyXML, n)
@@ -336,6 +358,7 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
ShowNotificationsDownSavedPosts = New XMLValue(Of Boolean)("SavedPosts", True, MyXML, n) ShowNotificationsDownSavedPosts = New XMLValue(Of Boolean)("SavedPosts", True, MyXML, n)
ShowNotificationsSTDownloader = New XMLValue(Of Boolean)("STDownloader", True, MyXML, n) ShowNotificationsSTDownloader = New XMLValue(Of Boolean)("STDownloader", True, MyXML, n)
ShowNotificationsSTDownloaderEveryDownload = New XMLValue(Of Boolean)("STDownloaderEveryDownload", True, MyXML, n) ShowNotificationsSTDownloaderEveryDownload = New XMLValue(Of Boolean)("STDownloaderEveryDownload", True, MyXML, n)
ShowNotificationsLOG = New XMLValue(Of Boolean)("LOG", True, MyXML, n)
ProgramText = New XMLValue(Of String)("ProgramText",, MyXML) ProgramText = New XMLValue(Of String)("ProgramText",, MyXML)
ProgramDescription = New XMLValue(Of String)("ProgramDescription",, MyXML) ProgramDescription = New XMLValue(Of String)("ProgramDescription",, MyXML)
@@ -672,6 +695,14 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
Friend Sub DeleteCachePath() Friend Sub DeleteCachePath()
Reddit.ChannelsCollection.ChannelsPathCache.Delete(SFO.Path, SFODelete.None, EDP.None) Reddit.ChannelsCollection.ChannelsPathCache.Delete(SFO.Path, SFODelete.None, EDP.None)
End Sub End Sub
Private Sub DeleteCachePathPermanent()
Try
Dim f As New SFile(PermanentCacheSnapshotsPath)
If f.Exists(SFO.Path, False) AndAlso Not SFile.GetFiles(f,, IO.SearchOption.AllDirectories, EDP.ReturnValue).ListExists Then _
f.Delete(SFO.Path, SFODelete.DeletePermanently, EDP.None)
Catch
End Try
End Sub
Friend Overloads Function UserExists(ByVal UserSite As String, ByVal UserID As String) As Boolean Friend Overloads Function UserExists(ByVal UserSite As String, ByVal UserID As String) As Boolean
Dim UserFinderBase As Predicate(Of IUserData) = Function(user) user.Site = UserSite And user.Name = UserID Dim UserFinderBase As Predicate(Of IUserData) = Function(user) user.Site = UserSite And user.Name = UserID
Dim UserFinder As Predicate(Of IUserData) = Function(ByVal user As IUserData) As Boolean Dim UserFinder As Predicate(Of IUserData) = Function(ByVal user As IUserData) As Boolean
@@ -930,6 +961,14 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
Friend ReadOnly Property FeedLastModeSubscriptions As XMLValue(Of Boolean) Friend ReadOnly Property FeedLastModeSubscriptions As XMLValue(Of Boolean)
Friend ReadOnly Property FeedShowFriendlyNames As XMLValue(Of Boolean) Friend ReadOnly Property FeedShowFriendlyNames As XMLValue(Of Boolean)
Friend ReadOnly Property FeedShowSpecialFeedsMediaItem As XMLValue(Of Boolean) Friend ReadOnly Property FeedShowSpecialFeedsMediaItem As XMLValue(Of Boolean)
#Region "MoveCopy"
Friend ReadOnly Property FeedMoveCopyLastLocation As XMLValue(Of SFile)
Friend ReadOnly Property FeedMoveCopyUpdateFileLocationOnMove As XMLValue(Of Boolean)
Friend ReadOnly Property FeedMoveCopyIsProfileChecked As XMLValue(Of Boolean)
Friend ReadOnly Property FeedMoveCopySeparateVideo As XMLValue(Of Boolean)
Friend ReadOnly Property FeedMoveCopyReplaceUserProfile As XMLValue(Of Boolean)
Friend ReadOnly Property FeedMoveCopyCreatePathProfile As XMLValue(Of Boolean)
#End Region
#End Region #End Region
#Region "New version properties" #Region "New version properties"
Friend ReadOnly Property CheckUpdatesAtStart As XMLValue(Of Boolean) Friend ReadOnly Property CheckUpdatesAtStart As XMLValue(Of Boolean)
@@ -944,6 +983,7 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
Channels Channels
SavedPosts SavedPosts
STDownloader STDownloader
LOG
End Enum End Enum
Friend ReadOnly Property ProcessNotification(ByVal Sender As NotificationObjects) As Boolean Friend ReadOnly Property ProcessNotification(ByVal Sender As NotificationObjects) As Boolean
Get Get
@@ -955,6 +995,7 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
Case NotificationObjects.Channels : Return ShowNotificationsDownChannels Case NotificationObjects.Channels : Return ShowNotificationsDownChannels
Case NotificationObjects.SavedPosts : Return ShowNotificationsDownSavedPosts Case NotificationObjects.SavedPosts : Return ShowNotificationsDownSavedPosts
Case NotificationObjects.STDownloader : Return ShowNotificationsSTDownloader Case NotificationObjects.STDownloader : Return ShowNotificationsSTDownloader
Case NotificationObjects.LOG : Return ShowNotificationsLOG
Case Else : Return True Case Else : Return True
End Select End Select
Else Else
@@ -970,6 +1011,7 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
Friend ReadOnly Property ShowNotificationsDownSavedPosts As XMLValue(Of Boolean) Friend ReadOnly Property ShowNotificationsDownSavedPosts As XMLValue(Of Boolean)
Friend ReadOnly Property ShowNotificationsSTDownloader As XMLValue(Of Boolean) Friend ReadOnly Property ShowNotificationsSTDownloader As XMLValue(Of Boolean)
Friend ReadOnly Property ShowNotificationsSTDownloaderEveryDownload As XMLValue(Of Boolean) Friend ReadOnly Property ShowNotificationsSTDownloaderEveryDownload As XMLValue(Of Boolean)
Friend ReadOnly Property ShowNotificationsLOG As XMLValue(Of Boolean)
#End Region #End Region
#Region "Other program properties" #Region "Other program properties"
Friend ReadOnly Property ProgramText As XMLValue(Of String) Friend ReadOnly Property ProgramText As XMLValue(Of String)
@@ -1007,6 +1049,7 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
End If End If
If Not Automation Is Nothing Then Automation.Dispose() If Not Automation Is Nothing Then Automation.Dispose()
Cache.Dispose() Cache.Dispose()
DeleteCachePathPermanent()
Plugins.Clear() Plugins.Clear()
LastCollections.Clear() LastCollections.Clear()
Users.ListClearDispose Users.ListClearDispose

Some files were not shown because too many files have changed in this diff Show More