Compare commits
6 Commits
2025.7.18.
...
2026.1.17.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e6d5fc2b95 | ||
|
|
6d4380ccac | ||
|
|
8dfd4e8bd1 | ||
|
|
1404afdfa3 | ||
|
|
5857fcfae3 | ||
|
|
e09752a2d5 |
318
Changelog.md
@@ -1,12 +1,125 @@
|
||||
# 2025.7.18.0
|
||||
# Program versions
|
||||
- [ffmpeg](https://github.com/AAndyProgram/SCrawler/wiki/Settings#ffmpeg)
|
||||
- x64 version - [release](https://github.com/GyanD/codexffmpeg/releases/tag/5.1.2); [zip](https://github.com/GyanD/codexffmpeg/releases/download/5.1.2/ffmpeg-5.1.2-full_build.zip); **version `5.1.2-full_build-www.gyan.dev`**
|
||||
- x86 version - [release](https://github.com/yt-dlp/FFmpeg-Builds/releases/tag/autobuild-2022-11-30-12-57); [zip](https://github.com/yt-dlp/FFmpeg-Builds/releases/download/autobuild-2022-11-30-12-57/ffmpeg-N-109274-gd7a5f068c2-win32-gpl.zip); **version `N-109457-geeb280f351-20221226`**
|
||||
- [Gallery-dl](https://github.com/AAndyProgram/SCrawler/wiki/Settings#gallery-dl) - **1.31.3**
|
||||
- [YT-DLP](https://github.com/AAndyProgram/SCrawler/wiki/Settings#yt-dlp) - **2025.12.08**
|
||||
- [Deno](https://github.com/AAndyProgram/SCrawler/wiki/Settings#deno) - latest *(`2.0.0` or higher)*
|
||||
- [OF-Scraper](https://github.com/AAndyProgram/SCrawler/wiki/Settings#of-scraper) - **3.12.9** ([release](https://github.com/datawhores/OF-Scraper/releases/tag/3.12.9))
|
||||
|
||||
# 2026
|
||||
|
||||
## 2026.1.17.0
|
||||
|
||||
*2026-01-17*
|
||||
|
||||
- Add
|
||||
- Sites:
|
||||
- OnlyFans: handling error `502`
|
||||
- Threads: user name and description extraction
|
||||
- TikTok: **downloading `Stories` and `Reposts`**
|
||||
- Download groups: excluded groups
|
||||
- Updated
|
||||
- yt-dlp up to version **2025.12.08**
|
||||
- gallery-dl up to version **1.31.3**
|
||||
- Fixed
|
||||
- Sites:
|
||||
- PornHub: videos aren't downloading
|
||||
- TikTok: new videos aren't downloading
|
||||
- xHamster: new users aren't added in some cases
|
||||
|
||||
# 2025
|
||||
|
||||
## 2025.11.25.0
|
||||
|
||||
*2025-11-25*
|
||||
|
||||
**ATTENTION!**
|
||||
|
||||
**An external JavaScript runtime is now required for full YouTube support**
|
||||
yt-dlp now requires users to have an external JavaScript runtime ([Deno](https://github.com/AAndyProgram/SCrawler/wiki/Settings#deno)) installed in order to solve the JavaScript challenges presented by YouTube.
|
||||
|
||||
**xHamster is back.** 🥳🎉 xHamster's downloading algorithms now partially utilize yt-dlp, so yt-dlp is now required for this site.
|
||||
|
||||
- Added
|
||||
- Sites:
|
||||
- TikTok: **download descriptions**
|
||||
- Download groups: groups downloading among other options (more [here](https://github.com/AAndyProgram/SCrawler/wiki/Settings#download-groups))
|
||||
- Saved posts: hotkey `Esc` to close the form
|
||||
- Minor improvements
|
||||
- Updated
|
||||
- yt-dlp up to version **2025.11.12**
|
||||
- gallery-dl up to version **1.30.10**
|
||||
- AutoDownloader: the modes are now removed. Now you can only enable/disable the auto download plan. All options can now be combined.
|
||||
- Fixed
|
||||
- Sites:
|
||||
- Twitter: the site name, description and avatar are not downloading
|
||||
- xHamster: **data is not downloading**
|
||||
- Minor bugs
|
||||
|
||||
## 2025.10.4.0
|
||||
|
||||
*2025-10-04*
|
||||
|
||||
**xHamster downloads are temporarily disabled**
|
||||
|
||||
- Added
|
||||
- Sites:
|
||||
- Bluesky: **saved posts downloading**
|
||||
- xHamster: **temporarily disable the plugin**
|
||||
- Minor improvements
|
||||
- Updated
|
||||
- yt-dlp up to version **2025.09.26**
|
||||
- gallery-dl up to version **1.30.9**
|
||||
|
||||
## 2025.9.1.0
|
||||
|
||||
*2025-09-01*
|
||||
|
||||
- Fixed
|
||||
- PornHub: data is not downloading
|
||||
|
||||
## 2025.8.30.0
|
||||
|
||||
*2025-08-30*
|
||||
|
||||
- Added
|
||||
- YouTube:
|
||||
- **video trim** *(button `Trim`)*
|
||||
- embed chapters into video file
|
||||
- add artist name when downloading audio
|
||||
- Correct handling of `webp` files
|
||||
- Minor improvements
|
||||
- Updated
|
||||
- yt-dlp up to version **2025.08.27**
|
||||
- gallery-dl up to version **1.30.5**
|
||||
- Fixed
|
||||
- **YouTube: downloading error**
|
||||
- Minor bugs
|
||||
|
||||
## 2025.8.1.0
|
||||
|
||||
*2025-08-01*
|
||||
|
||||
- Added
|
||||
- Sites:
|
||||
- Reddit: **bypass error `429`**
|
||||
- Twitter: **[large profile option](https://github.com/AAndyProgram/SCrawler/wiki/Settings#twitter-user-settings) in user settings**
|
||||
- Minor improvements
|
||||
- Updated
|
||||
- yt-dlp up to version **2025.07.21**
|
||||
- gallery-dl up to version **1.30.2**
|
||||
- Fixed
|
||||
- Reddit: in some cases crossposts don't download
|
||||
- Minor bugs
|
||||
|
||||
## 2025.7.18.0
|
||||
|
||||
*2025-07-18*
|
||||
|
||||
- Added
|
||||
- Sites:
|
||||
- OnlyFans:
|
||||
- **bypass unpurchased videos**
|
||||
- support for GIF files
|
||||
- OnlyFans: support for GIF files
|
||||
- Reddit: extended `429` error handling
|
||||
- Xhamster: support for downloading 'moments'
|
||||
- Minor improvements
|
||||
@@ -14,9 +127,10 @@
|
||||
- yt-dlp up to version **2025.06.30**
|
||||
- gallery-dl up to version **1.30.0**
|
||||
- Fixed
|
||||
- OnlyFans: **hanging on purchased content**
|
||||
- Minor bugs
|
||||
|
||||
# 2025.6.12.0
|
||||
## 2025.6.12.0
|
||||
|
||||
*2025-06-12*
|
||||
|
||||
@@ -30,7 +144,7 @@
|
||||
- Saved posts: text downloading with saved posts
|
||||
- Environment incorrect output
|
||||
|
||||
# 2025.6.1.0
|
||||
## 2025.6.1.0
|
||||
|
||||
*2025-06-01*
|
||||
|
||||
@@ -72,7 +186,7 @@
|
||||
- data is not downloaded in some cases
|
||||
- Minor bugs
|
||||
|
||||
# 2025.3.17.0
|
||||
## 2025.3.17.0
|
||||
|
||||
*2025-03-17*
|
||||
|
||||
@@ -86,7 +200,7 @@
|
||||
- PornHub: newly added users aren't downloading
|
||||
- Threads: users aren't updated if there is a pinned post
|
||||
|
||||
# 2025.2.25.0
|
||||
## 2025.2.25.0
|
||||
|
||||
*2025-02-25*
|
||||
|
||||
@@ -118,7 +232,7 @@
|
||||
- Threads: **data is not downloading**
|
||||
- Minor bugs
|
||||
|
||||
# 2025.1.12.0
|
||||
## 2025.1.12.0
|
||||
|
||||
*2025-01-12*
|
||||
|
||||
@@ -143,7 +257,8 @@
|
||||
- YouTube: **communities are not downloading** *(see settings in wiki)*
|
||||
- Minor bugs
|
||||
|
||||
# 2024.11.21.0
|
||||
# 2024
|
||||
## 2024.11.21.0
|
||||
|
||||
*2024-11-21*
|
||||
|
||||
@@ -166,7 +281,7 @@
|
||||
- Main window: in some cases users are not updated in the list
|
||||
- Minor bugs
|
||||
|
||||
# 2024.10.24.0
|
||||
## 2024.10.24.0
|
||||
|
||||
*2024-10-24*
|
||||
|
||||
@@ -191,7 +306,7 @@
|
||||
- Can't change data path (issue #206)
|
||||
- Minor bugs
|
||||
|
||||
# 2024.9.2.0
|
||||
## 2024.9.2.0
|
||||
|
||||
*2024-09-02*
|
||||
|
||||
@@ -207,7 +322,7 @@
|
||||
- YouTube (SCrawler): incorrect parsing of video page
|
||||
- Minor bugs
|
||||
|
||||
# 2024.8.10.0
|
||||
## 2024.8.10.0
|
||||
|
||||
*2024-08-10*
|
||||
|
||||
@@ -219,7 +334,7 @@
|
||||
- Fixed
|
||||
- YouTube (standalone app): **video is being parsed using cookies but is not downloading** *(Issue #205)*
|
||||
|
||||
# 2024.8.1.0
|
||||
## 2024.8.1.0
|
||||
|
||||
*2024-08-01*
|
||||
|
||||
@@ -228,7 +343,7 @@
|
||||
- Updated
|
||||
- yt-dlp up to version **2024.08.01**
|
||||
|
||||
# 2024.7.24.0
|
||||
## 2024.7.24.0
|
||||
|
||||
*2024-07-24*
|
||||
|
||||
@@ -251,7 +366,7 @@
|
||||
- OnlyFans: rules parsing bug
|
||||
- Minor bugs
|
||||
|
||||
# 2024.6.25.0
|
||||
## 2024.6.25.0
|
||||
|
||||
*2024-06-25*
|
||||
|
||||
@@ -265,7 +380,7 @@
|
||||
- Fixed
|
||||
- Minor bugs
|
||||
|
||||
# 2024.6.10.0
|
||||
## 2024.6.10.0
|
||||
|
||||
*2024-06-10*
|
||||
|
||||
@@ -278,7 +393,7 @@
|
||||
- Fixed
|
||||
- Minor bugs
|
||||
|
||||
# 2024.6.6.0
|
||||
## 2024.6.6.0
|
||||
|
||||
*2024-06-06*
|
||||
|
||||
@@ -294,7 +409,7 @@
|
||||
- OnlyFans: **data is not downloading**
|
||||
- Minor bugs
|
||||
|
||||
# 2024.6.4.0
|
||||
## 2024.6.4.0
|
||||
|
||||
*2024-06-04*
|
||||
|
||||
@@ -313,7 +428,7 @@
|
||||
- Twitter: deleting user directory when redownloading missing posts
|
||||
- Minor bugs
|
||||
|
||||
# 2024.5.19.0
|
||||
## 2024.5.19.0
|
||||
|
||||
*2024-05-19*
|
||||
|
||||
@@ -322,7 +437,7 @@
|
||||
- Fixed
|
||||
- YouTube (SCrawler): advanced settings are not saved when changed
|
||||
|
||||
# 2024.5.18.0
|
||||
## 2024.5.18.0
|
||||
|
||||
*2024-05-18*
|
||||
|
||||
@@ -349,7 +464,7 @@
|
||||
- Twitter: **data is not downloading due to domain change from twitter.com to x.com**
|
||||
- Minor bugs
|
||||
|
||||
# 2024.5.4.0
|
||||
## 2024.5.4.0
|
||||
|
||||
*2024-05-04*
|
||||
|
||||
@@ -364,7 +479,7 @@
|
||||
- Reddit: token update error
|
||||
- Threads: unable to obtain credentials (`ID`)
|
||||
|
||||
# 2024.4.26.0
|
||||
## 2024.4.26.0
|
||||
|
||||
*2024-04-26*
|
||||
|
||||
@@ -377,14 +492,14 @@
|
||||
- Fixed
|
||||
- xHamster: **saved posts aren't downloading**
|
||||
|
||||
# 2024.4.14.0
|
||||
## 2024.4.14.0
|
||||
|
||||
*2024-04-14*
|
||||
|
||||
- Fixed
|
||||
- Facebook: can't get tokens
|
||||
|
||||
# 2024.4.13.0
|
||||
## 2024.4.13.0
|
||||
|
||||
*2024-04-13*
|
||||
|
||||
@@ -398,7 +513,7 @@
|
||||
- YouTube: remove last download date when erasing history data
|
||||
- Instagram: **saved posts aren't downloading**
|
||||
|
||||
# 2024.4.10.0
|
||||
## 2024.4.10.0
|
||||
|
||||
*2024-04-10*
|
||||
|
||||
@@ -466,7 +581,7 @@
|
||||
- Feed: a scrolling bug where the feed scrolls up after returning to it
|
||||
- Minor bugs
|
||||
|
||||
# 2024.2.25.0
|
||||
## 2024.2.25.0
|
||||
|
||||
*2024-02-25*
|
||||
|
||||
@@ -500,7 +615,7 @@
|
||||
- TikTok: files with long names aren't downloaded
|
||||
- Minor bugs
|
||||
|
||||
# 2024.1.26.0
|
||||
## 2024.1.26.0
|
||||
|
||||
*2024-01-26*
|
||||
|
||||
@@ -512,7 +627,7 @@
|
||||
- Instagram: stories (user) downloading with the wrong aspect ratio for some users
|
||||
- Minor bugs
|
||||
|
||||
# 2024.1.20.0
|
||||
## 2024.1.20.0
|
||||
|
||||
*2024-01-20*
|
||||
|
||||
@@ -520,7 +635,7 @@
|
||||
- Instagram: **the ability to download reels**
|
||||
- LPSG: handle 404 error
|
||||
|
||||
# 2024.1.18.0
|
||||
## 2024.1.18.0
|
||||
|
||||
*2024-01-18*
|
||||
|
||||
@@ -530,7 +645,7 @@
|
||||
- YouTube (standalone app): URL array form doesn't show scrollbars
|
||||
- Minor bugs
|
||||
|
||||
# 2024.1.12.1
|
||||
## 2024.1.12.1
|
||||
|
||||
*2024-01-12*
|
||||
|
||||
@@ -543,7 +658,7 @@
|
||||
- YouTube: incorrect opening of a post from the feed
|
||||
- YouTube: wrong date to data parsing
|
||||
|
||||
# 2024.1.12.0
|
||||
## 2024.1.12.0
|
||||
|
||||
*2024-01-12*
|
||||
|
||||
@@ -559,7 +674,8 @@
|
||||
- xHamster: profiles are not downloading
|
||||
- Minor bugs
|
||||
|
||||
# 2023.12.27.0
|
||||
# 2023
|
||||
## 2023.12.27.0
|
||||
|
||||
*2023-12-27*
|
||||
|
||||
@@ -573,7 +689,7 @@
|
||||
- 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*
|
||||
|
||||
@@ -581,7 +697,7 @@
|
||||
- Twitter: some twitter profiles don't download completely
|
||||
- Minor bugs
|
||||
|
||||
# 2023.12.14.0
|
||||
## 2023.12.14.0
|
||||
|
||||
*2023-12-14*
|
||||
|
||||
@@ -589,7 +705,7 @@
|
||||
- YouTube: options `Create thumbnail files (video)` and `Create thumbnail files (music)`
|
||||
- YouTube: `Select all` and `Select none` buttons
|
||||
|
||||
# 2023.12.13.0
|
||||
## 2023.12.13.0
|
||||
|
||||
*2023-12-13*
|
||||
|
||||
@@ -601,7 +717,7 @@
|
||||
- Feed: saved posts are added to the end of the feed
|
||||
- xHamster: some videos won't download
|
||||
|
||||
# 2023.12.10.0
|
||||
## 2023.12.10.0
|
||||
|
||||
*2023-12-10*
|
||||
|
||||
@@ -610,7 +726,7 @@
|
||||
- Fixed
|
||||
- Twitter: data is not downloading
|
||||
|
||||
# 2023.12.7.0
|
||||
## 2023.12.7.0
|
||||
|
||||
*2023-12-07*
|
||||
|
||||
@@ -626,14 +742,14 @@
|
||||
- Standalone downloader: URL files are not deleted along with the file
|
||||
- Minor bugs
|
||||
|
||||
# 2023.11.25.0
|
||||
## 2023.11.25.0
|
||||
|
||||
*2023-11-25*
|
||||
|
||||
- Fixed
|
||||
- Reddit: missing refresh token button in the settings form
|
||||
|
||||
# 2023.11.24.0
|
||||
## 2023.11.24.0
|
||||
|
||||
*2023-11-24*
|
||||
|
||||
@@ -657,7 +773,7 @@ For those of you who use TikTok, I recommend updating [TikTok plugin](https://gi
|
||||
- YouTube: path not set when adding array to download
|
||||
- Minor bugs
|
||||
|
||||
# 2023.11.17.0
|
||||
## 2023.11.17.0
|
||||
|
||||
*2023-11-17*
|
||||
|
||||
@@ -687,7 +803,7 @@ For those of you who use TikTok, I recommend updating [TikTok plugin](https://gi
|
||||
- Automation: handle automation start error (in some cases) when changing scheduler
|
||||
- Minor bugs
|
||||
|
||||
# 2023.10.10.0
|
||||
## 2023.10.10.0
|
||||
|
||||
*2023-10-10*
|
||||
|
||||
@@ -713,7 +829,7 @@ For those of you who use TikTok, I recommend updating [TikTok plugin](https://gi
|
||||
- Standalone downloader: cached thumbnail is not removed when item is removed from the list
|
||||
- Minor bugs
|
||||
|
||||
# 2023.10.1.0
|
||||
## 2023.10.1.0
|
||||
|
||||
*2023-10-01*
|
||||
|
||||
@@ -728,14 +844,14 @@ For those of you who use TikTok, I recommend updating [TikTok plugin](https://gi
|
||||
- JustForFans: some profiles won't download
|
||||
- Minor bugs
|
||||
|
||||
# 2023.9.21.0
|
||||
## 2023.9.21.0
|
||||
|
||||
*2023-09-21*
|
||||
|
||||
- Fixed
|
||||
- PornHub: videos are not downloading
|
||||
|
||||
# 2023.9.20.0
|
||||
## 2023.9.20.0
|
||||
|
||||
*2023-09-20*
|
||||
|
||||
@@ -751,7 +867,7 @@ For those of you who use TikTok, I recommend updating [TikTok plugin](https://gi
|
||||
- Instagram: handle error 500
|
||||
- Collections: update labels only for the added user
|
||||
|
||||
# 2023.8.27.0
|
||||
## 2023.8.27.0
|
||||
|
||||
*2023-08-27*
|
||||
|
||||
@@ -770,7 +886,7 @@ For those of you who use TikTok, I recommend updating [TikTok plugin](https://gi
|
||||
- Auto downloader: downloading stuck
|
||||
- Minor bugs
|
||||
|
||||
# 2023.8.6.0
|
||||
## 2023.8.6.0
|
||||
|
||||
*2023-08-06*
|
||||
|
||||
@@ -858,7 +974,7 @@ For those of you who use TikTok, I recommend updating [TikTok plugin](https://gi
|
||||
- YouTube: a bug that caused the video to redownload
|
||||
- Minor bugs
|
||||
|
||||
# 2023.6.19.0
|
||||
## 2023.6.19.0
|
||||
|
||||
*2023-06-19*
|
||||
|
||||
@@ -878,7 +994,7 @@ For those of you who use TikTok, I recommend updating [TikTok plugin](https://gi
|
||||
- Progress bar bugs
|
||||
- Minor bugs
|
||||
|
||||
# 2023.6.9.0
|
||||
## 2023.6.9.0
|
||||
|
||||
*2023-06-09*
|
||||
|
||||
@@ -887,7 +1003,7 @@ For those of you who use TikTok, I recommend updating [TikTok plugin](https://gi
|
||||
- Twitter: make the algorithm faster
|
||||
- Make progress more informative
|
||||
|
||||
# 2023.6.8.0
|
||||
## 2023.6.8.0
|
||||
|
||||
*2023-06-08*
|
||||
|
||||
@@ -899,7 +1015,7 @@ For those of you who use TikTok, I recommend updating [TikTok plugin](https://gi
|
||||
- Twitter: profile not fully downloaded
|
||||
- Corrected form size for small monitors (Issue #136)
|
||||
|
||||
# 2023.6.5.0
|
||||
## 2023.6.5.0
|
||||
|
||||
*2023-06-05*
|
||||
|
||||
@@ -918,7 +1034,7 @@ For those of you who use TikTok, I recommend updating [TikTok plugin](https://gi
|
||||
- Saved posts: remove main progress perform when downloading saved posts
|
||||
- Minor bugs
|
||||
|
||||
# 2023.5.12.0
|
||||
## 2023.5.12.0
|
||||
|
||||
*2023-05-12*
|
||||
|
||||
@@ -936,7 +1052,7 @@ For those of you who use TikTok, I recommend updating [TikTok plugin](https://gi
|
||||
- Reddit: missing & broken images bug
|
||||
- Main window: collection pointing bug
|
||||
|
||||
# 2023.4.28.0
|
||||
## 2023.4.28.0
|
||||
|
||||
*2023-04-28*
|
||||
|
||||
@@ -980,7 +1096,7 @@ For those of you who use TikTok, I recommend updating [TikTok plugin](https://gi
|
||||
- PornHub: photo galleries bug (Issue #115)
|
||||
- Minor bugs
|
||||
|
||||
# 2023.3.5.0
|
||||
## 2023.3.5.0
|
||||
|
||||
*2023-03-05*
|
||||
|
||||
@@ -989,7 +1105,7 @@ For those of you who use TikTok, I recommend updating [TikTok plugin](https://gi
|
||||
- An error that could occur during Twitter MD5 comparison.
|
||||
- A bug in the ffmpeg file parts concatenation algorithm that could occur in some cases.
|
||||
|
||||
# 2023.3.1.0
|
||||
## 2023.3.1.0
|
||||
|
||||
*2023-03-01*
|
||||
|
||||
@@ -1011,7 +1127,7 @@ For those of you who use TikTok, I recommend updating [TikTok plugin](https://gi
|
||||
- (Issue #106) problem with non-Latin characters
|
||||
- ffmpeg: maximum input length error when merging parts of files
|
||||
|
||||
# 2023.2.5.0
|
||||
## 2023.2.5.0
|
||||
|
||||
*2023-02-05*
|
||||
|
||||
@@ -1020,7 +1136,7 @@ For those of you who use TikTok, I recommend updating [TikTok plugin](https://gi
|
||||
- Fixed
|
||||
- (Issue #101) Failed download Gfycat video in some cases
|
||||
|
||||
# 2023.1.27.0
|
||||
## 2023.1.27.0
|
||||
|
||||
*2023-01-27*
|
||||
|
||||
@@ -1034,7 +1150,7 @@ For those of you who use TikTok, I recommend updating [TikTok plugin](https://gi
|
||||
- `Interaction` option to the `Provider` attribute
|
||||
- `IPropertyProvider` interface
|
||||
|
||||
# 2023.1.24.1
|
||||
## 2023.1.24.1
|
||||
|
||||
*2023-01-24*
|
||||
|
||||
@@ -1043,7 +1159,7 @@ For those of you who use TikTok, I recommend updating [TikTok plugin](https://gi
|
||||
- Fixed
|
||||
- (Issue #100) some Imgur albums won't download
|
||||
|
||||
# 2023.1.24.0
|
||||
## 2023.1.24.0
|
||||
|
||||
*2023-01-24*
|
||||
|
||||
@@ -1051,7 +1167,7 @@ For those of you who use TikTok, I recommend updating [TikTok plugin](https://gi
|
||||
- (Issue #100) Imgur albums not downloading
|
||||
- When deleting a collection with the 'ban' option, users in the collection are not banned
|
||||
|
||||
# 2023.1.2.0
|
||||
## 2023.1.2.0
|
||||
|
||||
*2023-01-02*
|
||||
|
||||
@@ -1066,7 +1182,8 @@ For those of you who use TikTok, I recommend updating [TikTok plugin](https://gi
|
||||
- Fixed a bug in the user list loading algorithm
|
||||
- Notifications: pressing any button opens SCrawler
|
||||
|
||||
# 2022.12.27.0
|
||||
# 2022
|
||||
## 2022.12.27.0
|
||||
|
||||
*2022-12-27*
|
||||
|
||||
@@ -1076,7 +1193,7 @@ For those of you who use TikTok, I recommend updating [TikTok plugin](https://gi
|
||||
- Fixed
|
||||
- XVideos not downloading (sorry, I broke it in a previous release)
|
||||
|
||||
# 2022.12.26.0
|
||||
## 2022.12.26.0
|
||||
|
||||
*2022-12-26*
|
||||
|
||||
@@ -1099,7 +1216,7 @@ For those of you who use TikTok, I recommend updating [TikTok plugin](https://gi
|
||||
- (Issue #69) **RedGifs data is not downloading**. Again.
|
||||
- Minor bugs
|
||||
|
||||
# 2022.11.16.0
|
||||
## 2022.11.16.0
|
||||
|
||||
*2022-11-16*
|
||||
|
||||
@@ -1133,7 +1250,7 @@ For those of you who use TikTok, I recommend updating [TikTok plugin](https://gi
|
||||
- Users search form doesn't remember last size
|
||||
- Minor bugs
|
||||
|
||||
# 2022.10.23.0
|
||||
## 2022.10.23.0
|
||||
|
||||
*2022-10-23*
|
||||
|
||||
@@ -1152,7 +1269,7 @@ For those of you who use TikTok, I recommend updating [TikTok plugin](https://gi
|
||||
- (Issue #69) **RedGifs data is not downloading**. Requires token.
|
||||
- Minor bugs
|
||||
|
||||
# 2022.10.18.0
|
||||
## 2022.10.18.0
|
||||
|
||||
*2022-10-18*
|
||||
|
||||
@@ -1187,7 +1304,7 @@ For those of you who use TikTok, I recommend updating [TikTok plugin](https://gi
|
||||
- When trying to delete multiple collections, each collection asked for confirmation to delete
|
||||
- Minor bugs
|
||||
|
||||
# 2022.9.24.0
|
||||
## 2022.9.24.0
|
||||
|
||||
*2022-09-24*
|
||||
|
||||
@@ -1205,7 +1322,7 @@ For those of you who use TikTok, I recommend updating [TikTok plugin](https://gi
|
||||
- Bug in the XVIDEOS downloader
|
||||
- Minor bugs
|
||||
|
||||
# 2022.9.17.0
|
||||
## 2022.9.17.0
|
||||
|
||||
*2022-09-17*
|
||||
|
||||
@@ -1221,7 +1338,7 @@ For those of you who use TikTok, I recommend updating [TikTok plugin](https://gi
|
||||
- Incorrect feed sorting algorithm
|
||||
- Minor bugs
|
||||
|
||||
# 2022.9.16.0
|
||||
## 2022.9.16.0
|
||||
|
||||
*2022-09-16*
|
||||
|
||||
@@ -1230,7 +1347,7 @@ For those of you who use TikTok, I recommend updating [TikTok plugin](https://gi
|
||||
- Incorrect rendering of the 'Feed' table when the number of columns is more than one
|
||||
- Minor design bugs
|
||||
|
||||
# 2022.9.13.0
|
||||
## 2022.9.13.0
|
||||
|
||||
*2022-09-13*
|
||||
|
||||
@@ -1240,21 +1357,21 @@ For those of you who use TikTok, I recommend updating [TikTok plugin](https://gi
|
||||
- (Issue #70) Instagram posts not downloading if there are pinned posts that have already been downloaded
|
||||
- Minor bugs
|
||||
|
||||
# 2022.9.10.0
|
||||
## 2022.9.10.0
|
||||
|
||||
*2022-09-10*
|
||||
|
||||
- Fixed
|
||||
- The memory is still leaking. This time because of the video. *Using WMP was not the best choice.*
|
||||
|
||||
# 2022.9.8.1
|
||||
## 2022.9.8.1
|
||||
|
||||
*2022-09-08*
|
||||
|
||||
- Fixed
|
||||
- Unexpected memory leak when using the 'Feed' form
|
||||
|
||||
# 2022.9.8.0
|
||||
## 2022.9.8.0
|
||||
|
||||
*2022-09-08*
|
||||
|
||||
@@ -1265,7 +1382,7 @@ For those of you who use TikTok, I recommend updating [TikTok plugin](https://gi
|
||||
- Fixed
|
||||
- (Issue #67) Saved Instagram posts not downloading
|
||||
|
||||
# 2022.8.28.0
|
||||
## 2022.8.28.0
|
||||
|
||||
*2022-08-28*
|
||||
|
||||
@@ -1274,7 +1391,7 @@ For those of you who use TikTok, I recommend updating [TikTok plugin](https://gi
|
||||
- Fixed
|
||||
- Incorrect number of posts displayed in the Reddit channels downloader.
|
||||
|
||||
# 2022.8.22.0
|
||||
## 2022.8.22.0
|
||||
|
||||
*2022-08-22*
|
||||
|
||||
@@ -1288,7 +1405,7 @@ For those of you who use TikTok, I recommend updating [TikTok plugin](https://gi
|
||||
- AutoDownloader option ```Show notifications``` not saved
|
||||
- Minor bugs
|
||||
|
||||
# 2022.7.7.0
|
||||
## 2022.7.7.0
|
||||
|
||||
*2022-07-07*
|
||||
|
||||
@@ -1306,7 +1423,7 @@ For those of you who use TikTok, I recommend updating [TikTok plugin](https://gi
|
||||
- In some cases, Twitter image is not downloading
|
||||
- Minor bugs
|
||||
|
||||
# 2022.6.10.0
|
||||
## 2022.6.10.0
|
||||
|
||||
*2022-06-10*
|
||||
|
||||
@@ -1315,7 +1432,7 @@ For those of you who use TikTok, I recommend updating [TikTok plugin](https://gi
|
||||
- Fixed
|
||||
- Can't get Instagram user ID
|
||||
|
||||
# 2022.6.6.0
|
||||
## 2022.6.6.0
|
||||
|
||||
*2022-06-06*
|
||||
|
||||
@@ -1325,7 +1442,7 @@ For those of you who use TikTok, I recommend updating [TikTok plugin](https://gi
|
||||
- GIFs from Twitter not downloading
|
||||
- Not quite correct algorithm for stopping automation
|
||||
|
||||
# 2022.6.3.0
|
||||
## 2022.6.3.0
|
||||
|
||||
*2022-06-03*
|
||||
|
||||
@@ -1340,7 +1457,7 @@ Changed version numbering method. From now on, new versions will be numbered by
|
||||
- Videos hosted on Reddit that are downloaded via m3u8 playlists are missing an audio track.
|
||||
- Instagram hash not able to be auto-filled from cookies
|
||||
|
||||
# 3.0.0.10
|
||||
## 3.0.0.10
|
||||
|
||||
*2022-05-23*
|
||||
|
||||
@@ -1363,7 +1480,7 @@ Changed version numbering method. From now on, new versions will be numbered by
|
||||
- In some cases, the date and time are not added to the filename
|
||||
- Unable to download photos from Twitter in full resolution (4K)
|
||||
|
||||
# 3.0.0.9
|
||||
## 3.0.0.9
|
||||
|
||||
*2022-04-24*
|
||||
|
||||
@@ -1375,7 +1492,7 @@ Changed version numbering method. From now on, new versions will be numbered by
|
||||
- Removed adding "No Parsed" internal label when not needed
|
||||
- Redownloading Instagram Stories
|
||||
|
||||
# 3.0.0.8
|
||||
## 3.0.0.8
|
||||
|
||||
*2022-04-19*
|
||||
|
||||
@@ -1385,7 +1502,7 @@ Changed version numbering method. From now on, new versions will be numbered by
|
||||
- Fixed
|
||||
- The script does not run after the user download is complete
|
||||
|
||||
# 3.0.0.7
|
||||
## 3.0.0.7
|
||||
|
||||
*2022-04-14*
|
||||
|
||||
@@ -1397,7 +1514,7 @@ Changed version numbering method. From now on, new versions will be numbered by
|
||||
- (Issue #33) Instagram Stories downloading error
|
||||
- LPSG downloader does not download all content
|
||||
|
||||
# 3.0.0.6
|
||||
## 3.0.0.6
|
||||
|
||||
*2022-04-04*
|
||||
|
||||
@@ -1410,14 +1527,14 @@ Changed version numbering method. From now on, new versions will be numbered by
|
||||
- Incorrect behavior of the main progress bar when downloading saved posts
|
||||
- (Issue #25) Date and Time not added for Stories and Tagged Photos
|
||||
|
||||
# 3.0.0.5
|
||||
## 3.0.0.5
|
||||
|
||||
*2022-04-02*
|
||||
|
||||
- Added
|
||||
- ```New```, ```Hot```, ```Top``` Reddit channel and user download modes
|
||||
|
||||
# 3.0.0.4
|
||||
## 3.0.0.4
|
||||
|
||||
*2022-03-26*
|
||||
|
||||
@@ -1425,7 +1542,7 @@ Changed version numbering method. From now on, new versions will be numbered by
|
||||
- External plugins do not save information about downloaded files
|
||||
- The user cannot be added to the collection if a special path has been specified.
|
||||
|
||||
# 3.0.0.3
|
||||
## 3.0.0.3
|
||||
|
||||
*2022-03-24*
|
||||
|
||||
@@ -1438,7 +1555,7 @@ Changed version numbering method. From now on, new versions will be numbered by
|
||||
- Typo when applying "Download UHD" in XVIDEOS plugin
|
||||
- The sites filter does not work unless the "Fast profiles loading" option is enabled.
|
||||
|
||||
# 3.0.0.2
|
||||
## 3.0.0.2
|
||||
|
||||
*2022-03-22*
|
||||
|
||||
@@ -1450,7 +1567,7 @@ Changed version numbering method. From now on, new versions will be numbered by
|
||||
- Fixed
|
||||
- Minor bugs
|
||||
|
||||
# 3.0.0.1
|
||||
## 3.0.0.1
|
||||
|
||||
*2022-03-20*
|
||||
|
||||
@@ -1465,7 +1582,7 @@ Changed version numbering method. From now on, new versions will be numbered by
|
||||
- Some design fixes
|
||||
- Minor bugs
|
||||
|
||||
# 3.0.0.0
|
||||
## 3.0.0.0
|
||||
|
||||
*2022-03-17*
|
||||
|
||||
@@ -1507,7 +1624,7 @@ Changed version numbering method. From now on, new versions will be numbered by
|
||||
|
||||
At the requests of some users, I added [screenshots](ProgramScreenshots) of the program and added screenshots to [ReadMe](README.md) and the [guide](https://github.com/AAndyProgram/SCrawler/wiki).
|
||||
|
||||
# 2.0.0.4
|
||||
## 2.0.0.4
|
||||
|
||||
*2022-02-07*
|
||||
|
||||
@@ -1523,7 +1640,7 @@ At the requests of some users, I added [screenshots](ProgramScreenshots) of the
|
||||
- **Error when specifying network paths**
|
||||
- Minor bugs
|
||||
|
||||
# 2.0.0.3
|
||||
## 2.0.0.3
|
||||
|
||||
*2022-02-02*
|
||||
|
||||
@@ -1540,7 +1657,7 @@ At the requests of some users, I added [screenshots](ProgramScreenshots) of the
|
||||
- Collection ignored when validated when creating a new user
|
||||
- Incorrect number of Instagram profiles downloads per session
|
||||
|
||||
# 2.0.0.2
|
||||
## 2.0.0.2
|
||||
|
||||
*2022-01-23*
|
||||
|
||||
@@ -1564,7 +1681,8 @@ At the requests of some users, I added [screenshots](ProgramScreenshots) of the
|
||||
- Fixed
|
||||
- The program was showing incorrect information about the total numbers of images and videos downloaded when a Reddit user was created from a channel
|
||||
|
||||
# 2.0.0.1
|
||||
# 2021
|
||||
## 2.0.0.1
|
||||
|
||||
*2021-12-29*
|
||||
|
||||
@@ -1574,7 +1692,7 @@ At the requests of some users, I added [screenshots](ProgramScreenshots) of the
|
||||
- Incorrect filling of user parameters in the user creation form
|
||||
- In some cases, the global settings cannot be saved.
|
||||
|
||||
# 2.0.0.0
|
||||
## 2.0.0.0
|
||||
|
||||
*2021-12-27*
|
||||
|
||||
@@ -1593,7 +1711,7 @@ At the requests of some users, I added [screenshots](ProgramScreenshots) of the
|
||||
- Suspended profiles do not change status if the profile is no longer suspended
|
||||
- Limited download for Twitter not implemented
|
||||
|
||||
# 1.0.1.0
|
||||
## 1.0.1.0
|
||||
|
||||
*2021-12-20*
|
||||
|
||||
@@ -1616,7 +1734,7 @@ At the requests of some users, I added [screenshots](ProgramScreenshots) of the
|
||||
- Users in the main window are not refreshed if new users are added by a list that includes banned and/or unrecognized users.
|
||||
- Minor bugs
|
||||
|
||||
# 1.0.0.4
|
||||
## 1.0.0.4
|
||||
|
||||
*2021-12-12*
|
||||
|
||||
@@ -1626,7 +1744,7 @@ At the requests of some users, I added [screenshots](ProgramScreenshots) of the
|
||||
- Fixed
|
||||
- Images hosted on Imgur won't download
|
||||
|
||||
# 1.0.0.3
|
||||
## 1.0.0.3
|
||||
|
||||
*2021-12-11*
|
||||
|
||||
@@ -1634,7 +1752,7 @@ At the requests of some users, I added [screenshots](ProgramScreenshots) of the
|
||||
- Custom "Download videos" option is not saved
|
||||
- The "Download all" button is not activated after changing modes
|
||||
|
||||
# 1.0.0.2
|
||||
## 1.0.0.2
|
||||
|
||||
*2021-12-10*
|
||||
|
||||
@@ -1644,7 +1762,7 @@ At the requests of some users, I added [screenshots](ProgramScreenshots) of the
|
||||
- Fixed
|
||||
- In some cases, the "Stop" button is not activated after download start
|
||||
|
||||
# 1.0.0.1
|
||||
## 1.0.0.1
|
||||
|
||||
*2021-12-09*
|
||||
|
||||
@@ -1668,7 +1786,7 @@ At the requests of some users, I added [screenshots](ProgramScreenshots) of the
|
||||
- Wrong some Reddit videos parsing
|
||||
- Wrong some Reddit images parsing
|
||||
|
||||
# 1.0.0.0
|
||||
## 1.0.0.0
|
||||
|
||||
*2021-12-07*
|
||||
|
||||
|
||||
@@ -8,3 +8,4 @@ List of available plugins:
|
||||
|
||||
Tools:
|
||||
- [image2post](https://github.com/unknown81311/SCrawler-image2post) by @unknown81311: **get reddit post URL from file.**
|
||||
- [Update-SCrawler-Tools](https://github.com/cjb900/Update-SCrawler-Tools) by @cjb900: **a tool for updating third-party programs such as yt-dlp and gallery-dl**
|
||||
|
Before Width: | Height: | Size: 101 KiB After Width: | Height: | Size: 121 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 24 KiB |
@@ -1,5 +1,6 @@
|
||||
<!--
|
||||
# 🏳️🌈 Happy LGBT Pride Month 🎉
|
||||
|
||||
-->
|
||||
# 🏳️🌈 Social networks crawler 🏳️🌈
|
||||
|
||||
[](https://github.com/AAndyProgram/SCrawler/releases/latest)
|
||||
|
||||
@@ -136,4 +136,34 @@ Namespace API.YouTube.Base
|
||||
End If
|
||||
End Function
|
||||
End Structure
|
||||
Public Structure TrimOption : Implements IComparable(Of TrimOption)
|
||||
Public Name As String
|
||||
Public Start As Integer
|
||||
Public ReadOnly Property StartTime As TimeSpan
|
||||
Get
|
||||
Return TimeSpan.FromSeconds(Start)
|
||||
End Get
|
||||
End Property
|
||||
Public [End] As Integer
|
||||
Public ReadOnly Property EndTime As TimeSpan
|
||||
Get
|
||||
Return TimeSpan.FromSeconds([End])
|
||||
End Get
|
||||
End Property
|
||||
Public Shared Widening Operator CType(ByVal t As TrimOption) As String
|
||||
Return t.ToString
|
||||
End Operator
|
||||
Public Overrides Function ToString() As String
|
||||
Dim v$ = $"{Start} - {[End]}"
|
||||
If Not Name.IsEmptyString Then v = $"[{v}] - {Name}"
|
||||
Return v
|
||||
End Function
|
||||
Public Overrides Function Equals(ByVal Obj As Object) As Boolean
|
||||
Try : With DirectCast(Obj, TrimOption) : Return Start = .Start And [End] = .End : End With : Catch : End Try
|
||||
Return False
|
||||
End Function
|
||||
Private Function CompareTo(ByVal Other As TrimOption) As Integer Implements IComparable(Of TrimOption).CompareTo
|
||||
Return Start.CompareTo(Other.Start)
|
||||
End Function
|
||||
End Structure
|
||||
End Namespace
|
||||
@@ -268,6 +268,9 @@ Namespace API.YouTube.Base
|
||||
<Browsable(True), GridVisible, XMLVN({"Defaults"}, FileDateMode.None), Category("Defaults"), DisplayName("Add channel to file name"),
|
||||
Description("Add channel name before/after the file name")>
|
||||
Public ReadOnly Property FileAddChannelToFileName As XMLValue(Of FileDateMode)
|
||||
<Browsable(True), GridVisible, XMLVN({"Defaults"}, True), Category("Defaults"), DisplayName("Parse long user titles"),
|
||||
Description("Suitable for multiple artists")>
|
||||
Public ReadOnly Property ParseLongUserTitle As XMLValue(Of Boolean)
|
||||
#End Region
|
||||
#Region "Defaults ChannelsDownload"
|
||||
<Browsable(True), GridVisible, XMLVN({"Defaults", "Channels"}), Category("Defaults"), DisplayName("Default download tabs for channels"),
|
||||
@@ -319,8 +322,11 @@ Namespace API.YouTube.Base
|
||||
Description("Convert non-AVC codecs (eg 'VP9') to AVC. Not recommended due to high CPU usage!")>
|
||||
Public ReadOnly Property DefaultVideoConvertNonAVC As XMLValue(Of Boolean)
|
||||
<Browsable(True), GridVisible, XMLVN({"DefaultsVideo"}, False), Category("Defaults Video"), DisplayName("Embed thumbnail (video)"),
|
||||
Description("Embed thumbnail in the video as cover art. Default: true.")>
|
||||
Description("Embed thumbnail in the video as cover art. Default: false.")>
|
||||
Public ReadOnly Property DefaultVideoEmbedThumbnail As XMLValue(Of Boolean)
|
||||
<Browsable(True), GridVisible, XMLVN({"DefaultsVideo"}, True), Category("Defaults Video"), DisplayName("Embed chapters"),
|
||||
Description("Embed chapters in the video. Default: true.")>
|
||||
Public ReadOnly Property DefaultVideoEmbedChapters As XMLValue(Of Boolean)
|
||||
<Browsable(True), GridVisible, XMLVN({"DefaultsVideo"}), Category("Defaults Video"), DisplayName("Include zero size formats"),
|
||||
Description("Include formats with zero size (or undefined size).")>
|
||||
Public ReadOnly Property DefaultVideoIncludeNullSize As XMLValue(Of Boolean)
|
||||
@@ -495,6 +501,29 @@ Namespace API.YouTube.Base
|
||||
TypeConverter(GetType(ValueCollectionConverter)),
|
||||
Description("Additional format for downloading subtitles. This means that all subtitles will be converted to the formats you choose and saved as separate files.")>
|
||||
Public ReadOnly Property DefaultSubtitlesFormatAddit As XMLValuesCollection(Of String)
|
||||
<Browsable(True), GridVisible, XMLVN({"DefaultsSubtitles"}), Category("Defaults Subtitles"), DisplayName("Embed subtitles"),
|
||||
Description("Embed subtitles in the video (only for mp4, webm and mkv videos)")>
|
||||
Public ReadOnly Property DefaultSubtitlesEmbed As XMLValue(Of Boolean)
|
||||
#End Region
|
||||
#Region "Trim"
|
||||
<Browsable(True), GridVisible, XMLVN({"DefaultsTrim"}, False), Category("Defaults Trimming"), DisplayName("Delete original file"),
|
||||
Description("If true, the original file will be deleted after trimming")>
|
||||
Public ReadOnly Property TrimDeleteOriginalFile As XMLValue(Of Boolean)
|
||||
<Browsable(True), GridVisible, XMLVN({"DefaultsTrim"}, False), Category("Defaults Trimming"), DisplayName("Add to M3U8"),
|
||||
Description("If true, the trimmed files will be added to the M3U8 playlist (if selected)")>
|
||||
Public ReadOnly Property TrimAddTrimmedFilesToM3U8 As XMLValue(Of Boolean)
|
||||
<Browsable(True), GridVisible, XMLVN({"DefaultsTrim"}, False), Category("Defaults Trimming"), DisplayName("Separate folder"),
|
||||
Description("Place the trimmed files in a separate folder")>
|
||||
Public ReadOnly Property TrimSeparateFolder As XMLValue(Of Boolean)
|
||||
Friend Const TrimSeparateFolderNameDefault As String = "Trim"
|
||||
<Browsable(True), GridVisible, XMLVN({"DefaultsTrim"}, TrimSeparateFolderNameDefault), Category("Defaults Trimming"), DisplayName("Separate folder name"),
|
||||
Description("Name of a separate folder")>
|
||||
Public ReadOnly Property TrimSeparateFolderName As XMLValue(Of String)
|
||||
#End Region
|
||||
#Region "Errors"
|
||||
<Browsable(True), GridVisible, XMLVN({"Errors"}, True), Category("ERRORS"), DisplayName("Ignore downloading errors"),
|
||||
Description("Ignore download errors if some files are missing (e.g. subtitles) and continue downloading")>
|
||||
Public ReadOnly Property ErrorsIgnore As XMLValue(Of Boolean)
|
||||
#End Region
|
||||
#End Region
|
||||
#Region "Initializer"
|
||||
|
||||
158
SCrawler.YouTube/Controls/ChaptersForm.Designer.vb
generated
Normal file
@@ -0,0 +1,158 @@
|
||||
' Copyright (C) Andy https://github.com/AAndyProgram
|
||||
' This program is free software: you can redistribute it and/or modify
|
||||
' it under the terms of the GNU General Public License as published by
|
||||
' the Free Software Foundation, either version 3 of the License, or
|
||||
' (at your option) any later version.
|
||||
'
|
||||
' This program is distributed in the hope that it will be useful,
|
||||
' but WITHOUT ANY WARRANTY
|
||||
Namespace API.YouTube.Controls
|
||||
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
|
||||
Partial Friend Class ChaptersForm : Inherits System.Windows.Forms.Form
|
||||
<System.Diagnostics.DebuggerNonUserCode()>
|
||||
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
|
||||
Try
|
||||
If disposing AndAlso components IsNot Nothing Then
|
||||
components.Dispose()
|
||||
End If
|
||||
Finally
|
||||
MyBase.Dispose(disposing)
|
||||
End Try
|
||||
End Sub
|
||||
Private components As System.ComponentModel.IContainer
|
||||
<System.Diagnostics.DebuggerStepThrough()>
|
||||
Private Sub InitializeComponent()
|
||||
Dim CONTAINER_MAIN As System.Windows.Forms.ToolStripContainer
|
||||
Dim TP_MAIN As System.Windows.Forms.TableLayoutPanel
|
||||
Dim TP_BUTTONS As System.Windows.Forms.TableLayoutPanel
|
||||
Me.BTT_ALL = New System.Windows.Forms.Button()
|
||||
Me.BTT_NONE = New System.Windows.Forms.Button()
|
||||
Me.BTT_INVERT = New System.Windows.Forms.Button()
|
||||
Me.LIST_CHAPTERS = New System.Windows.Forms.CheckedListBox()
|
||||
CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer()
|
||||
TP_MAIN = New System.Windows.Forms.TableLayoutPanel()
|
||||
TP_BUTTONS = New System.Windows.Forms.TableLayoutPanel()
|
||||
CONTAINER_MAIN.ContentPanel.SuspendLayout()
|
||||
CONTAINER_MAIN.SuspendLayout()
|
||||
TP_MAIN.SuspendLayout()
|
||||
TP_BUTTONS.SuspendLayout()
|
||||
Me.SuspendLayout()
|
||||
'
|
||||
'CONTAINER_MAIN
|
||||
'
|
||||
'
|
||||
'CONTAINER_MAIN.ContentPanel
|
||||
'
|
||||
CONTAINER_MAIN.ContentPanel.Controls.Add(TP_MAIN)
|
||||
CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(384, 361)
|
||||
CONTAINER_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
|
||||
CONTAINER_MAIN.LeftToolStripPanelVisible = False
|
||||
CONTAINER_MAIN.Location = New System.Drawing.Point(0, 0)
|
||||
CONTAINER_MAIN.Name = "CONTAINER_MAIN"
|
||||
CONTAINER_MAIN.RightToolStripPanelVisible = False
|
||||
CONTAINER_MAIN.Size = New System.Drawing.Size(384, 361)
|
||||
CONTAINER_MAIN.TabIndex = 0
|
||||
CONTAINER_MAIN.TopToolStripPanelVisible = False
|
||||
'
|
||||
'TP_MAIN
|
||||
'
|
||||
TP_MAIN.ColumnCount = 1
|
||||
TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||
TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20.0!))
|
||||
TP_MAIN.Controls.Add(TP_BUTTONS, 0, 1)
|
||||
TP_MAIN.Controls.Add(Me.LIST_CHAPTERS, 0, 0)
|
||||
TP_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
|
||||
TP_MAIN.Location = New System.Drawing.Point(0, 0)
|
||||
TP_MAIN.Name = "TP_MAIN"
|
||||
TP_MAIN.RowCount = 2
|
||||
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 30.0!))
|
||||
TP_MAIN.Size = New System.Drawing.Size(384, 361)
|
||||
TP_MAIN.TabIndex = 0
|
||||
'
|
||||
'TP_BUTTONS
|
||||
'
|
||||
TP_BUTTONS.ColumnCount = 3
|
||||
TP_BUTTONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333!))
|
||||
TP_BUTTONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333!))
|
||||
TP_BUTTONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333!))
|
||||
TP_BUTTONS.Controls.Add(Me.BTT_ALL, 0, 0)
|
||||
TP_BUTTONS.Controls.Add(Me.BTT_NONE, 1, 0)
|
||||
TP_BUTTONS.Controls.Add(Me.BTT_INVERT, 2, 0)
|
||||
TP_BUTTONS.Dock = System.Windows.Forms.DockStyle.Fill
|
||||
TP_BUTTONS.Location = New System.Drawing.Point(0, 331)
|
||||
TP_BUTTONS.Margin = New System.Windows.Forms.Padding(0)
|
||||
TP_BUTTONS.Name = "TP_BUTTONS"
|
||||
TP_BUTTONS.RowCount = 1
|
||||
TP_BUTTONS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||
TP_BUTTONS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20.0!))
|
||||
TP_BUTTONS.Size = New System.Drawing.Size(384, 30)
|
||||
TP_BUTTONS.TabIndex = 1
|
||||
'
|
||||
'BTT_ALL
|
||||
'
|
||||
Me.BTT_ALL.Dock = System.Windows.Forms.DockStyle.Fill
|
||||
Me.BTT_ALL.Location = New System.Drawing.Point(3, 3)
|
||||
Me.BTT_ALL.Name = "BTT_ALL"
|
||||
Me.BTT_ALL.Size = New System.Drawing.Size(122, 24)
|
||||
Me.BTT_ALL.TabIndex = 0
|
||||
Me.BTT_ALL.Text = "All"
|
||||
Me.BTT_ALL.UseVisualStyleBackColor = True
|
||||
'
|
||||
'BTT_NONE
|
||||
'
|
||||
Me.BTT_NONE.Dock = System.Windows.Forms.DockStyle.Fill
|
||||
Me.BTT_NONE.Location = New System.Drawing.Point(131, 3)
|
||||
Me.BTT_NONE.Name = "BTT_NONE"
|
||||
Me.BTT_NONE.Size = New System.Drawing.Size(122, 24)
|
||||
Me.BTT_NONE.TabIndex = 1
|
||||
Me.BTT_NONE.Text = "None"
|
||||
Me.BTT_NONE.UseVisualStyleBackColor = True
|
||||
'
|
||||
'BTT_INVERT
|
||||
'
|
||||
Me.BTT_INVERT.Dock = System.Windows.Forms.DockStyle.Fill
|
||||
Me.BTT_INVERT.Location = New System.Drawing.Point(259, 3)
|
||||
Me.BTT_INVERT.Name = "BTT_INVERT"
|
||||
Me.BTT_INVERT.Size = New System.Drawing.Size(122, 24)
|
||||
Me.BTT_INVERT.TabIndex = 2
|
||||
Me.BTT_INVERT.Text = "Invert"
|
||||
Me.BTT_INVERT.UseVisualStyleBackColor = True
|
||||
'
|
||||
'LIST_CHAPTERS
|
||||
'
|
||||
Me.LIST_CHAPTERS.Dock = System.Windows.Forms.DockStyle.Fill
|
||||
Me.LIST_CHAPTERS.FormattingEnabled = True
|
||||
Me.LIST_CHAPTERS.Location = New System.Drawing.Point(3, 3)
|
||||
Me.LIST_CHAPTERS.Name = "LIST_CHAPTERS"
|
||||
Me.LIST_CHAPTERS.Size = New System.Drawing.Size(378, 325)
|
||||
Me.LIST_CHAPTERS.TabIndex = 0
|
||||
'
|
||||
'ChaptersForm
|
||||
'
|
||||
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
|
||||
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
|
||||
Me.ClientSize = New System.Drawing.Size(384, 361)
|
||||
Me.Controls.Add(CONTAINER_MAIN)
|
||||
Me.KeyPreview = True
|
||||
Me.MinimizeBox = False
|
||||
Me.MinimumSize = New System.Drawing.Size(400, 400)
|
||||
Me.Name = "ChaptersForm"
|
||||
Me.ShowIcon = False
|
||||
Me.ShowInTaskbar = False
|
||||
Me.Text = "Chapters"
|
||||
CONTAINER_MAIN.ContentPanel.ResumeLayout(False)
|
||||
CONTAINER_MAIN.ResumeLayout(False)
|
||||
CONTAINER_MAIN.PerformLayout()
|
||||
TP_MAIN.ResumeLayout(False)
|
||||
TP_BUTTONS.ResumeLayout(False)
|
||||
Me.ResumeLayout(False)
|
||||
|
||||
End Sub
|
||||
|
||||
Private WithEvents BTT_ALL As Button
|
||||
Private WithEvents BTT_NONE As Button
|
||||
Private WithEvents BTT_INVERT As Button
|
||||
Private WithEvents LIST_CHAPTERS As CheckedListBox
|
||||
End Class
|
||||
End Namespace
|
||||
129
SCrawler.YouTube/Controls/ChaptersForm.resx
Normal file
@@ -0,0 +1,129 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<metadata name="CONTAINER_MAIN.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>False</value>
|
||||
</metadata>
|
||||
<metadata name="TP_MAIN.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>False</value>
|
||||
</metadata>
|
||||
<metadata name="TP_BUTTONS.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>False</value>
|
||||
</metadata>
|
||||
</root>
|
||||
66
SCrawler.YouTube/Controls/ChaptersForm.vb
Normal file
@@ -0,0 +1,66 @@
|
||||
' Copyright (C) Andy https://github.com/AAndyProgram
|
||||
' This program is free software: you can redistribute it and/or modify
|
||||
' it under the terms of the GNU General Public License as published by
|
||||
' the Free Software Foundation, either version 3 of the License, or
|
||||
' (at your option) any later version.
|
||||
'
|
||||
' This program is distributed in the hope that it will be useful,
|
||||
' but WITHOUT ANY WARRANTY
|
||||
Imports PersonalUtilities.Forms
|
||||
Imports PersonalUtilities.Forms.Toolbars
|
||||
Imports SCrawler.API.YouTube.Base
|
||||
Imports SCrawler.API.YouTube.Objects
|
||||
Namespace API.YouTube.Controls
|
||||
Friend Class ChaptersForm
|
||||
Private WithEvents MyDefs As DefaultFormOptions
|
||||
Private ReadOnly Property MyData As YouTubeMediaContainerBase
|
||||
Private ReadOnly Property MyDataSelected As List(Of TrimOption)
|
||||
Friend ReadOnly Property MyResult As List(Of TrimOption)
|
||||
Friend Sub New(ByRef data As YouTubeMediaContainerBase, ByVal selected As IEnumerable(Of TrimOption))
|
||||
InitializeComponent()
|
||||
MyDefs = New DefaultFormOptions(Me, MyYouTubeSettings.DesignXml)
|
||||
MyData = data
|
||||
MyDataSelected = New List(Of TrimOption)
|
||||
MyDataSelected.ListAddList(selected)
|
||||
MyResult = New List(Of TrimOption)
|
||||
End Sub
|
||||
Private Sub ChaptersForm_Load(sender As Object, e As EventArgs) Handles Me.Load
|
||||
With MyDefs
|
||||
.MyViewInitialize()
|
||||
.AddOkCancelToolbar()
|
||||
|
||||
With LIST_CHAPTERS
|
||||
.BeginUpdate()
|
||||
.Items.AddRange(MyData.Chapters.Cast(Of Object).ToArray)
|
||||
If MyDataSelected.Count > 0 Then
|
||||
For i% = 0 To .Items.Count - 1 : .SetItemChecked(i, MyDataSelected.Contains(MyData.Chapters(i))) : Next
|
||||
End If
|
||||
.EndUpdate()
|
||||
End With
|
||||
|
||||
.EndLoaderOperations()
|
||||
End With
|
||||
End Sub
|
||||
Private Sub ChaptersForm_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed
|
||||
MyResult.Clear()
|
||||
MyDataSelected.Clear()
|
||||
End Sub
|
||||
Private Sub MyDefs_ButtonOkClick(ByVal Sender As Object, ByVal e As KeyHandleEventArgs) Handles MyDefs.ButtonOkClick
|
||||
With LIST_CHAPTERS
|
||||
For i% = 0 To .Items.Count - 1
|
||||
If .GetItemChecked(i) Then MyResult.Add(MyData.Chapters(i))
|
||||
Next
|
||||
End With
|
||||
MyDefs.CloseForm()
|
||||
End Sub
|
||||
Private Sub BTT_ALL_NONE_INVERT_Click(sender As Object, e As EventArgs) Handles BTT_ALL.Click, BTT_NONE.Click, BTT_INVERT.Click
|
||||
Dim v As Boolean = sender Is BTT_ALL
|
||||
Dim isInvert As Boolean = sender Is BTT_INVERT
|
||||
With LIST_CHAPTERS
|
||||
.BeginUpdate()
|
||||
For i% = 0 To .Items.Count - 1 : .SetItemChecked(i, If(isInvert, Not .GetItemChecked(i), v)) : Next
|
||||
.EndUpdate()
|
||||
End With
|
||||
End Sub
|
||||
End Class
|
||||
End Namespace
|
||||
274
SCrawler.YouTube/Controls/TrimOptionForm.Designer.vb
generated
Normal file
@@ -0,0 +1,274 @@
|
||||
' Copyright (C) Andy https://github.com/AAndyProgram
|
||||
' This program is free software: you can redistribute it and/or modify
|
||||
' it under the terms of the GNU General Public License as published by
|
||||
' the Free Software Foundation, either version 3 of the License, or
|
||||
' (at your option) any later version.
|
||||
'
|
||||
' This program is distributed in the hope that it will be useful,
|
||||
' but WITHOUT ANY WARRANTY
|
||||
Namespace API.YouTube.Controls
|
||||
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
|
||||
Partial Friend Class TrimOptionForm : Inherits System.Windows.Forms.Form
|
||||
<System.Diagnostics.DebuggerNonUserCode()>
|
||||
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
|
||||
Try
|
||||
If disposing AndAlso components IsNot Nothing Then
|
||||
components.Dispose()
|
||||
End If
|
||||
Finally
|
||||
MyBase.Dispose(disposing)
|
||||
End Try
|
||||
End Sub
|
||||
Private components As System.ComponentModel.IContainer
|
||||
<System.Diagnostics.DebuggerStepThrough()>
|
||||
Private Sub InitializeComponent()
|
||||
Dim CONTAINER_MAIN As System.Windows.Forms.ToolStripContainer
|
||||
Dim TP_MAIN As System.Windows.Forms.TableLayoutPanel
|
||||
Dim ActionButton1 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||
Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(TrimOptionForm))
|
||||
Dim TP_OPTIONS As System.Windows.Forms.TableLayoutPanel
|
||||
Me.TXT_NAME = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
||||
Me.TP_TIME_TIME = New System.Windows.Forms.TableLayoutPanel()
|
||||
Me.TXT_FROM_DATE = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
||||
Me.TXT_TO_DATE = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
||||
Me.OPT_INT = New System.Windows.Forms.RadioButton()
|
||||
Me.OPT_TIME = New System.Windows.Forms.RadioButton()
|
||||
Me.TP_TIME_INT = New System.Windows.Forms.TableLayoutPanel()
|
||||
Me.TXT_FROM_INT = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
||||
Me.TXT_TO_INT = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
||||
CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer()
|
||||
TP_MAIN = New System.Windows.Forms.TableLayoutPanel()
|
||||
TP_OPTIONS = New System.Windows.Forms.TableLayoutPanel()
|
||||
CONTAINER_MAIN.ContentPanel.SuspendLayout()
|
||||
CONTAINER_MAIN.SuspendLayout()
|
||||
TP_MAIN.SuspendLayout()
|
||||
CType(Me.TXT_NAME, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||
TP_OPTIONS.SuspendLayout()
|
||||
Me.TP_TIME_TIME.SuspendLayout()
|
||||
CType(Me.TXT_FROM_DATE, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||
CType(Me.TXT_TO_DATE, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||
Me.TP_TIME_INT.SuspendLayout()
|
||||
CType(Me.TXT_FROM_INT, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||
CType(Me.TXT_TO_INT, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||
Me.SuspendLayout()
|
||||
'
|
||||
'CONTAINER_MAIN
|
||||
'
|
||||
'
|
||||
'CONTAINER_MAIN.ContentPanel
|
||||
'
|
||||
CONTAINER_MAIN.ContentPanel.Controls.Add(TP_MAIN)
|
||||
CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(334, 112)
|
||||
CONTAINER_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
|
||||
CONTAINER_MAIN.LeftToolStripPanelVisible = False
|
||||
CONTAINER_MAIN.Location = New System.Drawing.Point(0, 0)
|
||||
CONTAINER_MAIN.Name = "CONTAINER_MAIN"
|
||||
CONTAINER_MAIN.RightToolStripPanelVisible = False
|
||||
CONTAINER_MAIN.Size = New System.Drawing.Size(334, 112)
|
||||
CONTAINER_MAIN.TabIndex = 0
|
||||
CONTAINER_MAIN.TopToolStripPanelVisible = False
|
||||
'
|
||||
'TP_MAIN
|
||||
'
|
||||
TP_MAIN.ColumnCount = 1
|
||||
TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||
TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20.0!))
|
||||
TP_MAIN.Controls.Add(Me.TXT_NAME, 0, 0)
|
||||
TP_MAIN.Controls.Add(TP_OPTIONS, 0, 1)
|
||||
TP_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
|
||||
TP_MAIN.Location = New System.Drawing.Point(0, 0)
|
||||
TP_MAIN.Name = "TP_MAIN"
|
||||
TP_MAIN.RowCount = 2
|
||||
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
|
||||
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||
TP_MAIN.Size = New System.Drawing.Size(334, 112)
|
||||
TP_MAIN.TabIndex = 0
|
||||
'
|
||||
'TXT_NAME
|
||||
'
|
||||
ActionButton1.BackgroundImage = CType(resources.GetObject("ActionButton1.BackgroundImage"), System.Drawing.Image)
|
||||
ActionButton1.Name = "Clear"
|
||||
ActionButton1.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
|
||||
Me.TXT_NAME.Buttons.Add(ActionButton1)
|
||||
Me.TXT_NAME.CaptionText = "Name"
|
||||
Me.TXT_NAME.CaptionToolTipText = "Section name"
|
||||
Me.TXT_NAME.CaptionWidth = 50.0R
|
||||
Me.TXT_NAME.Dock = System.Windows.Forms.DockStyle.Fill
|
||||
Me.TXT_NAME.Location = New System.Drawing.Point(3, 3)
|
||||
Me.TXT_NAME.Name = "TXT_NAME"
|
||||
Me.TXT_NAME.Size = New System.Drawing.Size(328, 22)
|
||||
Me.TXT_NAME.TabIndex = 0
|
||||
'
|
||||
'TP_OPTIONS
|
||||
'
|
||||
TP_OPTIONS.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single]
|
||||
TP_OPTIONS.ColumnCount = 2
|
||||
TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 30.0!))
|
||||
TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||
TP_OPTIONS.Controls.Add(Me.TP_TIME_TIME, 1, 1)
|
||||
TP_OPTIONS.Controls.Add(Me.OPT_INT, 0, 0)
|
||||
TP_OPTIONS.Controls.Add(Me.OPT_TIME, 0, 1)
|
||||
TP_OPTIONS.Controls.Add(Me.TP_TIME_INT, 1, 0)
|
||||
TP_OPTIONS.Dock = System.Windows.Forms.DockStyle.Fill
|
||||
TP_OPTIONS.Location = New System.Drawing.Point(3, 31)
|
||||
TP_OPTIONS.Name = "TP_OPTIONS"
|
||||
TP_OPTIONS.RowCount = 3
|
||||
TP_OPTIONS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
|
||||
TP_OPTIONS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
|
||||
TP_OPTIONS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||
TP_OPTIONS.Size = New System.Drawing.Size(328, 78)
|
||||
TP_OPTIONS.TabIndex = 1
|
||||
'
|
||||
'TP_TIME_TIME
|
||||
'
|
||||
Me.TP_TIME_TIME.ColumnCount = 2
|
||||
Me.TP_TIME_TIME.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
|
||||
Me.TP_TIME_TIME.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
|
||||
Me.TP_TIME_TIME.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20.0!))
|
||||
Me.TP_TIME_TIME.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20.0!))
|
||||
Me.TP_TIME_TIME.Controls.Add(Me.TXT_FROM_DATE, 0, 0)
|
||||
Me.TP_TIME_TIME.Controls.Add(Me.TXT_TO_DATE, 1, 0)
|
||||
Me.TP_TIME_TIME.Dock = System.Windows.Forms.DockStyle.Fill
|
||||
Me.TP_TIME_TIME.Location = New System.Drawing.Point(32, 27)
|
||||
Me.TP_TIME_TIME.Margin = New System.Windows.Forms.Padding(0)
|
||||
Me.TP_TIME_TIME.Name = "TP_TIME_TIME"
|
||||
Me.TP_TIME_TIME.RowCount = 1
|
||||
Me.TP_TIME_TIME.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||
Me.TP_TIME_TIME.Size = New System.Drawing.Size(295, 25)
|
||||
Me.TP_TIME_TIME.TabIndex = 3
|
||||
'
|
||||
'TXT_FROM_DATE
|
||||
'
|
||||
Me.TXT_FROM_DATE.CaptionPadding = New System.Windows.Forms.Padding(0, 0, 6, 0)
|
||||
Me.TXT_FROM_DATE.CaptionText = "From"
|
||||
Me.TXT_FROM_DATE.CaptionWidth = 40.0R
|
||||
Me.TXT_FROM_DATE.Dock = System.Windows.Forms.DockStyle.Fill
|
||||
Me.TXT_FROM_DATE.Location = New System.Drawing.Point(3, 3)
|
||||
Me.TXT_FROM_DATE.Name = "TXT_FROM_DATE"
|
||||
Me.TXT_FROM_DATE.PlaceholderEnabled = True
|
||||
Me.TXT_FROM_DATE.PlaceholderText = "h:mm:ss"
|
||||
Me.TXT_FROM_DATE.Size = New System.Drawing.Size(141, 22)
|
||||
Me.TXT_FROM_DATE.TabIndex = 0
|
||||
'
|
||||
'TXT_TO_DATE
|
||||
'
|
||||
Me.TXT_TO_DATE.CaptionPadding = New System.Windows.Forms.Padding(0, 0, 6, 0)
|
||||
Me.TXT_TO_DATE.CaptionText = "To"
|
||||
Me.TXT_TO_DATE.CaptionWidth = 40.0R
|
||||
Me.TXT_TO_DATE.Dock = System.Windows.Forms.DockStyle.Fill
|
||||
Me.TXT_TO_DATE.Location = New System.Drawing.Point(150, 3)
|
||||
Me.TXT_TO_DATE.Name = "TXT_TO_DATE"
|
||||
Me.TXT_TO_DATE.PlaceholderEnabled = True
|
||||
Me.TXT_TO_DATE.PlaceholderText = "h:mm:ss"
|
||||
Me.TXT_TO_DATE.Size = New System.Drawing.Size(142, 22)
|
||||
Me.TXT_TO_DATE.TabIndex = 1
|
||||
'
|
||||
'OPT_INT
|
||||
'
|
||||
Me.OPT_INT.AutoSize = True
|
||||
Me.OPT_INT.CheckAlign = System.Drawing.ContentAlignment.MiddleCenter
|
||||
Me.OPT_INT.Dock = System.Windows.Forms.DockStyle.Fill
|
||||
Me.OPT_INT.Location = New System.Drawing.Point(4, 4)
|
||||
Me.OPT_INT.Name = "OPT_INT"
|
||||
Me.OPT_INT.Size = New System.Drawing.Size(24, 19)
|
||||
Me.OPT_INT.TabIndex = 0
|
||||
Me.OPT_INT.TabStop = True
|
||||
Me.OPT_INT.UseVisualStyleBackColor = True
|
||||
'
|
||||
'OPT_TIME
|
||||
'
|
||||
Me.OPT_TIME.AutoSize = True
|
||||
Me.OPT_TIME.CheckAlign = System.Drawing.ContentAlignment.MiddleCenter
|
||||
Me.OPT_TIME.Dock = System.Windows.Forms.DockStyle.Fill
|
||||
Me.OPT_TIME.Location = New System.Drawing.Point(4, 30)
|
||||
Me.OPT_TIME.Name = "OPT_TIME"
|
||||
Me.OPT_TIME.Size = New System.Drawing.Size(24, 19)
|
||||
Me.OPT_TIME.TabIndex = 1
|
||||
Me.OPT_TIME.TabStop = True
|
||||
Me.OPT_TIME.UseVisualStyleBackColor = True
|
||||
'
|
||||
'TP_TIME_INT
|
||||
'
|
||||
Me.TP_TIME_INT.ColumnCount = 2
|
||||
Me.TP_TIME_INT.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
|
||||
Me.TP_TIME_INT.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
|
||||
Me.TP_TIME_INT.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20.0!))
|
||||
Me.TP_TIME_INT.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20.0!))
|
||||
Me.TP_TIME_INT.Controls.Add(Me.TXT_FROM_INT, 0, 0)
|
||||
Me.TP_TIME_INT.Controls.Add(Me.TXT_TO_INT, 1, 0)
|
||||
Me.TP_TIME_INT.Dock = System.Windows.Forms.DockStyle.Fill
|
||||
Me.TP_TIME_INT.Location = New System.Drawing.Point(32, 1)
|
||||
Me.TP_TIME_INT.Margin = New System.Windows.Forms.Padding(0)
|
||||
Me.TP_TIME_INT.Name = "TP_TIME_INT"
|
||||
Me.TP_TIME_INT.RowCount = 1
|
||||
Me.TP_TIME_INT.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||
Me.TP_TIME_INT.Size = New System.Drawing.Size(295, 25)
|
||||
Me.TP_TIME_INT.TabIndex = 2
|
||||
'
|
||||
'TXT_FROM_INT
|
||||
'
|
||||
Me.TXT_FROM_INT.CaptionPadding = New System.Windows.Forms.Padding(0, 0, 6, 0)
|
||||
Me.TXT_FROM_INT.CaptionText = "From"
|
||||
Me.TXT_FROM_INT.CaptionWidth = 40.0R
|
||||
Me.TXT_FROM_INT.Dock = System.Windows.Forms.DockStyle.Fill
|
||||
Me.TXT_FROM_INT.Location = New System.Drawing.Point(3, 3)
|
||||
Me.TXT_FROM_INT.Name = "TXT_FROM_INT"
|
||||
Me.TXT_FROM_INT.Size = New System.Drawing.Size(141, 22)
|
||||
Me.TXT_FROM_INT.TabIndex = 0
|
||||
'
|
||||
'TXT_TO_INT
|
||||
'
|
||||
Me.TXT_TO_INT.CaptionPadding = New System.Windows.Forms.Padding(0, 0, 6, 0)
|
||||
Me.TXT_TO_INT.CaptionText = "To"
|
||||
Me.TXT_TO_INT.CaptionWidth = 40.0R
|
||||
Me.TXT_TO_INT.Dock = System.Windows.Forms.DockStyle.Fill
|
||||
Me.TXT_TO_INT.Location = New System.Drawing.Point(150, 3)
|
||||
Me.TXT_TO_INT.Name = "TXT_TO_INT"
|
||||
Me.TXT_TO_INT.Size = New System.Drawing.Size(142, 22)
|
||||
Me.TXT_TO_INT.TabIndex = 1
|
||||
'
|
||||
'TrimOptionForm
|
||||
'
|
||||
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
|
||||
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
|
||||
Me.ClientSize = New System.Drawing.Size(334, 112)
|
||||
Me.Controls.Add(CONTAINER_MAIN)
|
||||
Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle
|
||||
Me.KeyPreview = True
|
||||
Me.MaximizeBox = False
|
||||
Me.MaximumSize = New System.Drawing.Size(350, 151)
|
||||
Me.MinimizeBox = False
|
||||
Me.MinimumSize = New System.Drawing.Size(350, 151)
|
||||
Me.Name = "TrimOptionForm"
|
||||
Me.ShowIcon = False
|
||||
Me.ShowInTaskbar = False
|
||||
Me.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide
|
||||
Me.Text = "Trim option"
|
||||
CONTAINER_MAIN.ContentPanel.ResumeLayout(False)
|
||||
CONTAINER_MAIN.ResumeLayout(False)
|
||||
CONTAINER_MAIN.PerformLayout()
|
||||
TP_MAIN.ResumeLayout(False)
|
||||
CType(Me.TXT_NAME, System.ComponentModel.ISupportInitialize).EndInit()
|
||||
TP_OPTIONS.ResumeLayout(False)
|
||||
TP_OPTIONS.PerformLayout()
|
||||
Me.TP_TIME_TIME.ResumeLayout(False)
|
||||
CType(Me.TXT_FROM_DATE, System.ComponentModel.ISupportInitialize).EndInit()
|
||||
CType(Me.TXT_TO_DATE, System.ComponentModel.ISupportInitialize).EndInit()
|
||||
Me.TP_TIME_INT.ResumeLayout(False)
|
||||
CType(Me.TXT_FROM_INT, System.ComponentModel.ISupportInitialize).EndInit()
|
||||
CType(Me.TXT_TO_INT, System.ComponentModel.ISupportInitialize).EndInit()
|
||||
Me.ResumeLayout(False)
|
||||
|
||||
End Sub
|
||||
|
||||
Private WithEvents TXT_NAME As PersonalUtilities.Forms.Controls.TextBoxExtended
|
||||
Private WithEvents OPT_INT As RadioButton
|
||||
Private WithEvents OPT_TIME As RadioButton
|
||||
Private WithEvents TP_TIME_INT As TableLayoutPanel
|
||||
Private WithEvents TP_TIME_TIME As TableLayoutPanel
|
||||
Private WithEvents TXT_FROM_DATE As PersonalUtilities.Forms.Controls.TextBoxExtended
|
||||
Private WithEvents TXT_TO_DATE As PersonalUtilities.Forms.Controls.TextBoxExtended
|
||||
Private WithEvents TXT_FROM_INT As PersonalUtilities.Forms.Controls.TextBoxExtended
|
||||
Private WithEvents TXT_TO_INT As PersonalUtilities.Forms.Controls.TextBoxExtended
|
||||
End Class
|
||||
End Namespace
|
||||
138
SCrawler.YouTube/Controls/TrimOptionForm.resx
Normal file
@@ -0,0 +1,138 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<metadata name="CONTAINER_MAIN.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>False</value>
|
||||
</metadata>
|
||||
<metadata name="TP_MAIN.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>False</value>
|
||||
</metadata>
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<data name="ActionButton1.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||
vgAADr4B6kKxwAAAAHpJREFUOE+1kVEKgDAMQ3e2/e+MXqpn6W/HxM7SpkIVB4HxSMKiTUTaFwVQ1X25
|
||||
DjMfSxskHBYsAxHJkjUjHgrUNMY4peaMPxb03rcZMVhgn2oDKAwn+L0aROH/Cny4NAGFSx8x+10ZDwV2
|
||||
gt+LOCxQsw1nPBS8VQBVTTzyhrdZSUm7AAAAAElFTkSuQmCC
|
||||
</value>
|
||||
</data>
|
||||
<metadata name="TP_OPTIONS.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>False</value>
|
||||
</metadata>
|
||||
</root>
|
||||
79
SCrawler.YouTube/Controls/TrimOptionForm.vb
Normal file
@@ -0,0 +1,79 @@
|
||||
' Copyright (C) Andy https://github.com/AAndyProgram
|
||||
' This program is free software: you can redistribute it and/or modify
|
||||
' it under the terms of the GNU General Public License as published by
|
||||
' the Free Software Foundation, either version 3 of the License, or
|
||||
' (at your option) any later version.
|
||||
'
|
||||
' This program is distributed in the hope that it will be useful,
|
||||
' but WITHOUT ANY WARRANTY
|
||||
Imports PersonalUtilities.Forms
|
||||
Imports PersonalUtilities.Forms.Toolbars
|
||||
Imports SCrawler.API.YouTube.Base
|
||||
Namespace API.YouTube.Controls
|
||||
Friend Class TrimOptionForm
|
||||
Private WithEvents MyDefs As DefaultFormOptions
|
||||
Friend Property MyTrimOption As TrimOption
|
||||
Private ReadOnly FieldsDateProvider As New CustomProvider(Function(v) AConvert(Of TimeSpan)(v, Nothing, EDP.ReturnValue))
|
||||
Private ReadOnly TCE As New ErrorsDescriber(False, False, False, New TimeSpan)
|
||||
Friend Sub New(Optional ByVal Opt As TrimOption = Nothing)
|
||||
InitializeComponent()
|
||||
MyDefs = New DefaultFormOptions(Me, MyYouTubeSettings.DesignXml)
|
||||
MyTrimOption = Opt
|
||||
End Sub
|
||||
Private Sub TrimOptionForm_Load(sender As Object, e As EventArgs) Handles Me.Load
|
||||
Try
|
||||
With MyDefs
|
||||
.MyViewInitialize()
|
||||
.AddOkCancelToolbar()
|
||||
|
||||
TXT_NAME.Text = MyTrimOption.Name
|
||||
TXT_FROM_INT.Text = MyTrimOption.Start
|
||||
TXT_TO_INT.Text = MyTrimOption.End
|
||||
|
||||
OPT_INT.Checked = True
|
||||
|
||||
.MyFieldsCheckerE = New FieldsChecker
|
||||
With .MyFieldsCheckerE
|
||||
.AddControl(Of Integer)(TXT_FROM_INT, "From")
|
||||
.AddControl(Of Integer)(TXT_TO_INT, "To")
|
||||
.AddControl(Of String)(TXT_FROM_DATE, "From (time)",, FieldsDateProvider)
|
||||
.AddControl(Of String)(TXT_TO_DATE, "To (time)",, FieldsDateProvider)
|
||||
.EndLoaderOperations()
|
||||
End With
|
||||
|
||||
.EndLoaderOperations()
|
||||
End With
|
||||
Catch ex As Exception
|
||||
MyDefs.InvokeLoaderError(ex)
|
||||
End Try
|
||||
End Sub
|
||||
Private Sub MyDefs_ButtonOkClick(ByVal Sender As Object, ByVal e As KeyHandleEventArgs) Handles MyDefs.ButtonOkClick
|
||||
If MyDefs.MyFieldsChecker.AllParamsOK Then
|
||||
MyTrimOption = New TrimOption With {
|
||||
.Name = TXT_NAME.Text,
|
||||
.Start = AConvert(Of Integer)(TXT_FROM_INT.Text, 0),
|
||||
.[End] = AConvert(Of Integer)(TXT_TO_INT.Text, 0)
|
||||
}
|
||||
MyDefs.CloseForm()
|
||||
End If
|
||||
End Sub
|
||||
Private Sub OPT_INT_TIME_CheckedChanged(sender As Object, e As EventArgs) Handles OPT_INT.CheckedChanged, OPT_TIME.CheckedChanged
|
||||
TP_TIME_INT.Enabled = OPT_INT.Checked
|
||||
TP_TIME_TIME.Enabled = OPT_TIME.Checked
|
||||
End Sub
|
||||
Private _TextHandlersEnabled As Boolean = True
|
||||
Private Sub TXT_FROM_TO_TextChanged(sender As Object, e As EventArgs) Handles TXT_FROM_INT.ActionOnTextChanged, TXT_TO_INT.ActionOnTextChanged,
|
||||
TXT_FROM_DATE.ActionOnTextChanged, TXT_TO_DATE.ActionOnTextChanged
|
||||
If _TextHandlersEnabled Then
|
||||
_TextHandlersEnabled = False
|
||||
Select Case DirectCast(sender, Control).Name
|
||||
Case TXT_FROM_INT.Name : TXT_FROM_DATE.Value = AConvert(Of String)(TimeSpan.FromSeconds(AConvert(Of Integer)(TXT_FROM_INT.Text, 0)), TimeToStringProviderH)
|
||||
Case TXT_TO_INT.Name : TXT_TO_DATE.Value = AConvert(Of String)(TimeSpan.FromSeconds(AConvert(Of Integer)(TXT_TO_INT.Text, 0)), TimeToStringProviderH)
|
||||
Case TXT_FROM_DATE.Name : TXT_FROM_INT.Text = CInt(CType(AConvert(Of TimeSpan)(TXT_FROM_DATE.Text, TCE), TimeSpan).TotalSeconds)
|
||||
Case TXT_TO_DATE.Name : TXT_TO_INT.Text = CInt(CType(AConvert(Of TimeSpan)(TXT_TO_DATE.Text, TCE), TimeSpan).TotalSeconds)
|
||||
End Select
|
||||
_TextHandlersEnabled = True
|
||||
End If
|
||||
End Sub
|
||||
End Class
|
||||
End Namespace
|
||||
@@ -73,6 +73,7 @@ Namespace API.YouTube.Controls
|
||||
Me.OPT_VIDEO = New System.Windows.Forms.RadioButton()
|
||||
Me.OPT_AUDIO = New System.Windows.Forms.RadioButton()
|
||||
Me.LBL_AUDIO_CODEC = New System.Windows.Forms.Label()
|
||||
Me.BTT_TRIM = New System.Windows.Forms.Button()
|
||||
Me.TXT_FPS = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
||||
Me.TXT_AUDIO_BITRATE = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
||||
Me.TP_HEADER_BASE = New System.Windows.Forms.TableLayoutPanel()
|
||||
@@ -545,20 +546,32 @@ Namespace API.YouTube.Controls
|
||||
Me.LBL_AUDIO_CODEC.TextAlign = System.Drawing.ContentAlignment.MiddleRight
|
||||
TT_MAIN.SetToolTip(Me.LBL_AUDIO_CODEC, "Output Audio Codec")
|
||||
'
|
||||
'BTT_TRIM
|
||||
'
|
||||
Me.BTT_TRIM.Dock = System.Windows.Forms.DockStyle.Fill
|
||||
Me.BTT_TRIM.Location = New System.Drawing.Point(541, 3)
|
||||
Me.BTT_TRIM.Name = "BTT_TRIM"
|
||||
Me.BTT_TRIM.Size = New System.Drawing.Size(45, 22)
|
||||
Me.BTT_TRIM.TabIndex = 2
|
||||
Me.BTT_TRIM.Text = "Trim"
|
||||
TT_MAIN.SetToolTip(Me.BTT_TRIM, "Trim the file by setting trimming options and/or selecting chapters")
|
||||
Me.BTT_TRIM.UseVisualStyleBackColor = True
|
||||
'
|
||||
'TP_FPS_BITRATE
|
||||
'
|
||||
TP_FPS_BITRATE.ColumnCount = 2
|
||||
TP_FPS_BITRATE.ColumnCount = 3
|
||||
TP_FPS_BITRATE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
|
||||
TP_FPS_BITRATE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
|
||||
TP_FPS_BITRATE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 51.0!))
|
||||
TP_FPS_BITRATE.Controls.Add(Me.TXT_FPS, 0, 0)
|
||||
TP_FPS_BITRATE.Controls.Add(Me.TXT_AUDIO_BITRATE, 1, 0)
|
||||
TP_FPS_BITRATE.Controls.Add(Me.BTT_TRIM, 2, 0)
|
||||
TP_FPS_BITRATE.Dock = System.Windows.Forms.DockStyle.Fill
|
||||
TP_FPS_BITRATE.Location = New System.Drawing.Point(6, 93)
|
||||
TP_FPS_BITRATE.Margin = New System.Windows.Forms.Padding(6, 0, 6, 0)
|
||||
TP_FPS_BITRATE.Name = "TP_FPS_BITRATE"
|
||||
TP_FPS_BITRATE.RowCount = 1
|
||||
TP_FPS_BITRATE.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||
TP_FPS_BITRATE.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
|
||||
TP_FPS_BITRATE.Size = New System.Drawing.Size(589, 28)
|
||||
TP_FPS_BITRATE.TabIndex = 6
|
||||
'
|
||||
@@ -577,7 +590,7 @@ Namespace API.YouTube.Controls
|
||||
Me.TXT_FPS.Location = New System.Drawing.Point(3, 2)
|
||||
Me.TXT_FPS.Margin = New System.Windows.Forms.Padding(3, 2, 3, 3)
|
||||
Me.TXT_FPS.Name = "TXT_FPS"
|
||||
Me.TXT_FPS.Size = New System.Drawing.Size(288, 22)
|
||||
Me.TXT_FPS.Size = New System.Drawing.Size(263, 22)
|
||||
Me.TXT_FPS.TabIndex = 0
|
||||
Me.TXT_FPS.TextBoxWidthMinimal = 30
|
||||
'
|
||||
@@ -593,9 +606,9 @@ Namespace API.YouTube.Controls
|
||||
" to change."
|
||||
Me.TXT_AUDIO_BITRATE.CaptionWidth = 75.0R
|
||||
Me.TXT_AUDIO_BITRATE.Dock = System.Windows.Forms.DockStyle.Fill
|
||||
Me.TXT_AUDIO_BITRATE.Location = New System.Drawing.Point(297, 3)
|
||||
Me.TXT_AUDIO_BITRATE.Location = New System.Drawing.Point(272, 3)
|
||||
Me.TXT_AUDIO_BITRATE.Name = "TXT_AUDIO_BITRATE"
|
||||
Me.TXT_AUDIO_BITRATE.Size = New System.Drawing.Size(289, 22)
|
||||
Me.TXT_AUDIO_BITRATE.Size = New System.Drawing.Size(263, 22)
|
||||
Me.TXT_AUDIO_BITRATE.TabIndex = 1
|
||||
'
|
||||
'TP_HEADER_BASE
|
||||
@@ -920,5 +933,6 @@ Namespace API.YouTube.Controls
|
||||
Private WithEvents CMB_PLS As PersonalUtilities.Forms.Controls.ComboBoxExtended
|
||||
Private WithEvents BTT_PLS_BROWSE As SCrawler.API.YouTube.Controls.ButtonRC
|
||||
Private WithEvents TXT_AUDIO_BITRATE As PersonalUtilities.Forms.Controls.TextBoxExtended
|
||||
Private WithEvents BTT_TRIM As Button
|
||||
End Class
|
||||
End Namespace
|
||||
@@ -139,98 +139,96 @@
|
||||
<data name="ActionButton1.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||
wwAADsMBx2+oZAAAAFFJREFUOE9joAr49u3bf1Lw169f50O1QgBI0MnJCY4/vP8Ix8hiILqtrQ3TEFIM
|
||||
AGGYIVDtpBsAwkQbgIyR1dDWAGLwqAGD0gByMFQ7JYCBAQChNviRiQ8ETwAAAABJRU5ErkJggg==
|
||||
vAAADrwBlbxySQAAAEhJREFUOE9jYKAG+Pbt239S8NevX+djGODk5ATHH95/hGNkMRDd1taGaQgpBiAb
|
||||
QrYBIEy0AdgMo70BxOBRAwalAeRguAGUAAChNviRcuLCdwAAAABJRU5ErkJggg==
|
||||
</value>
|
||||
</data>
|
||||
<data name="ActionButton2.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
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
|
||||
AAAASUVORK5CYII=
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAYIj+H5YGIizEb/aEAAAAAElFTkSuQmCC
|
||||
</value>
|
||||
</data>
|
||||
<metadata name="TT_MAIN.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
@@ -248,115 +246,113 @@
|
||||
<data name="ActionButton3.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||
wwAADsMBx2+oZAAAAFFJREFUOE9joAr49u3bf1Lw169f50O1QgBI0MnJCY4/vP8Ix8hiILqtrQ3TEFIM
|
||||
AGGYIVDtpBsAwkQbgIyR1dDWAGLwqAGD0gByMFQ7JYCBAQChNviRiQ8ETwAAAABJRU5ErkJggg==
|
||||
vAAADrwBlbxySQAAAEhJREFUOE9jYKAG+Pbt239S8NevX+djGODk5ATHH95/hGNkMRDd1taGaQgpBiAb
|
||||
QrYBIEy0AdgMo70BxOBRAwalAeRguAGUAAChNviRcuLCdwAAAABJRU5ErkJggg==
|
||||
</value>
|
||||
</data>
|
||||
<data name="ActionButton4.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
|
||||
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAeElE
|
||||
QVQ4T2P4//8/RRhMFHQfKgDi/yAaXQEhDCZAmkNbnvyXta4CciESLEws//FhmDqYAQUgzUBMngsowVgF
|
||||
ScFgYjQQsUsQi8FEYsXyAiD+D6LRFRDCYAKk2bPo6H9J40wgFyKBLeCQMUwdzIACkGYgHnKB+J8BAD5Q
|
||||
tqhi4tzWAAAAAElFTkSuQmCC
|
||||
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsMAAALDAE/QCLIAAAAd0lE
|
||||
QVQ4T2P4//8/AyUYTBR0Hyoo6D70H0SjKyCEYQb8D2158l/Wuuo/TIKFieU/PoxuQAFIs6x1FXkuoARj
|
||||
CJCKwcRoIGIKkoLBRGLF8oLEiuX/QTS6AkIYZsB/z6Kj/yWNM8kLRJDNIM2SxpnkuYASjCFAKgYAPlC2
|
||||
qCS4LQgAAAAASUVORK5CYII=
|
||||
</value>
|
||||
</data>
|
||||
<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
|
||||
vAAADrwBlbxySQAAAHpJREFUOE+1kVEKgDAMQ3e2/e+MXqpn6W/HxM7SpkIVB4HxSMKiTUTaFwVQ1X25
|
||||
DjMfSxskHBYsAxHJkjUjHgrUNMY4peaMPxb03rcZMVhgn2oDKAwn+L0aROH/Cny4NAGFSx8x+10ZDwV2
|
||||
gt+LOCxQsw1nPBS8VQBVTTzyhrdZSUm7AAAAAElFTkSuQmCC
|
||||
</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=
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAYIj+H5YGIizEb/aEAAAAAElFTkSuQmCC
|
||||
</value>
|
||||
</data>
|
||||
<metadata name="LB_SEP_1.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
@@ -383,122 +379,122 @@
|
||||
<data name="ActionButton7.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
|
||||
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
|
||||
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
|
||||
vAAADrwBlbxySQAAAHpJREFUOE+1kVEKgDAMQ3e2/e+MXqpn6W/HxM7SpkIVB4HxSMKiTUTaFwVQ1X25
|
||||
DjMfSxskHBYsAxHJkjUjHgrUNMY4peaMPxb03rcZMVhgn2oDKAwn+L0aROH/Cny4NAGFSx8x+10ZDwV2
|
||||
gt+LOCxQsw1nPBS8VQBVTTzyhrdZSUm7AAAAAElFTkSuQmCC
|
||||
</value>
|
||||
</data>
|
||||
<data name="ActionButton8.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
|
||||
vAAADrwBlbxySQAAAHpJREFUOE+1kVEKgDAMQ3e2/e+MXqpn6W/HxM7SpkIVB4HxSMKiTUTaFwVQ1X25
|
||||
DjMfSxskHBYsAxHJkjUjHgrUNMY4peaMPxb03rcZMVhgn2oDKAwn+L0aROH/Cny4NAGFSx8x+10ZDwV2
|
||||
gt+LOCxQsw1nPBS8VQBVTTzyhrdZSUm7AAAAAElFTkSuQmCC
|
||||
</value>
|
||||
</data>
|
||||
<data name="ActionButton9.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=
|
||||
vAAADrwBlbxySQAAARlJREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbWujg3dATZPKYZC6BQhvw1AMkg3dP
|
||||
XQyl7WIyJIEW5CbS0/jKE5GwpCghgg9s6/8/y5Kj6DA45zcAwAAAezB6rjNnB4XX244NHt8wGs7wblop
|
||||
yRGxwZQBYKIfbn477EvqusY4jj2MgMpPiwav7l9UyYXmdrs9duzP4ApUmd72sfrxVsD33JQISyClvFUX
|
||||
w9nJssvJFei9CJUtgQ7394Du3YKLJaCbLMuwqips21ZNuDve/35X8J7nuRcMsVwsbYEQYlSWpRcMMR5P
|
||||
bAH9fU3TeMEQSZLYgsMpsDRNvXCIr89vWyCEeC6KwguGmL/ObYGU8oFOwA2ewwgYY9f6f7iUf3DGkTcu
|
||||
khP7AAAAAElFTkSuQmCC
|
||||
</value>
|
||||
</data>
|
||||
<data name="ActionButton10.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
|
||||
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOElE
|
||||
QVQ4T2P4//8/QczOJyyqHpzfiE0OQwAZC8iqszAzs7CJ69o4BR768V/W2jcGXQ0KB4aFNS3dDQtnrbCb
|
||||
ePCK48wTN1wXXXzge/jXf/clV55zC4hIIatF0cjIyMikElzc57z0wX+XHd/+2+//99/ywP//xlu//tdb
|
||||
+eK/4Zp3/1WTOhYzARViNUAluKjTdf37/0ZTTn9TbdhwXblhwwW1/qOP1Ja9+K8w+95/6cm3/6v2Xvkv
|
||||
qKjniGGAoIqRpW3/4e8S9uGdzFz82gwMDFxAzCxm4ZegtuLDf+VJ1/8rZM25IqLvnM/CximCYYCic1QN
|
||||
v7x2JIwPwyrJ3XNUylddE9G2TWNmZOBDl4czmJiZMSRBmFdSyYyJgUEQmxwIYxWEYXZBCUls4sgYq6CA
|
||||
prWNbtG8nXKeaVPR5XiVjSxEzf0yYXy4BBMLO6eQjoOXZvrkbbazrv53Xf/2v4CSbjBMXkhBl1/CMyNZ
|
||||
qWnvGy5pNQ+YONwAfjXzAOupl/47LLr333L50/96q9/8l23YdES6cO5KuYqVW+R7Tj6SnfP0v4hryjyY
|
||||
HhQDmFjYeHVKFp7WX/Xuv9Kq9/+Vd/z7r7rv/3+l7f//y676DEwDN/9L+BVvYkKLCTgDhNkkVUyVlr74
|
||||
qbbz73/VOTc/qsy89kWx+9h7qbQpJwS1bbOAscGGrB6EUTggLOqf16C55ft/HlnNAFZOXgVWdi4FRgYG
|
||||
VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg==
|
||||
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsMAAALDAE/QCLIAAACM0lE
|
||||
QVQ4T2P4//8/AyHMzicsqh6c34guDsIYAshYQFadhZmZhU1c18Yp8NCP/7LWvjHoajA0gbCwpqW7YeGs
|
||||
FXYTD15xnHnihuuiiw98D//6777kynNuAREpnAYwMjIyqQQX9zkvffDfZce3//b7//23PPD/v/HWr//1
|
||||
Vr74b7jm3X/VpI7FTIyMjFgNUAku6nRd//6/0ZTT31QbNlxXbthwQa3/6CO1ZS/+K8y+91968u3/qr1X
|
||||
/gsq6jliGCCoYmRp23/4u4R9eCczF782AwMDFwMDA7OYhV+C2ooP/5UnXf+vkDXnioi+cz4LG6cIhgGK
|
||||
zlE1/PLakcguArsquXuOSvmqayLatmnMjAx86PJwBhMzM4YkCPNKKpkxMTAIootjGIANswtKSKKLoWMM
|
||||
ARAW0LS20S2at1POM20quhyvspGFqLlfJoYBTCzsnEI6Dl6a6ZO32c66+t91/dv/Akq6wTB5IQVdfgnP
|
||||
jGSlpr1vuKTVPDAM4FczD7Ceeum/w6J7/y2XP/2vt/rNf9mGTUekC+eulKtYuUW+5+Qj2TlP/4u4psxD
|
||||
dhGSC9h4dUoWntZf9e6/0qr3/5V3/Puvuu//f6Xt///Lrvr8X3ryzf8SfsWbmNBiAsV/bJIqpkpLX/xU
|
||||
2/n3v+qcmx9VZl77oth97L1U2pQTgtq2WUwMDGzI6jEMAGFR/7wGzS3f//PIagawcvIqsLJzKTAyMLCi
|
||||
q8NpABMLK4dCfOsSZlYOUXQ5bBgArRReBMoH61gAAAAASUVORK5CYII=
|
||||
</value>
|
||||
</data>
|
||||
<data name="ActionButton11.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
|
||||
vAAADrwBlbxySQAAAHpJREFUOE+1kVEKgDAMQ3e2/e+MXqpn6W/HxM7SpkIVB4HxSMKiTUTaFwVQ1X25
|
||||
DjMfSxskHBYsAxHJkjUjHgrUNMY4peaMPxb03rcZMVhgn2oDKAwn+L0aROH/Cny4NAGFSx8x+10ZDwV2
|
||||
gt+LOCxQsw1nPBS8VQBVTTzyhrdZSUm7AAAAAElFTkSuQmCC
|
||||
</value>
|
||||
</data>
|
||||
<data name="ActionButton12.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=
|
||||
vAAADrwBlbxySQAAARlJREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbWujg3dATZPKYZC6BQhvw1AMkg3dP
|
||||
XQyl7WIyJIEW5CbS0/jKE5GwpCghgg9s6/8/y5Kj6DA45zcAwAAAezB6rjNnB4XX244NHt8wGs7wblop
|
||||
yRGxwZQBYKIfbn477EvqusY4jj2MgMpPiwav7l9UyYXmdrs9duzP4ApUmd72sfrxVsD33JQISyClvFUX
|
||||
w9nJssvJFei9CJUtgQ7394Du3YKLJaCbLMuwqips21ZNuDve/35X8J7nuRcMsVwsbYEQYlSWpRcMMR5P
|
||||
bAH9fU3TeMEQSZLYgsMpsDRNvXCIr89vWyCEeC6KwguGmL/ObYGU8oFOwA2ewwgYY9f6f7iUf3DGkTcu
|
||||
khP7AAAAAElFTkSuQmCC
|
||||
</value>
|
||||
</data>
|
||||
<data name="ActionButton13.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
|
||||
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOElE
|
||||
QVQ4T2P4//8/QczOJyyqHpzfiE0OQwAZC8iqszAzs7CJ69o4BR768V/W2jcGXQ0KB4aFNS3dDQtnrbCb
|
||||
ePCK48wTN1wXXXzge/jXf/clV55zC4hIIatF0cjIyMikElzc57z0wX+XHd/+2+//99/ywP//xlu//tdb
|
||||
+eK/4Zp3/1WTOhYzARViNUAluKjTdf37/0ZTTn9TbdhwXblhwwW1/qOP1Ja9+K8w+95/6cm3/6v2Xvkv
|
||||
qKjniGGAoIqRpW3/4e8S9uGdzFz82gwMDFxAzCxm4ZegtuLDf+VJ1/8rZM25IqLvnM/CximCYYCic1QN
|
||||
v7x2JIwPwyrJ3XNUylddE9G2TWNmZOBDl4czmJiZMSRBmFdSyYyJgUEQmxwIYxWEYXZBCUls4sgYq6CA
|
||||
prWNbtG8nXKeaVPR5XiVjSxEzf0yYXy4BBMLO6eQjoOXZvrkbbazrv53Xf/2v4CSbjBMXkhBl1/CMyNZ
|
||||
qWnvGy5pNQ+YONwAfjXzAOupl/47LLr333L50/96q9/8l23YdES6cO5KuYqVW+R7Tj6SnfP0v4hryjyY
|
||||
HhQDmFjYeHVKFp7WX/Xuv9Kq9/+Vd/z7r7rv/3+l7f//y676DEwDN/9L+BVvYkKLCTgDhNkkVUyVlr74
|
||||
qbbz73/VOTc/qsy89kWx+9h7qbQpJwS1bbOAscGGrB6EUTggLOqf16C55ft/HlnNAFZOXgVWdi4FRgYG
|
||||
VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg==
|
||||
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsMAAALDAE/QCLIAAACM0lE
|
||||
QVQ4T2P4//8/AyHMzicsqh6c34guDsIYAshYQFadhZmZhU1c18Yp8NCP/7LWvjHoajA0gbCwpqW7YeGs
|
||||
FXYTD15xnHnihuuiiw98D//6777kynNuAREpnAYwMjIyqQQX9zkvffDfZce3//b7//23PPD/v/HWr//1
|
||||
Vr74b7jm3X/VpI7FTIyMjFgNUAku6nRd//6/0ZTT31QbNlxXbthwQa3/6CO1ZS/+K8y+91968u3/qr1X
|
||||
/gsq6jliGCCoYmRp23/4u4R9eCczF782AwMDFwMDA7OYhV+C2ooP/5UnXf+vkDXnioi+cz4LG6cIhgGK
|
||||
zlE1/PLakcguArsquXuOSvmqayLatmnMjAx86PJwBhMzM4YkCPNKKpkxMTAIootjGIANswtKSKKLoWMM
|
||||
ARAW0LS20S2at1POM20quhyvspGFqLlfJoYBTCzsnEI6Dl6a6ZO32c66+t91/dv/Akq6wTB5IQVdfgnP
|
||||
jGSlpr1vuKTVPDAM4FczD7Ceeum/w6J7/y2XP/2vt/rNf9mGTUekC+eulKtYuUW+5+Qj2TlP/4u4psxD
|
||||
dhGSC9h4dUoWntZf9e6/0qr3/5V3/Puvuu//f6Xt///Lrvr8X3ryzf8SfsWbmNBiAsV/bJIqpkpLX/xU
|
||||
2/n3v+qcmx9VZl77oth97L1U2pQTgtq2WUwMDGzI6jEMAGFR/7wGzS3f//PIagawcvIqsLJzKTAyMLCi
|
||||
q8NpABMLK4dCfOsSZlYOUXQ5bBgArRReBMoH61gAAAAASUVORK5CYII=
|
||||
</value>
|
||||
</data>
|
||||
<data name="ActionButton14.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
|
||||
vAAADrwBlbxySQAAAHpJREFUOE+1kVEKgDAMQ3e2/e+MXqpn6W/HxM7SpkIVB4HxSMKiTUTaFwVQ1X25
|
||||
DjMfSxskHBYsAxHJkjUjHgrUNMY4peaMPxb03rcZMVhgn2oDKAwn+L0aROH/Cny4NAGFSx8x+10ZDwV2
|
||||
gt+LOCxQsw1nPBS8VQBVTTzyhrdZSUm7AAAAAElFTkSuQmCC
|
||||
</value>
|
||||
</data>
|
||||
<data name="ActionButton15.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=
|
||||
vAAADrwBlbxySQAAARlJREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbWujg3dATZPKYZC6BQhvw1AMkg3dP
|
||||
XQyl7WIyJIEW5CbS0/jKE5GwpCghgg9s6/8/y5Kj6DA45zcAwAAAezB6rjNnB4XX244NHt8wGs7wblop
|
||||
yRGxwZQBYKIfbn477EvqusY4jj2MgMpPiwav7l9UyYXmdrs9duzP4ApUmd72sfrxVsD33JQISyClvFUX
|
||||
w9nJssvJFei9CJUtgQ7394Du3YKLJaCbLMuwqips21ZNuDve/35X8J7nuRcMsVwsbYEQYlSWpRcMMR5P
|
||||
bAH9fU3TeMEQSZLYgsMpsDRNvXCIr89vWyCEeC6KwguGmL/ObYGU8oFOwA2ewwgYY9f6f7iUf3DGkTcu
|
||||
khP7AAAAAElFTkSuQmCC
|
||||
</value>
|
||||
</data>
|
||||
<data name="ActionButton16.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
|
||||
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOElE
|
||||
QVQ4T2P4//8/QczOJyyqHpzfiE0OQwAZC8iqszAzs7CJ69o4BR768V/W2jcGXQ0KB4aFNS3dDQtnrbCb
|
||||
ePCK48wTN1wXXXzge/jXf/clV55zC4hIIatF0cjIyMikElzc57z0wX+XHd/+2+//99/ywP//xlu//tdb
|
||||
+eK/4Zp3/1WTOhYzARViNUAluKjTdf37/0ZTTn9TbdhwXblhwwW1/qOP1Ja9+K8w+95/6cm3/6v2Xvkv
|
||||
qKjniGGAoIqRpW3/4e8S9uGdzFz82gwMDFxAzCxm4ZegtuLDf+VJ1/8rZM25IqLvnM/CximCYYCic1QN
|
||||
v7x2JIwPwyrJ3XNUylddE9G2TWNmZOBDl4czmJiZMSRBmFdSyYyJgUEQmxwIYxWEYXZBCUls4sgYq6CA
|
||||
prWNbtG8nXKeaVPR5XiVjSxEzf0yYXy4BBMLO6eQjoOXZvrkbbazrv53Xf/2v4CSbjBMXkhBl1/CMyNZ
|
||||
qWnvGy5pNQ+YONwAfjXzAOupl/47LLr333L50/96q9/8l23YdES6cO5KuYqVW+R7Tj6SnfP0v4hryjyY
|
||||
HhQDmFjYeHVKFp7WX/Xuv9Kq9/+Vd/z7r7rv/3+l7f//y676DEwDN/9L+BVvYkKLCTgDhNkkVUyVlr74
|
||||
qbbz73/VOTc/qsy89kWx+9h7qbQpJwS1bbOAscGGrB6EUTggLOqf16C55ft/HlnNAFZOXgVWdi4FRgYG
|
||||
VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg==
|
||||
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsMAAALDAE/QCLIAAACM0lE
|
||||
QVQ4T2P4//8/AyHMzicsqh6c34guDsIYAshYQFadhZmZhU1c18Yp8NCP/7LWvjHoajA0gbCwpqW7YeGs
|
||||
FXYTD15xnHnihuuiiw98D//6777kynNuAREpnAYwMjIyqQQX9zkvffDfZce3//b7//23PPD/v/HWr//1
|
||||
Vr74b7jm3X/VpI7FTIyMjFgNUAku6nRd//6/0ZTT31QbNlxXbthwQa3/6CO1ZS/+K8y+91968u3/qr1X
|
||||
/gsq6jliGCCoYmRp23/4u4R9eCczF782AwMDFwMDA7OYhV+C2ooP/5UnXf+vkDXnioi+cz4LG6cIhgGK
|
||||
zlE1/PLakcguArsquXuOSvmqayLatmnMjAx86PJwBhMzM4YkCPNKKpkxMTAIootjGIANswtKSKKLoWMM
|
||||
ARAW0LS20S2at1POM20quhyvspGFqLlfJoYBTCzsnEI6Dl6a6ZO32c66+t91/dv/Akq6wTB5IQVdfgnP
|
||||
jGSlpr1vuKTVPDAM4FczD7Ceeum/w6J7/y2XP/2vt/rNf9mGTUekC+eulKtYuUW+5+Qj2TlP/4u4psxD
|
||||
dhGSC9h4dUoWntZf9e6/0qr3/5V3/Puvuu//f6Xt///Lrvr8X3ryzf8SfsWbmNBiAsV/bJIqpkpLX/xU
|
||||
2/n3v+qcmx9VZl77oth97L1U2pQTgtq2WUwMDGzI6jEMAGFR/7wGzS3f//PIagawcvIqsLJzKTAyMLCi
|
||||
q8NpABMLK4dCfOsSZlYOUXQ5bBgArRReBMoH61gAAAAASUVORK5CYII=
|
||||
</value>
|
||||
</data>
|
||||
<data name="ActionButton17.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
|
||||
vAAADrwBlbxySQAAAHpJREFUOE+1kVEKgDAMQ3e2/e+MXqpn6W/HxM7SpkIVB4HxSMKiTUTaFwVQ1X25
|
||||
DjMfSxskHBYsAxHJkjUjHgrUNMY4peaMPxb03rcZMVhgn2oDKAwn+L0aROH/Cny4NAGFSx8x+10ZDwV2
|
||||
gt+LOCxQsw1nPBS8VQBVTTzyhrdZSUm7AAAAAElFTkSuQmCC
|
||||
</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -465,6 +465,9 @@ Namespace API.YouTube.Controls
|
||||
TXT_FILE.Text = f
|
||||
End If
|
||||
End Sub
|
||||
Private Sub BTT_TRIM_Click(sender As Object, e As EventArgs) Handles BTT_TRIM.Click
|
||||
Using f As New VideoOptionsTrimForm(MyContainer) : f.ShowDialog() : End Using
|
||||
End Sub
|
||||
Private Sub TXT_SUBS_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As ActionButtonEventArgs) Handles TXT_SUBS.ActionOnButtonClick
|
||||
Select Case Sender.DefaultButton
|
||||
Case ADB.Open
|
||||
|
||||
166
SCrawler.YouTube/Controls/VideoOptionsTrimForm.Designer.vb
generated
Normal file
@@ -0,0 +1,166 @@
|
||||
' Copyright (C) Andy https://github.com/AAndyProgram
|
||||
' This program is free software: you can redistribute it and/or modify
|
||||
' it under the terms of the GNU General Public License as published by
|
||||
' the Free Software Foundation, either version 3 of the License, or
|
||||
' (at your option) any later version.
|
||||
'
|
||||
' This program is distributed in the hope that it will be useful,
|
||||
' but WITHOUT ANY WARRANTY
|
||||
Namespace API.YouTube.Controls
|
||||
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
|
||||
Partial Friend Class VideoOptionsTrimForm : Inherits System.Windows.Forms.Form
|
||||
<System.Diagnostics.DebuggerNonUserCode()>
|
||||
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
|
||||
Try
|
||||
If disposing AndAlso components IsNot Nothing Then
|
||||
components.Dispose()
|
||||
End If
|
||||
Finally
|
||||
MyBase.Dispose(disposing)
|
||||
End Try
|
||||
End Sub
|
||||
Private components As System.ComponentModel.IContainer
|
||||
<System.Diagnostics.DebuggerStepThrough()>
|
||||
Private Sub InitializeComponent()
|
||||
Me.components = New System.ComponentModel.Container()
|
||||
Dim CONTAINER_MAIN As System.Windows.Forms.ToolStripContainer
|
||||
Dim TP_MAIN As System.Windows.Forms.TableLayoutPanel
|
||||
Dim TP_OPTIONS As System.Windows.Forms.TableLayoutPanel
|
||||
Dim TT_MAIN As System.Windows.Forms.ToolTip
|
||||
Me.LIST_TRIM = New System.Windows.Forms.ListBox()
|
||||
Me.CH_DEL_ORIG = New System.Windows.Forms.CheckBox()
|
||||
Me.CH_ADD_M3U8 = New System.Windows.Forms.CheckBox()
|
||||
Me.CH_SEP_FOLDER = New System.Windows.Forms.CheckBox()
|
||||
CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer()
|
||||
TP_MAIN = New System.Windows.Forms.TableLayoutPanel()
|
||||
TP_OPTIONS = New System.Windows.Forms.TableLayoutPanel()
|
||||
TT_MAIN = New System.Windows.Forms.ToolTip(Me.components)
|
||||
CONTAINER_MAIN.ContentPanel.SuspendLayout()
|
||||
CONTAINER_MAIN.SuspendLayout()
|
||||
TP_MAIN.SuspendLayout()
|
||||
TP_OPTIONS.SuspendLayout()
|
||||
Me.SuspendLayout()
|
||||
'
|
||||
'CONTAINER_MAIN
|
||||
'
|
||||
'
|
||||
'CONTAINER_MAIN.ContentPanel
|
||||
'
|
||||
CONTAINER_MAIN.ContentPanel.Controls.Add(TP_MAIN)
|
||||
CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(434, 236)
|
||||
CONTAINER_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
|
||||
CONTAINER_MAIN.LeftToolStripPanelVisible = False
|
||||
CONTAINER_MAIN.Location = New System.Drawing.Point(0, 0)
|
||||
CONTAINER_MAIN.Name = "CONTAINER_MAIN"
|
||||
CONTAINER_MAIN.RightToolStripPanelVisible = False
|
||||
CONTAINER_MAIN.Size = New System.Drawing.Size(434, 261)
|
||||
CONTAINER_MAIN.TabIndex = 0
|
||||
'
|
||||
'TP_MAIN
|
||||
'
|
||||
TP_MAIN.ColumnCount = 1
|
||||
TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||
TP_MAIN.Controls.Add(Me.LIST_TRIM, 0, 1)
|
||||
TP_MAIN.Controls.Add(TP_OPTIONS, 0, 0)
|
||||
TP_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
|
||||
TP_MAIN.Location = New System.Drawing.Point(0, 0)
|
||||
TP_MAIN.Name = "TP_MAIN"
|
||||
TP_MAIN.RowCount = 2
|
||||
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 30.0!))
|
||||
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||
TP_MAIN.Size = New System.Drawing.Size(434, 236)
|
||||
TP_MAIN.TabIndex = 0
|
||||
'
|
||||
'LIST_TRIM
|
||||
'
|
||||
Me.LIST_TRIM.Dock = System.Windows.Forms.DockStyle.Fill
|
||||
Me.LIST_TRIM.FormattingEnabled = True
|
||||
Me.LIST_TRIM.Location = New System.Drawing.Point(3, 33)
|
||||
Me.LIST_TRIM.Name = "LIST_TRIM"
|
||||
Me.LIST_TRIM.Size = New System.Drawing.Size(428, 200)
|
||||
Me.LIST_TRIM.TabIndex = 0
|
||||
'
|
||||
'TP_OPTIONS
|
||||
'
|
||||
TP_OPTIONS.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single]
|
||||
TP_OPTIONS.ColumnCount = 3
|
||||
TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333!))
|
||||
TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33334!))
|
||||
TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33334!))
|
||||
TP_OPTIONS.Controls.Add(Me.CH_DEL_ORIG, 0, 0)
|
||||
TP_OPTIONS.Controls.Add(Me.CH_ADD_M3U8, 1, 0)
|
||||
TP_OPTIONS.Controls.Add(Me.CH_SEP_FOLDER, 2, 0)
|
||||
TP_OPTIONS.Dock = System.Windows.Forms.DockStyle.Fill
|
||||
TP_OPTIONS.Location = New System.Drawing.Point(3, 3)
|
||||
TP_OPTIONS.Name = "TP_OPTIONS"
|
||||
TP_OPTIONS.RowCount = 1
|
||||
TP_OPTIONS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||
TP_OPTIONS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 23.0!))
|
||||
TP_OPTIONS.Size = New System.Drawing.Size(428, 24)
|
||||
TP_OPTIONS.TabIndex = 1
|
||||
'
|
||||
'CH_DEL_ORIG
|
||||
'
|
||||
Me.CH_DEL_ORIG.AutoSize = True
|
||||
Me.CH_DEL_ORIG.Dock = System.Windows.Forms.DockStyle.Fill
|
||||
Me.CH_DEL_ORIG.Location = New System.Drawing.Point(4, 4)
|
||||
Me.CH_DEL_ORIG.Name = "CH_DEL_ORIG"
|
||||
Me.CH_DEL_ORIG.Size = New System.Drawing.Size(135, 16)
|
||||
Me.CH_DEL_ORIG.TabIndex = 0
|
||||
Me.CH_DEL_ORIG.Text = "Delete original file"
|
||||
TT_MAIN.SetToolTip(Me.CH_DEL_ORIG, "If checked, the original file will be deleted after trimming")
|
||||
Me.CH_DEL_ORIG.UseVisualStyleBackColor = True
|
||||
'
|
||||
'CH_ADD_M3U8
|
||||
'
|
||||
Me.CH_ADD_M3U8.AutoSize = True
|
||||
Me.CH_ADD_M3U8.Dock = System.Windows.Forms.DockStyle.Fill
|
||||
Me.CH_ADD_M3U8.Location = New System.Drawing.Point(146, 4)
|
||||
Me.CH_ADD_M3U8.Name = "CH_ADD_M3U8"
|
||||
Me.CH_ADD_M3U8.Size = New System.Drawing.Size(135, 16)
|
||||
Me.CH_ADD_M3U8.TabIndex = 1
|
||||
Me.CH_ADD_M3U8.Text = "Add to M3U8"
|
||||
TT_MAIN.SetToolTip(Me.CH_ADD_M3U8, "If checked, the trimmed files will be added to the M3U8 playlist (if selected)")
|
||||
Me.CH_ADD_M3U8.UseVisualStyleBackColor = True
|
||||
'
|
||||
'CH_SEP_FOLDER
|
||||
'
|
||||
Me.CH_SEP_FOLDER.AutoSize = True
|
||||
Me.CH_SEP_FOLDER.Dock = System.Windows.Forms.DockStyle.Fill
|
||||
Me.CH_SEP_FOLDER.Location = New System.Drawing.Point(288, 4)
|
||||
Me.CH_SEP_FOLDER.Name = "CH_SEP_FOLDER"
|
||||
Me.CH_SEP_FOLDER.Size = New System.Drawing.Size(136, 16)
|
||||
Me.CH_SEP_FOLDER.TabIndex = 2
|
||||
Me.CH_SEP_FOLDER.Text = "Separate folder"
|
||||
TT_MAIN.SetToolTip(Me.CH_SEP_FOLDER, "Place the trimmed files in a separate folder")
|
||||
Me.CH_SEP_FOLDER.UseVisualStyleBackColor = True
|
||||
'
|
||||
'VideoOptionsTrimForm
|
||||
'
|
||||
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
|
||||
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
|
||||
Me.ClientSize = New System.Drawing.Size(434, 261)
|
||||
Me.Controls.Add(CONTAINER_MAIN)
|
||||
Me.KeyPreview = True
|
||||
Me.MinimizeBox = False
|
||||
Me.MinimumSize = New System.Drawing.Size(450, 300)
|
||||
Me.Name = "VideoOptionsTrimForm"
|
||||
Me.ShowIcon = False
|
||||
Me.ShowInTaskbar = False
|
||||
Me.Text = "Trimming options"
|
||||
CONTAINER_MAIN.ContentPanel.ResumeLayout(False)
|
||||
CONTAINER_MAIN.ResumeLayout(False)
|
||||
CONTAINER_MAIN.PerformLayout()
|
||||
TP_MAIN.ResumeLayout(False)
|
||||
TP_OPTIONS.ResumeLayout(False)
|
||||
TP_OPTIONS.PerformLayout()
|
||||
Me.ResumeLayout(False)
|
||||
|
||||
End Sub
|
||||
|
||||
Private WithEvents LIST_TRIM As ListBox
|
||||
Private WithEvents CH_DEL_ORIG As CheckBox
|
||||
Private WithEvents CH_ADD_M3U8 As CheckBox
|
||||
Private WithEvents CH_SEP_FOLDER As CheckBox
|
||||
End Class
|
||||
End Namespace
|
||||
135
SCrawler.YouTube/Controls/VideoOptionsTrimForm.resx
Normal file
@@ -0,0 +1,135 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<metadata name="CONTAINER_MAIN.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>False</value>
|
||||
</metadata>
|
||||
<metadata name="TP_MAIN.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>False</value>
|
||||
</metadata>
|
||||
<metadata name="TP_OPTIONS.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>False</value>
|
||||
</metadata>
|
||||
<metadata name="TT_MAIN.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>False</value>
|
||||
</metadata>
|
||||
<metadata name="TT_MAIN.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
</root>
|
||||
167
SCrawler.YouTube/Controls/VideoOptionsTrimForm.vb
Normal file
@@ -0,0 +1,167 @@
|
||||
' Copyright (C) Andy https://github.com/AAndyProgram
|
||||
' This program is free software: you can redistribute it and/or modify
|
||||
' it under the terms of the GNU General Public License as published by
|
||||
' the Free Software Foundation, either version 3 of the License, or
|
||||
' (at your option) any later version.
|
||||
'
|
||||
' This program is distributed in the hope that it will be useful,
|
||||
' but WITHOUT ANY WARRANTY
|
||||
Imports PersonalUtilities.Forms
|
||||
Imports PersonalUtilities.Forms.Toolbars
|
||||
Imports SCrawler.API.YouTube.Objects
|
||||
Imports SCrawler.API.YouTube.Base
|
||||
Imports ETC = PersonalUtilities.Forms.Toolbars.EditToolbar.ControlItem
|
||||
Namespace API.YouTube.Controls
|
||||
Friend Class VideoOptionsTrimForm
|
||||
#Region "Declarations"
|
||||
Private WithEvents MyDefs As DefaultFormOptions
|
||||
Private ReadOnly Property MyMedia As YouTubeMediaContainerBase
|
||||
Private ReadOnly Property TrimData As List(Of TrimOption)
|
||||
Private WithEvents BTT_CLEAR_ALL As ToolStripButton
|
||||
Private WithEvents BTT_CHAPTERS As ToolStripButton
|
||||
#End Region
|
||||
#Region "Initializer"
|
||||
Friend Sub New(ByRef Media As YouTubeMediaContainerBase)
|
||||
InitializeComponent()
|
||||
MyDefs = New DefaultFormOptions(Me, MyYouTubeSettings.DesignXml)
|
||||
MyMedia = Media
|
||||
TrimData = New List(Of TrimOption)
|
||||
TrimData.ListAddList(Media.TrimOptions)
|
||||
BTT_CLEAR_ALL = New ToolStripButton("Clear", PersonalUtilities.My.Resources.DeletePic_Red_24) With {
|
||||
.DisplayStyle = ToolStripItemDisplayStyle.ImageAndText,
|
||||
.BackColor = MyColor.DeleteBack,
|
||||
.ForeColor = MyColor.DeleteFore
|
||||
}
|
||||
BTT_CHAPTERS = New ToolStripButton("Chapters") With {.DisplayStyle = ToolStripItemDisplayStyle.Text, .Enabled = Media.Chapters.Count > 0}
|
||||
End Sub
|
||||
#End Region
|
||||
#Region "Form handlers"
|
||||
Private Sub VideoOptionsTrimForm_Load(sender As Object, e As EventArgs) Handles Me.Load
|
||||
With MyDefs
|
||||
.MyViewInitialize()
|
||||
.AddOkCancelToolbar()
|
||||
.AddEditToolbar({ETC.Add, ETC.Edit, ETC.Delete, BTT_CLEAR_ALL, ETC.Separator, BTT_CHAPTERS})
|
||||
|
||||
Refill()
|
||||
|
||||
With MyMedia
|
||||
If Not .TrimOptionsSet Then
|
||||
With MyYouTubeSettings
|
||||
CH_DEL_ORIG.Checked = .TrimDeleteOriginalFile
|
||||
CH_ADD_M3U8.Checked = .TrimAddTrimmedFilesToM3U8
|
||||
CH_SEP_FOLDER.Checked = .TrimSeparateFolder
|
||||
End With
|
||||
Else
|
||||
CH_DEL_ORIG.Checked = .TrimDeleteOriginalFile
|
||||
CH_ADD_M3U8.Checked = .TrimAddTrimmedFilesToM3U8
|
||||
CH_SEP_FOLDER.Checked = .TrimSeparateFolder
|
||||
End If
|
||||
End With
|
||||
|
||||
.EndLoaderOperations()
|
||||
End With
|
||||
End Sub
|
||||
Private Sub VideoOptionsTrimForm_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed
|
||||
TrimData.Clear()
|
||||
End Sub
|
||||
#End Region
|
||||
#Region "Refill"
|
||||
Private Sub Refill(Optional ByVal DEL As Boolean = False)
|
||||
Dim indx% = _CurrentIndex
|
||||
With LIST_TRIM
|
||||
.BeginUpdate()
|
||||
.Items.Clear()
|
||||
If TrimData.Count > 0 Then
|
||||
TrimData.Sort()
|
||||
.Items.AddRange(TrimData.Cast(Of Object).ToArray)
|
||||
If DEL Then indx -= IIf(indx - 1 < 0, 0, 1)
|
||||
If indx.ValueBetween(0, TrimData.Count - 1) Then
|
||||
.SelectedIndex = indx
|
||||
ElseIf (indx - 1).ValueBetween(0, TrimData.Count - 1) Then
|
||||
.SelectedIndex = indx - 1
|
||||
ElseIf (indx + 1).ValueBetween(0, TrimData.Count - 1) Then
|
||||
.SelectedIndex = indx + 1
|
||||
End If
|
||||
End If
|
||||
.EndUpdate()
|
||||
End With
|
||||
End Sub
|
||||
#End Region
|
||||
#Region "Ok"
|
||||
Private Sub MyDefs_ButtonOkClick(ByVal Sender As Object, ByVal e As KeyHandleEventArgs) Handles MyDefs.ButtonOkClick
|
||||
With MyMedia
|
||||
.TrimOptions.Clear()
|
||||
.TrimDeleteOriginalFile = CH_DEL_ORIG.Checked
|
||||
.TrimAddTrimmedFilesToM3U8 = CH_ADD_M3U8.Checked
|
||||
.TrimSeparateFolder = CH_SEP_FOLDER.Checked
|
||||
.TrimOptionsSet = True
|
||||
End With
|
||||
|
||||
If TrimData.Count > 0 Then
|
||||
TrimData.Sort()
|
||||
Dim indx% = 0
|
||||
Dim c%
|
||||
Dim opt As TrimOption
|
||||
Dim dic As New Dictionary(Of String, Integer)
|
||||
For i% = 0 To TrimData.Count - 1
|
||||
opt = TrimData(i)
|
||||
If opt.Name.IsEmptyString Then
|
||||
indx += 1
|
||||
opt.Name = indx
|
||||
Else
|
||||
c = TrimData.LongCount(Function(d) Not d.Name.IsEmptyString AndAlso d.Name = opt.Name)
|
||||
If c > 1 Then
|
||||
If Not dic.ContainsKey(opt.Name) Then dic.Add(opt.Name, 0)
|
||||
dic(opt.Name) += 1
|
||||
opt.Name &= $"_{dic(opt.Name)}"
|
||||
End If
|
||||
End If
|
||||
TrimData(i) = opt
|
||||
Next
|
||||
dic.Clear()
|
||||
MyMedia.TrimOptions.AddRange(TrimData)
|
||||
End If
|
||||
|
||||
MyDefs.CloseForm()
|
||||
End Sub
|
||||
#End Region
|
||||
#Region "Edit"
|
||||
Private Sub MyDefs_ButtonAddClick(ByVal Sender As Object, ByVal e As EditToolbarEventArgs) Handles MyDefs.ButtonAddClick
|
||||
Using f As New TrimOptionForm
|
||||
f.ShowDialog()
|
||||
If f.DialogResult = DialogResult.OK AndAlso
|
||||
(TrimData.Count = 0 OrElse Not TrimData.Any(Function(t) t.End = f.MyTrimOption.End And t.Start = f.MyTrimOption.Start)) Then _
|
||||
TrimData.Add(f.MyTrimOption) : Refill()
|
||||
End Using
|
||||
End Sub
|
||||
Private Sub MyDefs_ButtonEditClick(ByVal Sender As Object, ByVal e As EditToolbarEventArgs) Handles MyDefs.ButtonEditClick
|
||||
If _CurrentIndex.ValueBetween(0, TrimData.Count - 1) Then
|
||||
Using f As New TrimOptionForm(TrimData(_CurrentIndex))
|
||||
f.ShowDialog()
|
||||
If f.DialogResult = DialogResult.OK Then TrimData(_CurrentIndex) = f.MyTrimOption : Refill()
|
||||
End Using
|
||||
End If
|
||||
End Sub
|
||||
Private Sub MyDefs_ButtonDeleteClickE(ByVal Sender As Object, ByVal e As EditToolbarEventArgs) Handles MyDefs.ButtonDeleteClickE
|
||||
If _CurrentIndex.ValueBetween(0, TrimData.Count - 1) AndAlso
|
||||
MsgBoxE({$"Are you sure you want to remove the following trim option?{vbCr}{vbCr}{TrimData(_CurrentIndex)}", "Remove trim option"}, vbYesNo + vbExclamation) = vbYes Then _
|
||||
TrimData.RemoveAt(_CurrentIndex) : Refill(True)
|
||||
End Sub
|
||||
Private Sub BTT_CLEAR_ALL_Click(sender As Object, e As EventArgs) Handles BTT_CLEAR_ALL.Click
|
||||
If MsgBoxE({$"Are you sure you want to remove ALL trim options?", "Remove trim option"}, vbYesNo + vbCritical) = vbYes Then TrimData.Clear() : Refill()
|
||||
End Sub
|
||||
Private Sub BTT_CHAPTERS_Click(sender As Object, e As EventArgs) Handles BTT_CHAPTERS.Click
|
||||
Using f As New ChaptersForm(MyMedia, TrimData)
|
||||
f.ShowDialog()
|
||||
If f.DialogResult = DialogResult.OK AndAlso f.MyResult.Count > 0 Then TrimData.ListAddList(f.MyResult, LAP.NotContainsOnly) : Refill()
|
||||
End Using
|
||||
End Sub
|
||||
#End Region
|
||||
#Region "List"
|
||||
Private _CurrentIndex As Integer = -1
|
||||
Private Sub LIST_TRIM_SelectedIndexChanged(sender As Object, e As EventArgs) Handles LIST_TRIM.SelectedIndexChanged
|
||||
_CurrentIndex = LIST_TRIM.SelectedIndex
|
||||
End Sub
|
||||
#End Region
|
||||
End Class
|
||||
End Namespace
|
||||
@@ -54,6 +54,7 @@ Namespace API.YouTube
|
||||
Friend ReadOnly DateBaseProvider As New ADateTime(ADateTime.Formats.BaseDateTime)
|
||||
Friend ReadOnly DateAddedProvider As New ADateTime(ADateTime.Formats.yyyymmdd) With {.DateSeparator = String.Empty}
|
||||
Friend ReadOnly TimeToStringProvider As IFormatProvider = New TimeToStringConverter
|
||||
Friend ReadOnly TimeToStringProviderH As IFormatProvider = New TimeToStringConverter(True)
|
||||
Friend ReadOnly TitleHtmlConverter As Func(Of String, String) = Function(Input) Input.StringRemoveWinForbiddenSymbols().StringTrim()
|
||||
Friend ReadOnly ProgressProvider As IMyProgressNumberProvider = MyProgressNumberProvider.Percentage
|
||||
Public ReadOnly TrueUrlRegEx As RParams = RParams.DM(Base.YouTubeFunctions.TrueUrlPattern, 0, EDP.ReturnValue)
|
||||
@@ -80,11 +81,15 @@ Namespace API.YouTube
|
||||
Private Class TimeToStringConverter : Implements ICustomProvider
|
||||
Private ReadOnly _Provider As New ADateTime("mm\:ss") With {.TimeParseMode = ADateTime.TimeModes.TimeSpan}
|
||||
Private ReadOnly _ProviderWithHours As New ADateTime("h\:mm\:ss") With {.TimeParseMode = ADateTime.TimeModes.TimeSpan}
|
||||
Private ReadOnly ForceHours As Boolean
|
||||
Private ReadOnly Property Provider(ByVal t As TimeSpan) As IFormatProvider
|
||||
Get
|
||||
Return If(t.Hours > 0, _ProviderWithHours, _Provider)
|
||||
Return If(t.Hours > 0 Or ForceHours, _ProviderWithHours, _Provider)
|
||||
End Get
|
||||
End Property
|
||||
Friend Sub New(Optional ByVal ForceHours As Boolean = False)
|
||||
Me.ForceHours = ForceHours
|
||||
End Sub
|
||||
Private Function Convert(ByVal Value As Object, ByVal DestinationType As Type, ByVal Provider As IFormatProvider,
|
||||
Optional ByVal NothingArg As Object = Nothing, Optional ByVal e As ErrorsDescriber = Nothing) As Object Implements ICustomProvider.Convert
|
||||
If Not IsNothing(Value) Then
|
||||
|
||||
@@ -336,6 +336,7 @@ Namespace DownloadObjects.STDownloader
|
||||
pForm.Dispose()
|
||||
End If
|
||||
If Not c Is Nothing Then
|
||||
If Not c.HasElements Then DirectCast(c, YouTubeMediaContainerBase).FileForceArtist()
|
||||
Dim f As Form
|
||||
Select Case c.ObjectType
|
||||
Case YouTubeMediaType.Single : f = New VideoOptionsForm(c) With {.UseCookies = useCookies}
|
||||
|
||||
@@ -13,7 +13,7 @@ Imports System.Runtime.InteropServices
|
||||
<Assembly: AssemblyDescription("YouTube plugin environment")>
|
||||
<Assembly: AssemblyCompany("AndyProgram")>
|
||||
<Assembly: AssemblyProduct("SCrawler.YouTube")>
|
||||
<Assembly: AssemblyCopyright("Copyright © 2025")>
|
||||
<Assembly: AssemblyCopyright("Copyright © 2026")>
|
||||
<Assembly: AssemblyTrademark("AndyProgram")>
|
||||
|
||||
<Assembly: ComVisible(False)>
|
||||
@@ -32,6 +32,6 @@ Imports System.Runtime.InteropServices
|
||||
' by using the '*' as shown below:
|
||||
' <Assembly: AssemblyVersion("1.0.*")>
|
||||
|
||||
<Assembly: AssemblyVersion("2025.6.12.0")>
|
||||
<Assembly: AssemblyFileVersion("2025.6.12.0")>
|
||||
<Assembly: AssemblyVersion("2025.11.25.0")>
|
||||
<Assembly: AssemblyFileVersion("2025.11.25.0")>
|
||||
<Assembly: NeutralResourcesLanguage("en")>
|
||||
|
||||
@@ -30,6 +30,11 @@ Namespace API.YouTube.Objects
|
||||
_File = CleanFileName(_File)
|
||||
End If
|
||||
End Sub
|
||||
Protected Friend Overrides Sub FileForceArtist()
|
||||
Dim __artistName$ = UserTitle.IfNullOrEmpty(AccountName)
|
||||
If Not _File.Name.IsEmptyString AndAlso Not _File.Name.ToLower.Contains(__artistName.ToLower) Then _
|
||||
_File.Name = $"{__artistName} - {_File.Name}"
|
||||
End Sub
|
||||
Public Overrides Function ToString(ByVal ForMediaItem As Boolean) As String
|
||||
Dim s$ = SizeStr
|
||||
If Not s.IsEmptyString Then s = $" [{s}]"
|
||||
|
||||
@@ -356,6 +356,14 @@ Namespace API.YouTube.Objects
|
||||
End If
|
||||
End Sub
|
||||
#End Region
|
||||
#Region "Chapters, Trimming"
|
||||
Friend ReadOnly Property Chapters As List(Of TrimOption)
|
||||
Friend ReadOnly Property TrimOptions As List(Of TrimOption)
|
||||
Friend Property TrimDeleteOriginalFile As Boolean = False
|
||||
Friend Property TrimAddTrimmedFilesToM3U8 As Boolean = False
|
||||
Friend Property TrimSeparateFolder As Boolean = False
|
||||
Friend Property TrimOptionsSet As Boolean = False
|
||||
#End Region
|
||||
#Region "IUserMedia Support"
|
||||
<XMLEC> Private Property Attempts As Integer Implements IUserMedia.Attempts
|
||||
Private _Object As Object = Nothing
|
||||
@@ -684,6 +692,8 @@ Namespace API.YouTube.Objects
|
||||
End If
|
||||
End Set
|
||||
End Property
|
||||
Protected Friend Overridable Sub FileForceArtist()
|
||||
End Sub
|
||||
Friend Sub FileDateUpdate()
|
||||
Dim n$ = _File.Name.StringTrim
|
||||
Dim s$ = IIf(n.IsEmptyString, String.Empty, " ")
|
||||
@@ -817,15 +827,20 @@ Namespace API.YouTube.Objects
|
||||
subs = ListAddList(Nothing, Subtitles.Select(Function(s, i) If(SubtitlesSelectedIndexes.Contains(i), s.FullID, String.Empty)),
|
||||
LAP.NotContainsOnly, EDP.ReturnValue).ListToString(",")
|
||||
subs = $"--write-subs --write-auto-subs --sub-format {OutputSubtitlesFormat.StringToLower} --sub-langs ""{subs}"" --convert-subs {OutputSubtitlesFormat.StringToLower}"
|
||||
If MyYouTubeSettings.DefaultSubtitlesEmbed Then subs = $"--write-auto-sub --embed-subs {subs}"
|
||||
End If
|
||||
If Not cmd.IsEmptyString Then
|
||||
'2023.3.4 -> 2023.7.6
|
||||
'cmd = $"yt-dlp -f ""{cmd}"""
|
||||
'cmd = $"yt-dlp -f {cmd}"
|
||||
cmd = $"{YTDLP_NAME} -f {cmd}"
|
||||
If Not MyYouTubeSettings.ReplaceModificationDate Then cmd &= " --no-mtime"
|
||||
'yt-dlp 2025.07.21
|
||||
'If Not MyYouTubeSettings.ReplaceModificationDate Then cmd &= " --no-mtime"
|
||||
cmd &= $" --{IIf(MyYouTubeSettings.ReplaceModificationDate.Value, String.Empty, "no-")}mtime"
|
||||
If MyYouTubeSettings.DefaultVideoEmbedChapters Then cmd &= " --embed-chapters --add-chapters"
|
||||
cmd.StringAppend(formats, " ")
|
||||
cmd.StringAppend(subs, " ")
|
||||
If MyYouTubeSettings.ErrorsIgnore Then cmd &= " --no-abort-on-error --ignore-errors"
|
||||
cmd.StringAppend(YouTubeFunctions.GetCookiesCommand(WithCookies, YouTubeCookieNetscapeFile), " ")
|
||||
cmd &= $" {URL} -o ""{File.PathWithSeparator}{File.Name}"""
|
||||
File.Exists(SFO.Path, True)
|
||||
@@ -843,6 +858,8 @@ Namespace API.YouTube.Objects
|
||||
_Subtitles = New List(Of Subtitles)
|
||||
_SubtitlesDelegated = New List(Of Subtitles)
|
||||
SubtitlesSelectedIndexes = New List(Of Integer)
|
||||
Chapters = New List(Of TrimOption)
|
||||
TrimOptions = New List(Of TrimOption)
|
||||
MediaObjects = New List(Of MediaObject)
|
||||
_Files = New List(Of SFile)
|
||||
|
||||
@@ -1265,6 +1282,7 @@ Namespace API.YouTube.Objects
|
||||
Dim fPatternFiles$ = $"{File.Name}*." & "{0}"
|
||||
Dim fAacAudio As New TempFileConversion(New SFile(String.Format(fPattern, aac)), Me)
|
||||
Dim mp3ThumbEmbedded As Boolean = False
|
||||
Dim audioFiles As New List(Of SFile)
|
||||
|
||||
Dim tempFilesList As New List(Of TempFileConversion)
|
||||
Dim ttFile As TempFileConversion
|
||||
@@ -1372,13 +1390,17 @@ Namespace API.YouTube.Objects
|
||||
format = format.StringToLower
|
||||
f = String.Format(fPattern, format)
|
||||
AddFile(f)
|
||||
audioFiles.Add(f)
|
||||
If Not f.Exists Then
|
||||
tryToConvert.Invoke(format, f)
|
||||
updateBitrate(f)
|
||||
If format = mp3 And Not mp3ThumbEmbedded And MyYouTubeSettings.DefaultAudioEmbedThumbnail_ExtractedFiles Then _
|
||||
embedThumbTo.Invoke(f) : mp3ThumbEmbedded = True
|
||||
If Not M3U8_PlaylistFiles.ListExists AndAlso f.Exists Then M3U8_Append(f)
|
||||
If format = mp3 AndAlso f.Exists AndAlso MyYouTubeSettings.VideoPlaylist_AddExtractedMP3.Value Then M3U8_Append(f)
|
||||
If f.Exists Then
|
||||
If format = mp3 And Not mp3ThumbEmbedded And MyYouTubeSettings.DefaultAudioEmbedThumbnail_ExtractedFiles Then _
|
||||
embedThumbTo.Invoke(f) : mp3ThumbEmbedded = True
|
||||
If M3U8_PlaylistFiles.ListExists OrElse
|
||||
(format = mp3 AndAlso MyYouTubeSettings.VideoPlaylist_AddExtractedMP3.Value) Then _
|
||||
M3U8_Append(f)
|
||||
End If
|
||||
End If
|
||||
Next
|
||||
End If
|
||||
@@ -1431,6 +1453,69 @@ Namespace API.YouTube.Objects
|
||||
If OutputVideoFPS > 0 AndAlso SelectedVideo.Bitrate <> OutputVideoFPS Then _
|
||||
reencodeFile("ffmpeg -i ""{0}"" -filter:v fps=" & OutputVideoFPS.ToString.Replace(", ", ".") & " -c:a copy ""{1}""")
|
||||
End If
|
||||
|
||||
'Trimming
|
||||
If TrimOptions.Count > 0 AndAlso File.Exists Then
|
||||
Const trimCommand$ = "ffmpeg -i ""{0}"" -ss {1} -to {2} -c:v copy -c:a copy ""{3}"""
|
||||
Dim trimFirstFile As SFile = Nothing
|
||||
Dim trimFirstAdded As Boolean = False
|
||||
Dim trimSingleReplace As Boolean = TrimOptions.Count = 1 And TrimDeleteOriginalFile
|
||||
Dim audioReplace As New Dictionary(Of SFile, SFile)
|
||||
Dim processTrim As Action(Of TrimOption, SFile, Boolean) =
|
||||
Sub(ByVal opt As TrimOption, ByVal pFile As SFile, ByVal isAudio As Boolean)
|
||||
Dim fNew As SFile = pFile
|
||||
fNew.Name &= $"_{opt.Name}"
|
||||
If TrimSeparateFolder Then fNew = $"{fNew.PathNoSeparator}\{MyYouTubeSettings.TrimSeparateFolderName.Value.IfNullOrEmpty(YouTubeSettings.TrimSeparateFolderNameDefault)}\{fNew.File}" : fNew.Exists(SFO.Path)
|
||||
format = fNew.Extension.StringToLower
|
||||
.Execute(String.Format(trimCommand,
|
||||
pFile,
|
||||
AConvert(Of String)(opt.StartTime, TimeToStringProvider),
|
||||
AConvert(Of String)(opt.EndTime, TimeToStringProvider),
|
||||
fNew))
|
||||
If fNew.Exists Then
|
||||
If trimFirstFile.IsEmptyString Then trimFirstFile = fNew
|
||||
If Not trimSingleReplace Then AddFile(fNew)
|
||||
If isAudio And trimSingleReplace And Not audioReplace.ContainsKey(pFile) Then audioReplace.Add(pFile, fNew)
|
||||
If format = mp3 And MyYouTubeSettings.DefaultAudioEmbedThumbnail_ExtractedFiles Then _
|
||||
embedThumbTo.Invoke(fNew) : mp3ThumbEmbedded = True
|
||||
If Not trimSingleReplace AndAlso
|
||||
(TrimAddTrimmedFilesToM3U8 Or (TrimDeleteOriginalFile And Not trimFirstAdded)) AndAlso
|
||||
(M3U8_PlaylistFiles.ListExists OrElse
|
||||
(format = mp3 AndAlso MyYouTubeSettings.VideoPlaylist_AddExtractedMP3.Value)) Then _
|
||||
M3U8_Append(fNew) : trimFirstAdded = True
|
||||
End If
|
||||
End Sub
|
||||
For Each tr As TrimOption In TrimOptions
|
||||
processTrim(tr, File, False)
|
||||
If audioFiles.Count > 0 Then
|
||||
For Each f In audioFiles : processTrim(tr, f, True) : Next
|
||||
End If
|
||||
Next
|
||||
If TrimDeleteOriginalFile Then
|
||||
Dim silentEDP As New ErrorsDescriber(EDP.ReturnValue)
|
||||
File.Delete(,, silentEDP)
|
||||
If trimSingleReplace Then
|
||||
File = SFile.Rename(trimFirstFile, File,, New ErrorsDescriber(False, False, False, trimFirstFile))
|
||||
If audioReplace.Count > 0 Then
|
||||
For Each kvf As KeyValuePair(Of SFile, SFile) In audioReplace
|
||||
If kvf.Key.Exists And kvf.Value.Exists Then
|
||||
kvf.Key.Delete(,, silentEDP)
|
||||
SFile.Rename(kvf.Value, kvf.Key,, silentEDP)
|
||||
End If
|
||||
Next
|
||||
audioReplace.Clear()
|
||||
End If
|
||||
Else
|
||||
File = trimFirstFile
|
||||
If audioFiles.Count > 0 Then
|
||||
For Each f In audioFiles
|
||||
If Not f = File Then f.Delete(,, silentEDP)
|
||||
Next
|
||||
End If
|
||||
End If
|
||||
End If
|
||||
|
||||
End If
|
||||
End If
|
||||
End If
|
||||
End With
|
||||
@@ -1658,12 +1743,20 @@ Namespace API.YouTube.Objects
|
||||
If Not tmpPls.IsEmptyString Then PlaylistTitle = tmpPls
|
||||
End If
|
||||
|
||||
Dim tmpTitle$
|
||||
UserID = .Value("uploader_id")
|
||||
UserTitle = TitleHtmlConverter.Invoke(.Value("uploader"))
|
||||
If Not UserTitle.IsEmptyString Then
|
||||
Dim tmpTitle$ = UserTitle.Replace("Topic", String.Empty).StringTrimEnd(" ", "-")
|
||||
tmpTitle = UserTitle.Replace("Topic", String.Empty).StringTrimEnd(" ", "-")
|
||||
If Not tmpTitle.IsEmptyString Then UserTitle = tmpTitle
|
||||
End If
|
||||
If MyYouTubeSettings.ParseLongUserTitle Or UserTitle.IsEmptyString Then
|
||||
tmpTitle = TitleHtmlConverter.Invoke(.Value("artist"))
|
||||
If Not tmpTitle.IsEmptyString Then
|
||||
If Not UserTitle.IsEmptyString AndAlso Not tmpTitle.Contains(UserTitle) Then tmpTitle = $"{UserTitle}, {tmpTitle}"
|
||||
UserTitle = ListAddList(Nothing, tmpTitle.Split(","), CType(Function(v$) v.StringTrim, Func(Of Object, Object)), EDP.ReturnValue).ListToString(" & ").IfNullOrEmpty(UserTitle)
|
||||
End If
|
||||
End If
|
||||
|
||||
Dim ext$ = IIf(IsMusic,
|
||||
MyYouTubeSettings.DefaultAudioCodecMusic.Value.StringToLower,
|
||||
@@ -1690,6 +1783,8 @@ Namespace API.YouTube.Objects
|
||||
ParseThumbnails(.Self)
|
||||
|
||||
ParseSubtitles(.Self)
|
||||
|
||||
ParseChapters(.Self)
|
||||
End With
|
||||
Return True
|
||||
End If
|
||||
@@ -1955,6 +2050,15 @@ Namespace API.YouTube.Objects
|
||||
End With
|
||||
End If
|
||||
End Sub
|
||||
Protected Sub ParseChapters(ByVal e As EContainer)
|
||||
With e({"chapters"})
|
||||
If .ListExists Then Chapters.AddRange(.Select(Function(ee) New TrimOption With {
|
||||
.Start = CInt(AConvert(Of Double)(ee.Value("start_time"), 0, EDP.ReturnValue)),
|
||||
.[End] = CInt(AConvert(Of Double)(ee.Value("end_time"), 0, EDP.ReturnValue)),
|
||||
.Name = CleanFileName(New SFile With {.Name = ee.Value("title")}).Name
|
||||
}))
|
||||
End With
|
||||
End Sub
|
||||
#End Region
|
||||
#Region "IEContainerProvider Support"
|
||||
Private Function GetElementsChecked() As IEnumerable(Of EContainer)
|
||||
@@ -2029,6 +2133,8 @@ Namespace API.YouTube.Objects
|
||||
_Subtitles.Clear()
|
||||
_SubtitlesDelegated.Clear()
|
||||
SubtitlesSelectedIndexes.Clear()
|
||||
Chapters.Clear()
|
||||
TrimOptions.Clear()
|
||||
MediaObjects.Clear()
|
||||
_Files.Clear()
|
||||
PostProcessing_OutputAudioFormats.Clear()
|
||||
|
||||
@@ -124,6 +124,12 @@
|
||||
<Compile Include="Controls\ChannelTabsChooserForm.vb">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Controls\ChaptersForm.Designer.vb">
|
||||
<DependentUpon>ChaptersForm.vb</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\ChaptersForm.vb">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Controls\FilterForm.Designer.vb">
|
||||
<DependentUpon>FilterForm.vb</DependentUpon>
|
||||
</Compile>
|
||||
@@ -136,6 +142,18 @@
|
||||
<Compile Include="Controls\PlayListParserForm.vb">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Controls\TrimOptionForm.Designer.vb">
|
||||
<DependentUpon>TrimOptionForm.vb</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\TrimOptionForm.vb">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Controls\VideoOptionsTrimForm.Designer.vb">
|
||||
<DependentUpon>VideoOptionsTrimForm.vb</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\VideoOptionsTrimForm.vb">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Controls\YTDataFilter.vb" />
|
||||
<Compile Include="Downloader\DownloadLocationsCollection.vb" />
|
||||
<Compile Include="Downloader\IDownloaderSettings.vb" />
|
||||
@@ -227,12 +245,21 @@
|
||||
<EmbeddedResource Include="Controls\ChannelTabsChooserForm.resx">
|
||||
<DependentUpon>ChannelTabsChooserForm.vb</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Controls\ChaptersForm.resx">
|
||||
<DependentUpon>ChaptersForm.vb</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Controls\FilterForm.resx">
|
||||
<DependentUpon>FilterForm.vb</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Controls\PlayListParserForm.resx">
|
||||
<DependentUpon>PlayListParserForm.vb</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Controls\TrimOptionForm.resx">
|
||||
<DependentUpon>TrimOptionForm.vb</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Controls\VideoOptionsTrimForm.resx">
|
||||
<DependentUpon>VideoOptionsTrimForm.vb</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Downloader\MediaItem.resx">
|
||||
<DependentUpon>MediaItem.vb</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
|
||||
@@ -13,7 +13,7 @@ Imports System.Runtime.InteropServices
|
||||
<Assembly: AssemblyDescription("SCrawler YouTube downloader")>
|
||||
<Assembly: AssemblyCompany("AndyProgram")>
|
||||
<Assembly: AssemblyProduct("SCrawler.YouTubeDownloader")>
|
||||
<Assembly: AssemblyCopyright("Copyright © 2025")>
|
||||
<Assembly: AssemblyCopyright("Copyright © 2026")>
|
||||
<Assembly: AssemblyTrademark("AndyProgram")>
|
||||
|
||||
<Assembly: ComVisible(False)>
|
||||
@@ -32,6 +32,6 @@ Imports System.Runtime.InteropServices
|
||||
' by using the '*' as shown below:
|
||||
' <Assembly: AssemblyVersion("1.0.*")>
|
||||
|
||||
<Assembly: AssemblyVersion("2025.6.12.0")>
|
||||
<Assembly: AssemblyFileVersion("2025.6.12.0")>
|
||||
<Assembly: AssemblyVersion("2025.11.25.0")>
|
||||
<Assembly: AssemblyFileVersion("2025.11.25.0")>
|
||||
<Assembly: NeutralResourcesLanguage("en")>
|
||||
|
||||
14
SCrawler.sln
@@ -29,6 +29,8 @@ Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "SCrawler.Updater", "SCrawle
|
||||
EndProject
|
||||
Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "SCrawler.Shared", "SCrawler.Shared\SCrawler.Shared.vbproj", "{DC634700-24C7-42DD-BF8F-87E6CC54E625}"
|
||||
EndProject
|
||||
Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "PersonalUtilities.Images", "..\..\MyUtilities\PersonalUtilities.Images\PersonalUtilities.Images.vbproj", "{B7EF76A9-96F3-4C53-B252-0AB5F79B67B3}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -135,6 +137,18 @@ Global
|
||||
{DC634700-24C7-42DD-BF8F-87E6CC54E625}.Release|x64.Build.0 = Release|x64
|
||||
{DC634700-24C7-42DD-BF8F-87E6CC54E625}.Release|x86.ActiveCfg = Release|x86
|
||||
{DC634700-24C7-42DD-BF8F-87E6CC54E625}.Release|x86.Build.0 = Release|x86
|
||||
{B7EF76A9-96F3-4C53-B252-0AB5F79B67B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B7EF76A9-96F3-4C53-B252-0AB5F79B67B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B7EF76A9-96F3-4C53-B252-0AB5F79B67B3}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{B7EF76A9-96F3-4C53-B252-0AB5F79B67B3}.Debug|x64.Build.0 = Debug|x64
|
||||
{B7EF76A9-96F3-4C53-B252-0AB5F79B67B3}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{B7EF76A9-96F3-4C53-B252-0AB5F79B67B3}.Debug|x86.Build.0 = Debug|x86
|
||||
{B7EF76A9-96F3-4C53-B252-0AB5F79B67B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B7EF76A9-96F3-4C53-B252-0AB5F79B67B3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B7EF76A9-96F3-4C53-B252-0AB5F79B67B3}.Release|x64.ActiveCfg = Release|x64
|
||||
{B7EF76A9-96F3-4C53-B252-0AB5F79B67B3}.Release|x64.Build.0 = Release|x64
|
||||
{B7EF76A9-96F3-4C53-B252-0AB5F79B67B3}.Release|x86.ActiveCfg = Release|x86
|
||||
{B7EF76A9-96F3-4C53-B252-0AB5F79B67B3}.Release|x86.Build.0 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -10,10 +10,8 @@ Namespace API.Base.GDL
|
||||
Friend Class GDLBatch : Inherits TokenBatch
|
||||
Friend Const UrlLibStart As String = "[urllib3.connectionpool][debug]"
|
||||
Friend Const UrlTextStart As String = UrlLibStart & " https"
|
||||
Friend Sub New(ByVal _Token As Threading.CancellationToken)
|
||||
MyBase.New(_Token)
|
||||
MainProcessName = "gallery-dl"
|
||||
ChangeDirectory(Settings.GalleryDLFile.File)
|
||||
Friend Sub New(ByVal _Token As Threading.CancellationToken, Optional ByVal __MainProcessName As String = Nothing, Optional ByVal WorkingDir As SFile = Nothing)
|
||||
MyBase.New(_Token, __MainProcessName.IfNullOrEmpty(Settings.GalleryDLFile.File.Name), WorkingDir.IfNullOrEmpty(Settings.GalleryDLFile.File))
|
||||
End Sub
|
||||
Protected Overrides Async Sub OutputDataReceiver(ByVal Sender As Object, ByVal e As DataReceivedEventArgs)
|
||||
If Not ProcessKilled Then
|
||||
|
||||
@@ -58,6 +58,11 @@ Namespace API.Base
|
||||
Return Type = Types.Audio Or Type = Types.AudioPre
|
||||
End Get
|
||||
End Property
|
||||
Friend ReadOnly Property IsPhotoType As Boolean
|
||||
Get
|
||||
Return Type = Types.Picture Or Type = Types.GIF
|
||||
End Get
|
||||
End Property
|
||||
Friend URL_BASE As String
|
||||
Friend URL As String
|
||||
Friend MD5 As String
|
||||
|
||||
@@ -13,10 +13,16 @@ Namespace API.Base
|
||||
Friend Property TempPostsList As List(Of String)
|
||||
Protected ReadOnly Token As CancellationToken
|
||||
Friend Property DebugMode As Boolean = False
|
||||
Friend Sub New(ByVal _Token As CancellationToken)
|
||||
Friend Sub New(ByVal _Token As CancellationToken, Optional ByVal _MainProcessName As String = Nothing, Optional ByVal WorkingDir As SFile = Nothing)
|
||||
MyBase.New(True)
|
||||
Token = _Token
|
||||
MainProcessName = _MainProcessName
|
||||
If Not WorkingDir.IsEmptyString Then ChangeDirectory(WorkingDir)
|
||||
End Sub
|
||||
Protected Overrides Function Internal_Execute(ByVal Commands As IEnumerable(Of String), ByVal e As ErrorsDescriber) As Boolean
|
||||
If Not Encoding.HasValue Then Encoding = UnicodeEncoding
|
||||
Return MyBase.Internal_Execute(Commands, e)
|
||||
End Function
|
||||
Public Overrides Sub Create()
|
||||
If TempPostsList Is Nothing Then TempPostsList = New List(Of String)
|
||||
MyBase.Create()
|
||||
|
||||
@@ -1439,6 +1439,16 @@ BlockNullPicture:
|
||||
Cache.Validate()
|
||||
Return Cache
|
||||
End Function
|
||||
#Region "GDL File Names"
|
||||
Protected GDLFileNameProvider As ANumbers = Nothing
|
||||
Protected Sub GDLResetFileNameProvider(Optional ByVal GroupSize As Integer? = Nothing)
|
||||
GDLFileNameProvider = New ANumbers With {.FormatOptions = ANumbers.Options.FormatNumberGroup + ANumbers.Options.Groups}
|
||||
GDLFileNameProvider.GroupSize = If(GroupSize, 3)
|
||||
End Sub
|
||||
Protected Function GDLRenameFile(ByVal Input As SFile, ByVal i As Integer) As SFile
|
||||
Return SFile.Rename(Input, $"{Input.PathWithSeparator}{i.NumToString(GDLFileNameProvider)}.{Input.Extension}",, EDP.ThrowException)
|
||||
End Function
|
||||
#End Region
|
||||
#Region "DownloadSingleObject"
|
||||
Protected IsSingleObjectDownload As Boolean = False
|
||||
Friend Overridable Sub DownloadSingleObject(ByVal Data As YouTube.Objects.IYouTubeMediaContainer, ByVal Token As CancellationToken) Implements IUserData.DownloadSingleObject
|
||||
@@ -1723,6 +1733,7 @@ BlockNullPicture:
|
||||
Dim vsf As Boolean = SeparateVideoFolderF
|
||||
Dim __isVideo As Boolean
|
||||
Dim __interrupt As Boolean
|
||||
Dim postProcessWebp As Boolean
|
||||
Dim f As SFile, fTxt As SFile
|
||||
Dim v As UserMedia
|
||||
Dim __fileDeleted As Boolean
|
||||
@@ -1782,6 +1793,7 @@ BlockNullPicture:
|
||||
If v.URL_BASE.IsEmptyString Then v.URL_BASE = v.URL
|
||||
|
||||
__fileDeleted = False
|
||||
postProcessWebp = False
|
||||
|
||||
If (v.Type = UTypes.Text And DownloadText) Or (Not f.IsEmptyString And Not v.URL.IsEmptyString) Then
|
||||
Try
|
||||
@@ -1794,8 +1806,9 @@ BlockNullPicture:
|
||||
Case UTypes.Video, UTypes.m3u8 : f.Extension = "mp4"
|
||||
Case UTypes.GIF : f.Extension = "gif"
|
||||
End Select
|
||||
ElseIf f.Extension = "webp" And Settings.DownloadNativeImageFormat Then
|
||||
f.Extension = "jpg"
|
||||
ElseIf f.Extension = UserImage.ExtWebp And Settings.DownloadNativeImageFormat And Settings.FfmpegFile.Exists Then
|
||||
'f.Extension = "jpg"
|
||||
postProcessWebp = True
|
||||
End If
|
||||
|
||||
If Not v.SpecialFolder.IsEmptyString Then
|
||||
@@ -1830,7 +1843,7 @@ BlockNullPicture:
|
||||
|
||||
updateDownCount(False)
|
||||
|
||||
v.File = ChangeFileNameByProvider(f, v)
|
||||
v.File = DownloadContentDefault_ConvertWebp(ChangeFileNameByProvider(f, v), postProcessWebp)
|
||||
v.State = UStates.Downloaded
|
||||
DownloadContentDefault_PostProcessing(v, f, Token)
|
||||
If UseMD5Comparison And (v.Type = UTypes.GIF Or v.Type = UTypes.Picture) Then
|
||||
@@ -1930,6 +1943,22 @@ stxt:
|
||||
End Function
|
||||
Protected Overridable Sub DownloadContentDefault_PostProcessing(ByRef m As UserMedia, ByVal File As SFile, ByVal Token As CancellationToken)
|
||||
End Sub
|
||||
Protected Overridable Function DownloadContentDefault_ConvertWebp(ByVal WebpFile As SFile, ByVal Process As Boolean) As SFile
|
||||
Dim f As SFile = WebpFile
|
||||
If Process AndAlso f.Exists Then
|
||||
f.Path = $"{f.PathWithSeparator}Sources"
|
||||
f.Exists(SFO.Path)
|
||||
If WebpFile.Copy(f) Then
|
||||
Dim newFile As SFile = WebpFile
|
||||
newFile.Extension = UserImage.ExtJpg
|
||||
f = UserImage.ConvertWebp(f, newFile)
|
||||
If f.Exists Then WebpFile.Delete(SFO.File, SFODelete.DeletePermanently, EDP.ReturnValue)
|
||||
Else
|
||||
f = WebpFile
|
||||
End If
|
||||
End If
|
||||
Return f
|
||||
End Function
|
||||
Protected Overridable Function DownloadContentDefault_ProcessDownloadException() As Boolean
|
||||
Return True
|
||||
End Function
|
||||
@@ -2434,6 +2463,7 @@ stxt:
|
||||
_TempPostsList.Clear()
|
||||
_MD5List.Clear()
|
||||
TokenPersonal = Nothing
|
||||
GDLFileNameProvider = Nothing
|
||||
If Not ProgressPre Is Nothing Then ProgressPre.Reset() : ProgressPre.Dispose()
|
||||
If Not Responser Is Nothing Then Responser.Dispose()
|
||||
If Not BTT_CONTEXT_DOWN Is Nothing Then BTT_CONTEXT_DOWN.Dispose()
|
||||
|
||||
@@ -8,11 +8,8 @@
|
||||
' but WITHOUT ANY WARRANTY
|
||||
Namespace API.Base.YTDLP
|
||||
Friend Class YTDLPBatch : Inherits GDL.GDLBatch
|
||||
Friend Sub New(ByVal _Token As Threading.CancellationToken)
|
||||
MyBase.New(_Token)
|
||||
Commands.Clear()
|
||||
MainProcessName = Settings.YtdlpFile.File.Name '"yt-dlp"
|
||||
ChangeDirectory(Settings.YtdlpFile.File)
|
||||
Friend Sub New(ByVal _Token As Threading.CancellationToken, Optional ByVal __MainProcessName As String = Nothing, Optional ByVal WorkingDir As SFile = Nothing)
|
||||
MyBase.New(_Token, __MainProcessName.IfNullOrEmpty(Settings.YtdlpFile.File.Name), WorkingDir.IfNullOrEmpty(Settings.YtdlpFile.File))
|
||||
End Sub
|
||||
End Class
|
||||
End Namespace
|
||||
@@ -14,7 +14,7 @@ Imports PersonalUtilities.Functions.RegularExpressions
|
||||
Imports PersonalUtilities.Tools.Web.Clients
|
||||
Imports PersonalUtilities.Tools.Web.Documents.JSON
|
||||
Namespace API.Bluesky
|
||||
<Manifest(BlueskySiteKey), SpecialForm(False)>
|
||||
<Manifest(BlueskySiteKey), SpecialForm(False), SavedPosts>
|
||||
Friend Class SiteSettings : Inherits SiteSettingsBase
|
||||
<PropertyOption(ControlText:="Cookies enabled", ControlToolTip:="If checked, cookies will be used in requests", IsAuth:=True), PXML, PClonable, HiddenControl>
|
||||
Friend ReadOnly Property CookiesEnabled As PropertyValue
|
||||
|
||||
@@ -79,22 +79,33 @@ Namespace API.Bluesky
|
||||
Private Overloads Sub DownloadData(ByVal Cursor As String, ByVal Token As CancellationToken)
|
||||
Dim URL$ = String.Empty
|
||||
Try
|
||||
If ID.IsEmptyString Then GetProfileInfo(Token)
|
||||
If ID.IsEmptyString Then Throw New ArgumentNullException("ID", "ID is null")
|
||||
If Not IsSavedPosts And ID.IsEmptyString Then GetProfileInfo(Token)
|
||||
If Not IsSavedPosts And ID.IsEmptyString Then Throw New ArgumentNullException("ID", "ID is null")
|
||||
If UpdateToken() Then
|
||||
Dim nextCursor$ = String.Empty
|
||||
Dim c%
|
||||
URL = $"https://bsky.social/xrpc/app.bsky.feed.getAuthorFeed?actor={ID_Encoded}&filter=posts_and_author_threads&includePins=false&limit=99"
|
||||
If Not Cursor.IsEmptyString Then URL &= $"&cursor={SymbolsConverter.ASCII.EncodeSymbolsOnly(Cursor)}"
|
||||
Dim n$(), p$()
|
||||
If IsSavedPosts Then
|
||||
URL = "https://bsky.social/xrpc/app.bsky.bookmark.getBookmarks"
|
||||
If Not Cursor.IsEmptyString Then URL &= $"?cursor={Cursor}"
|
||||
n = {"bookmarks"}
|
||||
p = {"item"}
|
||||
Else
|
||||
URL = $"https://bsky.social/xrpc/app.bsky.feed.getAuthorFeed?actor={ID_Encoded}&filter=posts_and_author_threads&includePins=false&limit=99"
|
||||
If Not Cursor.IsEmptyString Then URL &= $"&cursor={SymbolsConverter.ASCII.EncodeSymbolsOnly(Cursor)}"
|
||||
n = {"feed"}
|
||||
p = {"post"}
|
||||
End If
|
||||
Dim r$ = Responser.GetResponse(URL)
|
||||
TokenUpdateCountReset()
|
||||
If Not r.IsEmptyString Then
|
||||
Using j As EContainer = JsonDocument.Parse(r)
|
||||
If j.ListExists Then
|
||||
With j("feed")
|
||||
nextCursor = j.Value("cursor")
|
||||
With j(n)
|
||||
If .ListExists Then
|
||||
For Each post As EContainer In .Self
|
||||
With post({"post"})
|
||||
With post(p)
|
||||
c = DefaultParser(.Self,, nextCursor)
|
||||
Select Case c
|
||||
Case CInt(DateResult.Skip) * -1 : Continue For
|
||||
@@ -104,6 +115,8 @@ Namespace API.Bluesky
|
||||
If DownloadTopCount.HasValue AndAlso DownloadTopCount.Value <= _PostCount Then Exit Sub
|
||||
End With
|
||||
Next
|
||||
ElseIf IsSavedPosts Then
|
||||
nextCursor = String.Empty
|
||||
End If
|
||||
End With
|
||||
End If
|
||||
@@ -126,7 +139,7 @@ Namespace API.Bluesky
|
||||
Optional ByVal CheckTempPosts As Boolean = True, Optional ByVal State As UStates = UStates.Unknown) As Integer
|
||||
Const exitReturn% = CInt(DateResult.Exit) * -1
|
||||
Const skipReturn% = CInt(DateResult.Skip) * -1
|
||||
Dim postID$, postDate$, __url$, __urlBase$, __txt$, __userId$
|
||||
Dim postID$, postDate$, __url$, __urlBase$, __txt$, __userId$, __postAuthor$
|
||||
Dim updateUrl As Boolean
|
||||
Dim c% = 0
|
||||
Dim m As UserMedia
|
||||
@@ -138,11 +151,12 @@ Namespace API.Bluesky
|
||||
__urlBase = String.Empty
|
||||
__txt = String.Empty
|
||||
__userId = .Value({"author"}, "did")
|
||||
__postAuthor = String.Empty
|
||||
With .Item({"record"})
|
||||
If .ListExists Then
|
||||
'2025-01-28T02:42:12.415Z
|
||||
postDate = .Value("createdAt")
|
||||
NextCursor = postDate
|
||||
If Not IsSavedPosts Then NextCursor = postDate
|
||||
If CheckDateLimits Then
|
||||
Select Case CheckDatesLimit(postDate, DateProvider)
|
||||
Case DateResult.Skip : Return skipReturn 'Continue For
|
||||
@@ -155,9 +169,10 @@ Namespace API.Bluesky
|
||||
If _TempPostsList.Contains(postID) Then Return exitReturn Else _TmpPosts2.Add(postID)
|
||||
End If
|
||||
|
||||
If ParseUserMediaOnly And Not ID.IsEmptyString And Not __userId.IsEmptyString And Not ID = __userId Then Return skipReturn
|
||||
If ParseUserMediaOnly And Not IsSavedPosts And Not ID.IsEmptyString And Not __userId.IsEmptyString And Not ID = __userId Then Return skipReturn
|
||||
|
||||
__urlBase = $"https://bsky.app/profile/{NameTrue}/post/{postID}"
|
||||
__postAuthor = e.Value({"author"}, "did")
|
||||
__urlBase = $"https://bsky.app/profile/{If(IsSavedPosts, __postAuthor, NameTrue)}/post/{postID}"
|
||||
End If
|
||||
End With
|
||||
|
||||
@@ -190,7 +205,11 @@ Namespace API.Bluesky
|
||||
__url = d.Value("fullsize")
|
||||
If __url.IsEmptyString Then __url = d.Value({"image", "ref"}, "$link") : updateUrl = True
|
||||
If __url.IsEmptyString And SecondExtraction Then updateUrl = False : __url = e.Value({"embed"}, "thumb")
|
||||
If Not __url.IsEmptyString Then createMedia(__url, UTypes.Picture)
|
||||
If Not __url.IsEmptyString Then
|
||||
If updateUrl AndAlso Not __url.StartsWith("http") Then _
|
||||
__url = $"https://cdn.bsky.app/img/feed_fullsize/plain/{__postAuthor}/{__url}@jpeg"
|
||||
createMedia(__url, UTypes.Picture)
|
||||
End If
|
||||
Next
|
||||
End With
|
||||
End If
|
||||
|
||||
@@ -412,6 +412,7 @@ Namespace API.Instagram
|
||||
ThrowAny(Token)
|
||||
HasError = False
|
||||
Dim dt As Func(Of Boolean) = Function() (CBool(MySiteSettings.DownloadTimeline.Value) And GetTimeline) Or IsSavedPosts
|
||||
If FirstLoadingDone Then LastCursor = String.Empty
|
||||
If dt.Invoke And Not LastCursor.IsEmptyString Then
|
||||
s = IIf(IsSavedPosts, Sections.SavedPosts, Sections.Timeline)
|
||||
upClaimRequest.Invoke
|
||||
@@ -524,7 +525,7 @@ Namespace API.Instagram
|
||||
Protected Overrides Sub Responser_ResponseReceived(ByVal Sender As Object, ByVal e As EventArguments.WebDataResponse)
|
||||
Declarations.UpdateResponser(e, Responser, WwwClaimUpdate)
|
||||
End Sub
|
||||
Friend Enum Sections : Timeline : Reels : Tagged : Stories : UserStories : SavedPosts : End Enum
|
||||
Friend Enum Sections : Timeline : Reels : Tagged : Stories : UserStories : SavedPosts : Reposts : Likes : End Enum
|
||||
Protected Const StoriesFolder As String = "Stories"
|
||||
Private Const TaggedFolder As String = "Tagged"
|
||||
#Region "429 bypass"
|
||||
|
||||
@@ -219,12 +219,12 @@ Namespace API.OnlyFans
|
||||
DynamicRulesXml.Extension = "xml"
|
||||
ReplacePattern_RepoToRaw = New RParams("(.*github.com/([^/]+)/([^/]+)/blob/(.+))", Nothing, 0,
|
||||
RegexReturn.ReplaceChangeListMatch, EDP.ReturnValue) With {
|
||||
.PatternReplacement = "https://raw.githubusercontent.com/{2}/{3}/{4}"}
|
||||
.PatternReplacement = "https://raw.githubusercontent.com/{2}/{3}/refs/heads/{4}"}
|
||||
ReplacePattern_JsonInfo = ReplacePattern_RepoToRaw.Copy
|
||||
ReplacePattern_JsonInfo.PatternReplacement = "https://github.com/{2}/{3}/latest-commit/{4}"
|
||||
ReplacePattern_RawToRepo = ReplacePattern_RepoToRaw.Copy
|
||||
ReplacePattern_RawToRepo.Pattern = "(.*raw.githubusercontent.com/([^/]+)/([^/]+)/([^/]+)/(.+))"
|
||||
ReplacePattern_RawToRepo.PatternReplacement = "https://github.com/{2}/{3}/blob/{4}/{5}"
|
||||
ReplacePattern_RawToRepo.Pattern = "(.*raw.githubusercontent.com/([^/]+)/([^/]+)(/refs/heads)?/([^/]+)/(.+))"
|
||||
ReplacePattern_RawToRepo.PatternReplacement = "https://github.com/{2}/{3}/blob/{5}/{6}"
|
||||
ConfigRulesExtract = RParams.DMS("DYNAMIC_RULE"":(\{.+?\}[\r\n]+)", 1, RegexOptions.Singleline, EDP.ReturnValue)
|
||||
OFLOG = New TextSaver($"LOGs\OF_{Now:yyyyMMdd_HHmmss}.txt") With {.LogMode = True, .AutoSave = True, .AutoClear = True}
|
||||
AddHandler OFLOG.TextSaved, AddressOf OFLOG_TextSaved
|
||||
|
||||
@@ -88,6 +88,7 @@ Namespace API.OnlyFans
|
||||
Private _DownloadedPostsSession As Integer = 0
|
||||
Private FunctionErr As Integer = FunctionErrDef
|
||||
Private Const FunctionErrDef As Integer = -100
|
||||
Private _TimelineDownloading As Boolean = False
|
||||
Private Sub ValidateOFScraper()
|
||||
_OFScraperExists = ACheck(MySettings.OFScraperPath.Value) AndAlso CStr(MySettings.OFScraperPath.Value).CSFile.Exists
|
||||
End Sub
|
||||
@@ -110,7 +111,9 @@ Namespace API.OnlyFans
|
||||
If ID.IsEmptyString Then Throw New ArgumentNullException("ID", "Unable to get user ID")
|
||||
End If
|
||||
|
||||
_TimelineDownloading = True
|
||||
If MediaDownloadTimeline Then DownloadTimeline(IIf(IsSavedPosts, 0, String.Empty), Token)
|
||||
_TimelineDownloading = False
|
||||
If Not IsSavedPosts Then
|
||||
If MediaDownloadStories And FunctionErr = FunctionErrDef Then DownloadStories(Token)
|
||||
If MediaDownloadHighlights And FunctionErr = FunctionErrDef Then DownloadHighlights(Token)
|
||||
@@ -827,6 +830,8 @@ Namespace API.OnlyFans
|
||||
Return 3
|
||||
ElseIf Responser.StatusCode = Net.HttpStatusCode.InternalServerError Then '500
|
||||
Return 3
|
||||
ElseIf Not _TimelineDownloading And Responser.StatusCode = Net.HttpStatusCode.BadGateway Then '502
|
||||
Return 3
|
||||
Else
|
||||
Return 0
|
||||
End If
|
||||
|
||||
@@ -20,7 +20,7 @@ Namespace API.PornHub
|
||||
Friend ReadOnly RegexVideo_FlashVars_Vars As RParams = RParams.DM("var ([\w\d]{10,})=("".+?)(?=(;|\Z))", 0, RegexReturn.List)
|
||||
Friend ReadOnly RegexVideo_FlashVars_Compiler As RParams = RParams.DM("(?<=\*/)([\w\d\S]{10,})", 0, RegexReturn.List)
|
||||
Friend ReadOnly RegexVideo_FlashVars_UrlResolution As RParams = RParams.DMS("/(\d+)[^/]+\.mp4", 1, EDP.ReturnValue)
|
||||
Friend ReadOnly RegexUserVideos As RParams = RParams.DM("(\<li class=""pcVideoListItem)((?:(?!/li\>).)*?)(\<div.class=.private-vid-title((?:(?!/li\>).)*?)|)(\<a.href=.([^""]+?)"".title=.([^""]*?)"")(((?:(?!/li\>).)+?)(\<div class=.videoUploaderBlock)|)((?:(?!/li\>).)*?)(\</li\>)",
|
||||
Friend ReadOnly RegexUserVideos As RParams = RParams.DM("(\<li class=""pcVideoListItem)((?:(?!/li\>).)*?)(\<div.class=.private-vid-title((?:(?!/li\>).)*?)|)(\<a.href=.([^""]+?)"".title=.([^""]*?)"")(((?:(?!/li\>).)+?)(\<div class=.videoUploaderBlock.*?href=""([^""]+)"")|)((?:(?!/li\>).)*?)(\</li\>)",
|
||||
0, RegexOptions.Singleline, RegexReturn.List, EDP.ReturnValue, UnicodeHexConverter)
|
||||
Friend ReadOnly RegexVideo_Video_VideoKey As RParams = RParams.DMS("viewkey=([\w\d]+)", 1, EDP.ReturnValue)
|
||||
Friend ReadOnly RegexVideoPageTitle As RParams = RParams.DMS("meta (property|name)=""[^:]+?:title"" content=""([^""]+)""", 2, EDP.ReturnValue)
|
||||
|
||||
@@ -50,6 +50,7 @@ Namespace API.PornHub
|
||||
Friend URL As String
|
||||
Friend ID As String
|
||||
Friend Title As String
|
||||
Friend UserRef As String
|
||||
Friend Type As VideoTypes
|
||||
Friend Function ToUserMedia(Optional ByVal SpecialFolder As String = Nothing) As UserMedia
|
||||
Return New UserMedia(URL, UTypes.VideoPre) With {
|
||||
@@ -66,14 +67,16 @@ Namespace API.PornHub
|
||||
URL = String.Empty
|
||||
Else
|
||||
URL = String.Format(UrlPattern, URL.TrimStart("/"))
|
||||
|
||||
Title = TitleHtmlConverter(ParamsArray(1))
|
||||
If Not ParamsArray(2).IsEmptyString Then
|
||||
Type = VideoTypes.Private
|
||||
ElseIf Not ParamsArray(3).IsEmptyString Then
|
||||
Type = VideoTypes.Tagged
|
||||
'ElseIf Not ParamsArray(3).IsEmptyString Then
|
||||
' Type = VideoTypes.Tagged
|
||||
Else
|
||||
Type = VideoTypes.Uploaded
|
||||
End If
|
||||
If Not ParamsArray(3).IsEmptyString Then UserRef = ParamsArray(3).StringTrim
|
||||
End If
|
||||
End If
|
||||
Return Me
|
||||
@@ -338,10 +341,13 @@ Namespace API.PornHub
|
||||
Dim tryNextPage As Boolean = False
|
||||
Dim limit% = If(DownloadTopCount, -1)
|
||||
Dim cBefore% = _TempMediaList.Count
|
||||
Dim usrRef$ = String.Empty
|
||||
Dim npd$ = "?"
|
||||
If IsUser Then
|
||||
URL = $"https://www.pornhub.com/{PersonType}/{NameTrue}"
|
||||
usrRef = $"/{PersonType}/{NameTrue}"
|
||||
If Type = VideoTypes.Uploaded Then
|
||||
URL &= "/videos/upload"
|
||||
If Not PersonType = PersonTypeCannel Then URL &= "/videos/upload?o=mr" : npd = "&"
|
||||
ElseIf Type = VideoTypes.Tagged Then
|
||||
If Not SecondMode Then URL &= "/videos"
|
||||
specFolder = "Tagged"
|
||||
@@ -354,7 +360,7 @@ Namespace API.PornHub
|
||||
Else
|
||||
Throw New ArgumentException($"Type '{Type}' is not implemented in the video download function", "Type")
|
||||
End If
|
||||
If Page > 1 Then URL &= $"?page={Page}"
|
||||
If Page > 1 Then URL &= $"{npd}page={Page}"
|
||||
ElseIf SiteMode = SiteModes.Playlists Then
|
||||
If PlaylistToken.IsEmptyString Then Throw New ArgumentNullException("PlaylistToken", "Unable to get 'PlaylistToken'")
|
||||
URL = String.Format(PlayListUrlPattern, NameTrue, PlaylistToken, Page)
|
||||
@@ -367,12 +373,21 @@ Namespace API.PornHub
|
||||
'Debug.WriteLine(URL)
|
||||
Dim r$ = Responser.GetResponse(URL)
|
||||
If Not r.IsEmptyString Then
|
||||
Dim l As List(Of UserVideo) = RegexFields(Of UserVideo)(r, {RegexUserVideos}, {6, 7, 3, 10})
|
||||
Dim l As List(Of UserVideo) = RegexFields(Of UserVideo)(r, {RegexUserVideos}, {6, 7, 3, 11})
|
||||
'If l.ListExists And Not SiteMode = SiteModes.Playlists Then l = l.ListTake(3, l.Count).ToList
|
||||
If l.ListExists And Not SiteMode = SiteModes.Playlists Then l = l.ListTake(1, l.Count).ToList
|
||||
If l.ListExists And Not SiteMode = SiteModes.Playlists And Not IsUser Then l = l.ListTake(1, l.Count).ToList
|
||||
If l.ListExists Then
|
||||
If IsUser Then
|
||||
If Type = VideoTypes.Favorite Then
|
||||
If Type = VideoTypes.Tagged Then
|
||||
l = l.ListTake(4, l.Count)
|
||||
If l.ListExists Then l.RemoveAll(Function(uv) Not uv.UserRef.IsEmptyString AndAlso uv.UserRef = usrRef)
|
||||
ElseIf Type = VideoTypes.Uploaded Then
|
||||
If PersonType = PersonTypeCannel Then
|
||||
l = l.ListTake(4, l.Count)
|
||||
Else
|
||||
l.RemoveAll(Function(uv) Not uv.UserRef.IsEmptyString AndAlso Not uv.UserRef = usrRef)
|
||||
End If
|
||||
ElseIf Type = VideoTypes.Favorite Then
|
||||
l.RemoveAll(Function(uv) uv.Type = VideoTypes.Private)
|
||||
ElseIf Not PersonType = PersonTypeCannel Then
|
||||
l.RemoveAll(Function(uv) Not uv.Type = Type)
|
||||
|
||||
@@ -15,21 +15,32 @@ Imports PersonalUtilities.Tools.Web.Clients.Base
|
||||
Imports PersonalUtilities.Tools.Web.Documents.JSON
|
||||
Imports PersonalUtilities.Functions.XML
|
||||
Imports PersonalUtilities.Functions.RegularExpressions
|
||||
Imports DN = SCrawler.API.Base.DeclaredNames
|
||||
Imports DownDetector = SCrawler.API.Base.DownDetector
|
||||
Imports Download = SCrawler.Plugin.ISiteSettings.Download
|
||||
Namespace API.Reddit
|
||||
<Manifest(RedditSiteKey), SavedPosts, SpecialForm(False), UseDownDetector>
|
||||
<Manifest(RedditSiteKey), SavedPosts, SeparatedTasks, SpecialForm(False), UseDownDetector>
|
||||
Friend Class SiteSettings : Inherits SiteSettingsBase : Implements DownDetector.IDownDetector
|
||||
#Region "Declarations"
|
||||
#Region "Authorization"
|
||||
Private Const ApiClientID_Default As String = "dYctRA-SIJxyykHe27lGZg"
|
||||
Private Const ApiClientSecret_Default As String = "_5D6KzplRPDga-es1YlpzDIe9hiFlg"
|
||||
<PropertyOption(ControlText:="Login", ControlToolTip:="Your authorization username", IsAuth:=True), PXML, PClonable(Clone:=False)>
|
||||
Friend ReadOnly Property AuthUserName As PropertyValue
|
||||
<PropertyOption(ControlText:="Password", ControlToolTip:="Your authorization password", IsAuth:=True), PXML, PClonable(Clone:=False)>
|
||||
Friend ReadOnly Property AuthPassword As PropertyValue
|
||||
<PropertyOption(ControlText:="Client ID", ControlToolTip:="Your registered app client ID", IsAuth:=True), PXML, PClonable(Clone:=False)>
|
||||
Friend ReadOnly Property ApiClientID As PropertyValue
|
||||
<PropertyUpdater(NameOf(ApiClientID))> Private Function ApiClientID_SetDefault() As Boolean
|
||||
ApiClientID.Value = ApiClientID_Default
|
||||
Return True
|
||||
End Function
|
||||
<PropertyOption(ControlText:="Client Secret", ControlToolTip:="Your registered app client secret", IsAuth:=True), PXML, PClonable(Clone:=False)>
|
||||
Friend ReadOnly Property ApiClientSecret As PropertyValue
|
||||
<PropertyUpdater(NameOf(ApiClientSecret))> Private Function ApiClientSecret_SetDefault() As Boolean
|
||||
ApiClientSecret.Value = ApiClientSecret_Default
|
||||
Return True
|
||||
End Function
|
||||
<PropertyOption(ControlText:="Bearer token",
|
||||
ControlToolTip:="Bearer token (can be null)." & vbCr &
|
||||
"If you are using cookies to download the timeline, it is highly recommended that you add a token." & vbCr &
|
||||
@@ -103,12 +114,15 @@ Namespace API.Reddit
|
||||
End Function
|
||||
#End Region
|
||||
#Region "Other"
|
||||
<PropertyOption(ControlText:="Use M3U8", ControlToolTip:="Use M3U8 or mp4 for Reddit videos", IsAuth:=False), PXML, PClonable>
|
||||
<PropertyOption(ControlText:="Use M3U8", ControlToolTip:="Use M3U8 or mp4 for Reddit videos"), PXML, PClonable, HiddenControl>
|
||||
Friend ReadOnly Property UseM3U8 As PropertyValue
|
||||
<PropertyOption(ControlText:="Check image", ControlToolTip:="Check the image if it exists before downloading (it makes downloading very slow)", IsAuth:=False), PXML, PClonable>
|
||||
<PropertyOption(ControlText:="Check image", ControlToolTip:="Check the image if it exists before downloading (it makes downloading very slow)"), PXML, PClonable, HiddenControl>
|
||||
Friend ReadOnly Property CheckImage As PropertyValue
|
||||
<PropertyOption(ControlText:="Check image: get original", ControlToolTip:="Get the original image if it exists", IsAuth:=False), PXML, PClonable>
|
||||
<PropertyOption(ControlText:="Check image: get original", ControlToolTip:="Get the original image if it exists"), PXML, PClonable, HiddenControl>
|
||||
Friend ReadOnly Property CheckImageReturnOrig As PropertyValue
|
||||
<PropertyOption(ControlText:=DN.ConcurrentDownloadsCaption,
|
||||
ControlToolTip:=DN.ConcurrentDownloadsToolTip, AllowNull:=False), PXML, TaskCounter, PClonable>
|
||||
Friend ReadOnly Property ConcurrentDownloads As PropertyValue
|
||||
#End Region
|
||||
#Region "IDownDetector Support"
|
||||
Private ReadOnly Property IDownDetector_Value As Integer Implements DownDetector.IDownDetector.Value
|
||||
@@ -160,6 +174,7 @@ Namespace API.Reddit
|
||||
UseM3U8 = New PropertyValue(True)
|
||||
CheckImage = New PropertyValue(False)
|
||||
CheckImageReturnOrig = New PropertyValue(True)
|
||||
ConcurrentDownloads = New PropertyValue(1)
|
||||
|
||||
MDD = New MyDownDetector(Me)
|
||||
|
||||
@@ -167,10 +182,13 @@ Namespace API.Reddit
|
||||
ImageVideoContains = "reddit.com"
|
||||
UserRegex = RParams.DM("[htps:/]{7,8}.*?reddit.com/([user]{1,4})/([^/\?&]+)", 0, RegexReturn.ListByMatch, EDP.ReturnValue)
|
||||
End Sub
|
||||
Private Const SettingsVersionCurrent As Integer = 2
|
||||
Private Const SettingsVersionCurrent As Integer = 3
|
||||
Friend Overrides Sub EndInit()
|
||||
If CInt(SettingsVersion.Value) < SettingsVersionCurrent Then
|
||||
SettingsVersion.Value = SettingsVersionCurrent
|
||||
UseM3U8.Value = True
|
||||
CheckImage.Value = False
|
||||
CheckImageReturnOrig.Value = True
|
||||
BearerTokenUseCurl.Value = False
|
||||
End If
|
||||
MyBase.EndInit()
|
||||
@@ -208,6 +226,7 @@ Namespace API.Reddit
|
||||
End Sub
|
||||
End Class
|
||||
Friend Property SessionInterrupted As Boolean = False
|
||||
Friend Property RequestCount As Integer = 0
|
||||
Friend Overrides Function ReadyToDownload(ByVal What As Download) As Boolean
|
||||
If What = Download.Main Then
|
||||
Return Not SessionInterrupted
|
||||
@@ -223,6 +242,7 @@ Namespace API.Reddit
|
||||
End Function
|
||||
Friend Overrides Sub DownloadDone(ByVal What As Download)
|
||||
SessionInterrupted = False
|
||||
RequestCount = 0
|
||||
MDD.Reset()
|
||||
MyBase.DownloadDone(What)
|
||||
End Sub
|
||||
|
||||
@@ -8,19 +8,20 @@
|
||||
' but WITHOUT ANY WARRANTY
|
||||
Imports System.Net
|
||||
Imports System.Threading
|
||||
Imports PersonalUtilities.Functions.RegularExpressions
|
||||
Imports PersonalUtilities.Functions.XML
|
||||
Imports PersonalUtilities.Tools.ImageRenderer
|
||||
Imports PersonalUtilities.Tools.Web.Clients
|
||||
Imports PersonalUtilities.Tools.Web.Clients.Base
|
||||
Imports PersonalUtilities.Tools.Web.Documents.JSON
|
||||
Imports SCrawler.API.Base
|
||||
Imports SCrawler.API.Reddit.RedditViewExchange
|
||||
Imports SCrawler.API.YouTube.Objects
|
||||
Imports SCrawler.Plugin.Hosts
|
||||
Imports PersonalUtilities.Functions.XML
|
||||
Imports PersonalUtilities.Functions.RegularExpressions
|
||||
Imports PersonalUtilities.Tools.ImageRenderer
|
||||
Imports PersonalUtilities.Tools.Web.Clients
|
||||
Imports PersonalUtilities.Tools.Web.Documents.JSON
|
||||
Imports CPeriod = SCrawler.API.Reddit.IRedditView.Period
|
||||
Imports CView = SCrawler.API.Reddit.IRedditView.View
|
||||
Imports UStates = SCrawler.API.Base.UserMedia.States
|
||||
Imports UTypes = SCrawler.API.Base.UserMedia.Types
|
||||
Imports CView = SCrawler.API.Reddit.IRedditView.View
|
||||
Imports CPeriod = SCrawler.API.Reddit.IRedditView.Period
|
||||
Namespace API.Reddit
|
||||
Friend Class UserData : Inherits UserDataBase : Implements IChannelLimits, IRedditView
|
||||
#Region "Declarations"
|
||||
@@ -269,6 +270,8 @@ Namespace API.Reddit
|
||||
End If
|
||||
End With
|
||||
|
||||
Responser.ProcessExceptionDecision = AddressOf Err429Process
|
||||
|
||||
_TotalPostsDownloaded = 0
|
||||
If IsSavedPosts Then
|
||||
Responser.DecodersError = EDP.ReturnValue
|
||||
@@ -304,6 +307,7 @@ Namespace API.Reddit
|
||||
#End Region
|
||||
#Region "Download Functions (User, Channel)"
|
||||
Private Err429Count As Integer = 0
|
||||
Private Err429TryAgain As Boolean = False
|
||||
Private _TotalPostsDownloaded As Integer = 0
|
||||
Private ReadOnly _CrossPosts As List(Of String)
|
||||
Private Const SiteGfycatKey As String = "gfycat"
|
||||
@@ -311,6 +315,28 @@ Namespace API.Reddit
|
||||
Private Const Node_CrosspostRootId As String = "crosspostRootId"
|
||||
Private Const Node_CrosspostParentId As String = "crosspostParentId"
|
||||
Private Const Node_CrosspostParent As String = "crosspost_parent"
|
||||
Private Sub Wait429()
|
||||
With MySiteSettings
|
||||
If Not Err429TryAgain Then .RequestCount += 1
|
||||
Err429TryAgain = False
|
||||
If (.RequestCount Mod 100) = 0 Then Thread.Sleep(60100)
|
||||
End With
|
||||
End Sub
|
||||
Private Function Err429Process(ByVal Status As IResponserStatus, ByVal NullArg As Object, ByVal CurrErr As ErrorsDescriber) As ErrorsDescriber
|
||||
If Not Status Is Nothing AndAlso Status.StatusCode = 429 Then
|
||||
If Err429Count = 0 Then
|
||||
Err429Count += 1
|
||||
MySiteSettings.RequestCount = 100
|
||||
Err429TryAgain = True
|
||||
Return EDP.ReturnValue
|
||||
End If
|
||||
End If
|
||||
Return CurrErr
|
||||
End Function
|
||||
Private Sub Err429Reset()
|
||||
Err429Count = 0
|
||||
Err429TryAgain = False
|
||||
End Sub
|
||||
Private Sub DownloadDataUser(ByVal POST As String, ByVal Token As CancellationToken)
|
||||
Dim eObj% = 0
|
||||
Dim round% = 0
|
||||
@@ -331,8 +357,10 @@ Namespace API.Reddit
|
||||
'URL = $"https://gateway.reddit.com/desktopapi/v1/user/{NameTrue}/posts?rtj=only&allow_quarantined=true&allow_over18=1&include=identity&after={POST}&dist=25&sort={View}&t={Period}&layout=classic"
|
||||
URL = $"https://oauth.reddit.com/user/{NameTrue}/submitted.json?rtj=only&allow_quarantined=true&allow_over18=1&include=identity&after={POST}&dist=25&sort={View}&t={Period}&layout=classic"
|
||||
ThrowAny(Token)
|
||||
Wait429()
|
||||
Dim r$ = Responser.GetResponse(URL)
|
||||
If Not r.IsEmptyString Then
|
||||
Err429Reset()
|
||||
Using w As EContainer = JsonDocument.Parse(r).XmlIfNothing
|
||||
If w.Count > 0 Then
|
||||
'n = w.GetNode(JsonNodesJson)
|
||||
@@ -347,6 +375,7 @@ Namespace API.Reddit
|
||||
If CheckNode(.Self) Then
|
||||
|
||||
'Obtain post ID
|
||||
PostID = String.Empty
|
||||
PostTmp = .Value("name") '.Name
|
||||
If PostTmp.IsEmptyString Then PostTmp = .Value("id")
|
||||
If PostTmp.IsEmptyString Then Continue For
|
||||
@@ -354,8 +383,9 @@ Namespace API.Reddit
|
||||
If IsCrossPost(.Self) Then
|
||||
_CrossPosts.ListAddList({ .Value(Node_CrosspostRootId),
|
||||
.Value(Node_CrosspostParentId),
|
||||
.Value(Node_CrosspostParent)}, LNC)
|
||||
Continue For
|
||||
.Value(Node_CrosspostParent),
|
||||
PostTmp}, LNC)
|
||||
If ParseUserMediaOnly Then Continue For
|
||||
Else
|
||||
If Not _CrossPosts.Contains(PostTmp) Then PostID = PostTmp : PostTmp = String.Empty
|
||||
End If
|
||||
@@ -384,6 +414,8 @@ Namespace API.Reddit
|
||||
End Using
|
||||
If POST.IsEmptyString And ExistsDetected Then Exit Sub
|
||||
If Not _PostID().IsEmptyString And NewPostDetected Then DownloadDataUser(_PostID(), Token)
|
||||
ElseIf Err429TryAgain Then
|
||||
Continue Do
|
||||
End If
|
||||
_completed = True
|
||||
Catch ex As Exception
|
||||
@@ -420,9 +452,11 @@ Namespace API.Reddit
|
||||
End If
|
||||
|
||||
ThrowAny(Token)
|
||||
Wait429()
|
||||
Dim r$ = Responser.GetResponse(URL)
|
||||
If IsSavedPosts Then Err429Count = 0
|
||||
'If IsSavedPosts Then Err429Count = 0
|
||||
If Not r.IsEmptyString Then
|
||||
Err429Reset()
|
||||
Using w As EContainer = JsonDocument.Parse(r).XmlIfNothing
|
||||
If w.Count > 0 Then
|
||||
n = w.GetNode(ChannelJsonNodes)
|
||||
@@ -479,6 +513,8 @@ Namespace API.Reddit
|
||||
End Using
|
||||
If POST.IsEmptyString And ExistsDetected Then Exit Sub
|
||||
If Not PostID.IsEmptyString And NewPostDetected Then DownloadDataChannel(PostID, Token)
|
||||
ElseIf Err429TryAgain Then
|
||||
Continue Do
|
||||
End If
|
||||
_completed = True
|
||||
Catch ex As Exception
|
||||
@@ -496,11 +532,13 @@ Namespace API.Reddit
|
||||
End Sub
|
||||
#End Region
|
||||
#Region "GetUserInfo"
|
||||
Private Sub GetUserInfo()
|
||||
Private Sub GetUserInfo(Optional ByVal Round As Integer = 0)
|
||||
Try
|
||||
If Not IsSavedPosts And ChannelInfo Is Nothing Then
|
||||
Wait429()
|
||||
Dim r$ = Responser.GetResponse($"https://reddit.com/{IIf(IsChannel, "r", "user")}/{NameTrue}/about.json",, EDP.ReturnValue)
|
||||
If Not r.IsEmptyString Then
|
||||
Err429Reset()
|
||||
Using j As EContainer = JsonDocument.Parse(r)
|
||||
If Not j Is Nothing AndAlso j.Contains({"data", "subreddit"}) Then
|
||||
If ID.IsEmptyString Then ID = j.Value({"data"}, "id")
|
||||
@@ -516,6 +554,8 @@ Namespace API.Reddit
|
||||
End With
|
||||
End If
|
||||
End Using
|
||||
ElseIf Err429TryAgain And Round < 2 Then
|
||||
GetUserInfo(Round + 1)
|
||||
End If
|
||||
End If
|
||||
Catch ex As Exception
|
||||
@@ -631,16 +671,21 @@ Namespace API.Reddit
|
||||
Else
|
||||
Dim tPostId$ = e.Value(Node_CrosspostParent).IfNullOrEmpty(e.Value(Node_CrosspostParentId)).IfNullOrEmpty(e.Value(Node_CrosspostRootId))
|
||||
If Not PostID.IsEmptyString Then
|
||||
Dim r$ = Responser.GetResponse($"https://www.reddit.com/comments/{tPostId.Split("_").LastOrDefault}/.json",, EDP.ReturnValue)
|
||||
If Not r.IsEmptyString Then
|
||||
Using j As EContainer = JsonDocument.Parse(r, EDP.ReturnValue)
|
||||
If j.ListExists Then
|
||||
With j.ItemF({0, "data", "children", 0, "data"})
|
||||
If .ListExists Then added = ParseContainer(.Self, PostID, PostDate, UserID, False, PostText)
|
||||
End With
|
||||
End If
|
||||
End Using
|
||||
End If
|
||||
For ri% = 0 To 1
|
||||
Wait429()
|
||||
Dim r$ = Responser.GetResponse($"https://www.reddit.com/comments/{tPostId.Split("_").LastOrDefault}/.json",, EDP.ReturnValue)
|
||||
If Not r.IsEmptyString Then
|
||||
Err429Reset()
|
||||
Using j As EContainer = JsonDocument.Parse(r, EDP.ReturnValue)
|
||||
If j.ListExists Then
|
||||
With j.ItemF({0, "data", "children", 0, "data"})
|
||||
If .ListExists Then added = ParseContainer(.Self, PostID, PostDate, UserID, False, PostText)
|
||||
End With
|
||||
End If
|
||||
End Using
|
||||
Exit For
|
||||
End If
|
||||
Next
|
||||
End If
|
||||
End If
|
||||
End If
|
||||
@@ -906,7 +951,10 @@ Namespace API.Reddit
|
||||
End If
|
||||
Continue For
|
||||
Else
|
||||
Wait429()
|
||||
r = Responser.GetResponse(m.URL,, e)
|
||||
If r.IsEmptyString And Err429TryAgain Then _repeatForRedgifs = True
|
||||
If Not r.IsEmptyString Then Err429Reset()
|
||||
End If
|
||||
Loop While _repeatForRedgifs
|
||||
Else
|
||||
@@ -944,11 +992,13 @@ Namespace API.Reddit
|
||||
RedGifsResponser = RedGifsHost.Responser.Copy
|
||||
Dim respNoHeaders As Responser = Responser.Copy
|
||||
Dim m As UserMedia, m2 As UserMedia
|
||||
Dim r$, url$
|
||||
Dim r$ = String.Empty, url$
|
||||
Dim ri As Byte
|
||||
Dim j As EContainer
|
||||
Dim lastCount%, li%
|
||||
Dim rv As New ErrorsDescriber(EDP.ReturnValue)
|
||||
respNoHeaders.Headers.Clear()
|
||||
respNoHeaders.ProcessExceptionDecision = AddressOf Err429Process
|
||||
ProgressPre.ChangeMax(_ContentList.Count)
|
||||
For i% = 0 To _ContentList.Count - 1
|
||||
m = _ContentList(i)
|
||||
@@ -956,9 +1006,14 @@ Namespace API.Reddit
|
||||
If m.State = UStates.Missing AndAlso Not m.Post.ID.IsEmptyString Then
|
||||
ThrowAny(Token)
|
||||
url = $"https://www.reddit.com/comments/{m.Post.ID.Split("_").LastOrDefault}/.json"
|
||||
r = Responser.GetResponse(url,, rv)
|
||||
If r.IsEmptyString Then r = respNoHeaders.GetResponse(url,, rv)
|
||||
For ri = 0 To 1
|
||||
Wait429()
|
||||
r = Responser.GetResponse(url,, rv)
|
||||
If r.IsEmptyString Then Wait429() : r = respNoHeaders.GetResponse(url,, rv)
|
||||
If Not (r.IsEmptyString And Err429TryAgain) Then Exit For
|
||||
Next
|
||||
If Not r.IsEmptyString Then
|
||||
Err429Reset()
|
||||
j = JsonDocument.Parse(r, rv)
|
||||
If Not j Is Nothing Then
|
||||
If j.Count > 0 Then
|
||||
@@ -1101,13 +1156,22 @@ Namespace API.Reddit
|
||||
ElseIf .StatusCode = HttpStatusCode.InternalServerError Then '500
|
||||
If Not IsNothing(EObj) AndAlso IsNumeric(EObj) AndAlso CInt(EObj) = HttpStatusCode.InternalServerError Then Return 1
|
||||
Return HttpStatusCode.InternalServerError
|
||||
ElseIf .StatusCode = 429 And IsSavedPosts And Err429Count = 0 Then '429 (saved)
|
||||
Err429Count += 1
|
||||
Return 429
|
||||
'ElseIf .StatusCode = 429 And IsSavedPosts And Err429Count = 0 Then '429 (saved)
|
||||
' Err429Count += 1
|
||||
' Return 429
|
||||
ElseIf .StatusCode = 429 Then '429 (all)
|
||||
'If ((Not IsSavedPosts And CBool(MySiteSettings.UseTokenForTimelines.Value)) Or (IsSavedPosts And CBool(MySiteSettings.UseTokenForSavedPosts.Value))) AndAlso
|
||||
' Not MySiteSettings.CredentialsExists Then
|
||||
' LogError(Nothing, "[429] You should use OAuth authorization or disable " &
|
||||
' IIf(IsSavedPosts, "token usage for downloading saved posts", "the use of token and cookies for downloading timelines"))
|
||||
'Else
|
||||
' LogError(Nothing, "Too many requests (429). Try again later!")
|
||||
'End If
|
||||
'MySiteSettings.SessionInterrupted = True
|
||||
'Throw New Plugin.ExitException With {.Silent = True}
|
||||
If ((Not IsSavedPosts And CBool(MySiteSettings.UseTokenForTimelines.Value)) Or (IsSavedPosts And CBool(MySiteSettings.UseTokenForSavedPosts.Value))) AndAlso
|
||||
Not MySiteSettings.CredentialsExists Then
|
||||
LogError(Nothing, $"[{CInt(Responser.StatusCode)}] You should use OAuth authorization or disable " &
|
||||
LogError(Nothing, "[429] You should use OAuth authorization or disable " &
|
||||
IIf(IsSavedPosts, "token usage for downloading saved posts", "the use of token and cookies for downloading timelines"))
|
||||
Else
|
||||
LogError(Nothing, "Too many requests (429). Try again later!")
|
||||
|
||||
@@ -22,6 +22,7 @@ Namespace API.RedGifs
|
||||
Friend ReadOnly Property Token As PropertyValue
|
||||
<PropertyOption, ControlNumber(2), PClonable, HiddenControl>
|
||||
Private ReadOnly Property UserAgent As PropertyValue
|
||||
<PXML> Friend ReadOnly Property UseCookies As PropertyValue
|
||||
<PXML> Friend ReadOnly Property TokenLastDateUpdated As PropertyValue
|
||||
Private Const TokenName As String = "authorization"
|
||||
#Region "TokenUpdateInterval"
|
||||
@@ -47,6 +48,7 @@ Namespace API.RedGifs
|
||||
End With
|
||||
Token = New PropertyValue(t, GetType(String), Sub(v) UpdateResponse(NameOf(Token), v))
|
||||
UserAgent = New PropertyValue(If(Responser.UserAgentExists, Responser.UserAgent, String.Empty), GetType(String), Sub(v) UpdateResponse(NameOf(UserAgent), v))
|
||||
UseCookies = New PropertyValue(False)
|
||||
TokenLastDateUpdated = New PropertyValue(Now.AddYears(-1), GetType(Date))
|
||||
TokenUpdateInterval = New PropertyValue(60 * 12, GetType(Integer))
|
||||
TokenUpdateIntervalProvider = New TokenRefreshIntervalProvider
|
||||
@@ -62,11 +64,16 @@ Namespace API.RedGifs
|
||||
Case NameOf(Token) : Responser.Headers.Add(TokenName, Value)
|
||||
Case NameOf(UserAgent) : Responser.UserAgent = Value
|
||||
End Select
|
||||
Responser.SaveSettings()
|
||||
Responser.SaveSettings(, New ErrorsDescriber(EDP.ReturnValue + If(_TokenUpdating, EDP.None, EDP.SendToLog)))
|
||||
End Sub
|
||||
#End Region
|
||||
#Region "Token updaters"
|
||||
Private _TokenUpdating As Boolean = False
|
||||
Friend Function UpdateTokenIfRequired() As Boolean
|
||||
While _TokenUpdating : Threading.Thread.Sleep(100) : End While
|
||||
Return UpdateTokenIfRequired_Impl()
|
||||
End Function
|
||||
Private Function UpdateTokenIfRequired_Impl() As Boolean
|
||||
Dim d As Date? = AConvert(Of Date)(TokenLastDateUpdated.Value, AModes.Var, Nothing)
|
||||
If Not d.HasValue OrElse d.Value < Now.AddMinutes(-CInt(TokenUpdateInterval.Value)) Then
|
||||
Return UpdateToken()
|
||||
@@ -76,7 +83,12 @@ Namespace API.RedGifs
|
||||
End Function
|
||||
<PropertyUpdater(NameOf(Token))>
|
||||
Friend Function UpdateToken() As Boolean
|
||||
While _TokenUpdating : Threading.Thread.Sleep(100) : End While
|
||||
Return UpdateToken_Impl()
|
||||
End Function
|
||||
Private Function UpdateToken_Impl() As Boolean
|
||||
Try
|
||||
_TokenUpdating = True
|
||||
Dim r$
|
||||
Dim NewToken$ = String.Empty, NewAgent$ = String.Empty
|
||||
Using resp As New Responser : r = resp.GetResponse("https://api.redgifs.com/v2/auth/temporary",, EDP.ThrowException) : End Using
|
||||
@@ -98,6 +110,8 @@ Namespace API.RedGifs
|
||||
End If
|
||||
Catch ex As Exception
|
||||
Return ErrorsDescriber.Execute(EDP.SendToLog, ex, "[API.RedGifs.SiteSettings.UpdateToken]", False)
|
||||
Finally
|
||||
_TokenUpdating = False
|
||||
End Try
|
||||
End Function
|
||||
#End Region
|
||||
|
||||
@@ -36,6 +36,7 @@ Namespace API.RedGifs
|
||||
#End Region
|
||||
#Region "Download functions"
|
||||
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
|
||||
If Not MySettings.UseCookies.Value Then Responser.Cookies.Clear()
|
||||
DownloadData(1, Token)
|
||||
End Sub
|
||||
Private Overloads Sub DownloadData(ByVal Page As Integer, ByVal Token As CancellationToken)
|
||||
|
||||
17
SCrawler/API/ThreadsNet/Declarations.vb
Normal file
@@ -0,0 +1,17 @@
|
||||
' Copyright (C) Andy https://github.com/AAndyProgram
|
||||
' This program is free software: you can redistribute it and/or modify
|
||||
' it under the terms of the GNU General Public License as published by
|
||||
' the Free Software Foundation, either version 3 of the License, or
|
||||
' (at your option) any later version.
|
||||
'
|
||||
' This program is distributed in the hope that it will be useful,
|
||||
' but WITHOUT ANY WARRANTY
|
||||
Imports SCrawler.API.Base
|
||||
Imports PersonalUtilities.Functions.RegularExpressions
|
||||
Namespace API.ThreadsNet
|
||||
Friend Module Declarations
|
||||
Friend ReadOnly RegexUserID As RParams = RParams.DMS("""props"":\{[^\{\}]*?""user_id"":""(\d+)""", 1, EDP.ReturnValue)
|
||||
Friend ReadOnly RegexUserName As RParams = RParams.DMS("\<meta property=""og:title"" content=""([^\>]+)""\s*/\>", 1, TitleHtmlConverter, EDP.ReturnValue)
|
||||
Friend ReadOnly RegexUserDescr As RParams = RParams.DMS("\<meta property=""og:description"" content=""([^\>]+)""\s*/\>", 1, HtmlConverter, EDP.ReturnValue)
|
||||
End Module
|
||||
End Namespace
|
||||
@@ -388,8 +388,10 @@ Namespace API.ThreadsNet
|
||||
Dim newID$
|
||||
Dim idStr$ = String.Empty
|
||||
If Not r.IsEmptyString Then
|
||||
UserSiteNameUpdate(RegexReplace(r, RegexUserName))
|
||||
UserDescriptionUpdate(RegexReplace(r, RegexUserDescr))
|
||||
ParseTokens(r, 0)
|
||||
newID = RegexReplace(r, RParams.DMS("""props"":\{[^\{\}]*?""user_id"":""(\d+)""", 1, EDP.ReturnValue))
|
||||
newID = RegexReplace(r, RegexUserID)
|
||||
If ID.IsEmptyString OrElse ID = newID Then
|
||||
_IdChanged = ID.IsEmptyString
|
||||
ID = newID
|
||||
|
||||
@@ -11,6 +11,7 @@ Imports PersonalUtilities.Functions.RegularExpressions
|
||||
Namespace API.TikTok
|
||||
Friend Module Declarations
|
||||
Friend ReadOnly SimpleDateConverter As New ADateTime("yyyyMMdd")
|
||||
Friend ReadOnly SimpleDateConverterWithTime As New ADateTime("yyyyMMdd_HHmmss")
|
||||
Friend ReadOnly RegexTagsReplacer As RParams = RParams.DM("#\w+\s?", -1, RegexReturn.Replace,
|
||||
CType(Function(input$) String.Empty, Func(Of String, String)), EDP.ReturnValue)
|
||||
Friend ReadOnly RegexPhotoJson As RParams = RParams.DMS("UNIVERSAL_DATA_FOR_REHYDRATION__"" type=""application/json""\>([^\<]+)\<", 1,
|
||||
|
||||
@@ -10,11 +10,13 @@ Imports SCrawler.API.Base
|
||||
Imports SCrawler.Plugin
|
||||
Imports SCrawler.Plugin.Attributes
|
||||
Imports PersonalUtilities.Functions.RegularExpressions
|
||||
Imports DN = SCrawler.API.Base.DeclaredNames
|
||||
Namespace API.TikTok
|
||||
<Manifest("AndyProgram_TikTok"), SpecialForm(False), SeparatedTasks(1)>
|
||||
Friend Class SiteSettings : Inherits SiteSettingsBase
|
||||
#Region "Categories"
|
||||
Private Const CAT_DOWN As String = "Download"
|
||||
Private Const CAT_UserDefs_Title As String = DN.CAT_UserDefs & " (Title)"
|
||||
#End Region
|
||||
#Region "Download"
|
||||
<PropertyOption(ControlText:="Download videos", Category:=CAT_DOWN), PXML, PClonable>
|
||||
@@ -22,33 +24,47 @@ Namespace API.TikTok
|
||||
<PropertyOption(ControlText:="Download photos", Category:=CAT_DOWN), PXML, PClonable>
|
||||
Friend ReadOnly Property DownloadTTPhotos As PropertyValue
|
||||
#End Region
|
||||
<PropertyOption(ControlText:="Remove tags from title"), PXML, PClonable>
|
||||
#Region "User defaults"
|
||||
#Region "Sections"
|
||||
<PropertyOption(ControlText:="Get Timeline", Category:=DN.CAT_UserDefs), PXML, PClonable>
|
||||
Friend ReadOnly Property GetTimeline As PropertyValue
|
||||
<PropertyOption(ControlText:="Get User Stories", Category:=DN.CAT_UserDefs), PXML, PClonable>
|
||||
Friend ReadOnly Property GetStoriesUser As PropertyValue
|
||||
<PropertyOption(ControlText:="Get Reposts", Category:=DN.CAT_UserDefs), PXML, PClonable>
|
||||
Friend ReadOnly Property GetReposts As PropertyValue
|
||||
#End Region
|
||||
#Region "Title"
|
||||
<PropertyOption(ControlText:="Remove tags from title", Category:=CAT_UserDefs_Title), PXML, PClonable>
|
||||
Friend ReadOnly Property RemoveTagsFromTitle As PropertyValue
|
||||
<PropertyOption(ControlText:="Use native title", ControlToolTip:="Use a user-created video title for the filename instead of the video ID."), PXML, PClonable>
|
||||
<PropertyOption(ControlText:="Use native title", ControlToolTip:="Use a user-created video title for the filename instead of the video ID.",
|
||||
Category:=CAT_UserDefs_Title), PXML, PClonable>
|
||||
Friend ReadOnly Property TitleUseNative As PropertyValue
|
||||
<PropertyOption(ControlText:="Use native title (standalone downloader)",
|
||||
ControlToolTip:="Use a user-created video title for the filename instead of the video ID."), PXML, PClonable>
|
||||
ControlToolTip:="Use a user-created video title for the filename instead of the video ID.", Category:=CAT_UserDefs_Title), PXML, PClonable>
|
||||
Friend ReadOnly Property TitleUseNativeSTD As PropertyValue
|
||||
<PropertyOption(ControlText:="Add video ID to video title"), PXML, PClonable>
|
||||
<PropertyOption(ControlText:="Add video ID to video title", Category:=CAT_UserDefs_Title), PXML, PClonable>
|
||||
Friend ReadOnly Property TitleAddVideoID As PropertyValue
|
||||
<PropertyOption(ControlText:="Add video ID to video title (standalone downloader)"), PXML, PClonable>
|
||||
<PropertyOption(ControlText:="Add video ID to video title (standalone downloader)", Category:=CAT_UserDefs_Title), PXML, PClonable>
|
||||
Friend ReadOnly Property TitleAddVideoIDSTD As PropertyValue
|
||||
<PropertyOption(ControlText:="Use regex to clean video title"), PXML, PClonable>
|
||||
<PropertyOption(ControlText:="Use regex to clean video title", Category:=CAT_UserDefs_Title), PXML, PClonable>
|
||||
Friend ReadOnly Property TitleUseRegexForTitle As PropertyValue
|
||||
<PropertyOption(ControlText:="Title regex", ControlToolTip:="Regex to clean video title"), PXML, PClonable>
|
||||
<PropertyOption(ControlText:="Title regex", ControlToolTip:="Regex to clean video title", Category:=CAT_UserDefs_Title), PXML, PClonable>
|
||||
Friend ReadOnly Property TitleUseRegexForTitle_Value As PropertyValue
|
||||
#End Region
|
||||
#End Region
|
||||
<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>
|
||||
Friend ReadOnly Property UseParsedVideoDate As PropertyValue
|
||||
<PropertyOption(ControlText:="Use video date as file date (standalone downloader)",
|
||||
ControlToolTip:="Set the file date to the date the video was added (website) (if available)."), PXML, PClonable>
|
||||
Friend ReadOnly Property UseParsedVideoDateSTD As PropertyValue
|
||||
<DoNotUse> Friend Overrides Property DownloadText As PropertyValue
|
||||
<DoNotUse> Friend Overrides Property DownloadTextPosts As PropertyValue
|
||||
<DoNotUse> Friend Overrides Property DownloadTextSpecialFolder As PropertyValue
|
||||
Friend Sub New(ByVal AccName As String, ByVal Temp As Boolean)
|
||||
MyBase.New("TikTok", "www.tiktok.com", AccName, Temp, My.Resources.SiteResources.TikTokIcon_32, My.Resources.SiteResources.TikTokPic_192)
|
||||
|
||||
GetTimeline = New PropertyValue(True)
|
||||
GetStoriesUser = New PropertyValue(False)
|
||||
GetReposts = New PropertyValue(False)
|
||||
|
||||
DownloadTTVideos = New PropertyValue(True)
|
||||
DownloadTTPhotos = New PropertyValue(True)
|
||||
|
||||
@@ -79,5 +95,10 @@ Namespace API.TikTok
|
||||
Using f As New InternalSettingsForm(Options, Me, False) : f.ShowDialog() : End Using
|
||||
End If
|
||||
End Sub
|
||||
Friend Overrides Function GetUserPostUrl(ByVal User As UserDataBase, ByVal Media As UserMedia) As String
|
||||
Dim url$ = MyBase.GetUserPostUrl(User, Media)
|
||||
If Not url.IsEmptyString AndAlso url.EndsWith(UserData.GDL_POSTFIX) Then url = url.Replace(UserData.GDL_POSTFIX, String.Empty)
|
||||
Return url
|
||||
End Function
|
||||
End Class
|
||||
End Namespace
|
||||
@@ -7,16 +7,21 @@
|
||||
' This program is distributed in the hope that it will be useful,
|
||||
' but WITHOUT ANY WARRANTY
|
||||
Imports System.Threading
|
||||
Imports SCrawler.API.Base
|
||||
Imports SCrawler.API.YouTube.Objects
|
||||
Imports PersonalUtilities.Functions.XML
|
||||
Imports PersonalUtilities.Functions.RegularExpressions
|
||||
Imports PersonalUtilities.Functions.XML
|
||||
Imports PersonalUtilities.Tools
|
||||
Imports PersonalUtilities.Tools.Web.Documents.JSON
|
||||
Imports SCrawler.API.Base
|
||||
Imports SCrawler.API.YouTube.Objects
|
||||
Imports SCrawler.Plugin.Attributes
|
||||
Imports Sections = SCrawler.API.Instagram.UserData.Sections
|
||||
Imports UTypes = SCrawler.API.Base.UserMedia.Types
|
||||
Namespace API.TikTok
|
||||
Friend Class UserData : Inherits UserDataBase
|
||||
#Region "XML names"
|
||||
Private Const Name_GetTimeline As String = "GetTimeline"
|
||||
Private Const Name_GetStoriesUser As String = "GetStoriesUser"
|
||||
Private Const Name_GetReposts As String = "GetReposts"
|
||||
Private Const Name_RemoveTagsFromTitle As String = "RemoveTagsFromTitle"
|
||||
Private Const Name_TitleUseNative As String = "TitleUseNative"
|
||||
Private Const Name_TitleAddVideoID As String = "TitleAddVideoID"
|
||||
@@ -27,6 +32,7 @@ Namespace API.TikTok
|
||||
Private Const Name_PhotosDownloaded As String = "PhotosDownloaded"
|
||||
#End Region
|
||||
#Region "Declarations"
|
||||
Friend Const GDL_POSTFIX As String = "--GDL"
|
||||
Private ReadOnly Property MySettings As SiteSettings
|
||||
Get
|
||||
Return HOST.Source
|
||||
@@ -57,6 +63,9 @@ Namespace API.TikTok
|
||||
End If
|
||||
End Get
|
||||
End Property
|
||||
Friend Property GetTimeline As Boolean = True
|
||||
Friend Property GetStoriesUser As Boolean = False
|
||||
Friend Property GetReposts As Boolean = False
|
||||
Friend Property RemoveTagsFromTitle As Boolean = False
|
||||
Friend Property TitleUseNative As Boolean = True
|
||||
Friend Property TitleAddVideoID As Boolean = True
|
||||
@@ -73,6 +82,10 @@ Namespace API.TikTok
|
||||
Friend Overrides Sub ExchangeOptionsSet(ByVal Obj As Object)
|
||||
If Not Obj Is Nothing AndAlso TypeOf Obj Is UserExchangeOptions Then
|
||||
With DirectCast(Obj, UserExchangeOptions)
|
||||
.ApplyBase(Me)
|
||||
GetTimeline = .GetTimeline
|
||||
GetStoriesUser = .GetStoriesUser
|
||||
GetReposts = .GetReposts
|
||||
RemoveTagsFromTitle = .RemoveTagsFromTitle
|
||||
TitleUseNative = .TitleUseNative
|
||||
TitleAddVideoID = .TitleAddVideoID
|
||||
@@ -87,6 +100,9 @@ Namespace API.TikTok
|
||||
Protected Overrides Sub LoadUserInformation_OptionalFields(ByRef Container As XmlFile, ByVal Loading As Boolean)
|
||||
With Container
|
||||
If Loading Then
|
||||
GetTimeline = .Value(Name_GetTimeline).FromXML(Of Boolean)(True)
|
||||
GetStoriesUser = .Value(Name_GetStoriesUser).FromXML(Of Boolean)(False)
|
||||
GetReposts = .Value(Name_GetReposts).FromXML(Of Boolean)(False)
|
||||
RemoveTagsFromTitle = .Value(Name_RemoveTagsFromTitle).FromXML(Of Boolean)(False)
|
||||
TitleUseNative = .Value(Name_TitleUseNative).FromXML(Of Boolean)(True)
|
||||
TitleAddVideoID = .Value(Name_TitleAddVideoID).FromXML(Of Boolean)(True)
|
||||
@@ -97,6 +113,9 @@ Namespace API.TikTok
|
||||
TitleUseGlobalRegexOptions = .Value(Name_TitleUseGlobalRegexOptions).FromXML(Of Boolean)(True)
|
||||
PhotosDownloaded = .Value(Name_PhotosDownloaded).FromXML(Of Boolean)(False)
|
||||
Else
|
||||
.Add(Name_GetTimeline, GetTimeline.BoolToInteger)
|
||||
.Add(Name_GetStoriesUser, GetStoriesUser.BoolToInteger)
|
||||
.Add(Name_GetReposts, GetReposts.BoolToInteger)
|
||||
.Add(Name_RemoveTagsFromTitle, RemoveTagsFromTitle.BoolToInteger)
|
||||
.Add(Name_TitleUseNative, TitleUseNative.BoolToInteger)
|
||||
.Add(Name_TitleAddVideoID, TitleAddVideoID.BoolToInteger)
|
||||
@@ -165,17 +184,25 @@ Namespace API.TikTok
|
||||
Private Function GetPhotoNode() As Object()
|
||||
Return {"imageURL", "urlList", 0, 0}
|
||||
End Function
|
||||
Private Sub ValidateCache()
|
||||
If If(UserCache?.Disposed, True) Then UserCache = CreateCache()
|
||||
End Sub
|
||||
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 Overloads Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
|
||||
ValidateCache()
|
||||
If GetTimeline Then DownloadDataF(Sections.Timeline, Token)
|
||||
If GetStoriesUser Then DownloadDataF(Sections.UserStories, Token)
|
||||
If GetReposts Then DownloadDataF(Sections.Reposts, Token)
|
||||
End Sub
|
||||
Protected Overloads Sub DownloadDataF(ByVal Section As Sections, ByVal Token As CancellationToken)
|
||||
Dim URL$ = $"https://www.tiktok.com/@{NameTrue}"
|
||||
UserCache = CreateCache()
|
||||
Try
|
||||
Const photoPrefix$ = "photo_"
|
||||
Dim postID$, title$, postUrl$, newName$, t$, postID2$, imgUrl$
|
||||
Dim postID$, title$, postUrl$, newName$, t$, tOrig$, postID2$, imgUrl$, pText$
|
||||
Dim postDate As Date?
|
||||
Dim dateAfterC As Date? = Nothing
|
||||
Dim dateBefore As Date? = DownloadDateTo
|
||||
@@ -184,12 +211,24 @@ Namespace API.TikTok
|
||||
Dim titleRegex As RParams = GetTitleRegex()
|
||||
Dim vPath As SFile = Nothing, pPath As SFile = Nothing
|
||||
Dim file As SFile
|
||||
Dim j As EContainer, photo As EContainer
|
||||
Dim j As EContainer = Nothing, photo As EContainer, item As EContainer
|
||||
Dim photoNode As Object() = GetPhotoNode()
|
||||
Dim c%, cc%, i%
|
||||
Dim errDef As New ErrorsDescriber(EDP.ReturnValue)
|
||||
Dim infoParsed As Boolean = False
|
||||
|
||||
Dim gdlTmpIDs As New Dictionary(Of String, Integer)
|
||||
Dim gdlCmd$ = String.Empty
|
||||
Dim gdlIsNativeJson As Boolean
|
||||
|
||||
Dim __specFolder$ = String.Empty
|
||||
Dim __specFolder_Cr As Func(Of String, String) = Function(_sp$) String.Empty.StringAppend(__specFolder).StringAppend(_sp, "\") &
|
||||
IIf(__specFolder.IsEmptyString, String.Empty, "*")
|
||||
Select Case Section
|
||||
Case Sections.UserStories : URL &= "/stories" : __specFolder = "Stories (user)" : gdlCmd = "-o videos -o photos"
|
||||
Case Sections.Reposts : URL &= "/reposts" : __specFolder = "Reposts"
|
||||
End Select
|
||||
|
||||
If _ContentList.Count > 0 Then
|
||||
With (From d In _ContentList Where d.Post.Date.HasValue Select d.Post.Date.Value)
|
||||
If .ListExists Then dateAfterC = .Min
|
||||
@@ -214,19 +253,16 @@ Namespace API.TikTok
|
||||
End If
|
||||
End If
|
||||
|
||||
If DownloadVideos And Settings.YtdlpFile.Exists And CBool(MySettings.DownloadTTVideos.Value) Then
|
||||
If Section = Sections.Timeline And DownloadVideos And Settings.YtdlpFile.Exists And CBool(MySettings.DownloadTTVideos.Value) Then
|
||||
With UserCache.NewInstance : .Validate() : vPath = .RootDirectory : End With
|
||||
Using b As New YTDLP.YTDLPBatch(Token) With {.TempPostsList = _TempPostsList}
|
||||
b.Commands.Clear()
|
||||
b.ChangeDirectory(vPath)
|
||||
b.Encoding = BatchExecutor.UnicodeEncoding
|
||||
Using b As New YTDLP.YTDLPBatch(Token,, vPath) With {.TempPostsList = _TempPostsList}
|
||||
b.Execute(CreateYTCommand(vPath, URL, False, dateBefore, dateAfter))
|
||||
End Using
|
||||
End If
|
||||
|
||||
If DownloadImages And Settings.GalleryDLFile.Exists And CBool(MySettings.DownloadTTPhotos.Value) Then
|
||||
With UserCache.NewInstance : .Validate() : pPath = .RootDirectory : End With
|
||||
Using b As New GDL.GDLBatch(Token)
|
||||
Using b As New GDL.GDLBatch(Token,, pPath)
|
||||
With b
|
||||
If PhotosDownloaded And _TempPostsList.Count > 0 Then
|
||||
.TempPostsList = (From p As String In _TempPostsList
|
||||
@@ -235,9 +271,7 @@ Namespace API.TikTok
|
||||
Else
|
||||
.TempPostsList = New List(Of String)
|
||||
End If
|
||||
.ChangeDirectory(pPath)
|
||||
.Encoding = BatchExecutor.UnicodeEncoding
|
||||
.Execute(CreateGDLCommand(URL))
|
||||
.Execute(CreateGDLCommand(URL, gdlCmd))
|
||||
If Not PhotosDownloaded Then _ForceSaveUserInfo = True : _ForceSaveUserInfoOnException = True
|
||||
PhotosDownloaded = True
|
||||
End With
|
||||
@@ -247,6 +281,7 @@ Namespace API.TikTok
|
||||
ThrowAny(Token)
|
||||
|
||||
Dim files As List(Of SFile)
|
||||
'YTDLP
|
||||
If Not vPath.IsEmptyString AndAlso vPath.Exists(SFO.Path, False) Then
|
||||
files = SFile.GetFiles(vPath, "*.json",, errDef)
|
||||
If files.ListExists Then
|
||||
@@ -254,7 +289,7 @@ Namespace API.TikTok
|
||||
j = JsonDocument.Parse(file.GetText, errDef)
|
||||
If j.ListExists Then
|
||||
If j.Value("_type").StringToLower = "video" Then
|
||||
If Not baseDataObtained Then
|
||||
If Not baseDataObtained And Section = Sections.Timeline Then
|
||||
baseDataObtained = True
|
||||
If ID.IsEmptyString Then ID = j.Value("uploader_id")
|
||||
newName = j.Value("uploader")
|
||||
@@ -266,10 +301,13 @@ Namespace API.TikTok
|
||||
If Not _TempPostsList.Contains(postID) Then
|
||||
_TempPostsList.ListAddValue(postID, LNC)
|
||||
Else
|
||||
Exit For 'Exit Sub
|
||||
'Exit For 'Exit Sub
|
||||
Continue For
|
||||
End If
|
||||
title = GetNewFileName(j.Value("title").StringRemoveWinForbiddenSymbols,
|
||||
TitleUseNative, RemoveTagsFromTitle, TitleAddVideoID, postID, titleRegex)
|
||||
pText = j.Value("title")
|
||||
If Not j.Value("description").IsEmptyString Then pText &= vbCr & vbCr & j.Value("description")
|
||||
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)
|
||||
@@ -280,7 +318,13 @@ Namespace API.TikTok
|
||||
postUrl = j.Value("webpage_url")
|
||||
If postUrl.IsEmptyString Then postUrl = $"https://www.tiktok.com/@{Name}/video/{postID}"
|
||||
_TempMediaList.Add(New UserMedia(postUrl, UTypes.Video) With {
|
||||
.File = $"{title}.mp4", .Post = New UserPost(postID, postDate)})
|
||||
.File = $"{title}.mp4",
|
||||
.SpecialFolder = __specFolder_Cr(String.Empty),
|
||||
.Post = New UserPost(postID, postDate),
|
||||
.PostText = pText,
|
||||
.PostTextFileSpecialFolder = DownloadTextSpecialFolder,
|
||||
.PostTextFile = $"{ .File.Name}.txt"
|
||||
})
|
||||
End If
|
||||
j.Dispose()
|
||||
End If
|
||||
@@ -288,70 +332,183 @@ Namespace API.TikTok
|
||||
End If
|
||||
End If
|
||||
|
||||
j.DisposeIfReady
|
||||
|
||||
'GDL
|
||||
If Not pPath.IsEmptyString AndAlso pPath.Exists(SFO.Path, False) Then
|
||||
files = SFile.GetFiles(pPath, "*.txt",, errDef)
|
||||
If files.ListExists Then
|
||||
|
||||
If Not Section = Sections.Timeline Then
|
||||
GDLResetFileNameProvider(Math.Max(files.Count.ToString.Length, 2))
|
||||
For i = 0 To files.Count - 1 : files(i) = GDLRenameFile(files(i), i) : Next
|
||||
End If
|
||||
|
||||
For Each file In files
|
||||
t = file.GetText(errDef)
|
||||
If Not t.IsEmptyString Then t = RegexReplace(t, RegexPhotoJson)
|
||||
tOrig = t
|
||||
gdlIsNativeJson = False
|
||||
If Not t.IsEmptyString And Not Section = Sections.UserStories Then
|
||||
t = RegexReplace(t, RegexPhotoJson)
|
||||
If t.IsEmptyString Then t = tOrig : gdlIsNativeJson = True
|
||||
End If
|
||||
If Not t.IsEmptyString Then
|
||||
j = JsonDocument.Parse(t, errDef)
|
||||
If j.ListExists Then
|
||||
With j.ItemF({0, "webapp.video-detail", "itemInfo", "itemStruct"})
|
||||
If .ListExists Then
|
||||
postID = .Value("id")
|
||||
postID2 = $"{photoPrefix}{postID}"
|
||||
If Not _TempPostsList.Contains(postID2) Then _TempPostsList.ListAddValue(postID2, LNC) Else Exit For 'Exit Sub
|
||||
postDate = AConvert(Of Date)(j.Value("createTime"), UnixDate32Provider, Nothing)
|
||||
Select Case CheckDatesLimit(postDate, SimpleDateConverter)
|
||||
Case DateResult.Skip : Continue For
|
||||
Case DateResult.Exit : Exit For 'Exit Sub
|
||||
End Select
|
||||
If Section = Sections.UserStories Then
|
||||
With j("itemList")
|
||||
If .ListExists Then
|
||||
For Each item In .Self
|
||||
With item
|
||||
postID = .Value("id")
|
||||
postDate = AConvert(Of Date)(.Value("createTime"), UnixDate32Provider, Nothing)
|
||||
If Not _TempPostsList.Contains(postID) Then
|
||||
_TempPostsList.Add(postID)
|
||||
postUrl = $"https://www.tiktok.com/@{Name}/video/{postID}{GDL_POSTFIX}"
|
||||
If postDate.HasValue Then
|
||||
title = CStr(AConvert(Of String)(postDate.Value, SimpleDateConverterWithTime, String.Empty)).StringAppend(postID, " ")
|
||||
Else
|
||||
title = postID
|
||||
End If
|
||||
_TempMediaList.Add(New UserMedia(postUrl, UTypes.Video) With {
|
||||
.URL_BASE = postUrl,
|
||||
.SpecialFolder = __specFolder_Cr(String.Empty),
|
||||
.File = $"{title}.mp4",
|
||||
.Post = New UserPost(postID, postDate)
|
||||
})
|
||||
With .Item("video")
|
||||
If .ListExists AndAlso Not .Value("cover").IsEmptyString Then _
|
||||
_TempMediaList.Add(New UserMedia(.Value("cover"), UTypes.Picture) With {
|
||||
.URL_BASE = postUrl,
|
||||
.SpecialFolder = __specFolder_Cr("Photo"),
|
||||
.File = $"{title}.jpg"
|
||||
})
|
||||
End With
|
||||
Else
|
||||
Continue For
|
||||
End If
|
||||
End With
|
||||
Next
|
||||
End If
|
||||
End With
|
||||
ElseIf Section = Sections.Reposts And gdlIsNativeJson Then
|
||||
With j("itemList")
|
||||
If .ListExists Then
|
||||
For Each item In .Self
|
||||
With item
|
||||
postID = .Value("id")
|
||||
postID2 = $"{photoPrefix}{postID}"
|
||||
If Not _TempPostsList.Contains(postID) And Not _TempPostsList.Contains(postID2) Then
|
||||
title = GetNewFileName(.Value("title").StringRemoveWinForbiddenSymbols,
|
||||
TitleUseNative, RemoveTagsFromTitle, TitleAddVideoID, postID, titleRegex)
|
||||
pText = .Value("title")
|
||||
If Not .Value("desc").IsEmptyString Then
|
||||
pText &= vbCr & vbCr & .Value("desc")
|
||||
If title.IsEmptyString Then title = GetNewFileName(.Value("desc").StringRemoveWinForbiddenSymbols,
|
||||
TitleUseNative, RemoveTagsFromTitle, TitleAddVideoID, postID, titleRegex)
|
||||
End If
|
||||
postDate = AConvert(Of Date)(j.Value("createTime"), UnixDate32Provider, Nothing)
|
||||
If postDate.HasValue Then
|
||||
Select Case CheckDatesLimit(postDate, SimpleDateConverter)
|
||||
Case DateResult.Skip : Continue For
|
||||
Case DateResult.Exit : Exit For 'Exit Sub
|
||||
End Select
|
||||
End If
|
||||
|
||||
If Not infoParsed Then
|
||||
With .Item("author")
|
||||
If .ListExists Then
|
||||
infoParsed = True
|
||||
SimpleDownloadAvatar(.Value("avatarLarger").IfNullOrEmpty(.Value("avatarMedium")).IfNullOrEmpty(.Value("avatarThumb")),
|
||||
Function(ByVal ____url As String) As SFile
|
||||
Dim ____f As SFile = CreateFileFromUrl(____url)
|
||||
If Not ____f.Name.IsEmptyString Then ____f.Name = ____f.Name.Replace(":", "_").Replace("~", "-")
|
||||
If Not ____f.Extension.IsEmptyString Then
|
||||
If Not (____f.Extension = "jpg" Or ____f.Extension = "jpeg") Then
|
||||
____f.Extension = RegexReplace(____f.Extension, RParams.DMS("(.+)\?", 1, EDP.ReturnValue))
|
||||
If Not ____f.Extension.IsEmptyString AndAlso Not (____f.Extension = "jpg" Or ____f.Extension = "jpeg") Then ____f.Extension = String.Empty
|
||||
postUrl = .Value({"author"}, "uniqueId")
|
||||
If Not postUrl.IsEmptyString Then
|
||||
postUrl = $"https://www.tiktok.com/@{postUrl}/video/{postID}"
|
||||
_TempMediaList.Add(New UserMedia(postUrl, UTypes.Video) With {
|
||||
.File = $"{title}.mp4",
|
||||
.SpecialFolder = __specFolder_Cr(String.Empty),
|
||||
.Post = New UserPost(postID, postDate),
|
||||
.PostText = pText,
|
||||
.PostTextFileSpecialFolder = DownloadTextSpecialFolder,
|
||||
.PostTextFile = $"{ .File.Name}.txt"
|
||||
})
|
||||
If Not gdlTmpIDs.ContainsKey(postID) Then gdlTmpIDs.Add(postID, _TempMediaList.Count - 1)
|
||||
End If
|
||||
Else
|
||||
Continue For
|
||||
End If
|
||||
End With
|
||||
Next
|
||||
End If
|
||||
End With
|
||||
Else
|
||||
With j.ItemF({0, "webapp.video-detail", "itemInfo", "itemStruct"})
|
||||
If .ListExists Then
|
||||
postID = .Value("id")
|
||||
postID2 = $"{photoPrefix}{postID}"
|
||||
'If Not _TempPostsList.Contains(postID2) Then _TempPostsList.ListAddValue(postID2, LNC) Else Exit For 'Exit Sub
|
||||
postDate = AConvert(Of Date)(.Value("createTime"), UnixDate32Provider, Nothing)
|
||||
If Not Section = Sections.UserStories Then
|
||||
Select Case CheckDatesLimit(postDate, SimpleDateConverter)
|
||||
Case DateResult.Skip : Continue For
|
||||
Case DateResult.Exit : Exit For 'Exit Sub
|
||||
End Select
|
||||
End If
|
||||
|
||||
If Not infoParsed Then
|
||||
With .Item("author")
|
||||
If .ListExists Then
|
||||
infoParsed = True
|
||||
SimpleDownloadAvatar(.Value("avatarLarger").IfNullOrEmpty(.Value("avatarMedium")).IfNullOrEmpty(.Value("avatarThumb")),
|
||||
Function(ByVal ____url As String) As SFile
|
||||
Dim ____f As SFile = CreateFileFromUrl(____url)
|
||||
If Not ____f.Name.IsEmptyString Then ____f.Name = ____f.Name.Replace(":", "_").Replace("~", "-")
|
||||
If Not ____f.Extension.IsEmptyString Then
|
||||
If Not (____f.Extension = "jpg" Or ____f.Extension = "jpeg") Then
|
||||
____f.Extension = RegexReplace(____f.Extension, RParams.DMS("(.+)\?", 1, EDP.ReturnValue))
|
||||
If Not ____f.Extension.IsEmptyString AndAlso Not (____f.Extension = "jpg" Or ____f.Extension = "jpeg") Then ____f.Extension = String.Empty
|
||||
End If
|
||||
End If
|
||||
End If
|
||||
Return ____f
|
||||
End Function)
|
||||
UserSiteNameUpdate(.Value("nickname"))
|
||||
UserDescriptionUpdate(.Value("signature"))
|
||||
Return ____f
|
||||
End Function)
|
||||
UserSiteNameUpdate(.Value("nickname"))
|
||||
UserDescriptionUpdate(.Value("signature"))
|
||||
End If
|
||||
End With
|
||||
End If
|
||||
|
||||
title = GetNewFileName(.Value({"imagePost"}, "title").StringRemoveWinForbiddenSymbols,
|
||||
TitleUseNative, RemoveTagsFromTitle, TitleAddVideoID, postID, titleRegex)
|
||||
pText = .Value({"imagePost"}, "title")
|
||||
If Not .Value("desc").IsEmptyString Then pText &= vbCr & vbCr & .Value("desc")
|
||||
postUrl = $"https://www.tiktok.com/@{Name}/photo/{postID}"
|
||||
With .Item({"imagePost", "images"})
|
||||
If .ListExists Then
|
||||
If Not _TempPostsList.Contains(postID2) Then
|
||||
_TempPostsList.ListAddValue(postID2, LNC)
|
||||
If gdlTmpIDs.ContainsKey(postID) Then
|
||||
_TempMediaList.RemoveAt(gdlTmpIDs(postID))
|
||||
gdlTmpIDs.Remove(postID)
|
||||
End If
|
||||
Else
|
||||
Continue For 'Exit Sub
|
||||
End If
|
||||
i = 0
|
||||
c = .Count
|
||||
cc = Math.Max(c.ToString.Length, 3)
|
||||
For Each photo In .Self
|
||||
i += 1
|
||||
imgUrl = photo.ItemF(photoNode).XmlIfNothingValue
|
||||
If Not imgUrl.IsEmptyString Then _
|
||||
_TempMediaList.Add(New UserMedia(imgUrl, UTypes.Picture) With {
|
||||
.URL_BASE = postUrl,
|
||||
.SpecialFolder = __specFolder_Cr("Photo"),
|
||||
.File = $"{title}{IIf(c > 1, $"_{i.NumToString(ANumbers.Formats.NumberGroup, cc)}", String.Empty)}.jpg",
|
||||
.Post = New UserPost(postID, postDate),
|
||||
.PostText = pText,
|
||||
.PostTextFileSpecialFolder = DownloadTextSpecialFolder,
|
||||
.PostTextFile = $"{ .File.Name}.txt"
|
||||
})
|
||||
Next
|
||||
End If
|
||||
End With
|
||||
End If
|
||||
|
||||
title = GetNewFileName(j.Value({"imagePost"}, "title").StringRemoveWinForbiddenSymbols,
|
||||
TitleUseNative, RemoveTagsFromTitle, TitleAddVideoID, postID, titleRegex)
|
||||
postUrl = $"https://www.tiktok.com/@{Name}/photo/{postID}"
|
||||
With .Item({"imagePost", "images"})
|
||||
If .ListExists Then
|
||||
i = 0
|
||||
c = .Count
|
||||
cc = Math.Max(c.ToString.Length, 3)
|
||||
For Each photo In .Self
|
||||
i += 1
|
||||
imgUrl = photo.ItemF(photoNode).XmlIfNothingValue
|
||||
If Not imgUrl.IsEmptyString Then _
|
||||
_TempMediaList.Add(New UserMedia(imgUrl, UTypes.Picture) With {
|
||||
.URL_BASE = postUrl,
|
||||
.SpecialFolder = "Photo",
|
||||
.File = $"{title}{IIf(c > 1, $"_{i.NumToString(ANumbers.Formats.NumberGroup, cc)}", String.Empty)}.jpg",
|
||||
.Post = New UserPost(postID, postDate)})
|
||||
Next
|
||||
End If
|
||||
End With
|
||||
End If
|
||||
End With
|
||||
End With
|
||||
End If
|
||||
j.Dispose()
|
||||
End If
|
||||
End If
|
||||
@@ -359,6 +516,9 @@ Namespace API.TikTok
|
||||
End If
|
||||
End If
|
||||
|
||||
j.DisposeIfReady
|
||||
_TempPostsList.ListAddList(gdlTmpIDs.Keys)
|
||||
gdlTmpIDs.Clear()
|
||||
If _TempMediaList.Count > 0 Then LastDownloadDate = Now
|
||||
Catch ex As Exception
|
||||
ProcessException(ex, Token, $"data downloading error [{URL}]")
|
||||
@@ -422,7 +582,11 @@ Namespace API.TikTok
|
||||
End If
|
||||
If DateBefore.HasValue Then command &= $"--datebefore {DateBefore.Value.AddDays(1).ToStringDate(SimpleDateConverter)} "
|
||||
If DateAfter.HasValue Then command &= $"--dateafter {DateAfter.Value.AddDays(-1).ToStringDate(SimpleDateConverter)} "
|
||||
If Not CBool(If(IsSingleObjectDownload, MySettings.UseParsedVideoDateSTD, MySettings.UseParsedVideoDate).Value) Then command &= "--no-mtime "
|
||||
If Not CBool(If(IsSingleObjectDownload, MySettings.UseParsedVideoDateSTD, MySettings.UseParsedVideoDate).Value) Then
|
||||
command &= "--no-mtime "
|
||||
Else
|
||||
command &= "--mtime "
|
||||
End If
|
||||
If MySettings.CookiesNetscapeFile.Exists Then command &= $"--no-cookies-from-browser --cookies ""{MySettings.CookiesNetscapeFile}"" "
|
||||
command &= $"{URL} "
|
||||
If SupportOutput Then
|
||||
@@ -439,8 +603,17 @@ Namespace API.TikTok
|
||||
End Function
|
||||
#End Region
|
||||
#Region "GDL Support"
|
||||
Private Function CreateGDLCommand(ByVal URL As String) As String
|
||||
Return $"""{Settings.GalleryDLFile}"" --verbose --no-download --no-skip --write-pages {URL}"
|
||||
Private Function CreateGDLCommand(ByVal URL As String, Optional ByVal SectionCommand As String = Nothing,
|
||||
Optional ByVal IsDownload As Boolean = False, Optional ByVal Output As SFile = Nothing) As String
|
||||
Dim command$ = $"""{Settings.GalleryDLFile}"" "
|
||||
If Not IsDownload Then
|
||||
command &= "--verbose --no-download --no-skip --write-pages "
|
||||
Else
|
||||
command &= $"--dest ""{Output.PathNoSeparator}"" "
|
||||
End If
|
||||
If Not CBool(If(IsSingleObjectDownload, MySettings.UseParsedVideoDateSTD, MySettings.UseParsedVideoDate).Value) Then command &= "--no-mtime "
|
||||
command &= $"{SectionCommand} {URL}"
|
||||
Return command
|
||||
End Function
|
||||
#End Region
|
||||
#Region "DownloadContent, DownloadFile"
|
||||
@@ -452,8 +625,16 @@ Namespace API.TikTok
|
||||
End Function
|
||||
Protected Overrides Function DownloadFile(ByVal URL As String, ByVal Media As UserMedia, ByVal DestinationFile As SFile, ByVal Token As CancellationToken) As SFile
|
||||
Using b As New TokenBatch(Token) With {.FileExchanger = RootCacheTikTok}
|
||||
b.Encoding = BatchExecutor.UnicodeEncoding
|
||||
b.Execute(CreateYTCommand(DestinationFile, URL, True))
|
||||
If URL.EndsWith(GDL_POSTFIX) Then
|
||||
ValidateCache()
|
||||
Dim tmpPath As SFile
|
||||
With UserCache.NewInstance : .Validate() : tmpPath = .RootDirectory : End With
|
||||
b.Execute(CreateGDLCommand(URL.Replace(GDL_POSTFIX, String.Empty),, True, tmpPath))
|
||||
tmpPath = SFile.GetFiles(tmpPath, "*.mp4", IO.SearchOption.AllDirectories, EDP.ReturnValue).FirstOrDefault
|
||||
If Not tmpPath.IsEmptyString Then SFile.Move(tmpPath, DestinationFile)
|
||||
Else
|
||||
b.Execute(CreateYTCommand(DestinationFile, URL, True))
|
||||
End If
|
||||
End Using
|
||||
If DestinationFile.Exists Then Return DestinationFile Else Return Nothing
|
||||
End Function
|
||||
@@ -473,7 +654,6 @@ Namespace API.TikTok
|
||||
t = UTypes.Video
|
||||
If CBool(MySettings.TitleUseNativeSTD.Value) Then
|
||||
Using b As New BatchExecutor(True) With {
|
||||
.Encoding = BatchExecutor.UnicodeEncoding,
|
||||
.CleanAutomaticallyViaRegEx = True,
|
||||
.CleanAutomaticallyViaRegExRemoveAllCommands = True
|
||||
}
|
||||
@@ -494,11 +674,7 @@ Namespace API.TikTok
|
||||
Data.Title = defName
|
||||
Dim dir As SFile
|
||||
With If(Cache, Settings.Cache).NewInstance() : .Validate() : dir = .RootDirectory : End With
|
||||
Using b As New GDL.GDLBatch(Token)
|
||||
b.ChangeDirectory(dir)
|
||||
b.Encoding = BatchExecutor.UnicodeEncoding
|
||||
b.Execute(CreateGDLCommand(Data.URL))
|
||||
End Using
|
||||
Using b As New GDL.GDLBatch(Token,, dir) : b.Execute(CreateGDLCommand(Data.URL)) : End Using
|
||||
Dim file As SFile = SFile.GetFiles(dir, "*.txt",, EDP.ReturnValue).FirstOrDefault
|
||||
If file.Exists Then
|
||||
Dim r$ = file.GetText(EDP.ReturnValue)
|
||||
|
||||
@@ -6,9 +6,16 @@
|
||||
'
|
||||
' This program is distributed in the hope that it will be useful,
|
||||
' but WITHOUT ANY WARRANTY
|
||||
Imports SCrawler.Plugin
|
||||
Imports SCrawler.Plugin.Attributes
|
||||
Namespace API.TikTok
|
||||
Friend Class UserExchangeOptions
|
||||
Friend Class UserExchangeOptions : Inherits Base.EditorExchangeOptionsBase
|
||||
<PSetting(NameOf(SiteSettings.GetTimeline), NameOf(MySettings))>
|
||||
Friend Property GetTimeline As Boolean
|
||||
<PSetting(NameOf(SiteSettings.GetStoriesUser), NameOf(MySettings))>
|
||||
Friend Property GetStoriesUser As Boolean
|
||||
<PSetting(NameOf(SiteSettings.GetReposts), NameOf(MySettings))>
|
||||
Friend Property GetReposts As Boolean
|
||||
<PSetting(NameOf(SiteSettings.RemoveTagsFromTitle), NameOf(MySettings))>
|
||||
Friend Property RemoveTagsFromTitle As Boolean
|
||||
<PSetting(NameOf(SiteSettings.TitleUseNative), NameOf(MySettings))>
|
||||
@@ -21,9 +28,15 @@ Namespace API.TikTok
|
||||
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
|
||||
<PSetting(Address:=SettingAddress.None)> Friend Overrides Property UserName As String
|
||||
Private ReadOnly MySettings As SiteSettings
|
||||
Friend Sub New(ByVal u As UserData)
|
||||
MyBase.New(u)
|
||||
_ApplyBase_Name = False
|
||||
MySettings = u.HOST.Source
|
||||
GetTimeline = u.GetTimeline
|
||||
GetStoriesUser = u.GetStoriesUser
|
||||
GetReposts = u.GetReposts
|
||||
RemoveTagsFromTitle = u.RemoveTagsFromTitle
|
||||
TitleUseNative = u.TitleUseNative
|
||||
TitleAddVideoID = u.TitleAddVideoID
|
||||
@@ -32,7 +45,12 @@ Namespace API.TikTok
|
||||
TitleUseGlobalRegexOptions = u.TitleUseGlobalRegexOptions
|
||||
End Sub
|
||||
Friend Sub New(ByVal s As SiteSettings)
|
||||
MyBase.New(s)
|
||||
_ApplyBase_Name = False
|
||||
MySettings = s
|
||||
GetTimeline = s.GetTimeline.Value
|
||||
GetStoriesUser = s.GetStoriesUser.Value
|
||||
GetReposts = s.GetReposts.Value
|
||||
RemoveTagsFromTitle = s.RemoveTagsFromTitle.Value
|
||||
TitleUseNative = s.TitleUseNative.Value
|
||||
TitleAddVideoID = s.TitleAddVideoID.Value
|
||||
|
||||
@@ -50,6 +50,10 @@ Namespace API.Twitter
|
||||
Caption:="Force apply",
|
||||
ToolTip:="Force overrides the default parameters for the first download." & vbCr & "Applies to first download only.", LeftOffset:=DefaultOffset)>
|
||||
Friend Overridable Property DownloadModelForceApply As Boolean = False
|
||||
<PSetting(Address:=SettingAddress.User,
|
||||
Caption:="Large profile",
|
||||
ToolTip:="This setting is only used on the first download and is intended to temporarily override the default site settings if they are incompatible with downloading large profiles. After the first download is complete, this option will be disabled and cannot be enabled again.")>
|
||||
Friend Overridable Property LargeProfile As Boolean = False
|
||||
Private ReadOnly Property MySettings As Object
|
||||
Friend Sub New(ByVal s As SiteSettings)
|
||||
MyBase.New(s)
|
||||
@@ -76,6 +80,7 @@ Namespace API.Twitter
|
||||
UseMD5Comparison = u.UseMD5Comparison
|
||||
RemoveExistingDuplicates = u.RemoveExistingDuplicates
|
||||
MediaModelAllowNonUserTweets = u.MediaModelAllowNonUserTweets
|
||||
LargeProfile = u.LargeProfile
|
||||
If Not TypeOf u Is Mastodon.UserData Then
|
||||
DownloadModelForceApply = u.DownloadModelForceApply
|
||||
DownloadBroadcasts = u.DownloadBroadcasts
|
||||
|
||||
@@ -38,6 +38,7 @@ Namespace API.Twitter
|
||||
Private Const CAT_DOWN As String = "Downloading"
|
||||
#End Region
|
||||
#Region "Auth"
|
||||
Friend Property CookiesUpdateForce As Boolean = False
|
||||
<PropertyOption(ControlText:="Update cookies", ControlToolTip:="Update cookies during requests", IsAuth:=True), PXML, PClonable, HiddenControl>
|
||||
Friend ReadOnly Property CookiesUpdate As PropertyValue
|
||||
<PropertyOption(ControlText:="Use UserAgent", ControlToolTip:="Use UserAgent in requests", IsAuth:=True), PXML, PClonable>
|
||||
@@ -45,9 +46,9 @@ Namespace API.Twitter
|
||||
<PropertyOption(ControlText:="UserAgent", IsAuth:=True, AllowNull:=True, InheritanceName:=SettingsCLS.HEADER_DEF_UserAgent),
|
||||
PXML("UserAgent", OnlyForChecked:=True), PClonable>
|
||||
Private ReadOnly Property UserAgentXML As PropertyValue
|
||||
Friend ReadOnly Property UserAgent As String
|
||||
Friend ReadOnly Property UserAgent(Optional ByVal Force As Boolean = False) As String
|
||||
Get
|
||||
If CBool(UserAgentUse.Value) AndAlso Not CStr(UserAgentXML.Value).IsEmptyString Then
|
||||
If (CBool(UserAgentUse.Value) Or Force) AndAlso Not CStr(UserAgentXML.Value).IsEmptyString Then
|
||||
Return UserAgentXML.Value
|
||||
Else
|
||||
Return String.Empty
|
||||
@@ -73,6 +74,7 @@ Namespace API.Twitter
|
||||
#Region "Limits"
|
||||
Friend Const TimerDisabled As Integer = -1
|
||||
Friend Const TimerFirstUseTheSame As Integer = -2
|
||||
Friend Const TimerDefault As Integer = 20
|
||||
<PropertyOption(ControlText:="Abort on limit", ControlToolTip:="Abort twitter downloading when limit is reached", Category:=CAT_DOWN), PXML, PClonable>
|
||||
Friend Property AbortOnLimit As PropertyValue
|
||||
<PropertyOption(ControlText:="Download already parsed", ControlToolTip:="Download already parsed content on abort", Category:=CAT_DOWN), PXML, PClonable>
|
||||
@@ -143,6 +145,7 @@ Namespace API.Twitter
|
||||
End Property
|
||||
#End Region
|
||||
#Region "Initializer"
|
||||
Private Const SettingsVersionCurrent As Integer = 1
|
||||
Friend Sub New(ByVal AccName As String, ByVal Temp As Boolean)
|
||||
MyBase.New(TwitterSite, "x.com", AccName, Temp, My.Resources.SiteResources.TwitterIcon_32, My.Resources.SiteResources.TwitterIcon_32.ToBitmap)
|
||||
|
||||
@@ -153,7 +156,7 @@ Namespace API.Twitter
|
||||
.Cookies.Changed = False
|
||||
End With
|
||||
|
||||
UseNewIconXML = New PropertyValue(False)
|
||||
UseNewIconXML = New PropertyValue(True)
|
||||
|
||||
CookiesUpdate = New PropertyValue(False)
|
||||
UserAgentUse = New PropertyValue(True)
|
||||
@@ -192,6 +195,10 @@ Namespace API.Twitter
|
||||
UseNetscapeCookies = True
|
||||
End Sub
|
||||
Friend Overrides Sub EndInit()
|
||||
If Not SettingsVersion.Value = SettingsVersionCurrent Then
|
||||
UseNewIconXML.Value = True
|
||||
SettingsVersion.Value = SettingsVersionCurrent
|
||||
End If
|
||||
UpdateIcon()
|
||||
MyBase.EndInit()
|
||||
End Sub
|
||||
@@ -223,7 +230,7 @@ Namespace API.Twitter
|
||||
End Sub
|
||||
Friend Overrides Sub DownloadDone(ByVal What As ISiteSettings.Download)
|
||||
If UserNumber > 0 Then
|
||||
If CBool(CookiesUpdate.Value) Then
|
||||
If CBool(CookiesUpdate.Value) Or CookiesUpdateForce Then
|
||||
With CookieKeeper.ParseNetscapeText(CookiesNetscapeFile.GetText(EDP.ReturnValue), EDP.ReturnValue)
|
||||
If .ListExists Then
|
||||
Responser.Cookies.Clear()
|
||||
@@ -250,6 +257,7 @@ Namespace API.Twitter
|
||||
End With
|
||||
End If
|
||||
LIMIT_ABORT = False
|
||||
CookiesUpdateForce = False
|
||||
MyBase.DownloadDone(What)
|
||||
End Sub
|
||||
#End Region
|
||||
|
||||
@@ -30,6 +30,7 @@ Namespace API.Twitter
|
||||
Private Const Name_GifsSpecialFolder As String = "GifsSpecialFolder"
|
||||
Private Const Name_GifsPrefix As String = "GifsPrefix"
|
||||
Private Const Name_IsCommunity As String = "IsCommunity"
|
||||
Private Const Name_LargeProfile As String = "LargeProfile"
|
||||
Private Const Name_DownloadModelChanged As String = "DownloadModelChanged"
|
||||
#End Region
|
||||
#Region "Declarations"
|
||||
@@ -62,6 +63,47 @@ Namespace API.Twitter
|
||||
Friend Property GifsSpecialFolder As String = String.Empty
|
||||
Friend Property GifsPrefix As String = String.Empty
|
||||
Friend Property IsCommunity As Boolean = False
|
||||
#Region "LargeProfile"
|
||||
Friend Property LargeProfile As Boolean = False
|
||||
Private ReadOnly Property LargeProfileOverride As Boolean
|
||||
Get
|
||||
Return LargeProfile And Not FirstDownloadComplete
|
||||
End Get
|
||||
End Property
|
||||
Private ReadOnly Property CookiesUpdate As Boolean
|
||||
Get
|
||||
If LargeProfileOverride Then
|
||||
MySettings.CookiesUpdateForce = True
|
||||
Return True
|
||||
Else
|
||||
Return MySettings.CookiesUpdate.Value
|
||||
End If
|
||||
End Get
|
||||
End Property
|
||||
Private ReadOnly Property UserAgent As String
|
||||
Get
|
||||
If LargeProfileOverride Then
|
||||
Return MySettings.UserAgent(True).IfNullOrEmpty(Settings.UserAgent)
|
||||
Else
|
||||
Return MySettings.UserAgent
|
||||
End If
|
||||
End Get
|
||||
End Property
|
||||
Private ReadOnly Property SleepTimerBeforeFirst As Integer
|
||||
Get
|
||||
Dim v% = MySettings.SleepTimerBeforeFirst.Value
|
||||
If LargeProfileOverride And v <= 0 And v <> SiteSettings.TimerFirstUseTheSame Then v = SiteSettings.TimerFirstUseTheSame
|
||||
Return v
|
||||
End Get
|
||||
End Property
|
||||
Private ReadOnly Property SleepTimer As Integer
|
||||
Get
|
||||
Dim v% = MySettings.SleepTimer.Value
|
||||
If LargeProfileOverride And v <= 0 Then v = SiteSettings.TimerDefault
|
||||
Return v
|
||||
End Get
|
||||
End Property
|
||||
#End Region
|
||||
Private ReadOnly LikesPosts As List(Of String)
|
||||
Private ReadOnly PostsKV As List(Of PKV)
|
||||
Private ReadOnly _DataNames As List(Of String)
|
||||
@@ -70,14 +112,6 @@ Namespace API.Twitter
|
||||
Return HOST.Source
|
||||
End Get
|
||||
End Property
|
||||
Private FileNameProvider As ANumbers = Nothing
|
||||
Private Sub ResetFileNameProvider(Optional ByVal GroupSize As Integer? = Nothing)
|
||||
FileNameProvider = New ANumbers With {.FormatOptions = ANumbers.Options.FormatNumberGroup + ANumbers.Options.Groups}
|
||||
FileNameProvider.GroupSize = If(GroupSize, 3)
|
||||
End Sub
|
||||
Private Function RenameGdlFile(ByVal Input As SFile, ByVal i As Integer) As SFile
|
||||
Return SFile.Rename(Input, $"{Input.PathWithSeparator}{i.NumToString(FileNameProvider)}.{Input.Extension}",, EDP.ThrowException)
|
||||
End Function
|
||||
Friend Function GetUserUrl() As String
|
||||
Return $"https://x.com{IIf(IsCommunity, SiteSettings.CommunitiesUser, String.Empty)}/{NameTrue}"
|
||||
End Function
|
||||
@@ -100,6 +134,7 @@ Namespace API.Twitter
|
||||
DownloadModelForceApply = .DownloadModelForceApply
|
||||
MediaModelAllowNonUserTweets = .MediaModelAllowNonUserTweets
|
||||
DownloadBroadcasts = .DownloadBroadcasts
|
||||
LargeProfile = .LargeProfile
|
||||
Dim dModel As DownloadModels = DownloadModel
|
||||
If .DownloadModelMedia Then DownloadModel += DownloadModels.Media
|
||||
If .DownloadModelProfile Or .DownloadBroadcasts Then DownloadModel += DownloadModels.Profile
|
||||
@@ -155,6 +190,7 @@ Namespace API.Twitter
|
||||
StartMD5Checked = .Value(Name_StartMD5Checked).FromXML(Of Boolean)(False)
|
||||
MediaModelAllowNonUserTweets = .Value(Name_MediaModelAllowNonUserTweets).FromXML(Of Boolean)(False)
|
||||
IsCommunity = .Value(Name_IsCommunity).FromXML(Of Boolean)(False)
|
||||
LargeProfile = .Value(Name_LargeProfile).FromXML(Of Boolean)(False)
|
||||
Else
|
||||
If Name.Contains("@") And Not IsCommunity Then
|
||||
IsCommunity = True
|
||||
@@ -180,6 +216,7 @@ Namespace API.Twitter
|
||||
.Add(Name_StartMD5Checked, StartMD5Checked.BoolToInteger)
|
||||
.Add(Name_MediaModelAllowNonUserTweets, MediaModelAllowNonUserTweets.BoolToInteger)
|
||||
.Add(Name_IsCommunity, IsCommunity.BoolToInteger)
|
||||
.Add(Name_LargeProfile, LargeProfile.BoolToInteger)
|
||||
.Add(Name_TrueName, NameTrue(True))
|
||||
End If
|
||||
End With
|
||||
@@ -434,10 +471,10 @@ Namespace API.Twitter
|
||||
ThrowAny(Token)
|
||||
Dim timelineFiles As List(Of SFile) = SFile.GetFiles(dir, "*.txt",, EDP.ReturnValue)
|
||||
If timelineFiles.ListExists Then
|
||||
ResetFileNameProvider(Math.Max(timelineFiles.Count.ToString.Length, 2))
|
||||
GDLResetFileNameProvider(Math.Max(timelineFiles.Count.ToString.Length, 2))
|
||||
'rename files
|
||||
If Not DEBUG_PROFILE Then
|
||||
For i = 0 To timelineFiles.Count - 1 : timelineFiles(i) = RenameGdlFile(timelineFiles(i), i) : Next
|
||||
For i = 0 To timelineFiles.Count - 1 : timelineFiles(i) = GDLRenameFile(timelineFiles(i), i) : Next
|
||||
End If
|
||||
'parse files
|
||||
For i = 0 To timelineFiles.Count - 1
|
||||
@@ -488,16 +525,19 @@ Namespace API.Twitter
|
||||
With j({"data", "user", "result"})
|
||||
If .ListExists Then
|
||||
If ID.IsEmptyString Then ID = .Value("rest_id")
|
||||
icon = .Value({"avatar"}, "image_url")
|
||||
UserSiteNameUpdate(.Value({"core"}, "name"))
|
||||
Dim tScreenName$ = .Value({"core"}, "screen_name")
|
||||
With .Item({"legacy"})
|
||||
If .ListExists Then
|
||||
If .Value("screen_name").StringToLower = NameTrue.ToLower Then
|
||||
If .Value("screen_name").IfNullOrEmpty(tScreenName).StringToLower = NameTrue.ToLower Then
|
||||
UserSiteNameUpdate(.Value("name"))
|
||||
UserDescriptionUpdate(.Value("description"))
|
||||
|
||||
icon = .Value("profile_image_url_https")
|
||||
If icon.IsEmptyString Then icon = .Value("profile_image_url_https")
|
||||
If Not icon.IsEmptyString Then icon = icon.Replace("_normal", String.Empty)
|
||||
If DownloadIconBanner Then
|
||||
SimpleDownloadAvatar(.Value("profile_banner_url"), fileCrFunc)
|
||||
SimpleDownloadAvatar(.Value("profile_banner_url").IfNullOrEmpty(.Value({"legacy"}, "profile_banner_url")), fileCrFunc)
|
||||
SimpleDownloadAvatar(icon, fileCrFunc)
|
||||
End If
|
||||
End If
|
||||
@@ -615,6 +655,7 @@ nextpIndx:
|
||||
End If
|
||||
DownloadModelForceApply = False
|
||||
FirstDownloadComplete = True
|
||||
LargeProfile = False
|
||||
Catch jsonNull_ex As JsonDocumentException When jsonNull_ex.State = WebDocumentEventArgs.States.Error
|
||||
Throw New Plugin.ExitException("No deserialized data found")
|
||||
Catch limit_ex As TwitterLimitException
|
||||
@@ -632,14 +673,14 @@ nextpIndx:
|
||||
Dim f As SFile = GetDataFromGalleryDL("https://x.com/i/bookmarks", Settings.Cache, True, Token)
|
||||
Dim files As List(Of SFile) = SFile.GetFiles(f, "*.txt")
|
||||
If files.ListExists Then
|
||||
ResetFileNameProvider(Math.Max(files.Count.ToString.Length, 3))
|
||||
GDLResetFileNameProvider(Math.Max(files.Count.ToString.Length, 3))
|
||||
Dim id$
|
||||
Dim nodes As List(Of String()) = GetContainerSubnodes()
|
||||
Dim node$()
|
||||
Dim j As EContainer, jj As EContainer
|
||||
Dim jErr As New ErrorsDescriber(EDP.ReturnValue)
|
||||
For i% = 0 To files.Count - 1
|
||||
f = RenameGdlFile(files(i), i)
|
||||
f = GDLRenameFile(files(i), i)
|
||||
j = JsonDocument.Parse(f.GetText, jErr)
|
||||
If Not j Is Nothing Then
|
||||
With j.ItemF({"data", 0, "timeline", "instructions", 0, "entries"})
|
||||
@@ -806,9 +847,7 @@ nextpIndx:
|
||||
Private ReadOnly KillOnLimit As Boolean
|
||||
Friend LimitReached As Boolean = False
|
||||
Friend Sub New(ByVal Dir As SFile, ByVal _Token As CancellationToken, ByVal _KillOnLimit As Boolean)
|
||||
MyBase.New(_Token)
|
||||
Commands.Clear()
|
||||
If Not Dir.IsEmptyString Then ChangeDirectory(Dir)
|
||||
MyBase.New(_Token,, Dir)
|
||||
KillOnLimit = _KillOnLimit
|
||||
End Sub
|
||||
Protected Overrides Async Function Validate(ByVal Value As String) As Task
|
||||
@@ -839,8 +878,8 @@ nextpIndx:
|
||||
End Class
|
||||
Private ReadOnly Property SleepTimerValue(ByVal First As Boolean) As Integer
|
||||
Get
|
||||
Dim fTimer% = If(First, MySettings.SleepTimerBeforeFirst, MySettings.SleepTimer).Value
|
||||
If First And fTimer = SiteSettings.TimerFirstUseTheSame Then fTimer = MySettings.SleepTimer.Value
|
||||
Dim fTimer% = If(First, SleepTimerBeforeFirst, SleepTimer)
|
||||
If First And fTimer = SiteSettings.TimerFirstUseTheSame Then fTimer = SleepTimer
|
||||
Return fTimer
|
||||
End Get
|
||||
End Property
|
||||
@@ -1060,10 +1099,10 @@ nextpIndx:
|
||||
Private Function GdlCreateConf(ByVal Path As SFile) As SFile
|
||||
Try
|
||||
Dim conf As SFile = $"{Path.PathWithSeparator}TwitterGdlConfig.conf"
|
||||
Dim __userAgent$ = MySettings.UserAgent
|
||||
Dim __userAgent$ = UserAgent
|
||||
If Not __userAgent.IsEmptyString Then __userAgent = $"""user-agent"": ""{__userAgent}"","
|
||||
Dim confText$ = "{""extractor"":{""cookies"": """ & MySettings.CookiesNetscapeFile.ToString.Replace("\", "/") &
|
||||
$""",""cookies-update"": {IIf(CBool(MySettings.CookiesUpdate.Value), "true", "false")}," & __userAgent &
|
||||
$""",""cookies-update"": {IIf(CookiesUpdate, "true", "false")}," & __userAgent &
|
||||
"""twitter"":{""tweet-endpoint"": ""detail"",""cards"": false,""conversations"": true,""pinned"": false,""quoted"": false,""replies"": true,""retweets"": true,""strategy"": null,""text-tweets"": false,""twitpic"": false,""unique"": true,""users"": ""timeline"",""videos"": true}}}"
|
||||
If conf.Exists(SFO.Path, True, EDP.ThrowException) Then TextSaver.SaveTextToFile(confText, conf)
|
||||
If Not conf.Exists Then Throw New IO.FileNotFoundException("Can't find Twitter GDL config file", conf)
|
||||
@@ -1093,7 +1132,7 @@ nextpIndx:
|
||||
Dim files As List(Of SFile)
|
||||
Dim lim%
|
||||
Dim specFolder$ = IIf(_ReparseLikes, "Likes", String.Empty)
|
||||
ResetFileNameProvider()
|
||||
GDLResetFileNameProvider()
|
||||
cache = If(IsSingleObjectDownload, Settings.Cache, CreateCache())
|
||||
If _ReparseLikes Then lim = LikesPosts.Count Else lim = _ContentList.Count
|
||||
ProgressPre.ChangeMax(lim)
|
||||
@@ -1119,7 +1158,7 @@ nextpIndx:
|
||||
files = SFile.GetFiles(f, "*.txt")
|
||||
If files.ListExists Then
|
||||
For ii = 0 To files.Count - 1
|
||||
f = RenameGdlFile(files(ii), ii)
|
||||
f = GDLRenameFile(files(ii), ii)
|
||||
j = JsonDocument.Parse(f.GetText)
|
||||
If Not j Is Nothing Then
|
||||
With j.ItemF({"data", 0, "instructions", 0, "entries"})
|
||||
|
||||
@@ -14,7 +14,11 @@ Imports PersonalUtilities.Functions.RegularExpressions
|
||||
Namespace API.Xhamster
|
||||
<Manifest(XhamsterSiteKey), SavedPosts, SpecialForm(True), SpecialForm(False), TaskGroup(SettingsCLS.TaskStackNamePornSite)>
|
||||
Friend Class SiteSettings : Inherits SiteSettingsBase
|
||||
#Region "Consts"
|
||||
Friend Const GetMomentsCaption As String = "Get moments (short videos)"
|
||||
#End Region
|
||||
#Region "Declarations"
|
||||
Private Const CAT_YTDLP As String = "yt-dlp support"
|
||||
<PXML("Domains"), PClonable> Private ReadOnly Property SiteDomains As PropertyValue
|
||||
Private Shadows ReadOnly Property DefaultInstance As SiteSettings
|
||||
Get
|
||||
@@ -33,6 +37,19 @@ Namespace API.Xhamster
|
||||
ControlToolTip:="If enabled and the video is downloaded in a non-native format, the video will be re-encoded." & vbCr &
|
||||
"Attention! Enabling this setting results in maximum CPU usage."), PXML, PClonable>
|
||||
Friend ReadOnly Property ReencodeVideos As PropertyValue
|
||||
<PropertyOption(ControlText:="Use yt-dlp to get file info", ControlToolTip:="If checked, yt-dlp will be used to get information about the file", Category:=CAT_YTDLP), PXML, PClonable, HiddenControl>
|
||||
Friend ReadOnly Property UseYTDLPJSON As PropertyValue
|
||||
<PropertyOption(ControlText:="Use yt-dlp to download the file", ControlToolTip:="If checked, yt-dlp will be used to download the file instead of the internal algorithm", Category:=CAT_YTDLP), PXML, PClonable, HiddenControl>
|
||||
Friend ReadOnly Property UseYTDLPDownload As PropertyValue
|
||||
Private ReadOnly Property UseYtDlp As Boolean
|
||||
Get
|
||||
Return CBool(UseYTDLPJSON.Value) Or CBool(UseYTDLPDownload.Value)
|
||||
End Get
|
||||
End Property
|
||||
<PropertyOption(ControlText:="Disable internal algorithm", ControlToolTip:="If checked, the internal algorithm will be forcibly disabled and replaced with yt-dlp", Category:=CAT_YTDLP), PXML, PClonable, HiddenControl>
|
||||
Friend ReadOnly Property UseYTDLPForceDisableInternal As PropertyValue
|
||||
<PropertyOption(ControlText:=GetMomentsCaption, Category:=DeclaredNames.CAT_UserDefs), PXML, PClonable>
|
||||
Friend ReadOnly Property GetMoments As PropertyValue
|
||||
<DoNotUse> Friend Overrides Property DownloadText As PropertyValue
|
||||
<DoNotUse> Friend Overrides Property DownloadTextPosts As PropertyValue
|
||||
<DoNotUse> Friend Overrides Property DownloadTextSpecialFolder As PropertyValue
|
||||
@@ -46,12 +63,17 @@ Namespace API.Xhamster
|
||||
Domains.DestinationProp = SiteDomains
|
||||
DownloadUHD = New PropertyValue(False)
|
||||
ReencodeVideos = New PropertyValue(False)
|
||||
UseYTDLPJSON = New PropertyValue(True)
|
||||
UseYTDLPDownload = New PropertyValue(True)
|
||||
UseYTDLPForceDisableInternal = New PropertyValue(False)
|
||||
GetMoments = New PropertyValue(True)
|
||||
|
||||
_SubscriptionsAllowed = True
|
||||
UrlPatternUser = "https://xhamster.com/{0}/{1}"
|
||||
UserRegex = RParams.DMS($"/({UserOption}|{ChannelOption}|{P_Creators})/([^/]+)(\Z|.*)", 0, RegexReturn.ListByMatch)
|
||||
UserRegex = RParams.DMS($"/({UserOption}|{UserOption2}|{ChannelOption}|{P_Creators})/([^/]+)(\Z|.*)", 0, RegexReturn.ListByMatch)
|
||||
ImageVideoContains = "xhamster"
|
||||
UserOptionsType = GetType(UserExchangeOptions)
|
||||
UseNetscapeCookies = True
|
||||
End Sub
|
||||
Friend Overrides Sub EndInit()
|
||||
Domains.PopulateInitialDomains(SiteDomains.Value)
|
||||
@@ -75,7 +97,7 @@ Namespace API.Xhamster
|
||||
Return New UserData
|
||||
End Function
|
||||
Friend Overrides Function Available(ByVal What As ISiteSettings.Download, ByVal Silent As Boolean) As Boolean
|
||||
If Settings.UseM3U8 AndAlso MyBase.Available(What, Silent) Then
|
||||
If (Not UseYtDlp Or (UseYtDlp And Settings.YtdlpFile.Exists)) AndAlso Settings.UseM3U8 AndAlso MyBase.Available(What, Silent) Then
|
||||
If What = ISiteSettings.Download.SavedPosts Then
|
||||
Return Responser.CookiesExists
|
||||
Else
|
||||
@@ -96,7 +118,8 @@ Namespace API.Xhamster
|
||||
End Function
|
||||
#Region "IsMyUser, IsMyImageVideo"
|
||||
Friend Const ChannelOption As String = "channels"
|
||||
Private Const UserOption As String = "users"
|
||||
Friend Const UserOption As String = "users/profiles"
|
||||
Private Const UserOption2 As String = "users"
|
||||
Friend Const P_Search As String = "search"
|
||||
Friend Const P_Tags As String = "tags"
|
||||
Friend Const P_Categories As String = "categories"
|
||||
|
||||
@@ -6,14 +6,16 @@
|
||||
'
|
||||
' This program is distributed in the hope that it will be useful,
|
||||
' but WITHOUT ANY WARRANTY
|
||||
Imports System.Text
|
||||
Imports System.Threading
|
||||
Imports SCrawler.API.Base
|
||||
Imports SCrawler.API.YouTube.Objects
|
||||
Imports PersonalUtilities.Functions.RegularExpressions
|
||||
Imports PersonalUtilities.Functions.XML
|
||||
Imports PersonalUtilities.Functions.XML.Base
|
||||
Imports PersonalUtilities.Functions.RegularExpressions
|
||||
Imports PersonalUtilities.Tools
|
||||
Imports PersonalUtilities.Tools.Web.Clients
|
||||
Imports PersonalUtilities.Tools.Web.Documents.JSON
|
||||
Imports SCrawler.API.Base
|
||||
Imports SCrawler.API.YouTube.Objects
|
||||
Imports UTypes = SCrawler.API.Base.UserMedia.Types
|
||||
Namespace API.Xhamster
|
||||
Friend Class UserData : Inherits UserDataBase : Implements IPSite
|
||||
@@ -175,10 +177,16 @@ Namespace API.Xhamster
|
||||
Friend Overrides Sub ExchangeOptionsSet(ByVal Obj As Object)
|
||||
If Not Obj Is Nothing AndAlso TypeOf Obj Is UserExchangeOptions Then DirectCast(Obj, UserExchangeOptions).Apply(Me)
|
||||
End Sub
|
||||
Private MyCache As CacheKeeper = Nothing
|
||||
Private Sub ResetCache()
|
||||
MyCache.DisposeIfReady(False)
|
||||
MyCache = Nothing
|
||||
End Sub
|
||||
#End Region
|
||||
#Region "Initializer"
|
||||
Friend Sub New()
|
||||
UseInternalM3U8Function = True
|
||||
UseInternalDownloadFileFunction = True
|
||||
UseClientTokens = True
|
||||
_TempPhotoData = New List(Of UserMedia)
|
||||
SessionPosts = New List(Of String)
|
||||
@@ -234,6 +242,9 @@ Namespace API.Xhamster
|
||||
Private SearchPostsCount As Integer = 0
|
||||
Private ReadOnly SessionPosts As List(Of String)
|
||||
Private _PageVideosRepeat As Integer = 0
|
||||
Friend Overrides Sub DownloadData(Token As CancellationToken)
|
||||
Try : MyBase.DownloadData(Token) : Finally : ResetCache() : End Try
|
||||
End Sub
|
||||
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
|
||||
Try
|
||||
_TempPhotoData.Clear()
|
||||
@@ -242,7 +253,7 @@ Namespace API.Xhamster
|
||||
SessionPosts.Clear()
|
||||
Responser.CookiesAsHeader = True
|
||||
If DownloadVideos Then DownloadData(1, True, False, Token)
|
||||
If GetMoments Then DownloadData(1, True, True, Token)
|
||||
If DownloadVideos And GetMoments Then DownloadData(1, True, True, Token)
|
||||
If Not IsChannel And Not IsCreator And DownloadImages And Not IsSubscription Then
|
||||
DownloadData(1, False, False, Token)
|
||||
ReparsePhoto(Token)
|
||||
@@ -301,7 +312,7 @@ Namespace API.Xhamster
|
||||
ElseIf IsCreator Or SiteMode = SiteModes.Tags Or SiteMode = SiteModes.Categories Or SiteMode = SiteModes.Pornstars Then
|
||||
URL = GetNonUserUrl(Page)
|
||||
Else
|
||||
URL = $"https://xhamster.com/users/{NameTrue}/{If(GetMoments, "moments", IIf(IsVideo, "videos", "photos"))}{IIf(Page = 1, String.Empty, $"/{Page}")}"
|
||||
URL = $"https://xhamster.com/{SiteSettings.UserOption}/{NameTrue}/{If(GetMoments, "moments", IIf(IsVideo, "videos", "photos"))}{IIf(Page = 1, String.Empty, $"/{Page}")}"
|
||||
End If
|
||||
ThrowAny(Token)
|
||||
|
||||
@@ -401,9 +412,9 @@ Namespace API.Xhamster
|
||||
If _TempMediaList(i).Type = UTypes.VideoPre Then
|
||||
m = _TempMediaList(i)
|
||||
If Not m.URL_BASE.IsEmptyString Then
|
||||
m2 = Nothing
|
||||
m2 = m
|
||||
ThrowAny(Token)
|
||||
If GetM3U8(m2, m.URL_BASE, m.SpecialFolder) Then
|
||||
If GetM3U8_Init(m2, m.URL_BASE, m.SpecialFolder, i) Then
|
||||
m2.URL_BASE = m.URL_BASE
|
||||
_TempMediaList(i) = m2
|
||||
Else
|
||||
@@ -431,9 +442,9 @@ Namespace API.Xhamster
|
||||
If Not DownloadTopCount.HasValue OrElse c <= DownloadTopCount.Value Then
|
||||
m = _TempMediaList(i)
|
||||
If Not m.URL_BASE.IsEmptyString Then
|
||||
m2 = Nothing
|
||||
m2 = m
|
||||
ThrowAny(Token)
|
||||
If GetM3U8(m2, m.URL_BASE, String.Empty) Then
|
||||
If GetM3U8_Init(m2, m.URL_BASE, String.Empty, i) Then
|
||||
m2.URL_BASE = m.URL_BASE
|
||||
_TempMediaList(i) = m2
|
||||
c += 1
|
||||
@@ -472,7 +483,7 @@ Namespace API.Xhamster
|
||||
If Not r.IsEmptyString Then
|
||||
Using j As EContainer = JsonDocument.Parse(r).XmlIfNothing
|
||||
If j.Count > 0 Then
|
||||
MaxPage = j.Value({"pagination"}, "maxPage").FromXML(Of Integer)(-1)
|
||||
MaxPage = j.Value({"pagination"}, "maxPage").IfNullOrEmpty(j.Value({"galleryPage", "paginationProps"}, "lastPageNumber")).FromXML(Of Integer)(-1)
|
||||
With j({"photosGalleryModel"}, "photos")
|
||||
If .ListExists Then
|
||||
For Each e In .Self
|
||||
@@ -514,7 +525,7 @@ Namespace API.Xhamster
|
||||
If m.State = UserMedia.States.Missing AndAlso Not m.URL_BASE.IsEmptyString Then
|
||||
ThrowAny(Token)
|
||||
m2 = Nothing
|
||||
If GetM3U8(m2, m.URL_BASE, m.SpecialFolder) Then
|
||||
If GetM3U8_Init(m2, m.URL_BASE, m.SpecialFolder, i) Then
|
||||
m2.URL_BASE = m.URL_BASE
|
||||
m2.State = UserMedia.States.Missing
|
||||
m2.Attempts = m.Attempts
|
||||
@@ -535,25 +546,85 @@ Namespace API.Xhamster
|
||||
End Sub
|
||||
#End Region
|
||||
#Region "GetM3U8"
|
||||
Private Overloads Function GetM3U8(ByRef m As UserMedia, ByVal URL As String, ByVal SpecFolder As String) As Boolean
|
||||
Private Structure XMMediaInfo : Implements IComparable(Of XMMediaInfo)
|
||||
Friend URL As String
|
||||
Friend Type As UTypes
|
||||
Friend IsInternal As Boolean
|
||||
Friend Thumb As String
|
||||
Friend FormatID As String
|
||||
Friend Width As Integer
|
||||
Friend Height As Integer
|
||||
Friend Title As String
|
||||
Private Function CompareTo(ByVal Other As XMMediaInfo) As Integer Implements IComparable(Of XMMediaInfo).CompareTo
|
||||
Return Width.CompareTo(Other.Width) * -1
|
||||
End Function
|
||||
End Structure
|
||||
Private Function GetM3U8_Init(ByRef m As UserMedia, ByVal URL As String, ByVal SpecFolder As String, ByVal n As Integer) As Boolean
|
||||
Try
|
||||
If Not URL.IsEmptyString Then
|
||||
Dim r$ = Responser.GetResponse(URL)
|
||||
If Not r.IsEmptyString Then r = RegexReplace(r, HtmlScript)
|
||||
Dim IsInternal As Boolean = False
|
||||
Dim r$ = GetMediaInfo(URL, n, IsInternal)
|
||||
If Not r.IsEmptyString Then
|
||||
Using j As EContainer = JsonDocument.Parse(r)
|
||||
If j.ListExists Then
|
||||
m = ExtractMedia(j("videoModel"), UTypes.VideoPre,,,, SpecFolder)
|
||||
m.URL_BASE = URL
|
||||
If IsSubscription Then
|
||||
With j("videoModel")
|
||||
If .ListExists Then
|
||||
m.URL = .Value("thumbURL").IfNullOrEmpty(.Value("previewThumbURL"))
|
||||
Return Not m.URL.IsEmptyString
|
||||
End If
|
||||
End With
|
||||
If IsInternal AndAlso GetM3U8_Internal(m, URL, j, SpecFolder) Then
|
||||
Return True
|
||||
Else
|
||||
Return GetM3U8(m, j, SpecFolder)
|
||||
Dim xmm As New XMMediaInfo
|
||||
Dim __checkURL As Func(Of EContainer, XMMediaInfo, XMMediaInfo) =
|
||||
Function(ByVal jj As EContainer, ByVal __xmm As XMMediaInfo) As XMMediaInfo
|
||||
With jj.Value("url").StringToLower
|
||||
If Not .IsEmptyString AndAlso .EndsWith(".m3u8") Or .EndsWith(".mp4") Then __xmm.URL = .Self
|
||||
End With
|
||||
Return __xmm
|
||||
End Function
|
||||
Dim __applyXMM As Func(Of EContainer, XMMediaInfo, XMMediaInfo) =
|
||||
Function(ByVal jj As EContainer, ByVal __xmm As XMMediaInfo) As XMMediaInfo
|
||||
With jj
|
||||
__xmm.Type = IIf(__xmm.URL.ToLower.EndsWith(".m3u8"), UTypes.m3u8, UTypes.Video)
|
||||
__xmm.Width = AConvert(Of Integer)(.Value("width"), 1, EDP.ReturnValue)
|
||||
__xmm.Height = AConvert(Of Integer)(.Value("height"), 1, EDP.ReturnValue)
|
||||
__xmm.FormatID = .Value("format_id")
|
||||
End With
|
||||
Return __xmm
|
||||
End Function
|
||||
xmm = __checkURL(j, xmm)
|
||||
If Not xmm.URL.IsEmptyString Then
|
||||
xmm = __applyXMM(j, xmm)
|
||||
Else
|
||||
With j("formats")
|
||||
If .ListExists Then
|
||||
Dim l As New List(Of XMMediaInfo)
|
||||
Dim tmpXMM As XMMediaInfo
|
||||
For Each format As EContainer In .Self
|
||||
tmpXMM = New XMMediaInfo
|
||||
tmpXMM = __checkURL(format, tmpXMM)
|
||||
If Not tmpXMM.URL.IsEmptyString Then
|
||||
tmpXMM = __applyXMM(format, tmpXMM)
|
||||
l.Add(tmpXMM)
|
||||
End If
|
||||
Next
|
||||
If l.Count > 0 Then
|
||||
If Not CBool(MySettings.DownloadUHD.Value) AndAlso l.LongCount(Function(v) v.Height <= 1080) > 0 Then _
|
||||
l.RemoveAll(Function(v) v.Height > 1080)
|
||||
l.Sort()
|
||||
xmm = l.First
|
||||
l.Clear()
|
||||
End If
|
||||
End If
|
||||
End With
|
||||
End If
|
||||
If Not xmm.URL.IsEmptyString Then
|
||||
xmm.IsInternal = False
|
||||
xmm.Thumb = j.Value("thumbnail")
|
||||
xmm.Title = TitleHtmlConverter(j.Value("title").IfNullOrEmpty(j.Value("fulltitle")))
|
||||
If Not xmm.Title.IsEmptyString Then m.File.Name = xmm.Title
|
||||
m.Type = xmm.Type
|
||||
m.URL = IIf(IsSubscription, xmm.Thumb, xmm.URL)
|
||||
m.Object = xmm
|
||||
m.SpecialFolder = SpecFolder
|
||||
Return True
|
||||
End If
|
||||
End If
|
||||
End If
|
||||
End Using
|
||||
@@ -561,18 +632,132 @@ Namespace API.Xhamster
|
||||
End If
|
||||
Return False
|
||||
Catch ex As Exception
|
||||
Return ErrorsDescriber.Execute(EDP.ReturnValue, ex, $"[{ToStringForLog()}]: API.Xhamster.GetM3U8({URL})", False)
|
||||
Return ErrorsDescriber.Execute(EDP.ReturnValue, ex, $"[{ToStringForLog()}]: API.Xhamster.GetM3U8_Init({URL})", False)
|
||||
End Try
|
||||
End Function
|
||||
Private Overloads Function GetM3U8(ByRef m As UserMedia, ByVal j As EContainer, ByVal SpecFolder As String) As Boolean
|
||||
Dim node As EContainer = j({"xplayerSettings", "sources", "hls"})
|
||||
Private Function GetMediaInfo(ByVal URL As String, ByVal n As Integer, ByRef IsInternal As Boolean) As String
|
||||
Try
|
||||
If Not URL.IsEmptyString Then
|
||||
Dim r$ = String.Empty
|
||||
Dim f As SFile
|
||||
If IsSubscription Then
|
||||
Try
|
||||
If Not CBool(MySettings.UseYTDLPForceDisableInternal.Value) Then r = Responser.GetResponse(URL)
|
||||
Catch exr As Exception
|
||||
ErrorsDescriber.Execute(EDP.SendToLog, exr, $"[{ToStringForLog()}]: API.Xhamster.GetMediaInfo({URL})", False)
|
||||
End Try
|
||||
If Not r.IsEmptyString Then r = RegexReplace(r, HtmlScript)
|
||||
If Not r.IsEmptyString Then
|
||||
IsInternal = True
|
||||
Return r
|
||||
Else
|
||||
f = YTDLPGetInfo(URL, n)
|
||||
If f.Exists Then IsInternal = False : Return f.GetText
|
||||
End If
|
||||
Else
|
||||
f = YTDLPGetInfo(URL, n)
|
||||
If f.Exists Then IsInternal = False : Return f.GetText
|
||||
End If
|
||||
End If
|
||||
Return String.Empty
|
||||
Catch ex As Exception
|
||||
Return ErrorsDescriber.Execute(EDP.SendToLog + EDP.ReturnValue, ex, $"[{ToStringForLog()}]: API.Xhamster.GetMediaInfo({URL})", String.Empty)
|
||||
End Try
|
||||
End Function
|
||||
Private Function GetM3U8_Internal(ByRef m As UserMedia, ByVal URL As String, ByVal j As EContainer, ByVal SpecFolder As String) As Boolean
|
||||
Try
|
||||
If j.ListExists Then
|
||||
m = ExtractMedia(j("videoModel"), UTypes.VideoPre,,,, SpecFolder)
|
||||
m.URL_BASE = URL
|
||||
m.SpecialFolder = SpecFolder
|
||||
If IsSubscription Then
|
||||
With j("videoModel")
|
||||
If .ListExists Then
|
||||
m.URL = .Value("thumbURL").IfNullOrEmpty(.Value("previewThumbURL"))
|
||||
m.Object = New XMMediaInfo With {
|
||||
.IsInternal = True,
|
||||
.Thumb = m.URL,
|
||||
.URL = URL,
|
||||
.Type = UTypes.VideoPre
|
||||
}
|
||||
Return Not m.URL.IsEmptyString
|
||||
End If
|
||||
End With
|
||||
Else
|
||||
Return GetM3U8_Internal_GetURL(m, j)
|
||||
End If
|
||||
End If
|
||||
Return False
|
||||
Catch ex As Exception
|
||||
Return ErrorsDescriber.Execute(EDP.ReturnValue, ex, $"[{ToStringForLog()}]: API.Xhamster.GetM3U8_Internal({URL})", False)
|
||||
End Try
|
||||
End Function
|
||||
Private Function GetM3U8_Internal_GetURL(ByRef m As UserMedia, ByVal j As EContainer, Optional ByVal r As Integer = 0) As Boolean
|
||||
Const urlNode$ = "url"
|
||||
Dim node As EContainer = j({"xplayerSettings", "sources", If(r = 0, "hls", "standard")})
|
||||
Dim t As UTypes = UTypes.Undefined
|
||||
If node.ListExists Then
|
||||
Dim url$ = node.GetNode({New NodeParams("url", True, True, True, True, 2)}).XmlIfNothingValue
|
||||
If Not url.IsEmptyString Then m.URL = url : m.Type = UTypes.m3u8 : Return True
|
||||
Dim url$ 'node.GetNode({New NodeParams("url", True, True, True, True, 2)}).XmlIfNothingValue
|
||||
Dim jn As EContainer, jn2 As EContainer
|
||||
Dim __getUrl As Func(Of EContainer, String) = Function(jj) If(jj.Contains(urlNode), jj.Value(urlNode), String.Empty)
|
||||
url = __getUrl(node)
|
||||
If url.IsEmptyString Then
|
||||
For Each jn In node
|
||||
If jn.Contains(urlNode) Then
|
||||
url = __getUrl(jn)
|
||||
ElseIf jn.Count > 0 Then
|
||||
For Each jn2 In jn
|
||||
url = __getUrl(jn2)
|
||||
If Not url.IsEmptyString Then Exit For
|
||||
Next
|
||||
End If
|
||||
If Not url.IsEmptyString Then Exit For
|
||||
Next
|
||||
End If
|
||||
If Not url.IsEmptyString Then
|
||||
If url.ToLower.EndsWith(".m3u8") Then
|
||||
t = UTypes.m3u8
|
||||
ElseIf url.ToLower.EndsWith(".mp4") Then
|
||||
t = UTypes.Video
|
||||
End If
|
||||
If Not t = UTypes.Undefined Then
|
||||
m.URL = url
|
||||
m.Type = t
|
||||
m.Object = New XMMediaInfo With {
|
||||
.IsInternal = True,
|
||||
.Type = t,
|
||||
.URL = url,
|
||||
.Thumb = j.Value({"videoModel"}, "thumbURL").IfNullOrEmpty(j.Value({"videoModel"}, "previewThumbURL"))
|
||||
}
|
||||
Return True
|
||||
End If
|
||||
End If
|
||||
End If
|
||||
If r = 0 Then Return GetM3U8_Internal_GetURL(m, j, r + 1)
|
||||
Return False
|
||||
End Function
|
||||
#End Region
|
||||
#Region "yt-dlp support"
|
||||
Private Function YTDLPGetInfo(ByVal URL As String, ByVal n As Integer) As SFile
|
||||
Try
|
||||
Dim cc As CacheKeeper
|
||||
If IsSingleObjectDownload Then
|
||||
cc = Settings.Cache
|
||||
Else
|
||||
If MyCache Is Nothing Then MyCache = CreateCache() : MyCache.Validate()
|
||||
cc = MyCache
|
||||
End If
|
||||
Dim path As SFile = cc.NewPath
|
||||
Dim c$ = If(MySettings.CookiesNetscapeFile.Exists, $" --no-cookies-from-browser --cookies ""{MySettings.CookiesNetscapeFile}""", String.Empty)
|
||||
Dim cmd$ = $"{Settings.YtdlpFile} --write-info-json --skip-download{c} {URL} -o ""{path.PathWithSeparator}file"""
|
||||
path.Exists()
|
||||
Using ytdlp As New YTDLP.YTDLPBatch(TokenPersonal,, path) : ytdlp.Encoding = Settings.CMDEncoding : ytdlp.Execute(cmd) : End Using
|
||||
Return SFile.GetFiles(path, "*.json",, EDP.ReturnValue).FirstOrDefault
|
||||
Catch ex As Exception
|
||||
Return ErrorsDescriber.Execute(EDP.SendToLog + EDP.ReturnValue, ex, $"API.Xhamster.UserData.YTDLPGetInfo({URL})", New SFile)
|
||||
End Try
|
||||
End Function
|
||||
#End Region
|
||||
#Region "DownloadSingleObject"
|
||||
Protected Overrides Sub DownloadSingleObject_GetPosts(ByVal Data As IYouTubeMediaContainer, ByVal Token As CancellationToken)
|
||||
_ContentList.Add(New UserMedia(Data.URL_BASE) With {.State = UserMedia.States.Missing})
|
||||
@@ -583,9 +768,35 @@ Namespace API.Xhamster
|
||||
Protected Overrides Sub DownloadContent(ByVal Token As CancellationToken)
|
||||
DownloadContentDefault(Token)
|
||||
End Sub
|
||||
Private Function XMMObjectExists(ByVal Media As UserMedia) As Boolean
|
||||
Return Not IsNothing(Media.Object) AndAlso TypeOf Media.Object Is XMMediaInfo
|
||||
End Function
|
||||
Protected Overrides Function DownloadM3U8(ByVal URL As String, ByVal Media As UserMedia, ByVal DestinationFile As SFile, ByVal Token As CancellationToken) As SFile
|
||||
Media.File = DestinationFile
|
||||
Return M3U8.Download(Media, Responser, MySettings.DownloadUHD.Value, Token, Progress, Not IsSingleObjectDownload, MySettings.ReencodeVideos.Value)
|
||||
If CBool(MySettings.UseYTDLPDownload.Value) Then
|
||||
If XMMObjectExists(Media) Then Return YTDLPDownload(Media, DestinationFile, Token)
|
||||
Return Nothing
|
||||
Else
|
||||
Media.File = DestinationFile
|
||||
Return M3U8.Download(Media, Responser, MySettings.DownloadUHD.Value, Token, Progress, Not IsSingleObjectDownload, MySettings.ReencodeVideos.Value)
|
||||
End If
|
||||
End Function
|
||||
Protected Overrides Function ValidateDownloadFile(ByVal URL As String, ByVal Media As UserMedia, ByRef Interrupt As Boolean) As Boolean
|
||||
If Not Media.IsPhotoType AndAlso CBool(MySettings.UseYTDLPDownload.Value) Then
|
||||
If Not Media.URL_BASE.IsEmptyString And XMMObjectExists(Media) AndAlso
|
||||
Not DirectCast(Media.Object, XMMediaInfo).FormatID.IsEmptyString Then Return True
|
||||
Interrupt = True
|
||||
End If
|
||||
Return False
|
||||
End Function
|
||||
Protected Overrides Function DownloadFile(ByVal URL As String, ByVal Media As UserMedia, ByVal DestinationFile As SFile, ByVal Token As CancellationToken) As SFile
|
||||
Return YTDLPDownload(Media, DestinationFile, Token)
|
||||
End Function
|
||||
Private Function YTDLPDownload(ByVal Media As UserMedia, ByVal DestinationFile As SFile, ByVal Token As CancellationToken) As SFile
|
||||
DestinationFile.Extension = "mp4"
|
||||
Dim c$ = If(MySettings.CookiesNetscapeFile.Exists, $" --no-cookies-from-browser --cookies ""{MySettings.CookiesNetscapeFile}""", String.Empty)
|
||||
Dim cmd$ = $"{Settings.YtdlpFile} --format {DirectCast(Media.Object, XMMediaInfo).FormatID}{c} {Media.URL_BASE} -o ""{DestinationFile}"""
|
||||
Using ytdlp As New YTDLP.YTDLPBatch(TokenPersonal,, DestinationFile) : ytdlp.Encoding = Settings.CMDEncoding : ytdlp.Execute(cmd) : End Using
|
||||
Return DestinationFile
|
||||
End Function
|
||||
#End Region
|
||||
#Region "Create media"
|
||||
@@ -651,7 +862,7 @@ Namespace API.Xhamster
|
||||
#End Region
|
||||
#Region "IDisposable support"
|
||||
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
|
||||
If Not disposedValue And disposing Then _TempPhotoData.Clear() : SessionPosts.Clear()
|
||||
If Not disposedValue And disposing Then _TempPhotoData.Clear() : SessionPosts.Clear() : ResetCache()
|
||||
MyBase.Dispose(disposing)
|
||||
End Sub
|
||||
#End Region
|
||||
|
||||
@@ -10,7 +10,7 @@ Imports SCrawler.API.Base
|
||||
Imports SCrawler.Plugin.Attributes
|
||||
Namespace API.Xhamster
|
||||
Friend NotInheritable Class UserExchangeOptions : Inherits API.Base.EditorExchangeOptionsBase_P
|
||||
<PSetting(Address:=SettingAddress.User, Caption:="Get moments")>
|
||||
<PSetting(Address:=SettingAddress.User, Caption:=SiteSettings.GetMomentsCaption)>
|
||||
Friend Property GetMoments As Boolean = False
|
||||
Friend Sub New()
|
||||
MyBase.New
|
||||
@@ -19,6 +19,10 @@ Namespace API.Xhamster
|
||||
MyBase.New(DirectCast(u, UserData))
|
||||
GetMoments = DirectCast(u, UserData).GetMoments
|
||||
End Sub
|
||||
Friend Sub New(ByVal s As SiteSettings)
|
||||
MyBase.New(s)
|
||||
GetMoments = s.GetMoments.Value
|
||||
End Sub
|
||||
Friend Overrides Sub Apply(ByRef u As IPSite)
|
||||
MyBase.Apply(u)
|
||||
DirectCast(u, UserData).GetMoments = GetMoments
|
||||
|
||||
@@ -17,11 +17,6 @@ Namespace DownloadObjects
|
||||
Friend Class AutoDownloader : Inherits GroupParameters : Implements IIndexable, IEContainerProvider, IComparable(Of AutoDownloader)
|
||||
Friend Event PauseChanged(ByVal Value As PauseModes)
|
||||
Friend Event PlanChanged As Scheduler.PlanChangedEventHandler
|
||||
Friend Enum Modes As Integer
|
||||
None = 0
|
||||
Specified = 3
|
||||
Groups = 4
|
||||
End Enum
|
||||
Friend Const NoPauseMode As Integer = -100
|
||||
Friend Enum PauseModes As Integer
|
||||
Disabled = -2
|
||||
@@ -188,8 +183,9 @@ Namespace DownloadObjects
|
||||
End Class
|
||||
#End Region
|
||||
#Region "XML Names"
|
||||
Private Const Name_Mode As String = "Mode"
|
||||
Private Const Name_Groups As String = "Groups"
|
||||
'TODELETE: AutoDownloader.Modes
|
||||
<Obsolete> Private Const Name_Mode As String = "Mode"
|
||||
Private Const Name_Enabled As String = "Enabled"
|
||||
Private Const Name_IsManual As String = "IsManual"
|
||||
Private Const Name_Timer As String = "Timer"
|
||||
Private Const Name_StartupDelay As String = "StartupDelay"
|
||||
@@ -247,17 +243,16 @@ Namespace DownloadObjects
|
||||
End Get
|
||||
End Property
|
||||
Friend Property Source As Scheduler
|
||||
Private _Mode As Modes = Modes.None
|
||||
Friend Property Mode As Modes
|
||||
Private _Enabled As Boolean = False
|
||||
Friend Property Enabled As Boolean
|
||||
Get
|
||||
Return _Mode
|
||||
Return _Enabled
|
||||
End Get
|
||||
Set(ByVal m As Modes)
|
||||
_Mode = m
|
||||
If _Mode = Modes.None Then [Stop]()
|
||||
Set(ByVal e As Boolean)
|
||||
_Enabled = e
|
||||
If Not _Enabled Then [Stop]()
|
||||
End Set
|
||||
End Property
|
||||
Friend ReadOnly Property Groups As List(Of String)
|
||||
Friend Property IsManual As Boolean = False
|
||||
Friend Property Timer As Integer = DefaultTimer
|
||||
Friend Property StartupDelay As Integer = 1
|
||||
@@ -371,7 +366,6 @@ Namespace DownloadObjects
|
||||
End Get
|
||||
End Property
|
||||
Friend Sub New(Optional ByVal IsNewPlan As Boolean = False)
|
||||
Groups = New List(Of String)
|
||||
UserKeys = New List(Of NotifiedUser)
|
||||
_IsNewPlan = IsNewPlan
|
||||
Initialization = False
|
||||
@@ -379,10 +373,17 @@ Namespace DownloadObjects
|
||||
Friend Sub New(ByVal x As EContainer)
|
||||
Me.New
|
||||
Initialization = True
|
||||
Mode = x.Value(Name_Mode).FromXML(Of Integer)(Modes.None)
|
||||
Import(x)
|
||||
#Disable Warning BC40008
|
||||
If x.Contains(Name_Mode) Then
|
||||
Dim g% = x.Value(Name_Mode).FromXML(Of Integer)(0)
|
||||
If g = 4 Then GroupsOnly = True
|
||||
Enabled = g
|
||||
Else
|
||||
Enabled = x.Value(Name_Enabled).FromXML(Of Boolean)(False)
|
||||
End If
|
||||
#Enable Warning
|
||||
If Name.IsEmptyString Then Name = "Default"
|
||||
Groups.ListAddList(x.Value(Name_Groups).StringToList(Of String)("|"), LAP.NotContainsOnly)
|
||||
|
||||
IsManual = x.Value(Name_IsManual).FromXML(Of Boolean)(False)
|
||||
Timer = x.Value(Name_Timer).FromXML(Of Integer)(DefaultTimer)
|
||||
@@ -408,8 +409,7 @@ Namespace DownloadObjects
|
||||
newObj.Copy(Me)
|
||||
With newObj
|
||||
.Name = String.Empty
|
||||
._Mode = _Mode
|
||||
.Groups.ListAddList(Groups, LAP.ClearBeforeAdd)
|
||||
.Enabled = Enabled
|
||||
.IsManual = IsManual
|
||||
.Timer = Timer
|
||||
.StartupDelay = StartupDelay
|
||||
@@ -441,8 +441,7 @@ Namespace DownloadObjects
|
||||
End Sub
|
||||
Private Function ToEContainer(Optional ByVal e As ErrorsDescriber = Nothing) As EContainer Implements IEContainerProvider.ToEContainer
|
||||
Return Export(New EContainer(Scheduler.Name_Plan, String.Empty) From {
|
||||
New EContainer(Name_Mode, CInt(Mode)),
|
||||
New EContainer(Name_Groups, Groups.ListToString("|")),
|
||||
New EContainer(Name_Enabled, Enabled.BoolToInteger),
|
||||
New EContainer(Name_IsManual, IsManual.BoolToInteger),
|
||||
New EContainer(Name_Timer, Timer),
|
||||
New EContainer(Name_StartupDelay, StartupDelay),
|
||||
@@ -467,7 +466,7 @@ Namespace DownloadObjects
|
||||
If Not IsManual Or Force Then
|
||||
If Init Then _StartTime = Now
|
||||
_IsNewPlan = False
|
||||
If Not Working And Not Mode = Modes.None Then _Working = True
|
||||
If Not Working And Enabled Then _Working = True
|
||||
RaiseEvent PlanChanged(Me)
|
||||
End If
|
||||
End Sub
|
||||
@@ -556,12 +555,12 @@ Namespace DownloadObjects
|
||||
Get
|
||||
If _StopRequested Then _Working = False
|
||||
Return (Working Or IsManual) And ((IsManual And _ForceStartRequested) Or (Not IsManual And NextExecutionDate < Now And (Not IsPaused Or IgnorePause)) Or _ForceStartRequested) And
|
||||
Not _StopRequested And Not Mode = Modes.None And (Not Downloader.Working Or IgnoreDownloaderWorking)
|
||||
Not _StopRequested And Enabled And (Not Downloader.Working Or IgnoreDownloaderWorking)
|
||||
End Get
|
||||
End Property
|
||||
Friend ReadOnly Property NextDate As Date?
|
||||
Get
|
||||
If Not _StopRequested And Not Mode = Modes.None Then
|
||||
If Not _StopRequested And Enabled Then
|
||||
If IsManual Or _ForceStartRequested Then
|
||||
Return Now.AddYears(-10)
|
||||
ElseIf Not IsPaused And Not IsManual And Working Then
|
||||
@@ -583,8 +582,6 @@ Namespace DownloadObjects
|
||||
Dim Keys As New List(Of String)
|
||||
Try
|
||||
Dim users As New List(Of IUserData)
|
||||
Dim GName$
|
||||
Dim i%
|
||||
Dim doRound% = -1, doLim% = Settings.Plugins.Count
|
||||
Dim DownloadedUsersCount% = 0
|
||||
Dim DownloadedSubscriptionsCount% = 0
|
||||
@@ -614,16 +611,9 @@ Namespace DownloadObjects
|
||||
Catch n_ex As Exception
|
||||
End Try
|
||||
End Sub
|
||||
Select Case Mode
|
||||
Case Modes.Specified : users.ListAddList(DownloadGroup.GetUsers(Me))
|
||||
Case Modes.Groups
|
||||
If Groups.Count > 0 And Settings.Groups.Count > 0 Then
|
||||
For Each GName In Groups
|
||||
i = Settings.Groups.IndexOf(GName)
|
||||
If i >= 0 Then users.ListAddList(Settings.Groups(i).GetUsers, LAP.IgnoreICopier, LAP.NotContainsOnly)
|
||||
Next
|
||||
End If
|
||||
End Select
|
||||
|
||||
If Enabled Then users.ListAddList(DownloadGroup.GetUsers(Me))
|
||||
|
||||
If users.Count > 0 Then
|
||||
Keys.ListAddList(users.Select(Function(u) u.Key))
|
||||
With Downloader
|
||||
@@ -699,7 +689,6 @@ Namespace DownloadObjects
|
||||
If Not disposedValue And disposing Then
|
||||
[Stop]()
|
||||
UserKeys.ListClearDispose()
|
||||
Groups.Clear()
|
||||
End If
|
||||
MyBase.Dispose(disposing)
|
||||
End Sub
|
||||
|
||||
@@ -25,19 +25,14 @@ Namespace DownloadObjects
|
||||
Me.components = New System.ComponentModel.Container()
|
||||
Dim CONTAINER_MAIN As System.Windows.Forms.ToolStripContainer
|
||||
Dim TP_MODE 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(AutoDownloaderEditorForm))
|
||||
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 TP_NOTIFY As System.Windows.Forms.TableLayoutPanel
|
||||
Dim ActionButton4 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||
Dim ActionButton5 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||
Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(AutoDownloaderEditorForm))
|
||||
Dim ActionButton1 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||
Dim ActionButton2 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||
Dim TT_MAIN As System.Windows.Forms.ToolTip
|
||||
Me.DEF_GROUP = New SCrawler.DownloadObjects.Groups.GroupDefaults()
|
||||
Me.OPT_SPEC = New System.Windows.Forms.RadioButton()
|
||||
Me.OPT_ENABLED = New System.Windows.Forms.RadioButton()
|
||||
Me.OPT_DISABLED = New System.Windows.Forms.RadioButton()
|
||||
Me.OPT_GROUP = New System.Windows.Forms.RadioButton()
|
||||
Me.TXT_GROUPS = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
||||
Me.CH_NOTIFY = New System.Windows.Forms.CheckBox()
|
||||
Me.CH_SHOW_PIC = New System.Windows.Forms.CheckBox()
|
||||
Me.CH_SHOW_PIC_USER = New System.Windows.Forms.CheckBox()
|
||||
@@ -54,7 +49,6 @@ Namespace DownloadObjects
|
||||
CONTAINER_MAIN.SuspendLayout()
|
||||
Me.DEF_GROUP.SuspendLayout()
|
||||
TP_MODE.SuspendLayout()
|
||||
CType(Me.TXT_GROUPS, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||
TP_NOTIFY.SuspendLayout()
|
||||
CType(Me.TXT_TIMER, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||
CType(Me.NUM_DELAY, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||
@@ -66,7 +60,7 @@ Namespace DownloadObjects
|
||||
'CONTAINER_MAIN.ContentPanel
|
||||
'
|
||||
CONTAINER_MAIN.ContentPanel.Controls.Add(Me.DEF_GROUP)
|
||||
CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(476, 519)
|
||||
CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(476, 494)
|
||||
CONTAINER_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
|
||||
CONTAINER_MAIN.LeftToolStripPanelVisible = False
|
||||
CONTAINER_MAIN.Location = New System.Drawing.Point(0, 0)
|
||||
@@ -82,7 +76,6 @@ Namespace DownloadObjects
|
||||
Me.DEF_GROUP.ColumnCount = 1
|
||||
Me.DEF_GROUP.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||
Me.DEF_GROUP.Controls.Add(TP_MODE, 0, 0)
|
||||
Me.DEF_GROUP.Controls.Add(Me.TXT_GROUPS, 0, 12)
|
||||
Me.DEF_GROUP.Controls.Add(TP_NOTIFY, 0, 13)
|
||||
Me.DEF_GROUP.Controls.Add(Me.TXT_TIMER, 0, 15)
|
||||
Me.DEF_GROUP.Controls.Add(Me.NUM_DELAY, 0, 16)
|
||||
@@ -111,21 +104,18 @@ Namespace DownloadObjects
|
||||
Me.DEF_GROUP.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
|
||||
Me.DEF_GROUP.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
|
||||
Me.DEF_GROUP.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||
Me.DEF_GROUP.Size = New System.Drawing.Size(476, 519)
|
||||
Me.DEF_GROUP.Size = New System.Drawing.Size(476, 494)
|
||||
Me.DEF_GROUP.TabIndex = 0
|
||||
'
|
||||
'TP_MODE
|
||||
'
|
||||
TP_MODE.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single]
|
||||
TP_MODE.ColumnCount = 3
|
||||
TP_MODE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333!))
|
||||
TP_MODE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333!))
|
||||
TP_MODE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333!))
|
||||
TP_MODE.ColumnCount = 2
|
||||
TP_MODE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
|
||||
TP_MODE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
|
||||
TP_MODE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20.0!))
|
||||
TP_MODE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20.0!))
|
||||
TP_MODE.Controls.Add(Me.OPT_SPEC, 1, 0)
|
||||
TP_MODE.Controls.Add(Me.OPT_ENABLED, 1, 0)
|
||||
TP_MODE.Controls.Add(Me.OPT_DISABLED, 0, 0)
|
||||
TP_MODE.Controls.Add(Me.OPT_GROUP, 2, 0)
|
||||
TP_MODE.Dock = System.Windows.Forms.DockStyle.Fill
|
||||
TP_MODE.Location = New System.Drawing.Point(1, 1)
|
||||
TP_MODE.Margin = New System.Windows.Forms.Padding(0)
|
||||
@@ -135,18 +125,18 @@ Namespace DownloadObjects
|
||||
TP_MODE.Size = New System.Drawing.Size(474, 25)
|
||||
TP_MODE.TabIndex = 0
|
||||
'
|
||||
'OPT_SPEC
|
||||
'OPT_ENABLED
|
||||
'
|
||||
Me.OPT_SPEC.AutoSize = True
|
||||
Me.OPT_SPEC.Dock = System.Windows.Forms.DockStyle.Fill
|
||||
Me.OPT_SPEC.Location = New System.Drawing.Point(161, 4)
|
||||
Me.OPT_SPEC.Name = "OPT_SPEC"
|
||||
Me.OPT_SPEC.Size = New System.Drawing.Size(150, 17)
|
||||
Me.OPT_SPEC.TabIndex = 3
|
||||
Me.OPT_SPEC.TabStop = True
|
||||
Me.OPT_SPEC.Text = "Specified"
|
||||
TT_MAIN.SetToolTip(Me.OPT_SPEC, "Select parameters")
|
||||
Me.OPT_SPEC.UseVisualStyleBackColor = True
|
||||
Me.OPT_ENABLED.AutoSize = True
|
||||
Me.OPT_ENABLED.Dock = System.Windows.Forms.DockStyle.Fill
|
||||
Me.OPT_ENABLED.Location = New System.Drawing.Point(240, 4)
|
||||
Me.OPT_ENABLED.Name = "OPT_ENABLED"
|
||||
Me.OPT_ENABLED.Size = New System.Drawing.Size(230, 17)
|
||||
Me.OPT_ENABLED.TabIndex = 3
|
||||
Me.OPT_ENABLED.TabStop = True
|
||||
Me.OPT_ENABLED.Text = "Enabled"
|
||||
TT_MAIN.SetToolTip(Me.OPT_ENABLED, "Select parameters")
|
||||
Me.OPT_ENABLED.UseVisualStyleBackColor = True
|
||||
'
|
||||
'OPT_DISABLED
|
||||
'
|
||||
@@ -154,48 +144,13 @@ Namespace DownloadObjects
|
||||
Me.OPT_DISABLED.Dock = System.Windows.Forms.DockStyle.Fill
|
||||
Me.OPT_DISABLED.Location = New System.Drawing.Point(4, 4)
|
||||
Me.OPT_DISABLED.Name = "OPT_DISABLED"
|
||||
Me.OPT_DISABLED.Size = New System.Drawing.Size(150, 17)
|
||||
Me.OPT_DISABLED.Size = New System.Drawing.Size(229, 17)
|
||||
Me.OPT_DISABLED.TabIndex = 0
|
||||
Me.OPT_DISABLED.TabStop = True
|
||||
Me.OPT_DISABLED.Text = "Disabled"
|
||||
TT_MAIN.SetToolTip(Me.OPT_DISABLED, "Automation disabled")
|
||||
Me.OPT_DISABLED.UseVisualStyleBackColor = True
|
||||
'
|
||||
'OPT_GROUP
|
||||
'
|
||||
Me.OPT_GROUP.AutoSize = True
|
||||
Me.OPT_GROUP.Dock = System.Windows.Forms.DockStyle.Fill
|
||||
Me.OPT_GROUP.Location = New System.Drawing.Point(318, 4)
|
||||
Me.OPT_GROUP.Name = "OPT_GROUP"
|
||||
Me.OPT_GROUP.Size = New System.Drawing.Size(152, 17)
|
||||
Me.OPT_GROUP.TabIndex = 4
|
||||
Me.OPT_GROUP.TabStop = True
|
||||
Me.OPT_GROUP.Text = "Groups"
|
||||
TT_MAIN.SetToolTip(Me.OPT_GROUP, "Download groups")
|
||||
Me.OPT_GROUP.UseVisualStyleBackColor = True
|
||||
'
|
||||
'TXT_GROUPS
|
||||
'
|
||||
ActionButton1.BackgroundImage = CType(resources.GetObject("ActionButton1.BackgroundImage"), System.Drawing.Image)
|
||||
ActionButton1.Name = "Edit"
|
||||
ActionButton2.BackgroundImage = CType(resources.GetObject("ActionButton2.BackgroundImage"), System.Drawing.Image)
|
||||
ActionButton2.Name = "Info"
|
||||
ActionButton2.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Info
|
||||
ActionButton2.ToolTipText = "Open group"
|
||||
ActionButton3.BackgroundImage = CType(resources.GetObject("ActionButton3.BackgroundImage"), System.Drawing.Image)
|
||||
ActionButton3.Name = "Clear"
|
||||
Me.TXT_GROUPS.Buttons.Add(ActionButton1)
|
||||
Me.TXT_GROUPS.Buttons.Add(ActionButton2)
|
||||
Me.TXT_GROUPS.Buttons.Add(ActionButton3)
|
||||
Me.TXT_GROUPS.CaptionText = "Groups"
|
||||
Me.TXT_GROUPS.CaptionWidth = 50.0R
|
||||
Me.TXT_GROUPS.Dock = System.Windows.Forms.DockStyle.Fill
|
||||
Me.TXT_GROUPS.Location = New System.Drawing.Point(4, 331)
|
||||
Me.TXT_GROUPS.Name = "TXT_GROUPS"
|
||||
Me.TXT_GROUPS.Size = New System.Drawing.Size(468, 22)
|
||||
Me.TXT_GROUPS.TabIndex = 1
|
||||
Me.TXT_GROUPS.TextBoxReadOnly = True
|
||||
'
|
||||
'TP_NOTIFY
|
||||
'
|
||||
TP_NOTIFY.ColumnCount = 4
|
||||
@@ -266,9 +221,9 @@ Namespace DownloadObjects
|
||||
'
|
||||
'TXT_TIMER
|
||||
'
|
||||
ActionButton4.BackgroundImage = CType(resources.GetObject("ActionButton4.BackgroundImage"), System.Drawing.Image)
|
||||
ActionButton4.Name = "Refresh"
|
||||
Me.TXT_TIMER.Buttons.Add(ActionButton4)
|
||||
ActionButton1.BackgroundImage = CType(resources.GetObject("ActionButton1.BackgroundImage"), System.Drawing.Image)
|
||||
ActionButton1.Name = "Refresh"
|
||||
Me.TXT_TIMER.Buttons.Add(ActionButton1)
|
||||
Me.TXT_TIMER.CaptionText = "Timer"
|
||||
Me.TXT_TIMER.CaptionToolTipEnabled = True
|
||||
Me.TXT_TIMER.CaptionToolTipText = "Timer (in minutes)"
|
||||
@@ -281,9 +236,9 @@ Namespace DownloadObjects
|
||||
'
|
||||
'NUM_DELAY
|
||||
'
|
||||
ActionButton5.BackgroundImage = CType(resources.GetObject("ActionButton5.BackgroundImage"), System.Drawing.Image)
|
||||
ActionButton5.Name = "Refresh"
|
||||
Me.NUM_DELAY.Buttons.Add(ActionButton5)
|
||||
ActionButton2.BackgroundImage = CType(resources.GetObject("ActionButton2.BackgroundImage"), System.Drawing.Image)
|
||||
ActionButton2.Name = "Refresh"
|
||||
Me.NUM_DELAY.Buttons.Add(ActionButton2)
|
||||
Me.NUM_DELAY.CaptionText = "Delay"
|
||||
Me.NUM_DELAY.CaptionToolTipEnabled = True
|
||||
Me.NUM_DELAY.CaptionToolTipText = "Startup delay"
|
||||
@@ -348,7 +303,6 @@ Namespace DownloadObjects
|
||||
Me.DEF_GROUP.PerformLayout()
|
||||
TP_MODE.ResumeLayout(False)
|
||||
TP_MODE.PerformLayout()
|
||||
CType(Me.TXT_GROUPS, System.ComponentModel.ISupportInitialize).EndInit()
|
||||
TP_NOTIFY.ResumeLayout(False)
|
||||
TP_NOTIFY.PerformLayout()
|
||||
CType(Me.TXT_TIMER, System.ComponentModel.ISupportInitialize).EndInit()
|
||||
@@ -357,12 +311,10 @@ Namespace DownloadObjects
|
||||
|
||||
End Sub
|
||||
Private WithEvents DEF_GROUP As DownloadObjects.Groups.GroupDefaults
|
||||
Private WithEvents TXT_GROUPS As PersonalUtilities.Forms.Controls.TextBoxExtended
|
||||
Private WithEvents OPT_SPEC As RadioButton
|
||||
Private WithEvents OPT_ENABLED As RadioButton
|
||||
Private WithEvents OPT_DISABLED As RadioButton
|
||||
Private WithEvents CH_NOTIFY As CheckBox
|
||||
Private WithEvents TXT_TIMER As PersonalUtilities.Forms.Controls.TextBoxExtended
|
||||
Private WithEvents OPT_GROUP As RadioButton
|
||||
Private WithEvents LBL_LAST_TIME_UP As Label
|
||||
Private WithEvents NUM_DELAY As PersonalUtilities.Forms.Controls.TextBoxExtended
|
||||
Private WithEvents CH_SHOW_PIC As CheckBox
|
||||
|
||||
@@ -129,85 +129,6 @@
|
||||
<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>
|
||||
<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>
|
||||
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
|
||||
AAAASUVORK5CYII=
|
||||
</value>
|
||||
</data>
|
||||
<data name="ActionButton2.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1
|
||||
MAAA6mAAADqYAAAXb5JfxUYAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAFQSURBVFhH7ZfNDcIwFIMZoXcm
|
||||
YBtGYRHECIgTR1ZhBsS9YoJgQ1Poi5sfqhIOWPqkqvV7dWlI0oVzriry5Dd5HSS0PFwasAEn0AJn4Dle
|
||||
o6fpykaVHYDNwB7YG6ZgzWiQrABosAbqaXNh7bprN1AyAAp3b42msuva9ooGYIFpELA931D2FI+VxzAI
|
||||
gTIdAEb+7KpBz+p4RclQyifoXwdKwgAwcMAl3/mEAOz9GJgokQGyR/sHr8CzlwFwgU+vCuagUQE4gSjz
|
||||
HGxUAM5iyiyxUp4IJ5QEAYomHCvlidCiJAigjKNYKU8M6B/g9wJUH4TV/4ZFE5GV8kSQE1HRVGylPBHC
|
||||
qbh0MbJSnhH0YtQFyFqOiZXyCOLLMQVDckNCrJRHEN+QeMGY3JJZKY8hb0vmxQLTYAplm1IvFNbblnuh
|
||||
Qb0Pk3exGZjv06wW8uT3cIs7jQnSONrSxH0AAAAASUVORK5CYII=
|
||||
</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>
|
||||
<metadata name="TP_NOTIFY.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>False</value>
|
||||
</metadata>
|
||||
@@ -216,36 +137,37 @@
|
||||
This means that if any user data has been downloaded with the plan, a simple notification will be shown with the number of users downloaded.
|
||||
The 'Image' and 'User icon' parameters will be ignored.</value>
|
||||
</data>
|
||||
<data name="ActionButton4.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<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/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
|
||||
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOElE
|
||||
QVQ4T2P4//8/QczOJyyqHpzfiE0OQwAZC8iqszAzs7CJ69o4BR768V/W2jcGXQ0KB4aFNS3dDQtnrbCb
|
||||
ePCK48wTN1wXXXzge/jXf/clV55zC4hIIatF0cjIyMikElzc57z0wX+XHd/+2+//99/ywP//xlu//tdb
|
||||
+eK/4Zp3/1WTOhYzARViNUAluKjTdf37/0ZTTn9TbdhwXblhwwW1/qOP1Ja9+K8w+95/6cm3/6v2Xvkv
|
||||
qKjniGGAoIqRpW3/4e8S9uGdzFz82gwMDFxAzCxm4ZegtuLDf+VJ1/8rZM25IqLvnM/CximCYYCic1QN
|
||||
v7x2JIwPwyrJ3XNUylddE9G2TWNmZOBDl4czmJiZMSRBmFdSyYyJgUEQmxwIYxWEYXZBCUls4sgYq6CA
|
||||
prWNbtG8nXKeaVPR5XiVjSxEzf0yYXy4BBMLO6eQjoOXZvrkbbazrv53Xf/2v4CSbjBMXkhBl1/CMyNZ
|
||||
qWnvGy5pNQ+YONwAfjXzAOupl/47LLr333L50/96q9/8l23YdES6cO5KuYqVW+R7Tj6SnfP0v4hryjyY
|
||||
HhQDmFjYeHVKFp7WX/Xuv9Kq9/+Vd/z7r7rv/3+l7f//y676DEwDN/9L+BVvYkKLCTgDhNkkVUyVlr74
|
||||
qbbz73/VOTc/qsy89kWx+9h7qbQpJwS1bbOAscGGrB6EUTggLOqf16C55ft/HlnNAFZOXgVWdi4FRgYG
|
||||
VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg==
|
||||
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsPAAALDwGS+QOlAAACM0lE
|
||||
QVQ4T2P4//8/AyHMzicsqh6c34guDsIYAshYQFadhZmZhU1c18Yp8NCP/7LWvjHoajA0gbCwpqW7YeGs
|
||||
FXYTD15xnHnihuuiiw98D//6777kynNuAREpnAYwMjIyqQQX9zkvffDfZce3//b7//23PPD/v/HWr//1
|
||||
Vr74b7jm3X/VpI7FTIyMjFgNUAku6nRd//6/0ZTT31QbNlxXbthwQa3/6CO1ZS/+K8y+91968u3/qr1X
|
||||
/gsq6jliGCCoYmRp23/4u4R9eCczF782AwMDFwMDA7OYhV+C2ooP/5UnXf+vkDXnioi+cz4LG6cIhgGK
|
||||
zlE1/PLakcguArsquXuOSvmqayLatmnMjAx86PJwBhMzM4YkCPNKKpkxMTAIootjGIANswtKSKKLoWMM
|
||||
ARAW0LS20S2at1POM20quhyvspGFqLlfJoYBTCzsnEI6Dl6a6ZO32c66+t91/dv/Akq6wTB5IQVdfgnP
|
||||
jGSlpr1vuKTVPDAM4FczD7Ceeum/w6J7/y2XP/2vt/rNf9mGTUekC+eulKtYuUW+5+Qj2TlP/4u4psxD
|
||||
dhGSC9h4dUoWntZf9e6/0qr3/5V3/Puvuu//f6Xt///Lrvr8X3ryzf8SfsWbmNBiAsV/bJIqpkpLX/xU
|
||||
2/n3v+qcmx9VZl77oth97L1U2pQTgtq2WUwMDGzI6jEMAGFR/7wGzS3f//PIagawcvIqsLJzKTAyMLCi
|
||||
q8NpABMLK4dCfOsSZlYOUXQ5bBgArRReBMoH61gAAAAASUVORK5CYII=
|
||||
</value>
|
||||
</data>
|
||||
<data name="ActionButton5.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<data name="ActionButton2.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
|
||||
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOElE
|
||||
QVQ4T2P4//8/QczOJyyqHpzfiE0OQwAZC8iqszAzs7CJ69o4BR768V/W2jcGXQ0KB4aFNS3dDQtnrbCb
|
||||
ePCK48wTN1wXXXzge/jXf/clV55zC4hIIatF0cjIyMikElzc57z0wX+XHd/+2+//99/ywP//xlu//tdb
|
||||
+eK/4Zp3/1WTOhYzARViNUAluKjTdf37/0ZTTn9TbdhwXblhwwW1/qOP1Ja9+K8w+95/6cm3/6v2Xvkv
|
||||
qKjniGGAoIqRpW3/4e8S9uGdzFz82gwMDFxAzCxm4ZegtuLDf+VJ1/8rZM25IqLvnM/CximCYYCic1QN
|
||||
v7x2JIwPwyrJ3XNUylddE9G2TWNmZOBDl4czmJiZMSRBmFdSyYyJgUEQmxwIYxWEYXZBCUls4sgYq6CA
|
||||
prWNbtG8nXKeaVPR5XiVjSxEzf0yYXy4BBMLO6eQjoOXZvrkbbazrv53Xf/2v4CSbjBMXkhBl1/CMyNZ
|
||||
qWnvGy5pNQ+YONwAfjXzAOupl/47LLr333L50/96q9/8l23YdES6cO5KuYqVW+R7Tj6SnfP0v4hryjyY
|
||||
HhQDmFjYeHVKFp7WX/Xuv9Kq9/+Vd/z7r7rv/3+l7f//y676DEwDN/9L+BVvYkKLCTgDhNkkVUyVlr74
|
||||
qbbz73/VOTc/qsy89kWx+9h7qbQpJwS1bbOAscGGrB6EUTggLOqf16C55ft/HlnNAFZOXgVWdi4FRgYG
|
||||
VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg==
|
||||
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsPAAALDwGS+QOlAAACM0lE
|
||||
QVQ4T2P4//8/AyHMzicsqh6c34guDsIYAshYQFadhZmZhU1c18Yp8NCP/7LWvjHoajA0gbCwpqW7YeGs
|
||||
FXYTD15xnHnihuuiiw98D//6777kynNuAREpnAYwMjIyqQQX9zkvffDfZce3//b7//23PPD/v/HWr//1
|
||||
Vr74b7jm3X/VpI7FTIyMjFgNUAku6nRd//6/0ZTT31QbNlxXbthwQa3/6CO1ZS/+K8y+91968u3/qr1X
|
||||
/gsq6jliGCCoYmRp23/4u4R9eCczF782AwMDFwMDA7OYhV+C2ooP/5UnXf+vkDXnioi+cz4LG6cIhgGK
|
||||
zlE1/PLakcguArsquXuOSvmqayLatmnMjAx86PJwBhMzM4YkCPNKKpkxMTAIootjGIANswtKSKKLoWMM
|
||||
ARAW0LS20S2at1POM20quhyvspGFqLlfJoYBTCzsnEI6Dl6a6ZO32c66+t91/dv/Akq6wTB5IQVdfgnP
|
||||
jGSlpr1vuKTVPDAM4FczD7Ceeum/w6J7/y2XP/2vt/rNf9mGTUekC+eulKtYuUW+5+Qj2TlP/4u4psxD
|
||||
dhGSC9h4dUoWntZf9e6/0qr3/5V3/Puvuu//f6Xt///Lrvr8X3ryzf8SfsWbmNBiAsV/bJIqpkpLX/xU
|
||||
2/n3v+qcmx9VZl77oth97L1U2pQTgtq2WUwMDGzI6jEMAGFR/7wGzS3f//PIagawcvIqsLJzKTAyMLCi
|
||||
q8NpABMLK4dCfOsSZlYOUXQ5bBgArRReBMoH61gAAAAASUVORK5CYII=
|
||||
</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -9,17 +9,14 @@
|
||||
Imports SCrawler.DownloadObjects.Groups
|
||||
Imports PersonalUtilities.Forms
|
||||
Imports PersonalUtilities.Forms.Controls.Base
|
||||
Imports DModes = SCrawler.DownloadObjects.AutoDownloader.Modes
|
||||
Namespace DownloadObjects
|
||||
Friend Class AutoDownloaderEditorForm
|
||||
Private WithEvents MyDefs As DefaultFormOptions
|
||||
Private ReadOnly MyGroups As List(Of String)
|
||||
Private ReadOnly Property Plan As AutoDownloader
|
||||
Friend Sub New(ByRef _Plan As AutoDownloader)
|
||||
InitializeComponent()
|
||||
Plan = _Plan
|
||||
MyDefs = New DefaultFormOptions(Me, Settings.Design)
|
||||
MyGroups.ListAddList(Plan.Groups, LAP.NotContainsOnly)
|
||||
End Sub
|
||||
Private Class AutomationTimerChecker : Inherits FieldsCheckerProviderBase
|
||||
Public Overrides Property ErrorMessage As String
|
||||
@@ -45,19 +42,12 @@ Namespace DownloadObjects
|
||||
.MyViewInitialize(True)
|
||||
.AddOkCancelToolbar()
|
||||
With Plan
|
||||
Select Case .Mode
|
||||
Case DModes.None : OPT_DISABLED.Checked = True
|
||||
Case DModes.Specified : OPT_SPEC.Checked = True
|
||||
Case DModes.Groups : OPT_GROUP.Checked = True
|
||||
End Select
|
||||
If Enabled Then OPT_ENABLED.Checked = True Else OPT_DISABLED.Checked = True
|
||||
|
||||
TXT_GROUPS.CaptionWidth = GroupDefaults.CaptionWidthDefault
|
||||
TXT_TIMER.CaptionWidth = GroupDefaults.CaptionWidthDefault
|
||||
NUM_DELAY.CaptionWidth = GroupDefaults.CaptionWidthDefault
|
||||
|
||||
DEF_GROUP.Set(Plan)
|
||||
If MyGroups.Count > 0 Then TXT_GROUPS.Text = MyGroups.ListToString
|
||||
If Settings.Groups.Count = 0 Then TXT_GROUPS.Clear() : TXT_GROUPS.Enabled = False
|
||||
CH_NOTIFY.Checked = .ShowNotifications
|
||||
CH_NOTIFY_SIMPLE.Checked = .ShowSimpleNotification
|
||||
CH_SHOW_PIC.Checked = .ShowPictureDownloaded
|
||||
@@ -79,27 +69,14 @@ Namespace DownloadObjects
|
||||
If DEF_GROUP.TXT_NAME.IsEmptyString And Settings.Automation.Count = 0 Then DEF_GROUP.TXT_NAME.Text = "Default"
|
||||
End With
|
||||
End Sub
|
||||
Private Sub AutoDownloaderEditorForm_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed
|
||||
MyGroups.Clear()
|
||||
End Sub
|
||||
Private Sub AutoDownloaderEditorForm_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
|
||||
Try
|
||||
If e = ShowUsersButtonKey AndAlso Not OPT_DISABLED.Checked Then
|
||||
Dim users As New List(Of API.Base.IUserData)
|
||||
If OPT_GROUP.Checked Then
|
||||
If MyGroups.Count > 0 Then
|
||||
Dim i%
|
||||
For Each groupName$ In MyGroups
|
||||
i = Settings.Groups.IndexOf(groupName)
|
||||
If i >= 0 Then users.ListAddList(DownloadGroup.GetUsers(Settings.Groups(i)), LAP.NotContainsOnly, LAP.IgnoreICopier)
|
||||
Next
|
||||
End If
|
||||
Else
|
||||
Using g As New GroupParameters
|
||||
DEF_GROUP.Get(g)
|
||||
users.ListAddList(DownloadGroup.GetUsers(g))
|
||||
End Using
|
||||
End If
|
||||
Using g As New GroupParameters
|
||||
DEF_GROUP.Get(g)
|
||||
users.ListAddList(DownloadGroup.GetUsers(g), LAP.IgnoreICopier)
|
||||
End Using
|
||||
GroupUsersViewer.Show(users, $"S {DEF_GROUP.TXT_NAME.Text}")
|
||||
users.Clear()
|
||||
End If
|
||||
@@ -110,14 +87,8 @@ Namespace DownloadObjects
|
||||
Private Sub MyDefs_ButtonOkClick(ByVal Sender As Object, ByVal e As KeyHandleEventArgs) Handles MyDefs.ButtonOkClick
|
||||
If MyDefs.MyFieldsChecker.AllParamsOK Then
|
||||
With Plan
|
||||
Select Case True
|
||||
Case OPT_DISABLED.Checked : .Mode = DModes.None
|
||||
Case OPT_SPEC.Checked : .Mode = DModes.Specified
|
||||
Case OPT_GROUP.Checked : .Mode = DModes.Groups
|
||||
End Select
|
||||
.Enabled = OPT_ENABLED.Checked
|
||||
DEF_GROUP.Get(Plan)
|
||||
.Groups.Clear()
|
||||
.Groups.ListAddList(MyGroups)
|
||||
.ShowNotifications = CH_NOTIFY.Checked
|
||||
.ShowSimpleNotification = CH_NOTIFY_SIMPLE.Checked
|
||||
.ShowPictureDownloaded = CH_SHOW_PIC.Checked
|
||||
@@ -131,42 +102,20 @@ Namespace DownloadObjects
|
||||
MyDefs.CloseForm()
|
||||
End If
|
||||
End Sub
|
||||
Private Sub TXT_GROUPS_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As EventArgs) Handles TXT_GROUPS.ActionOnButtonClick
|
||||
Select Case Sender.DefaultButton
|
||||
Case ActionButton.DefaultButtons.Edit
|
||||
Using f As New LabelsForm(MyGroups, (From g As DownloadGroup In Settings.Groups Where Not g.IsViewFilter Select g.Name)) With {
|
||||
.Text = "Groups (F3 to edit)",
|
||||
.Icon = My.Resources.GroupByIcon_16,
|
||||
.IsGroups = True
|
||||
}
|
||||
f.ShowDialog()
|
||||
If f.DialogResult = DialogResult.OK Then MyGroups.ListAddList(f.LabelsList, LAP.ClearBeforeAdd) : TXT_GROUPS.Text = MyGroups.ListToString
|
||||
End Using
|
||||
Case ActionButton.DefaultButtons.Clear : MyGroups.Clear()
|
||||
Case ActionButton.DefaultButtons.Info
|
||||
Try
|
||||
If MyGroups.Count > 0 Then
|
||||
Dim i% = Settings.Groups.IndexOf(MyGroups(0))
|
||||
If i >= 0 Then
|
||||
Using gf As New GroupEditorForm(Settings.Groups(i)) : gf.ShowDialog() : End Using
|
||||
End If
|
||||
End If
|
||||
Catch ex As Exception
|
||||
ErrorsDescriber.Execute(EDP.LogMessageValue, ex, "Show group")
|
||||
End Try
|
||||
End Select
|
||||
End Sub
|
||||
Private Sub ChangeEnabled() Handles OPT_DISABLED.CheckedChanged,
|
||||
OPT_SPEC.CheckedChanged, OPT_GROUP.CheckedChanged,
|
||||
OPT_ENABLED.CheckedChanged,
|
||||
CH_NOTIFY.CheckedChanged, CH_NOTIFY_SIMPLE.CheckedChanged
|
||||
DEF_GROUP.Enabled = OPT_SPEC.Checked
|
||||
TXT_GROUPS.Enabled = OPT_GROUP.Checked
|
||||
TXT_TIMER.Enabled = Not OPT_DISABLED.Checked
|
||||
NUM_DELAY.Enabled = Not OPT_DISABLED.Checked
|
||||
CH_NOTIFY.Enabled = Not OPT_DISABLED.Checked
|
||||
Dim __enabled As Boolean = Not OPT_DISABLED.Checked
|
||||
DEF_GROUP.Enabled = __enabled
|
||||
TXT_TIMER.Enabled = __enabled
|
||||
NUM_DELAY.Enabled = __enabled
|
||||
CH_NOTIFY.Enabled = __enabled
|
||||
CH_NOTIFY_SIMPLE.Enabled = CH_NOTIFY.Enabled And CH_NOTIFY.Checked
|
||||
CH_SHOW_PIC.Enabled = CH_NOTIFY.Checked And Not OPT_DISABLED.Checked And Not CH_NOTIFY_SIMPLE.Checked
|
||||
CH_SHOW_PIC_USER.Enabled = CH_NOTIFY.Checked And Not OPT_DISABLED.Checked And Not CH_NOTIFY_SIMPLE.Checked
|
||||
|
||||
If Settings.Labels.Count = 0 Then DEF_GROUP.LabelsEnabled = False
|
||||
If Settings.Groups.Count = 0 Then DEF_GROUP.GroupsEnabled = False
|
||||
End Sub
|
||||
Private Sub NUM_DELAY_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As EventArgs) Handles NUM_DELAY.ActionOnButtonClick
|
||||
If Sender.DefaultButton = ActionButton.DefaultButtons.Clear Then NUM_DELAY.Value = 0
|
||||
|
||||
@@ -144,7 +144,7 @@ Namespace DownloadObjects
|
||||
|
||||
If UpdateBase Then UpdateBaseButton(Not p = PauseModes.Disabled)
|
||||
If Not VerifyAll OrElse Settings.Automation.All(Function(ByVal plan As AutoDownloader) As Boolean
|
||||
If plan.Mode = AutoDownloader.Modes.None Then
|
||||
If Not plan.Enabled Then
|
||||
Return True
|
||||
Else
|
||||
Return plan.Pause = p
|
||||
|
||||
@@ -507,24 +507,7 @@ Namespace DownloadObjects
|
||||
Private Sub ShowPlanUsers()
|
||||
Try
|
||||
If _LatestSelected.ValueBetween(0, Settings.Automation.Count - 1) Then
|
||||
With Settings.Automation(_LatestSelected)
|
||||
Dim users As New List(Of API.Base.IUserData)
|
||||
If Not .Mode = AutoDownloader.Modes.None Then
|
||||
If .Mode = AutoDownloader.Modes.Groups Then
|
||||
If .Groups.Count > 0 Then
|
||||
Dim i%
|
||||
For Each groupName$ In .Groups
|
||||
i = Settings.Groups.IndexOf(groupName)
|
||||
If i >= 0 Then users.ListAddList(Groups.DownloadGroup.GetUsers(Settings.Groups(i)), LAP.NotContainsOnly, LAP.IgnoreICopier)
|
||||
Next
|
||||
End If
|
||||
Else
|
||||
users.ListAddList(Groups.DownloadGroup.GetUsers(.Self))
|
||||
End If
|
||||
End If
|
||||
Groups.GroupUsersViewer.Show(users, $"S { .Name}")
|
||||
users.Clear()
|
||||
End With
|
||||
With Settings.Automation(_LatestSelected) : Groups.GroupUsersViewer.Show(Groups.DownloadGroup.GetUsers(.Self), $"S { .Name}") : End With
|
||||
End If
|
||||
Catch ex As Exception
|
||||
ErrorsDescriber.Execute(EDP.LogMessageValue, ex, "Show plan users")
|
||||
|
||||
@@ -16,6 +16,7 @@ Namespace DownloadObjects
|
||||
Friend Event DownloadDone As NotificationEventHandler
|
||||
Friend Event ProgressChanged(ByVal Main As Boolean, ByVal IsMaxValue As Boolean, ByVal IsDone As Boolean)
|
||||
Friend Event FeedFilesChanged As TDownloader.FeedFilesChangedEventHandler
|
||||
Friend Event KeyDown As KeyEventHandler
|
||||
#End Region
|
||||
#Region "Declarations"
|
||||
#Region "Controls"
|
||||
@@ -126,6 +127,10 @@ Namespace DownloadObjects
|
||||
TP_MAIN.Controls.Add(LBL_INFO, 0, 1)
|
||||
End If
|
||||
|
||||
For Each btt As Button In {BTT_OPEN, BTT_START, BTT_STOP}
|
||||
If Not btt Is Nothing Then AddHandler btt.KeyDown, AddressOf BTT_KeyDown
|
||||
Next
|
||||
|
||||
With Job
|
||||
.Progress = New MyProgressExt(PR_MAIN, PR_PRE, LBL_INFO) With {.ResetProgressOnMaximumChanges = False}
|
||||
With DirectCast(.Progress, MyProgressExt)
|
||||
@@ -149,6 +154,9 @@ Namespace DownloadObjects
|
||||
.Dock = DockStyle.Fill
|
||||
}
|
||||
End Sub
|
||||
Private Sub BTT_KeyDown(ByVal Sender As Object, ByVal e As KeyEventArgs)
|
||||
RaiseEvent KeyDown(Sender, e)
|
||||
End Sub
|
||||
#End Region
|
||||
Friend Function [Get]() As TableLayoutPanel
|
||||
Return TP_MAIN
|
||||
|
||||
@@ -43,6 +43,7 @@ Friend Class DownloadSavedPostsForm
|
||||
For Each j As DownloadProgress In JobsList
|
||||
AddHandler j.DownloadDone, AddressOf Jobs_DownloadDone
|
||||
AddHandler j.FeedFilesChanged, AddressOf Jobs_FeedFilesChanged
|
||||
AddHandler j.KeyDown, AddressOf DownloadSavedPostsForm_KeyDown
|
||||
TP_MAIN.RowStyles.Add(New RowStyle(SizeType.Absolute, 60))
|
||||
TP_MAIN.RowCount += 1
|
||||
TP_MAIN.Controls.Add(j.Get, 0, TP_MAIN.RowStyles.Count - 1)
|
||||
@@ -54,6 +55,9 @@ Friend Class DownloadSavedPostsForm
|
||||
MaximumSize = s
|
||||
End If
|
||||
End Sub
|
||||
Private Sub DownloadSavedPostsForm_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown, BTT_DOWN_ALL.KeyDown, BTT_STOP_ALL.KeyDown
|
||||
If e.KeyCode = Keys.Escape Then Close()
|
||||
End Sub
|
||||
Private Sub DownloadSavedPostsForm_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
|
||||
e.Cancel = True
|
||||
Hide()
|
||||
|
||||
@@ -7,9 +7,10 @@
|
||||
' This program is distributed in the hope that it will be useful,
|
||||
' but WITHOUT ANY WARRANTY
|
||||
Imports System.ComponentModel
|
||||
Imports SCrawler.API.Base
|
||||
Imports System.IO
|
||||
Imports PersonalUtilities.Forms
|
||||
Imports PersonalUtilities.Tools
|
||||
Imports SCrawler.API.Base
|
||||
Imports UserMediaD = SCrawler.DownloadObjects.TDownloader.UserMediaD
|
||||
Namespace DownloadObjects
|
||||
<ToolboxItem(False), DesignTimeVisible(False)>
|
||||
@@ -137,28 +138,18 @@ Namespace DownloadObjects
|
||||
End Sub
|
||||
#End Region
|
||||
#Region "Converter"
|
||||
Private Const ExtWebp As String = "webp"
|
||||
Private Const ExtJpg As String = "jpg"
|
||||
Private Function ConvertWebp(ByVal file As SFile, Optional ByVal NewCacheDir As Boolean = False) As SFile
|
||||
If file.Extension = ExtWebp Then
|
||||
If Settings.FfmpegFile.Exists Then
|
||||
Dim dir As SFile
|
||||
If NewCacheDir Then dir = Settings.Cache.NewPath Else dir = Settings.Cache
|
||||
Dim f As SFile = file
|
||||
f.Path = dir.Path
|
||||
f.Extension = ExtJpg
|
||||
Using imgBatch As New BatchExecutor
|
||||
With imgBatch
|
||||
.ChangeDirectory(dir)
|
||||
.Execute($"""{Settings.FfmpegFile}"" -i ""{file}"" ""{f}""")
|
||||
End With
|
||||
End Using
|
||||
If f.Exists Then Return f
|
||||
End If
|
||||
Else
|
||||
Return file
|
||||
End If
|
||||
Return Nothing
|
||||
Private Const ExtWebp As String = UserImage.ExtWebp
|
||||
Private Const ExtJpg As String = UserImage.ExtJpg
|
||||
Private Function ConvertOptional(ByVal file As SFile, ByVal GetError As Boolean, ByRef IsWebP As Boolean) As ImageRenderer
|
||||
Dim ir As ImageRenderer2 = Nothing
|
||||
Try
|
||||
ir = New ImageRenderer2(file, EDP.ThrowException)
|
||||
If ir.HasError Then Throw If(ir.ImgErr, New Exception) Else Return ir
|
||||
Catch ex As Exception
|
||||
IsWebP = ir?.NativeFormat.IfNullOrEmpty(ExtJpg) = ExtWebp
|
||||
ir.DisposeIfReady
|
||||
If GetError Then Throw ex Else Return Nothing
|
||||
End Try
|
||||
End Function
|
||||
#End Region
|
||||
#Region "Initializers"
|
||||
@@ -174,6 +165,42 @@ Namespace DownloadObjects
|
||||
Public Sub New()
|
||||
InitializeComponent()
|
||||
End Sub
|
||||
Private Class ImageRenderer2 : Inherits ImageRenderer
|
||||
Friend NativeFormat As String = Nothing
|
||||
Friend ImgErr As Exception = Nothing
|
||||
Friend Sub New(ByVal ImgPath As SFile, Optional ByVal e As ErrorsDescriber = Nothing)
|
||||
MyBase.New()
|
||||
Try
|
||||
If ImgPath.Exists(SFO.File, False) Then
|
||||
OriginalImageBytes = SFile.GetBytes(ImgPath, EDP.ThrowException)
|
||||
Try
|
||||
OriginalImage = GetImage(OriginalImageBytes)
|
||||
Catch exInternal As Exception
|
||||
HasError = True
|
||||
ImgErr = exInternal
|
||||
NativeFormat = GetTrueFormat(OriginalImageBytes, EDP.ReturnValue)
|
||||
End Try
|
||||
End If
|
||||
Address = ImgPath
|
||||
Catch ex As Exception
|
||||
HasError = True
|
||||
NativeFormat = GetTrueFormat(OriginalImageBytes, EDP.ReturnValue)
|
||||
If Not e.Exists Then e = EDP.ThrowException
|
||||
ErrorsDescriber.Execute(e, ex, $"ImageRenderer2.New({ImgPath})")
|
||||
End Try
|
||||
End Sub
|
||||
Friend Shared Function GetTrueFormat(ByVal Img() As Byte, Optional ByVal e As ErrorsDescriber = Nothing) As String
|
||||
Try
|
||||
Using ms As New MemoryStream(Img, 0, Img.Length)
|
||||
Return System.Windows.Media.Imaging.BitmapDecoder.Create(ms, Windows.Media.Imaging.BitmapCreateOptions.PreservePixelFormat,
|
||||
Windows.Media.Imaging.BitmapCacheOption.OnLoad).Metadata.Format
|
||||
End Using
|
||||
Catch ex As Exception
|
||||
If Not e.Exists Then e = EDP.ThrowException
|
||||
Return ErrorsDescriber.Execute(e, ex, "[ImageRenderer2.GetTrueFormat()]")
|
||||
End Try
|
||||
End Function
|
||||
End Class
|
||||
Friend Sub New(ByVal Media As UserMediaD, ByVal Width As Integer, ByVal Height As Integer, ByVal IsSession As Boolean, ByVal ExtractText As Boolean)
|
||||
Try
|
||||
InitializeComponent()
|
||||
@@ -211,7 +238,7 @@ Namespace DownloadObjects
|
||||
End With
|
||||
If Not imgFile.Exists Then
|
||||
Settings.Cache.Validate()
|
||||
If GetWebFile(Media.Data.URL, imgFile, EDP.None) AndAlso imgFile.Exists Then File = ConvertWebp(imgFile)
|
||||
If GetWebFile(Media.Data.URL, imgFile, EDP.None) AndAlso imgFile.Exists Then File = UserImage.ConvertWebp(imgFile, Nothing)
|
||||
Else
|
||||
File = imgFile
|
||||
End If
|
||||
@@ -260,10 +287,17 @@ Namespace DownloadObjects
|
||||
End If
|
||||
End If
|
||||
End If
|
||||
tmpMediaFile = ConvertWebp(tmpMediaFile, True)
|
||||
Dim webpConverted As Boolean = False
|
||||
Dim isWebp As Boolean = False
|
||||
tmpMediaFile = UserImage.ConvertWebp(tmpMediaFile, Nothing,,, webpConverted)
|
||||
If tmpMediaFile.IsEmptyString Then Throw New ArgumentNullException With {.HelpLink = 1}
|
||||
Try
|
||||
MyImage = New ImageRenderer(tmpMediaFile, EDP.ThrowException)
|
||||
For kConv As Byte = 0 To 1
|
||||
If kConv = 1 Then tmpMediaFile = UserImage.ConvertWebp(tmpMediaFile, Nothing, True, isWebp, webpConverted)
|
||||
If Not tmpMediaFile.IsEmptyString Then MyImage = ConvertOptional(tmpMediaFile, kConv = 1 Or webpConverted, isWebp)
|
||||
If Not MyImage Is Nothing Then Exit For
|
||||
Next
|
||||
If MyImage Is Nothing Then Throw New Exception
|
||||
Catch
|
||||
MyImage.DisposeIfReady
|
||||
MyImage = New ImageRenderer(New Bitmap(10, 10))
|
||||
|
||||
@@ -245,7 +245,7 @@ Namespace DownloadObjects.Groups
|
||||
If Not Settings.Automation Is Nothing AndAlso Settings.Automation.Count > 0 Then
|
||||
Dim aIncl As New List(Of String)
|
||||
For Each plan As AutoDownloader In Settings.Automation
|
||||
If plan.Mode = AutoDownloader.Modes.Groups AndAlso plan.Groups.Count > 0 AndAlso plan.Groups.Contains(Name) Then aIncl.Add(plan.Name)
|
||||
If plan.Groups.Count > 0 AndAlso plan.Groups.Contains(Name) Then aIncl.Add(plan.Name)
|
||||
Next
|
||||
If aIncl.Count > 0 Then
|
||||
MsgBoxE({$"The '{Name}' group cannot be deleted because it is included in the following scheduler plans:{vbCr}{vbCr}" &
|
||||
@@ -285,6 +285,7 @@ Namespace DownloadObjects.Groups
|
||||
Try
|
||||
If Settings.Users.Count > 0 Then
|
||||
With Instance
|
||||
If TypeOf .Self Is AutoDownloader AndAlso Not DirectCast(.Self, AutoDownloader).Enabled Then Return Nothing
|
||||
Dim downDate As Date? = Nothing
|
||||
If .DaysNumber > 0 Then
|
||||
With Now.AddDays(- .DaysNumber) : downDate = New Date(.Year, .Month, .Day, 0, 0, 0) : End With
|
||||
@@ -363,10 +364,32 @@ Namespace DownloadObjects.Groups
|
||||
Dim CheckSites As Predicate(Of IUserData) = Function(user) _
|
||||
(.Sites.Count = 0 OrElse .Sites.Contains(user.Site)) AndAlso
|
||||
(.SitesExcluded.Count = 0 OrElse Not .SitesExcluded.Contains(user.Site))
|
||||
Dim users As IEnumerable(Of IUserData) =
|
||||
Settings.GetUsers(Function(user) CheckLabels.Invoke(user) AndAlso CheckSites.Invoke(user) AndAlso
|
||||
CheckParams.Invoke(user) AndAlso CheckSubscription.Invoke(user) AndAlso
|
||||
CheckDays.Invoke(user) AndAlso CheckDateRange.Invoke(user))
|
||||
Dim users As New List(Of IUserData)
|
||||
Dim l As New ListAddParams(LAP.IgnoreICopier)
|
||||
If Not .GroupsOnly Or (.GroupsOnly And .Groups.Count = 0) Then
|
||||
users.ListAddList(Settings.GetUsers(Function(user) CheckLabels.Invoke(user) AndAlso CheckSites.Invoke(user) AndAlso
|
||||
CheckParams.Invoke(user) AndAlso CheckSubscription.Invoke(user) AndAlso
|
||||
CheckDays.Invoke(user) AndAlso CheckDateRange.Invoke(user)), l)
|
||||
End If
|
||||
If Settings.Groups.Count > 0 Then
|
||||
Dim i%
|
||||
Dim groupName$
|
||||
l.NotContainsOnly = True
|
||||
If .Groups.Count > 0 Then
|
||||
For Each groupName In .Groups
|
||||
i = Settings.Groups.IndexOf(groupName)
|
||||
If i >= 0 Then users.ListAddList(Settings.Groups(i).GetUsers, l)
|
||||
Next
|
||||
End If
|
||||
l.DisableDispose = True
|
||||
If .GroupsExcluded.Count > 0 Then
|
||||
For Each groupName In .GroupsExcluded
|
||||
i = Settings.Groups.IndexOf(groupName)
|
||||
If i >= 0 Then users.ListDisposeRemove(Settings.Groups(i).GetUsers, l)
|
||||
Next
|
||||
End If
|
||||
End If
|
||||
|
||||
If .UsersCount <> 0 And users.ListExists Then
|
||||
users = users.ListTake(If(.UsersCount > 0, -1, -2), Math.Abs(.UsersCount))
|
||||
If .UsersCount < 0 Then users = users.ListReverse
|
||||
|
||||
@@ -10,10 +10,11 @@ Imports PersonalUtilities.Forms
|
||||
Imports PersonalUtilities.Forms.Controls
|
||||
Imports PersonalUtilities.Forms.Controls.Base
|
||||
Imports ADB = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons
|
||||
Imports CaptionModes = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes
|
||||
Namespace DownloadObjects.Groups
|
||||
Public Class GroupDefaults : Inherits TableLayoutPanel
|
||||
#Region "Constants"
|
||||
Friend Const CaptionWidthDefault As Integer = 55
|
||||
Friend Const CaptionWidthDefault As Integer = 60 '55
|
||||
#End Region
|
||||
#Region "Declarations"
|
||||
Private ReadOnly TP_1 As TableLayoutPanel 'CH_REGULAR, CH_TEMPORARY, CH_FAV
|
||||
@@ -49,13 +50,21 @@ Namespace DownloadObjects.Groups
|
||||
|
||||
Private WithEvents TXT_LABELS As TextBoxExtended
|
||||
Private WithEvents TXT_SITES As TextBoxExtended
|
||||
Private WithEvents TXT_GROUPS As TextBoxExtended
|
||||
Friend WithEvents TXT_NAME As TextBoxExtended
|
||||
|
||||
Private ReadOnly Labels As List(Of String)
|
||||
Private ReadOnly LabelsExcluded As List(Of String)
|
||||
Private ReadOnly Sites As List(Of String)
|
||||
Private ReadOnly SitesExcluded As List(Of String)
|
||||
Private ReadOnly Groups As List(Of String)
|
||||
Private ReadOnly GroupsExcluded As List(Of String)
|
||||
Private ReadOnly TT_MAIN As ToolTip
|
||||
Friend ReadOnly Property GroupsOnly As Boolean
|
||||
Get
|
||||
Return TXT_GROUPS.Checked
|
||||
End Get
|
||||
End Property
|
||||
#End Region
|
||||
#Region "Initializer"
|
||||
Public Sub New()
|
||||
@@ -63,6 +72,8 @@ Namespace DownloadObjects.Groups
|
||||
LabelsExcluded = New List(Of String)
|
||||
Sites = New List(Of String)
|
||||
SitesExcluded = New List(Of String)
|
||||
Groups = New List(Of String)
|
||||
GroupsExcluded = New List(Of String)
|
||||
TT_MAIN = New ToolTip
|
||||
|
||||
InitTextBox(TXT_LABELS, "Labels", {New ActionButton(ADB.Edit) With {.ToolTipText = "Edit selected labels"},
|
||||
@@ -73,6 +84,17 @@ Namespace DownloadObjects.Groups
|
||||
New ActionButton(ADB.Delete) With {.ToolTipText = "Edit excluded sites"}, ADB.Clear})
|
||||
TXT_SITES.TextBoxReadOnly = True
|
||||
|
||||
InitTextBox(TXT_GROUPS, "Groups", {New ActionButton(ADB.Edit) With {.ToolTipText = "Edit selected groups"},
|
||||
New ActionButton(ADB.Delete) With {.ToolTipText = "Edit excluded groups"}, ADB.Clear}, CaptionModes.CheckBox)
|
||||
With TXT_GROUPS
|
||||
.TextBoxReadOnly = True
|
||||
.CaptionCheckAlign = ContentAlignment.MiddleLeft
|
||||
.ChangeControlsEnableOnCheckedChange = False
|
||||
.CaptionToolTipText = "If checked, only the selected groups will be downloaded. All other options will be ignored."
|
||||
.CaptionToolTipEnabled = True
|
||||
.EndInit()
|
||||
End With
|
||||
|
||||
InitTextBox(TXT_NAME, "Name", {ADB.Clear})
|
||||
|
||||
CH_REGULAR = New CheckBox With {.Text = "Regular", .Name = "CH_REGULAR", .Checked = True, .Dock = DockStyle.Fill}
|
||||
@@ -209,12 +231,14 @@ Namespace DownloadObjects.Groups
|
||||
.EndInit()
|
||||
End With
|
||||
End Sub
|
||||
Private Sub InitTextBox(ByRef TXT As TextBoxExtended, ByVal Caption As String, ByVal Buttons As ActionButton())
|
||||
Private Sub InitTextBox(ByRef TXT As TextBoxExtended, ByVal Caption As String, ByVal Buttons As ActionButton(),
|
||||
Optional ByVal CaptionMode As CaptionModes = CaptionModes.Label)
|
||||
TXT = New TextBoxExtended
|
||||
With TXT
|
||||
.BeginInit()
|
||||
.Buttons.AddRange(Buttons)
|
||||
.CaptionText = Caption
|
||||
.CaptionMode = CaptionMode
|
||||
.CaptionWidth = CaptionWidthDefault
|
||||
.Dock = DockStyle.Fill
|
||||
.EndInit()
|
||||
@@ -240,7 +264,7 @@ Namespace DownloadObjects.Groups
|
||||
CellBorderStyle = TableLayoutPanelCellBorderStyle.Single
|
||||
ColumnCount = 1
|
||||
ColumnStyles.Add(New ColumnStyle(SizeType.Percent, 100))
|
||||
RowCount = 13
|
||||
RowCount = 14
|
||||
RowStyles.Add(New RowStyle(SizeType.Absolute, 25))
|
||||
RowStyles.Add(New RowStyle(SizeType.Absolute, 28))
|
||||
RowStyles.Add(New RowStyle(SizeType.Absolute, 25))
|
||||
@@ -253,6 +277,7 @@ Namespace DownloadObjects.Groups
|
||||
RowStyles.Add(New RowStyle(SizeType.Absolute, 25))
|
||||
RowStyles.Add(New RowStyle(SizeType.Absolute, 28))
|
||||
RowStyles.Add(New RowStyle(SizeType.Absolute, 28))
|
||||
RowStyles.Add(New RowStyle(SizeType.Absolute, 28))
|
||||
RowStyles.Add(New RowStyle(SizeType.Percent, 100))
|
||||
End If
|
||||
Controls.Add(TXT_NAME, 0, 1)
|
||||
@@ -269,6 +294,7 @@ Namespace DownloadObjects.Groups
|
||||
|
||||
Controls.Add(TXT_LABELS, 0, 10)
|
||||
Controls.Add(TXT_SITES, 0, 11)
|
||||
Controls.Add(TXT_GROUPS, 0, 12)
|
||||
End Sub
|
||||
#End Region
|
||||
#Region "Control handlers"
|
||||
@@ -277,6 +303,8 @@ Namespace DownloadObjects.Groups
|
||||
LabelsExcluded.Clear()
|
||||
Sites.Clear()
|
||||
SitesExcluded.Clear()
|
||||
Groups.Clear()
|
||||
GroupsExcluded.Clear()
|
||||
CH_REGULAR.Dispose()
|
||||
CH_TEMPORARY.Dispose()
|
||||
CH_FAV.Dispose()
|
||||
@@ -296,6 +324,7 @@ Namespace DownloadObjects.Groups
|
||||
NUM_DAYS.Dispose()
|
||||
TXT_LABELS.Dispose()
|
||||
TXT_SITES.Dispose()
|
||||
TXT_GROUPS.Dispose()
|
||||
TXT_NAME.Dispose()
|
||||
TT_MAIN.Dispose()
|
||||
ClearTP(TP_1)
|
||||
@@ -338,7 +367,7 @@ Namespace DownloadObjects.Groups
|
||||
End If
|
||||
End Using
|
||||
End With
|
||||
Case ADB.Clear : Labels.Clear() : LabelsExcluded.Clear() : TXT_LABELS.Clear() : UpdateLabelsText()
|
||||
Case ADB.Clear : Labels.Clear() : LabelsExcluded.Clear() : UpdateLabelsText()
|
||||
End Select
|
||||
End Sub
|
||||
Private Sub TXT_SITES_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As ActionButtonEventArgs) Handles TXT_SITES.ActionOnButtonClick
|
||||
@@ -354,18 +383,38 @@ Namespace DownloadObjects.Groups
|
||||
End If
|
||||
End Using
|
||||
End With
|
||||
Case ADB.Clear : Sites.Clear() : SitesExcluded.Clear() : TXT_SITES.Clear() : UpdateSitesText()
|
||||
Case ADB.Clear : Sites.Clear() : SitesExcluded.Clear() : UpdateSitesText()
|
||||
End Select
|
||||
End Sub
|
||||
Private Sub TXT_GROUPS_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As ActionButtonEventArgs) Handles TXT_GROUPS.ActionOnButtonClick
|
||||
Select Case Sender.DefaultButton
|
||||
Case ADB.Edit, ADB.Delete
|
||||
With If(Sender.DefaultButton = ADB.Edit, Groups, GroupsExcluded)
|
||||
Using f As New LabelsForm(.Self, (From g As DownloadGroup In Settings.Groups Where Not g.IsViewFilter Select g.Name)) With {
|
||||
.Text = $"Groups {IIf(Sender.DefaultButton = ADB.Delete, "excluded ", String.Empty)}(F3 to edit)",
|
||||
.Icon = My.Resources.GroupByIcon_16,
|
||||
.IsGroups = True
|
||||
}
|
||||
f.ShowDialog()
|
||||
If f.DialogResult = DialogResult.OK Then .ListAddList(f.LabelsList, LAP.ClearBeforeAdd) : UpdateGroupsText()
|
||||
End Using
|
||||
End With
|
||||
Case ADB.Clear : Groups.Clear() : GroupsExcluded.Clear() : UpdateGroupsText()
|
||||
End Select
|
||||
End Sub
|
||||
Private Sub UpdateLabelsText()
|
||||
TXT_LABELS.Clear()
|
||||
If Not _JustExcludeOptions Then TXT_LABELS.Text = Labels.ListToString
|
||||
If LabelsExcluded.Count > 0 Then TXT_LABELS.Text.StringAppend($"EXCLUDED: {LabelsExcluded.ListToString}", "; ")
|
||||
__UpdateTextImpl(TXT_LABELS, Labels, LabelsExcluded)
|
||||
End Sub
|
||||
Private Sub UpdateSitesText()
|
||||
TXT_SITES.Clear()
|
||||
If Not _JustExcludeOptions Then TXT_SITES.Text = Sites.ListToString
|
||||
If SitesExcluded.Count > 0 Then TXT_SITES.Text.StringAppend($"EXCLUDED: {SitesExcluded.ListToString}", "; ")
|
||||
__UpdateTextImpl(TXT_SITES, Sites, SitesExcluded)
|
||||
End Sub
|
||||
Private Sub UpdateGroupsText()
|
||||
__UpdateTextImpl(TXT_GROUPS, Groups, GroupsExcluded)
|
||||
End Sub
|
||||
Private Sub __UpdateTextImpl(ByRef txt As TextBoxExtended, ByVal filter As List(Of String), ByVal excluded As List(Of String))
|
||||
txt.Clear()
|
||||
txt.Text = filter.ListToString
|
||||
If excluded.Count > 0 Then txt.Text.StringAppend($"EXCLUDED: {excluded.ListToString}", "; ")
|
||||
End Sub
|
||||
#End Region
|
||||
#Region "Get/set"
|
||||
@@ -410,6 +459,10 @@ Namespace DownloadObjects.Groups
|
||||
.Sites.ListAddList(Sites)
|
||||
.SitesExcluded.Clear()
|
||||
.SitesExcluded.ListAddList(SitesExcluded)
|
||||
.Groups.Clear()
|
||||
.Groups.ListAddList(Groups)
|
||||
.GroupsExcluded.ListAddList(GroupsExcluded)
|
||||
.GroupsOnly = GroupsOnly
|
||||
End With
|
||||
End If
|
||||
End Sub
|
||||
@@ -457,20 +510,23 @@ Namespace DownloadObjects.Groups
|
||||
Sites.ListAddList(.Sites)
|
||||
SitesExcluded.ListAddList(.SitesExcluded)
|
||||
UpdateSitesText()
|
||||
|
||||
Groups.ListAddList(.Groups)
|
||||
GroupsExcluded.ListAddList(.GroupsExcluded)
|
||||
TXT_GROUPS.Checked = .GroupsOnly
|
||||
UpdateGroupsText()
|
||||
End With
|
||||
End If
|
||||
End Sub
|
||||
#End Region
|
||||
#Region "Enabled"
|
||||
Private _Enabled As Boolean = True
|
||||
Private _JustExcludeOptions As Boolean = False
|
||||
Friend Overloads Property Enabled() As Boolean
|
||||
Get
|
||||
Return _Enabled
|
||||
End Get
|
||||
Set(ByVal e As Boolean)
|
||||
_Enabled = e
|
||||
_JustExcludeOptions = False
|
||||
TP_1.Enabled = e
|
||||
TP_2.Enabled = e
|
||||
TP_3.Enabled = e
|
||||
@@ -481,8 +537,26 @@ Namespace DownloadObjects.Groups
|
||||
NUM_DAYS.Enabled = e
|
||||
TXT_LABELS.Enabled = e
|
||||
TXT_SITES.Enabled = e
|
||||
TXT_GROUPS.Enabled = e
|
||||
UpdateLabelsText()
|
||||
UpdateSitesText()
|
||||
UpdateGroupsText()
|
||||
End Set
|
||||
End Property
|
||||
Friend Property GroupsEnabled As Boolean
|
||||
Get
|
||||
Return TXT_GROUPS.Enabled
|
||||
End Get
|
||||
Set(ByVal e As Boolean)
|
||||
TXT_GROUPS.Enabled = e
|
||||
End Set
|
||||
End Property
|
||||
Friend Property LabelsEnabled As Boolean
|
||||
Get
|
||||
Return TXT_LABELS.Enabled
|
||||
End Get
|
||||
Set(ByVal e As Boolean)
|
||||
TXT_LABELS.Enabled = e
|
||||
End Set
|
||||
End Property
|
||||
#End Region
|
||||
|
||||
15
SCrawler/Download/Groups/GroupEditorForm.Designer.vb
generated
@@ -35,13 +35,13 @@ Namespace DownloadObjects.Groups
|
||||
'CONTAINER_MAIN.ContentPanel
|
||||
'
|
||||
CONTAINER_MAIN.ContentPanel.Controls.Add(Me.DEFS_GROUP)
|
||||
CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(476, 328)
|
||||
CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(476, 331)
|
||||
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(476, 328)
|
||||
CONTAINER_MAIN.Size = New System.Drawing.Size(476, 356)
|
||||
CONTAINER_MAIN.TabIndex = 0
|
||||
CONTAINER_MAIN.TopToolStripPanelVisible = False
|
||||
'
|
||||
@@ -53,7 +53,7 @@ Namespace DownloadObjects.Groups
|
||||
Me.DEFS_GROUP.Dock = System.Windows.Forms.DockStyle.Fill
|
||||
Me.DEFS_GROUP.Location = New System.Drawing.Point(0, 0)
|
||||
Me.DEFS_GROUP.Name = "DEFS_GROUP"
|
||||
Me.DEFS_GROUP.RowCount = 13
|
||||
Me.DEFS_GROUP.RowCount = 14
|
||||
Me.DEFS_GROUP.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 0!))
|
||||
Me.DEFS_GROUP.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
|
||||
Me.DEFS_GROUP.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
|
||||
@@ -66,23 +66,24 @@ Namespace DownloadObjects.Groups
|
||||
Me.DEFS_GROUP.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
|
||||
Me.DEFS_GROUP.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
|
||||
Me.DEFS_GROUP.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
|
||||
Me.DEFS_GROUP.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
|
||||
Me.DEFS_GROUP.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||
Me.DEFS_GROUP.Size = New System.Drawing.Size(476, 328)
|
||||
Me.DEFS_GROUP.Size = New System.Drawing.Size(476, 331)
|
||||
Me.DEFS_GROUP.TabIndex = 0
|
||||
'
|
||||
'GroupEditorForm
|
||||
'
|
||||
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
|
||||
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
|
||||
Me.ClientSize = New System.Drawing.Size(476, 328)
|
||||
Me.ClientSize = New System.Drawing.Size(476, 356)
|
||||
Me.Controls.Add(CONTAINER_MAIN)
|
||||
Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle
|
||||
Me.Icon = Global.SCrawler.My.Resources.Resources.GroupByIcon_16
|
||||
Me.KeyPreview = True
|
||||
Me.MaximizeBox = False
|
||||
Me.MaximumSize = New System.Drawing.Size(492, 367)
|
||||
Me.MaximumSize = New System.Drawing.Size(492, 395)
|
||||
Me.MinimizeBox = False
|
||||
Me.MinimumSize = New System.Drawing.Size(492, 367)
|
||||
Me.MinimumSize = New System.Drawing.Size(492, 395)
|
||||
Me.Name = "GroupEditorForm"
|
||||
Me.ShowInTaskbar = False
|
||||
Me.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide
|
||||
|
||||
@@ -78,6 +78,8 @@ Namespace DownloadObjects.Groups
|
||||
.MyFieldsChecker.EndLoaderOperations()
|
||||
.EndLoaderOperations()
|
||||
.MyOkCancel.EnableOK = True
|
||||
If Settings.Labels.Count = 0 Then DEFS_GROUP.LabelsEnabled = False
|
||||
If Settings.Groups.Count = 0 Then DEFS_GROUP.GroupsEnabled = False
|
||||
End With
|
||||
End Sub
|
||||
Private Sub GroupEditorForm_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
|
||||
|
||||
@@ -311,28 +311,15 @@ Namespace DownloadObjects.Groups
|
||||
Dim users As New List(Of API.Base.IUserData)
|
||||
If Not IsViewFilter Then
|
||||
i = Settings.Groups.IndexOf(MyGroups(_LatestSelected))
|
||||
If i >= 0 Then users.ListAddList(DownloadGroup.GetUsers(Settings.Groups(i))) : n = $"F {Settings.Groups(i).Name}"
|
||||
If i >= 0 Then users.ListAddList(DownloadGroup.GetUsers(Settings.Groups(i)), LAP.IgnoreICopier) : n = $"F {Settings.Groups(i).Name}"
|
||||
ElseIf _LatestSelected.ValueBetween(0, MyGroupParams.Count - 1) Then
|
||||
With MyGroupParams(_LatestSelected)
|
||||
users.ListAddList(DownloadGroup.GetUsers(.Self), LAP.IgnoreICopier)
|
||||
n = .Name
|
||||
If TypeOf .Self Is AutoDownloader Then
|
||||
With DirectCast(.Self, AutoDownloader)
|
||||
If Not .Mode = AutoDownloader.Modes.None Then
|
||||
If .Mode = AutoDownloader.Modes.Groups Then
|
||||
If .Groups.Count > 0 Then
|
||||
For Each groupName$ In .Groups
|
||||
i = Settings.Groups.IndexOf(groupName)
|
||||
If i >= 0 Then users.ListAddList(DownloadGroup.GetUsers(Settings.Groups(i)), LAP.NotContainsOnly, LAP.IgnoreICopier)
|
||||
Next
|
||||
End If
|
||||
Else
|
||||
users.ListAddList(DownloadGroup.GetUsers(.Self))
|
||||
End If
|
||||
End If
|
||||
n = $"S { .Name}"
|
||||
End With
|
||||
n = $"S {n}"
|
||||
ElseIf TypeOf .Self Is DownloadGroup Then
|
||||
i = Settings.Groups.IndexOf(.Name, .IsViewFilter)
|
||||
If i >= 0 Then users.ListAddList(DownloadGroup.GetUsers(Settings.Groups(i))) : n = $"G {Settings.Groups(i).Name}"
|
||||
n = $"G {n}"
|
||||
End If
|
||||
End With
|
||||
End If
|
||||
|
||||
@@ -16,6 +16,9 @@ Namespace DownloadObjects.Groups
|
||||
Property LabelsExcludedIgnore As Boolean
|
||||
ReadOnly Property Sites As List(Of String)
|
||||
ReadOnly Property SitesExcluded As List(Of String)
|
||||
ReadOnly Property Groups As List(Of String)
|
||||
ReadOnly Property GroupsExcluded As List(Of String)
|
||||
Property GroupsOnly As Boolean
|
||||
Property Regular As Boolean
|
||||
Property Temporary As Boolean
|
||||
Property Favorite As Boolean
|
||||
@@ -56,6 +59,9 @@ Namespace DownloadObjects.Groups
|
||||
Protected Const Name_LabelsExcludedIgnore As String = "LabelsExcludedIgnore"
|
||||
Protected Const Name_Sites As String = "Sites"
|
||||
Protected Const Name_Sites_Excluded As String = "SitesExcluded"
|
||||
Protected Const Name_Groups As String = "Groups"
|
||||
Protected Const Name_GroupsExcluded As String = "GroupsExcluded"
|
||||
Protected Const Name_GroupsOnly As String = "GroupsOnly"
|
||||
Protected Const Name_DaysNumber As String = "DaysNumber"
|
||||
Protected Const Name_DaysIsDownloaded As String = "DaysIsDownloaded"
|
||||
Protected Const Name_UserDeleted As String = "UserDeleted"
|
||||
@@ -74,6 +80,9 @@ Namespace DownloadObjects.Groups
|
||||
Friend Property LabelsExcludedIgnore As Boolean = False Implements IGroup.LabelsExcludedIgnore
|
||||
Friend ReadOnly Property Sites As List(Of String) Implements IGroup.Sites
|
||||
Friend ReadOnly Property SitesExcluded As List(Of String) Implements IGroup.SitesExcluded
|
||||
Friend ReadOnly Property Groups As List(Of String) Implements IGroup.Groups
|
||||
Friend ReadOnly Property GroupsExcluded As List(Of String) Implements IGroup.GroupsExcluded
|
||||
Friend Property GroupsOnly As Boolean = False Implements IGroup.GroupsOnly
|
||||
Friend Property Regular As Boolean = True Implements IGroup.Regular
|
||||
Friend Property Temporary As Boolean = True Implements IGroup.Temporary
|
||||
Friend Property Favorite As Boolean = True Implements IGroup.Favorite
|
||||
@@ -98,6 +107,8 @@ Namespace DownloadObjects.Groups
|
||||
LabelsExcluded = New List(Of String)
|
||||
Sites = New List(Of String)
|
||||
SitesExcluded = New List(Of String)
|
||||
Groups = New List(Of String)
|
||||
GroupsExcluded = New List(Of String)
|
||||
End Sub
|
||||
#End Region
|
||||
#Region "Base functions"
|
||||
@@ -121,6 +132,9 @@ Namespace DownloadObjects.Groups
|
||||
LabelsExcludedIgnore = .LabelsExcludedIgnore
|
||||
Sites.ListAddList(.Sites, LAP.ClearBeforeAdd)
|
||||
SitesExcluded.ListAddList(.SitesExcluded, LAP.ClearBeforeAdd)
|
||||
Groups.ListAddList(.Groups, LAP.ClearBeforeAdd)
|
||||
GroupsExcluded.ListAddList(.GroupsExcluded, LAP.ClearBeforeAdd)
|
||||
GroupsOnly = .GroupsOnly
|
||||
Regular = .Regular
|
||||
Temporary = .Temporary
|
||||
Favorite = .Favorite
|
||||
@@ -153,6 +167,9 @@ Namespace DownloadObjects.Groups
|
||||
LabelsExcludedIgnore = e.Value(Name_LabelsExcludedIgnore).FromXML(Of Boolean)(False)
|
||||
If Not e.Value(Name_Sites).IsEmptyString Then Sites.ListAddList(e.Value(Name_Sites).Split("|"), l)
|
||||
If Not e.Value(Name_Sites_Excluded).IsEmptyString Then SitesExcluded.ListAddList(e.Value(Name_Sites_Excluded).Split("|"), l)
|
||||
If Not e.Value(Name_Groups).IsEmptyString Then Groups.ListAddList(e.Value(Name_Groups).Split("|"), l)
|
||||
If Not e.Value(Name_GroupsExcluded).IsEmptyString Then GroupsExcluded.ListAddList(e.Value(Name_GroupsExcluded).Split("|"), l)
|
||||
GroupsOnly = e.Value(Name_GroupsOnly).FromXML(Of Boolean)(False)
|
||||
|
||||
Regular = e.Value(Name_Regular).FromXML(Of Boolean)(True)
|
||||
Temporary = e.Value(Name_Temporary).FromXML(Of Boolean)(True)
|
||||
@@ -190,6 +207,9 @@ Namespace DownloadObjects.Groups
|
||||
New EContainer(Name_LabelsExcludedIgnore, LabelsExcludedIgnore.BoolToInteger),
|
||||
New EContainer(Name_Sites, Sites.ListToString("|")),
|
||||
New EContainer(Name_Sites_Excluded, SitesExcluded.ListToString("|")),
|
||||
New EContainer(Name_Groups, Groups.ListToString("|")),
|
||||
New EContainer(Name_GroupsExcluded, GroupsExcluded.ListToString("|")),
|
||||
New EContainer(Name_GroupsOnly, GroupsOnly.BoolToInteger),
|
||||
New EContainer(Name_Regular, Regular.BoolToInteger),
|
||||
New EContainer(Name_Temporary, Temporary.BoolToInteger),
|
||||
New EContainer(Name_Favorite, Favorite.BoolToInteger),
|
||||
@@ -219,6 +239,8 @@ Namespace DownloadObjects.Groups
|
||||
LabelsExcluded.Clear()
|
||||
Sites.Clear()
|
||||
SitesExcluded.Clear()
|
||||
Groups.Clear()
|
||||
GroupsExcluded.Clear()
|
||||
End If
|
||||
disposedValue = True
|
||||
End If
|
||||
|
||||
@@ -187,24 +187,24 @@ Namespace Editors
|
||||
Private Sub MyDefs_ButtonOkClick(ByVal Sender As Object, ByVal e As KeyHandleEventArgs) Handles MyDefs.ButtonOkClick
|
||||
If MyDefs.MyFieldsChecker.AllParamsOK Then
|
||||
With Settings
|
||||
Dim a As Func(Of String, Object, Integer) =
|
||||
Function(t, v) MsgBoxE({$"You are set up higher than default count of along {t} downloading tasks." & vbNewLine &
|
||||
$"Default: {SettingsCLS.DefaultMaxDownloadingTasks}" & vbNewLine &
|
||||
$"Your value: {CInt(v)}" & vbNewLine &
|
||||
"Increasing this value may lead to higher CPU usage." & vbNewLine &
|
||||
"Do you really want to continue?",
|
||||
"Increasing download tasks"},
|
||||
vbExclamation,,, {"Confirm", $"Set to default ({SettingsCLS.DefaultMaxDownloadingTasks})", "Cancel"})
|
||||
Dim a As Func(Of String, Integer, Object, Integer) =
|
||||
Function(t, vc, v) MsgBoxE({$"You are set up higher than default count of along {t} downloading tasks." & vbNewLine &
|
||||
$"Default: {vc}" & vbNewLine &
|
||||
$"Your value: {CInt(v)}" & vbNewLine &
|
||||
"Increasing this value may lead to higher CPU usage." & vbNewLine &
|
||||
"Do you really want to continue?",
|
||||
"Increasing download tasks"},
|
||||
vbExclamation,,, {"Confirm", $"Set to default ({vc})", "Cancel"})
|
||||
|
||||
If CInt(TXT_MAX_JOBS_USERS.Value) > SettingsCLS.DefaultMaxDownloadingTasks Then
|
||||
Select Case a.Invoke("users", TXT_MAX_JOBS_USERS.Value)
|
||||
Select Case a.Invoke("users", SettingsCLS.DefaultMaxDownloadingTasks, TXT_MAX_JOBS_USERS.Value)
|
||||
Case 1 : TXT_MAX_JOBS_USERS.Value = SettingsCLS.DefaultMaxDownloadingTasks
|
||||
Case 2 : Exit Sub
|
||||
End Select
|
||||
End If
|
||||
If CInt(TXT_MAX_JOBS_CHANNELS.Value) > SettingsCLS.DefaultMaxDownloadingTasks Then
|
||||
Select Case a.Invoke("channels", TXT_MAX_JOBS_CHANNELS.Value)
|
||||
Case 1 : TXT_MAX_JOBS_CHANNELS.Value = SettingsCLS.DefaultMaxDownloadingTasks
|
||||
If CInt(TXT_MAX_JOBS_CHANNELS.Value) > SettingsCLS.DefaultMaxDownloadingTasks_Channels Then
|
||||
Select Case a.Invoke("channels", SettingsCLS.DefaultMaxDownloadingTasks_Channels, TXT_MAX_JOBS_CHANNELS.Value)
|
||||
Case 1 : TXT_MAX_JOBS_CHANNELS.Value = SettingsCLS.DefaultMaxDownloadingTasks_Channels
|
||||
Case 2 : Exit Sub
|
||||
End Select
|
||||
End If
|
||||
@@ -407,7 +407,7 @@ Namespace Editors
|
||||
If Sender.DefaultButton = ADB.Refresh Then TXT_MAX_JOBS_USERS.Value = SettingsCLS.DefaultMaxDownloadingTasks
|
||||
End Sub
|
||||
Private Sub TXT_MAX_JOBS_CHANNELS_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As EventArgs) Handles TXT_MAX_JOBS_CHANNELS.ActionOnButtonClick
|
||||
If Sender.DefaultButton = ADB.Refresh Then TXT_MAX_JOBS_CHANNELS.Value = SettingsCLS.DefaultMaxDownloadingTasks
|
||||
If Sender.DefaultButton = ADB.Refresh Then TXT_MAX_JOBS_CHANNELS.Value = SettingsCLS.DefaultMaxDownloadingTasks_Channels
|
||||
End Sub
|
||||
Private Sub ChangePositionControlsEnabling() Handles OPT_FILE_NAME_REPLACE.CheckedChanged, OPT_FILE_NAME_ADD_DATE.CheckedChanged
|
||||
Dim b As Boolean = OPT_FILE_NAME_ADD_DATE.Checked And OPT_FILE_NAME_ADD_DATE.Enabled
|
||||
|
||||
2
SCrawler/MainFrame.Designer.vb
generated
@@ -368,7 +368,7 @@ Partial Public Class MainFrame : Inherits System.Windows.Forms.Form
|
||||
Me.BTT_FEED.Name = "BTT_FEED"
|
||||
Me.BTT_FEED.Size = New System.Drawing.Size(52, 22)
|
||||
Me.BTT_FEED.Text = "Feed"
|
||||
Me.BTT_FEED.ToolTipText = "Feed of recently downloaded data (Ctrl+F)"
|
||||
Me.BTT_FEED.ToolTipText = "Feed of recently downloaded data (Alt+F)"
|
||||
'
|
||||
'BTT_CHANNELS
|
||||
'
|
||||
|
||||
@@ -184,36 +184,37 @@
|
||||
<data name="MENU_VIEW.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
|
||||
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAABkSURBVDhPY6AKyO86WFDQfeg/iIYKkQZAmkNbnvyXta76
|
||||
DxViYGFi+Y8PQ5VBAMhmkGYgJs8FAw9GA5EKILFiWUFixfL/IBoqRBoAafYsOvpf0jiTvEAE2QzSLGmU
|
||||
MeQCkYEBAD3tUdo+/cEPAAAAAElFTkSuQmCC
|
||||
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAABkSURBVDhPY2CgBsjvOlhQ0H3oP4hGlyMKgDSHtjz5L2td
|
||||
9R8mxsLE8h8fRjEAZDNIs6x1FXkuGHgwGohUAIkVywoSK5b/B9HockQBkGbPoqP/JY0zyQtEkM0gzZJG
|
||||
GeS5YEABAD3tUdqXHMg6AAAAAElFTkSuQmCC
|
||||
</value>
|
||||
</data>
|
||||
<data name="BTT_LOG.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
|
||||
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAFmSURBVFhH1dc/K4VhHMbxJ5EFEQbFiERKCotIrMJIiYEi
|
||||
pbwCZcOqJC9AikUWiqRkJYtSRDbESMT3V07dna7zHHru+9T51me+Ts//E+V7LRjFFAZRiZzUhDVc4/vX
|
||||
B47Rh6D14Aqp4XQ36ECQ2nALNezaQjG8Vo5DqMF0bxiA1+bwCTWoLMFbNTiDGsrkABXw0jDsKldDmdyj
|
||||
HokrwCrUSBz7wXbRJs4eLkdQI9m0I3ENeIAaiGN3QjMSZ4fxv+ffnKIKibOnmhqI84V5eMleOHY41VAm
|
||||
9k7wdgtW4wRqSHlCP7y2AjWmbMB7Y7DzqgZdz2iF9zrxCDXq2oU9uLz31+tgAcHahhp1DSFY9pGhRl29
|
||||
CFYXxrMoQ7BmsZfFPkoRpHWow+56hX26BWkRatR1gRIEaQLvUMMpOyhCkBpxBzWcMoOgLUMNm0vUIWj2
|
||||
ebaJF7jj5+hGTiqE/f+bxDRGUIt8LIp+AC/GHt3tQnwvAAAAAElFTkSuQmCC
|
||||
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGTSURBVFhH1ZfPK21RGIaf5GaCCAPF0JVISWEiElNhSIkB
|
||||
RUr5C5QZpkryB0gxkQlFUjKlO1HKjcwQQyJatdXp7TtnH3t/Z+CpZ7be7z3tH2uvA7+cFmAUmAIGgSpd
|
||||
UCiagDXgCviMfAOOgT5d7E0P8C+jWL0GOjTkRRtwY5SqW0CJhtNSARwaZZYvwIAOSMsc8G6UZXNJB6Sh
|
||||
FjgzSnJ5AFTqoKQMR0+5luTyFmjQQUkoAlaNgjjDDw4PbWrC5nJkFORjuw5Lwl/gzhgeZ3gTmnVYEsJl
|
||||
/On9D54C1TosCWFX0+FxfgDzOigp4YMTLqeW5DJ8E9xewRrgxCjJ5gPQr0PSsmIUZXNDwx6MRfdVy9RH
|
||||
oFXDHnQC90ahuhttXO7k+xwsaNCTbaNQHdKQJ+GQoYVqr4Y86QLGYyzXkCezwF6M+0CZBr1YNy65+hwd
|
||||
3QrColGoXgClGvRiAng1SjPdAf5o0ItG4L9RmumMhrxZNkq/vQTqNeBNOJ5tAk9Sfg506+JCURz9/5sE
|
||||
poERoE4X/Rq+AC/GHt09Rk0KAAAAAElFTkSuQmCC
|
||||
</value>
|
||||
</data>
|
||||
<data name="BTT_BUG_REPORT.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
|
||||
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG
|
||||
YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9
|
||||
0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw
|
||||
bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc
|
||||
VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9
|
||||
c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32
|
||||
Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo
|
||||
mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+
|
||||
kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D
|
||||
TgDQASA1MVpwzwAAAABJRU5ErkJggg==
|
||||
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIFSURBVDhPpZLtS1NhGMbPPxJmmlYSgqHiKzGU1EDxg4iK
|
||||
YKyG2WBogqMYJQOtCEVRFBGdTBCJfRnkS4VaaWNT5sqx1BUxRXxDHYxAJLvkusEeBaPAB+5z4Jzn+t3X
|
||||
/aLhnEfjo8m+dCoa+7/C3O2Hqe0zDC+8KG+cRZHZhdzaaWTVTCLDMIY0vfM04Nfh77/G/sEhwpEDbO3t
|
||||
I7TxE8urEVy99fT/AL5gWDLrTB/hnF4XsW0khCu5ln8DmJliT2AXrcNBsU1gj/MH4nMeKwBrPktM28xM
|
||||
cX79DFKrHHD5d9D26hvicx4pABt2lpg10zYzU0zr7+e3xXGcrkEB2O2TNec9nJFwB3alZn5jZorfeDZh
|
||||
6Q3g8s06BeCoKF4MRURoH1+BY2oNCbeb0TIclIYxOhzf8frTOuo7FxCbbVIAzpni0iceEc8vhzEwGkJD
|
||||
lx83ymxifejdKjRNk/8PWnyIyTQqAJek0jqHwfEVscu31baIu8+90sTE4nY025dQ2/5FIPpnXlzKuK8A
|
||||
HBUzHot52djqQ6HZhfR7IwK4mKpHtvEDMqvfCiQ6zaAAXM8x94aIWTNrLLG4kVUzgaTSPlzLtyJOZxbb
|
||||
1wtfyg4Q+AfA3aZlButjSfxGcUJBk4g5tuP3haQKRKXcUQDOmbvNTpPOJeFFjordZmbWTNvMTHFUcpUC
|
||||
nOccAdABIDXXE1nzAAAAAElFTkSuQmCC
|
||||
</value>
|
||||
</data>
|
||||
<metadata name="Toolbar_BOTTOM.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
|
||||
@@ -801,29 +801,6 @@ CloseResume:
|
||||
f.ShowDialog()
|
||||
If f.DialogResult = DialogResult.OK Then
|
||||
Dim filter As GroupParameters = f.FilterSelected
|
||||
If Not filter Is Nothing AndAlso TypeOf filter Is AutoDownloader Then
|
||||
With DirectCast(filter, AutoDownloader)
|
||||
If .Mode = AutoDownloader.Modes.Groups Then
|
||||
If .Groups.Count = 0 Then
|
||||
MsgBoxE({"The scheduler plan you select doesn't contain any group!", msgTitle}, vbCritical)
|
||||
Exit Sub
|
||||
ElseIf .Groups.Count > 1 Then
|
||||
MsgBoxE({"The scheduler plan you select contains more than one group." & vbCr &
|
||||
"You need to choose a plan with one group or without groups!", msgTitle}, vbCritical)
|
||||
Exit Sub
|
||||
Else
|
||||
Dim i% = Settings.Groups.IndexOf(.Groups(0))
|
||||
If i >= 0 Then
|
||||
filter = Settings.Groups(i).Copy
|
||||
Else
|
||||
MsgBoxE({$"A group named '{ .Groups(0)}' cannot be found in existing groups.", msgTitle}, vbCritical)
|
||||
filter = Nothing
|
||||
Exit Sub
|
||||
End If
|
||||
End If
|
||||
End If
|
||||
End With
|
||||
End If
|
||||
If Not filter Is Nothing Then
|
||||
If filter.IsViewFilter Then
|
||||
With DirectCast(filter, DownloadGroup)
|
||||
|
||||
@@ -13,7 +13,7 @@ Imports System.Runtime.InteropServices
|
||||
<Assembly: AssemblyDescription("Social networks media downloader")>
|
||||
<Assembly: AssemblyCompany("AndyProgram")>
|
||||
<Assembly: AssemblyProduct("SCrawler")>
|
||||
<Assembly: AssemblyCopyright("Copyright © 2025")>
|
||||
<Assembly: AssemblyCopyright("Copyright © 2026")>
|
||||
<Assembly: AssemblyTrademark("AndyProgram")>
|
||||
|
||||
<Assembly: ComVisible(False)>
|
||||
@@ -32,6 +32,6 @@ Imports System.Runtime.InteropServices
|
||||
' by using the '*' as shown below:
|
||||
' <Assembly: AssemblyVersion("1.0.*")>
|
||||
|
||||
<Assembly: AssemblyVersion("2025.7.18.0")>
|
||||
<Assembly: AssemblyFileVersion("2025.7.18.0")>
|
||||
<Assembly: AssemblyVersion("2026.1.17.0")>
|
||||
<Assembly: AssemblyFileVersion("2026.1.17.0")>
|
||||
<Assembly: NeutralResourcesLanguage("en")>
|
||||
|
||||
@@ -128,6 +128,7 @@
|
||||
<Reference Include="Microsoft.Threading.Tasks.Extensions.Desktop, Version=1.0.168.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Deployment" />
|
||||
@@ -142,6 +143,7 @@
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="WindowsBase" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Import Include="Microsoft.VisualBasic" />
|
||||
@@ -253,6 +255,7 @@
|
||||
<Compile Include="API\ThisVid\SiteSettings.vb" />
|
||||
<Compile Include="API\ThisVid\UserData.vb" />
|
||||
<Compile Include="API\ThisVid\UserExchangeOptions.vb" />
|
||||
<Compile Include="API\ThreadsNet\Declarations.vb" />
|
||||
<Compile Include="API\ThreadsNet\SiteSettings.vb" />
|
||||
<Compile Include="API\ThreadsNet\UserData.vb" />
|
||||
<Compile Include="API\TikTok\Declarations.vb" />
|
||||
@@ -713,6 +716,10 @@
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\MyUtilities\PersonalUtilities.Images\PersonalUtilities.Images.vbproj">
|
||||
<Project>{b7ef76a9-96f3-4c53-b252-0ab5f79b67b3}</Project>
|
||||
<Name>PersonalUtilities.Images</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\MyUtilities\PersonalUtilities.Notifications\PersonalUtilities.Notifications.vbproj">
|
||||
<Project>{fc532253-1ab3-4def-a28a-dfdd9a481eb2}</Project>
|
||||
<Name>PersonalUtilities.Notifications</Name>
|
||||
|
||||
@@ -23,6 +23,7 @@ Imports DoubleClickBehavior = SCrawler.DownloadObjects.STDownloader.DoubleClickB
|
||||
Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
|
||||
#Region "Constants: defaults"
|
||||
Friend Const DefaultMaxDownloadingTasks As Integer = 5
|
||||
Friend Const DefaultMaxDownloadingTasks_Channels As Integer = 1
|
||||
Friend Const TaskStackNamePornSite As String = "Porn sites"
|
||||
Friend Const Name_Node_Sites As String = "Sites"
|
||||
Private Const SitesValuesSeparator As String = ","
|
||||
@@ -194,7 +195,7 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
|
||||
Private ReadOnly BlackListFile As SFile = $"{SettingsFolderName}\BlackList.txt"
|
||||
Private ReadOnly UsersSettingsFile As SFile = $"{SettingsFolderName}\Users.xml"
|
||||
Private ReadOnly Property SettingsVersion As XMLValue(Of Integer)
|
||||
Private Const SettingsVersionCurrent As Integer = 2
|
||||
Private Const SettingsVersionCurrent As Integer = 3
|
||||
Friend ShortcutOpenFeed As New ButtonKey(Keys.F, True)
|
||||
Friend ShortcutOpenSearch As New ButtonKey(Keys.F,, True)
|
||||
Private Sub ChangeFeedOpenMode()
|
||||
@@ -366,9 +367,7 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
|
||||
ReparseMissingInTheRoutine = New XMLValue(Of Boolean)("ReparseMissingInTheRoutine", False, MyXML, n)
|
||||
UseDefaultAccountIfMissing = New XMLValue(Of Boolean)("UseDefaultAccountIfMissing", True, MyXML, n)
|
||||
AutomationBrushUndownloadedPlansMinutes = New XMLValue(Of Integer)("AutomationBrushUndownloadedPlansMinutes", 10080, MyXML, n)
|
||||
DownDetectorEnabled = New XMLValue(Of Boolean)("DownDetectorEnabled", True, MyXML, n)
|
||||
'TODELETE: DownDetectorEnabled change
|
||||
If SettingsVersion.Value < SettingsVersionCurrent Then DownDetectorEnabled.Value = False 'SettingsVersionCurrent = 2
|
||||
DownDetectorEnabled = New XMLValue(Of Boolean)("DownDetectorEnabled", False, MyXML, n)
|
||||
|
||||
'Downloading: file naming
|
||||
n = {"Downloading", "FileName"}
|
||||
@@ -392,7 +391,7 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
|
||||
ChannelsDefaultReadyForDownload = New XMLValue(Of Boolean)("ChannelsDefaultReadyForDownload", False, MyXML, n)
|
||||
ChannelsDefaultTemporary = New XMLValue(Of Boolean)("ChannelsDefaultTemporary", True, MyXML, n)
|
||||
ChannelsHideExistsUser = New XMLValue(Of Boolean)("HideExistsUser", True, MyXML, n)
|
||||
ChannelsMaxJobsCount = New XMLValue(Of Integer)("MaxJobsCount", DefaultMaxDownloadingTasks, MyXML, n)
|
||||
ChannelsMaxJobsCount = New XMLValue(Of Integer)("MaxJobsCount", DefaultMaxDownloadingTasks_Channels, MyXML, n)
|
||||
n = {Name_Node_Sites, "Channels", "Users"}
|
||||
FromChannelDownloadTop = New XMLValue(Of Integer)("FromChannelDownloadTop", 10, MyXML, n)
|
||||
FromChannelDownloadTopUse = New XMLValue(Of Boolean)("FromChannelDownloadTopUse", False, MyXML, n)
|
||||
@@ -497,6 +496,8 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
|
||||
AdvancedFilter.IsViewFilter = True
|
||||
Labels.AddRange({AdvancedFilter}.GetGroupsLabels, False)
|
||||
|
||||
'TODELETE: DefaultMaxDownloadingTasks_Channels
|
||||
If Not SettingsVersion = SettingsVersionCurrent Then ChannelsMaxJobsCount.Value = DefaultMaxDownloadingTasks_Channels 'SettingsVersionCurrent = 3
|
||||
SettingsVersion.Value = SettingsVersionCurrent
|
||||
|
||||
MyXML.EndUpdate()
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
'
|
||||
' This program is distributed in the hope that it will be useful,
|
||||
' but WITHOUT ANY WARRANTY
|
||||
Imports System.IO
|
||||
Imports PersonalUtilities.Tools
|
||||
Friend Class UserImage : Inherits ImageRenderer
|
||||
Friend Const ImagePrefix As String = "UserPicture"
|
||||
@@ -97,4 +98,56 @@ Friend Class UserImage : Inherits ImageRenderer
|
||||
Friend Overloads Shared Function CreateImageFromText(ByVal Text As String, ByVal File As SFile) As Boolean
|
||||
Return CreateImageFromText(Text, FormFont, Color.Black, TextImageWidth, File, Color.White,, EDP.ThrowException)
|
||||
End Function
|
||||
Friend Const ExtWebp As String = "webp"
|
||||
Friend Const ExtJpg As String = "jpg"
|
||||
Friend Shared Function ConvertWebp(ByVal InitFile As SFile, ByVal DestFile As SFile,
|
||||
Optional ByVal Force As Boolean = False, Optional ByVal ToWebP As Boolean = False,
|
||||
Optional ByRef Result As Boolean = False) As SFile
|
||||
Result = False
|
||||
If InitFile.Extension = ExtWebp Or Force Then
|
||||
If Settings.FfmpegFile.Exists Or ToWebP Then
|
||||
Dim dir As SFile
|
||||
Dim postfix$ = String.Empty
|
||||
If DestFile.IsEmptyString Then
|
||||
dir = $"{Settings.Cache.RootDirectory.PathWithSeparator}ConvWebp\"
|
||||
Settings.Cache.AddPath(dir)
|
||||
postfix = $"_{InitFile.GetHashCode}"
|
||||
Else
|
||||
dir = New SFile With {.Path = DestFile.Path}
|
||||
End If
|
||||
dir.Exists(SFO.Path)
|
||||
Dim f As SFile = DestFile.IfNullOrEmpty(InitFile)
|
||||
f.Path = dir.PathNoSeparator
|
||||
If Not postfix.IsEmptyString Then f.Name &= postfix
|
||||
f.Extension = IIf(ToWebP, ExtWebp, ExtJpg)
|
||||
|
||||
If DestFile.IsEmptyString AndAlso f.Exists AndAlso Not f.Extension = ExtWebp Then Return f
|
||||
|
||||
If ToWebP Then
|
||||
If Not f.Exists Then InitFile.Copy(f)
|
||||
If f.Exists Then
|
||||
InitFile = f
|
||||
f.Extension = ExtJpg
|
||||
Else
|
||||
Throw New ArgumentNullException With {.HelpLink = 1}
|
||||
End If
|
||||
End If
|
||||
If Not ConvertWebpTryImageMagick(InitFile, f) Then
|
||||
Using imgBatch As New BatchExecutor
|
||||
With imgBatch
|
||||
.ChangeDirectory(dir)
|
||||
.Execute($"""{Settings.FfmpegFile}"" -i ""{InitFile}"" ""{f}""")
|
||||
End With
|
||||
End Using
|
||||
End If
|
||||
If f.Exists Then Result = True : Return f
|
||||
End If
|
||||
Else
|
||||
Return InitFile
|
||||
End If
|
||||
Return Nothing
|
||||
End Function
|
||||
Private Shared Function ConvertWebpTryImageMagick(ByVal InitFile As SFile, ByVal DestFile As SFile) As Boolean
|
||||
Return ImageRendererExt.ConvertWebp(InitFile, DestFile, EDP.SendToLog + EDP.ReturnValue)
|
||||
End Function
|
||||
End Class
|
||||