Compare commits
60 Commits
2023.12.14
...
2025.2.25.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2f838929cc | ||
|
|
4d74f5204b | ||
|
|
b42832719f | ||
|
|
aedcebc781 | ||
|
|
00a06d3e9a | ||
|
|
2055461829 | ||
|
|
723155e20c | ||
|
|
effaa3b65b | ||
|
|
e285de10f6 | ||
|
|
26db0e3e24 | ||
|
|
0b0933b6f0 | ||
|
|
3ce9c55575 | ||
|
|
ef36a11566 | ||
|
|
dea14d35af | ||
|
|
744698c99e | ||
|
|
aef4ce1c8f | ||
|
|
93ea2a55ac | ||
|
|
2ae8c3acfc | ||
|
|
53dcb3e2c6 | ||
|
|
ca384e54d6 | ||
|
|
5a1b5c828a | ||
|
|
22c59b41f0 | ||
|
|
444b3521eb | ||
|
|
ec2266f1bf | ||
|
|
7d9255c916 | ||
|
|
5b5857e31d | ||
|
|
46372ec9fb | ||
|
|
7296fda977 | ||
|
|
5f90bf6a99 | ||
|
|
718eccc3c3 | ||
|
|
efa09fb457 | ||
|
|
b252d32a7e | ||
|
|
34cd510507 | ||
|
|
f5dd791941 | ||
|
|
2a2c12c651 | ||
|
|
2bacc17ac4 | ||
|
|
7a68067d77 | ||
|
|
d1eacc2db2 | ||
|
|
3f38803643 | ||
|
|
09760a6926 | ||
|
|
75039ac4d2 | ||
|
|
03e3a07947 | ||
|
|
d283d9c9f9 | ||
|
|
b9100bd3c1 | ||
|
|
0ea2156ada | ||
|
|
520280b038 | ||
|
|
10516f229b | ||
|
|
c3f0831768 | ||
|
|
74a0404670 | ||
|
|
52a43b9207 | ||
|
|
5bc559c448 | ||
|
|
b37f641582 | ||
|
|
e00dfec701 | ||
|
|
94edf23570 | ||
|
|
0246af9b69 | ||
|
|
c458f1cd1d | ||
|
|
e3da1bf1d3 | ||
|
|
dde024276b | ||
|
|
7a33c02497 | ||
|
|
5bd79ff3c2 |
@@ -1,11 +1,14 @@
|
|||||||
# Contributor's Guide
|
# Contributor's Guide
|
||||||
|
|
||||||
I welcome requests! Follow these steps to contribute:
|
Follow these steps to contribute:
|
||||||
|
|
||||||
1. Find an [issue](https://github.com/AAndyProgram/SCrawler/issues) that needs assistance.
|
1. Find an [issue](https://github.com/AAndyProgram/SCrawler/issues) that needs assistance.
|
||||||
1. Let me know you are working on it by posting a comment on the issue.
|
1. Let me know you're working on this by posting a comment on this issue.
|
||||||
1. If you find an error in the code, please provide a link to the file and the line number.
|
1. If you find a bug in the code, please provide a link to the file and line number.
|
||||||
1. If you have a code change suggestion, you can post a replacement code block. I also accept pull requests.
|
1. If you have a code change suggestion, you can post a replacement code block.<!-- I also accept pull requests.-->
|
||||||
|
|
||||||
|
# How to report a problem
|
||||||
|
|
||||||
|
**[Read here](https://github.com/AAndyProgram/SCrawler/blob/main/FAQ.md#how-to-report-a-problem)**
|
||||||
|
|
||||||
# How to build from source
|
# How to build from source
|
||||||
1. Delete the `PersonalUtilities` project from the solution.
|
1. Delete the `PersonalUtilities` project from the solution.
|
||||||
@@ -24,7 +27,7 @@ I welcome requests! Follow these steps to contribute:
|
|||||||
**I'm currently not accepting requests to develop new sites.**
|
**I'm currently not accepting requests to develop new sites.**
|
||||||
|
|
||||||
1. Check [issues](https://github.com/AAndyProgram/SCrawler/issues) (open and [closed](https://github.com/AAndyProgram/SCrawler/issues?q=is%3Aissue+is%3Aclosed)) and [discussions](https://github.com/AAndyProgram/SCrawler/discussions) to find your issue. Perhaps I have already answered your request.
|
1. Check [issues](https://github.com/AAndyProgram/SCrawler/issues) (open and [closed](https://github.com/AAndyProgram/SCrawler/issues?q=is%3Aissue+is%3Aclosed)) and [discussions](https://github.com/AAndyProgram/SCrawler/discussions) to find your issue. Perhaps I have already answered your request.
|
||||||
1. If you don't find anything, create a new issue with your request. I usually reply as soon as possible (within the next few hours).
|
1. If you don't find anything, create a new issue with your request.
|
||||||
|
|
||||||
# Requirements for new site requests
|
# Requirements for new site requests
|
||||||
|
|
||||||
|
|||||||
495
Changelog.md
@@ -1,3 +1,498 @@
|
|||||||
|
# 2025.2.25.0
|
||||||
|
|
||||||
|
*2025-02-25*
|
||||||
|
|
||||||
|
- Added
|
||||||
|
- Sites:
|
||||||
|
- **Bluesky**
|
||||||
|
- Facebook: **`Reels` downloads**
|
||||||
|
- OnlyFans: default value for `App-Token`
|
||||||
|
- Pinterest: **sub-boards downloading**
|
||||||
|
- Threads: ability to manually change `UserName`
|
||||||
|
- Twitter:
|
||||||
|
- new icon support
|
||||||
|
- **sleep timers to fully download large profiles**
|
||||||
|
- Feed:
|
||||||
|
- ability to invert selection
|
||||||
|
- open post URL when double-clicking on subscription image
|
||||||
|
- Minor improvements
|
||||||
|
- Updated
|
||||||
|
- yt-dlp up to version **2025.02.19**
|
||||||
|
- gallery-dl up to version **1.28.5**
|
||||||
|
- PluginProvider
|
||||||
|
- `IPluginContentProvider`: added property `NameTrue`
|
||||||
|
- Fixed
|
||||||
|
- Sites:
|
||||||
|
- Facebook: videos are not downloading
|
||||||
|
- LPSG: simplified 403 error
|
||||||
|
- PornHub: photos & videos are not downloading
|
||||||
|
- Reddit: **token does not update automatically**
|
||||||
|
- Threads: **data is not downloading**
|
||||||
|
- Minor bugs
|
||||||
|
|
||||||
|
# 2025.1.12.0
|
||||||
|
|
||||||
|
*2025-01-12*
|
||||||
|
|
||||||
|
- Added
|
||||||
|
- Sites:
|
||||||
|
- YouTube (standalone app):
|
||||||
|
- ability to add channel name to file name (`Add channel to file name`)
|
||||||
|
- adding channel name and video URL to info file
|
||||||
|
- OnlyFans: **built-in usage of DRM keys**
|
||||||
|
- Threads: automatically change `heic` extension to `jpg`
|
||||||
|
- Twitter: download broadcasts *(user option)*
|
||||||
|
- Minor improvements
|
||||||
|
- Updated
|
||||||
|
- yt-dlp up to version **2024.12.23**
|
||||||
|
- gallery-dl up to version **1.28.3**
|
||||||
|
- **OF-Scraper** up to version **3.12.9** *(you must update it personally)*
|
||||||
|
- Fixed
|
||||||
|
- Sites:
|
||||||
|
- DownDetector: fixed 403 error
|
||||||
|
- OnlyFans: **DRM videos not downloading**
|
||||||
|
- xHamster: some videos are not downloading
|
||||||
|
- YouTube: **communities are not downloading** *(see settings in wiki)*
|
||||||
|
- Minor bugs
|
||||||
|
|
||||||
|
# 2024.11.21.0
|
||||||
|
|
||||||
|
*2024-11-21*
|
||||||
|
|
||||||
|
- Added
|
||||||
|
- Sites:
|
||||||
|
- Instagram:
|
||||||
|
- setting to skip errors without disabling download *(site settings)*
|
||||||
|
- settings to force update of username and/or user information *(user settings)*
|
||||||
|
- setting to continue downloading profile if error 560 occurs while downloading user stories *(site settings)*
|
||||||
|
- improve username update algorithm
|
||||||
|
- YouTube: 404 error handling (community)
|
||||||
|
- Main window: add extra buttons for special download (limited and dated) in collection
|
||||||
|
- Global settings: ability to change the feed opening shortcut (`Ctrl+F`/`Alt+F` *(Settings - Behavior)*)
|
||||||
|
- Minor improvements
|
||||||
|
- Updated
|
||||||
|
- yt-dlp up to version **2024.11.18**
|
||||||
|
- gallery-dl up to version **1.27.7**
|
||||||
|
- Fixed
|
||||||
|
- Users: network paths aren't working
|
||||||
|
- Main window: in some cases users are not updated in the list
|
||||||
|
- Minor bugs
|
||||||
|
|
||||||
|
# 2024.10.24.0
|
||||||
|
|
||||||
|
*2024-10-24*
|
||||||
|
|
||||||
|
- Added
|
||||||
|
- YouTube (standalone app):
|
||||||
|
- settings `Embed thumbnail (cover)` and `Allow webm formats`
|
||||||
|
- changed cover selection for music downloads
|
||||||
|
- allow `webm` formats if there are no `mp4` formats via http protocol (issue #211)
|
||||||
|
- Sites:
|
||||||
|
- Instagram:
|
||||||
|
- **ability to manually change username**
|
||||||
|
- **mark user as non-existent if user `ID` cannot be obtained**
|
||||||
|
- Twitter: **ability to manually change username**
|
||||||
|
- Main window: add users search button to 'Info' menu
|
||||||
|
- Minor improvements
|
||||||
|
- Updated
|
||||||
|
- yt-dlp up to version **2024.10.22**
|
||||||
|
- gallery-dl up to version **1.27.6**
|
||||||
|
- Fixed
|
||||||
|
- YouTube (standalone app): adding incorrect playlist lines
|
||||||
|
- Reddit: incorrect UNIX date parsing
|
||||||
|
- Can't change data path (issue #206)
|
||||||
|
- Minor bugs
|
||||||
|
|
||||||
|
# 2024.9.2.0
|
||||||
|
|
||||||
|
*2024-09-02*
|
||||||
|
|
||||||
|
- Added
|
||||||
|
- Instagram: options to enable/disable image extraction from video
|
||||||
|
- Feed: **prompt before moving entire feed/session**
|
||||||
|
- Main window: hotkeys `Alt+U` and `Ctrl+U` to open the user search form
|
||||||
|
- Minor improvements
|
||||||
|
- Updated
|
||||||
|
- gallery-dl up to version **1.27.3**
|
||||||
|
- Fixed
|
||||||
|
- **OnlyFans**: data is not downloading
|
||||||
|
- YouTube (SCrawler): incorrect parsing of video page
|
||||||
|
- Minor bugs
|
||||||
|
|
||||||
|
# 2024.8.10.0
|
||||||
|
|
||||||
|
*2024-08-10*
|
||||||
|
|
||||||
|
- Added
|
||||||
|
- Feed: button to open file folder
|
||||||
|
- Updated
|
||||||
|
- yt-dlp up to version **2024.08.06**
|
||||||
|
- gallery-dl up to version **1.27.2**
|
||||||
|
- Fixed
|
||||||
|
- YouTube (standalone app): **video is being parsed using cookies but is not downloading** *(Issue #205)*
|
||||||
|
|
||||||
|
# 2024.8.1.0
|
||||||
|
|
||||||
|
*2024-08-01*
|
||||||
|
|
||||||
|
- Added
|
||||||
|
- Minor improvements
|
||||||
|
- Updated
|
||||||
|
- yt-dlp up to version **2024.08.01**
|
||||||
|
|
||||||
|
# 2024.7.24.0
|
||||||
|
|
||||||
|
*2024-07-24*
|
||||||
|
|
||||||
|
- Added
|
||||||
|
- YouTube (standalone app)
|
||||||
|
- ability to convert non-`AVC` codecs (eg `VP9`) to `AVC` (`Settings` - `Defaults Video` - `Convert non-AVC codecs to AVC`)
|
||||||
|
- add the ability to set the playlist creation mode: absolute links, relative links, or both (`Settings` - `Music` - `Create M3U8: creation mode`)
|
||||||
|
- Threads: **saved posts downloading**
|
||||||
|
- Feed
|
||||||
|
- hotkeys `Esc` and `Ctrl+W` to close the form
|
||||||
|
- the ability to search for missing files in *special feeds*
|
||||||
|
- Scheduler: the ability to execute a script after the scheduler plan is executed *(`Settings` - `Behavior`)*
|
||||||
|
- Main window:
|
||||||
|
- added hotkey `Ctrl+F` to show the feed
|
||||||
|
- changed the hotkey from `Ctrl+F` to `Alt+F` to show the search form
|
||||||
|
- Updated
|
||||||
|
- yt-dlp up to version **2024.07.16**
|
||||||
|
- Fixed
|
||||||
|
- YouTube (standalone app): video files with line breaks in the name do not download correctly
|
||||||
|
- OnlyFans: rules parsing bug
|
||||||
|
- Minor bugs
|
||||||
|
|
||||||
|
# 2024.6.25.0
|
||||||
|
|
||||||
|
*2024-06-25*
|
||||||
|
|
||||||
|
**ATTENTION! To support downloading of DRM protected videos (OnlyFans), please update OF-Scraper to version [3.10.7](https://github.com/datawhores/OF-Scraper/releases/tag/3.10.7) (download `zip`, not `exe`).**
|
||||||
|
|
||||||
|
- Added
|
||||||
|
- OnlyFans: **new dynamic rules updating algorithm**
|
||||||
|
- Feed: ability to set the last session as the current one
|
||||||
|
- Updated
|
||||||
|
- gallery-dl up to version **1.27.1**
|
||||||
|
- Fixed
|
||||||
|
- Minor bugs
|
||||||
|
|
||||||
|
# 2024.6.10.0
|
||||||
|
|
||||||
|
*2024-06-10*
|
||||||
|
|
||||||
|
- Added
|
||||||
|
- YouTube (standalone app): add option to add extracted MP3 to playlist (`Settings` - `Defaults Video` - `Add extracted MP3 to playlist`)
|
||||||
|
- Feed
|
||||||
|
- settings to show/hide site name and file type from media title
|
||||||
|
- ability to move/copy files of a loaded feed/session to another location
|
||||||
|
- ability to reset current session
|
||||||
|
- Fixed
|
||||||
|
- Minor bugs
|
||||||
|
|
||||||
|
# 2024.6.6.0
|
||||||
|
|
||||||
|
*2024-06-06*
|
||||||
|
|
||||||
|
**ATTENTION!**
|
||||||
|
1. **To support downloading of DRM protected videos (OnlyFans), please update OF-Scraper to version [3.10](https://github.com/datawhores/OF-Scraper/releases/tag/3.10) (download `zip`, not `exe`).**
|
||||||
|
2. **If there is a `OFScraperConfigPattern.json` file in the SCrawler settings folder, replace the text of the file with [this text](https://github.com/AAndyProgram/SCrawler/blob/main/SCrawler/API/OnlyFans/OFScraperConfigPattern.json).**
|
||||||
|
3. **Set the value to `Dynamic rules` (in the site settings) = `https://raw.githubusercontent.com/Growik/onlyfans-dynamic-rules/main/rules.json`.**
|
||||||
|
|
||||||
|
- Added
|
||||||
|
- OnlyFans: new OF-Scraper option (`keydb_api`)
|
||||||
|
- Minor improvements
|
||||||
|
- Fixed
|
||||||
|
- OnlyFans: **data is not downloading**
|
||||||
|
- Minor bugs
|
||||||
|
|
||||||
|
# 2024.6.4.0
|
||||||
|
|
||||||
|
*2024-06-04*
|
||||||
|
|
||||||
|
**If you were using the [`yt-dlp-TTUser`](https://github.com/bashonly/yt-dlp-TTUser) plugin, you should remove it because this plugin was added to yt-dlp itself! Read more [here](https://github.com/AAndyProgram/SCrawler/wiki/Settings#tiktok-requirements).**
|
||||||
|
|
||||||
|
- Added
|
||||||
|
- Added highlighting of scheduler plans (working, stopped, pending, etc.)
|
||||||
|
- YouTube (standalone app): add option to add the video upload date before/after the file name (`Settings` - `Defaults` - `Add date to file name`)
|
||||||
|
- Twitter: **`Communities` downloading**
|
||||||
|
- Feed: ability to select one of the download sessions and set it as the current session
|
||||||
|
- Minor improvements
|
||||||
|
- Updated
|
||||||
|
- yt-dlp up to version **2024.05.27**
|
||||||
|
- gallery-dl up to version **1.27.0**
|
||||||
|
- Fixed
|
||||||
|
- Twitter: deleting user directory when redownloading missing posts
|
||||||
|
- Minor bugs
|
||||||
|
|
||||||
|
# 2024.5.19.0
|
||||||
|
|
||||||
|
*2024-05-19*
|
||||||
|
|
||||||
|
- Added
|
||||||
|
- YouTube (standalone app): add upload date to description (request #192) (`Settings` - `Info` - `Create description files: add upload date`, `Create description files: create without description`).
|
||||||
|
- Fixed
|
||||||
|
- YouTube (SCrawler): advanced settings are not saved when changed
|
||||||
|
|
||||||
|
# 2024.5.18.0
|
||||||
|
|
||||||
|
*2024-05-18*
|
||||||
|
|
||||||
|
- Added
|
||||||
|
- YouTube (standalone app): highlight frame rates higher/lower than this value (`Settings` - `Defaults Video` - `Highlight FPS (higher/lower)`).
|
||||||
|
- Sites
|
||||||
|
- Instagram: 'DownDetector' support to determine if the site is accessible
|
||||||
|
- Reddit: change the naming method of video files (hosted on Reddit) to the `YYYYMMDD_HHMMSS` pattern
|
||||||
|
- Twitter
|
||||||
|
- `Likes` downloading *(user settings)*
|
||||||
|
- **changed domain from twitter.com to x.com**
|
||||||
|
- Site settings: group options by category
|
||||||
|
- Minor improvements
|
||||||
|
- PluginProvider
|
||||||
|
- `PropertyOption` attribute: set category name when `IsAuth = True`
|
||||||
|
- `ISiteSettings`: added `UserAgentDefault` property
|
||||||
|
- Updated
|
||||||
|
- gallery-dl up to version **1.27.0-dev**
|
||||||
|
- Fixed
|
||||||
|
- Sites
|
||||||
|
- Instagram: incorrect definition of pinned posts
|
||||||
|
- Threads: new posts are no longer downloaded from profiles with pinned posts
|
||||||
|
- Reddit: bypass error 429 for saved posts
|
||||||
|
- Twitter: **data is not downloading due to domain change from twitter.com to x.com**
|
||||||
|
- Minor bugs
|
||||||
|
|
||||||
|
# 2024.5.4.0
|
||||||
|
|
||||||
|
*2024-05-04*
|
||||||
|
|
||||||
|
- Added
|
||||||
|
- YouTube (standalone app): setting to remove specific characters (`Defaults` - `Remove characters`)
|
||||||
|
- Instagram: simplify the `Connection closed` error
|
||||||
|
- Users search: add `Friendly name` to search results
|
||||||
|
- Fixed
|
||||||
|
- YouTube (standalone app): incorrect download processing when the file name ends with a dot (Issue #188)
|
||||||
|
- The program is freezes when editing users in some cases
|
||||||
|
- Sites
|
||||||
|
- Reddit: token update error
|
||||||
|
- Threads: unable to obtain credentials (`ID`)
|
||||||
|
|
||||||
|
# 2024.4.26.0
|
||||||
|
|
||||||
|
*2024-04-26*
|
||||||
|
|
||||||
|
- Added
|
||||||
|
- Site settings: the values that can be extracted from cookies immediately populate fields
|
||||||
|
- Feed: ability to load the last session of the current day (if it exists) as the current session after restarting SCrawler
|
||||||
|
- Users search: include friendly name matches in search result
|
||||||
|
- Updated
|
||||||
|
- gallery-dl up to version **1.26.9**
|
||||||
|
- Fixed
|
||||||
|
- xHamster: **saved posts aren't downloading**
|
||||||
|
|
||||||
|
# 2024.4.14.0
|
||||||
|
|
||||||
|
*2024-04-14*
|
||||||
|
|
||||||
|
- Fixed
|
||||||
|
- Facebook: can't get tokens
|
||||||
|
|
||||||
|
# 2024.4.13.0
|
||||||
|
|
||||||
|
*2024-04-13*
|
||||||
|
|
||||||
|
- Added
|
||||||
|
- Minor improvements
|
||||||
|
- PluginProvider
|
||||||
|
- IPluginContentProvider: added `ResetHistoryData` function
|
||||||
|
- Fixed
|
||||||
|
- Sites
|
||||||
|
- TikTok: remove last download date when erasing history data
|
||||||
|
- YouTube: remove last download date when erasing history data
|
||||||
|
- Instagram: **saved posts aren't downloading**
|
||||||
|
|
||||||
|
# 2024.4.10.0
|
||||||
|
|
||||||
|
*2024-04-10*
|
||||||
|
|
||||||
|
**For those of you who use TikTok, it is highly recommended to update TikTok plugin (using [these instructions](https://github.com/AAndyProgram/SCrawler/wiki/Settings#how-to-install-yt-dlp-ttuser-plugin)) to the latest version!**
|
||||||
|
|
||||||
|
**ATTENTION! This version includes changes to downloading groups (including the scheduler) and the settings file. Once you start using it, you won't be able to downgrade. I recommend making a backup of your SCrawler settings folder. It is also recommended to check all of your download groups settings and scheduler plans settings.**
|
||||||
|
|
||||||
|
- Added
|
||||||
|
- Sites
|
||||||
|
- TikTok: more settings for standalone downloader
|
||||||
|
- Instagram:
|
||||||
|
- automatically reset download options after updating credentials
|
||||||
|
- **ability to extract an image (if it exists) from a video that contains a static image**
|
||||||
|
- updated reels downloading function
|
||||||
|
- GraphQL support
|
||||||
|
- request timers (per request)
|
||||||
|
- OnlyFans:
|
||||||
|
- **download stories**
|
||||||
|
- option to disable timeline downloading
|
||||||
|
- Reddit: added `Check image` setting (unchecked by default) to make Reddit downloading faster
|
||||||
|
- **YouTube (standalone app)**:
|
||||||
|
- **the ability to add downloaded item(s) to a playlist**
|
||||||
|
- **the ability to create a playlist from downloaded music**
|
||||||
|
- calculation and display of the actual size of downloaded files
|
||||||
|
- **the ability to change audio bitrate** *(you can also set the default bitrate in `Defaults Audio` - `Bitrate`)*
|
||||||
|
- **embed thumbnail in the extracted audio (`mp3` only) as cover art** (Settings: `Defaults Audio` - `Embed thumbnail (extracted files)`)
|
||||||
|
- Exclude `drc` *(dynamic range compression)* from parsing results
|
||||||
|
- Standalone downloader:
|
||||||
|
- allow thumbnail to be saved with file
|
||||||
|
- calculation and display of the actual size of downloaded files
|
||||||
|
- Feed:
|
||||||
|
- add hotkeys: `Home`, `End`, `Up`, `Page Up`, `Down`, `Page Down`
|
||||||
|
- ability to save/load views
|
||||||
|
- Scheduler: **`All` and `Default` options removed.** *Only `Disabled`, `Specified` and `Groups` are available.*
|
||||||
|
- Download groups: **filter users who have been (not)downloaded in the last `x` days** *(download groups, advanced filter (main window), scheduler)*.
|
||||||
|
- Main window:
|
||||||
|
- ability to save/load views (`View` - `Save/Load view`)
|
||||||
|
- **all filter options from the `View` menu have now been moved to `Filter`**
|
||||||
|
- Settings:
|
||||||
|
- ability to confirm mass download using the `F6` key *(to protect against accidental pressing) (`Settings` - `Behavior`)*
|
||||||
|
- the ability to find the program environment
|
||||||
|
- default headers (`Settings` - `Headers`)
|
||||||
|
- Added the ability to display group users *(works in scheduler, scheduler plans, download groups)*
|
||||||
|
- Added exclusion of last 3 days from deleting session files
|
||||||
|
- Other improvements
|
||||||
|
- Updated
|
||||||
|
- **yt-dlp up to version 2024.04.09**
|
||||||
|
- PluginProvider
|
||||||
|
- Add `PropertyValueEventArgs` class
|
||||||
|
- PropertyValue:
|
||||||
|
- add `Checked` parameter
|
||||||
|
- add `OnCheckboxCheckedChange` handler
|
||||||
|
- ISiteSettings:
|
||||||
|
- add `CMDEncoding`, `EnvironmentPrograms` properties
|
||||||
|
- add `EnvironmentProgramsUpdated` function
|
||||||
|
- Fixed
|
||||||
|
- Sites
|
||||||
|
- PornHub: some videos won't download
|
||||||
|
- xHamster:
|
||||||
|
- some videos are missing when downloading creators
|
||||||
|
- user videos aren't downloading
|
||||||
|
- **JustForFans: fixed video downloading**
|
||||||
|
- TikTok (standalone downloader): files with long names aren't downloaded
|
||||||
|
- Users: incorrect decision to set last update date, which resulted in an incorrect last download date for some users
|
||||||
|
- Feed: a scrolling bug where the feed scrolls up after returning to it
|
||||||
|
- Minor bugs
|
||||||
|
|
||||||
|
# 2024.2.25.0
|
||||||
|
|
||||||
|
*2024-02-25*
|
||||||
|
|
||||||
|
- Added
|
||||||
|
- A `Feed` button has been added to notifications
|
||||||
|
- Feed:
|
||||||
|
- ability to merge multiple special feeds into one
|
||||||
|
- ability to select all/none media
|
||||||
|
- ability to add to a special feed(s) with removal from the current one
|
||||||
|
- the name of the loaded feed is now displayed in the form title
|
||||||
|
- `Refresh` button now refreshes the loaded feed
|
||||||
|
- ability to move/copy media
|
||||||
|
- Scheduler: the ability to move tasks (higher, lower) *(just a view attribute, doesn't affect the scheduler)*
|
||||||
|
- YouTube (standalone app): add `Open file` to the context menu
|
||||||
|
- YouTube (standalone app): **the ability to edit each playlist item**
|
||||||
|
- YouTube (standalone app): **embed thumbnail in the audio/video as cover art** (Settings: `Defaults Audio` - `Embed thumbnail`; `Defaults Video` - `Embed thumbnail (video)`)
|
||||||
|
- Instagram: the `csrftoken` can now be automatically extracted from cookies
|
||||||
|
- Instagram: remove `x-ig-www-claim` from settings
|
||||||
|
- Threads: the `csrftoken` can now be automatically extracted from cookies
|
||||||
|
- Threads: simplify 500 error when updating tokens
|
||||||
|
- Facebook: simplify token update errors
|
||||||
|
- OnlyFans: handle 500 error
|
||||||
|
- Plugins: added `ReplaceInternalPluginAttribute` attribute
|
||||||
|
- Other improvements
|
||||||
|
- Fixed
|
||||||
|
- Main window: incorrect sorting of profiles and collections
|
||||||
|
- Standalone downloader: url array form doesn't show scrollbars
|
||||||
|
- Feed: image rendering bug
|
||||||
|
- YouTube (standalone app): audio codec does not change when changing audio/video in the video options form
|
||||||
|
- Instagram: error downloading single post
|
||||||
|
- TikTok: files with long names aren't downloaded
|
||||||
|
- Minor bugs
|
||||||
|
|
||||||
|
# 2024.1.26.0
|
||||||
|
|
||||||
|
*2024-01-26*
|
||||||
|
|
||||||
|
- Added
|
||||||
|
- YouTube (standalone app): **the ability to reduce video FPS**
|
||||||
|
- TikTok: the ability to use a regex to clean the title
|
||||||
|
- YouTube (SCrawler): the ability to ignore community errors
|
||||||
|
- Fixed
|
||||||
|
- Instagram: stories (user) downloading with the wrong aspect ratio for some users
|
||||||
|
- Minor bugs
|
||||||
|
|
||||||
|
# 2024.1.20.0
|
||||||
|
|
||||||
|
*2024-01-20*
|
||||||
|
|
||||||
|
- Added
|
||||||
|
- Instagram: **the ability to download reels**
|
||||||
|
- LPSG: handle 404 error
|
||||||
|
|
||||||
|
# 2024.1.18.0
|
||||||
|
|
||||||
|
*2024-01-18*
|
||||||
|
|
||||||
|
- Fixed
|
||||||
|
- Main window: incorrect collection sorting
|
||||||
|
- xHamster: some user videos were not downloaded
|
||||||
|
- YouTube (standalone app): URL array form doesn't show scrollbars
|
||||||
|
- Minor bugs
|
||||||
|
|
||||||
|
# 2024.1.12.1
|
||||||
|
|
||||||
|
*2024-01-12*
|
||||||
|
|
||||||
|
- Added
|
||||||
|
- YouTube (SCrawler): data downloading by dates
|
||||||
|
- Feed: ability to merge multiple session feeds into one
|
||||||
|
- Feed: remove session number from special feeds
|
||||||
|
- Fixed
|
||||||
|
- **Instagram**: stories (user) downloading with the wrong aspect ratio for some users
|
||||||
|
- YouTube: incorrect opening of a post from the feed
|
||||||
|
- YouTube: wrong date to data parsing
|
||||||
|
|
||||||
|
# 2024.1.12.0
|
||||||
|
|
||||||
|
*2024-01-12*
|
||||||
|
|
||||||
|
- Added
|
||||||
|
- Feed: added a prompt before clearing the current session
|
||||||
|
- xHamster: creators
|
||||||
|
- YouTube communities: add error to log
|
||||||
|
- Added scheduler to tray menu
|
||||||
|
- Other improvements
|
||||||
|
- Fixed
|
||||||
|
- Feed: there is no option to create a new feed when adding checked items
|
||||||
|
- **Instagram**: downloading of tagged posts
|
||||||
|
- xHamster: profiles are not downloading
|
||||||
|
- Minor bugs
|
||||||
|
|
||||||
|
# 2023.12.27.0
|
||||||
|
|
||||||
|
*2023-12-27*
|
||||||
|
|
||||||
|
- Added
|
||||||
|
- Notification of new log data
|
||||||
|
- OnlyFans: **OF-Scrapper support to download DRM protected videos**
|
||||||
|
- Other improvements
|
||||||
|
- Fixed
|
||||||
|
- The default options are changed (`Favorite`, `Temporary`, etc.) when changing an account for a created user
|
||||||
|
- When changing the account for a created user, the new account does not apply to that user until SCrawler is restarted
|
||||||
|
- Saved posts: session file is not updated when new data is added
|
||||||
|
- Minor bugs
|
||||||
|
|
||||||
|
# 2023.12.15.0
|
||||||
|
|
||||||
|
*2023-12-15*
|
||||||
|
|
||||||
|
- Fixed
|
||||||
|
- Twitter: some twitter profiles don't download completely
|
||||||
|
- Minor bugs
|
||||||
|
|
||||||
# 2023.12.14.0
|
# 2023.12.14.0
|
||||||
|
|
||||||
*2023-12-14*
|
*2023-12-14*
|
||||||
|
|||||||
164
FAQ.md
@@ -1,120 +1,100 @@
|
|||||||
# Frequently asked questions
|
|
||||||
|
|
||||||
**Please read the [GUIDE](https://github.com/AAndyProgram/SCrawler/wiki/) Before asking a question!**
|
**Join our Discord server**: https://discord.gg/uFNUXvFFmg
|
||||||
|
<br/>*You can get help faster there!*
|
||||||
|
|
||||||
**Also read [here](README.md) for basic information.**
|
# Docs
|
||||||
|
- Basic info: https://github.com/AAndyProgram/SCrawler/blob/main/README.md
|
||||||
|
- **GUIDE**: https://github.com/AAndyProgram/SCrawler/wiki/
|
||||||
|
- Settings: https://github.com/AAndyProgram/SCrawler/wiki/Settings
|
||||||
|
- Discord: https://discord.gg/uFNUXvFFmg
|
||||||
|
|
||||||
Most of your questions are already answered. All settings, functions, buttons and everything else described in the guide.
|
Most of your questions are already answered. All settings, functions, buttons and everything else described in the guide.
|
||||||
|
|
||||||
Any other questions I will keep in this file.
|
# Backup
|
||||||
|
I strongly recommend you to **regularly** create backup copies of the settings files. **An [example script](https://github.com/AAndyProgram/SCrawler/blob/main/Tools/ArchiveSCrawlerUsersDataFiles.bat) for this** on GitHub (you **should adapt** it to your environment, and you can use it when [SCrawler is closed](https://github.com/AAndyProgram/SCrawler/wiki/Settings#behavior)).
|
||||||
|
|
||||||
----
|
**This way you'll always have the latest backup of your settings files and can restore it if something goes wrong!**
|
||||||
|
|
||||||
#### Q: **HOW TO SETUP COOKIES**
|
# How to report a problem
|
||||||
|
1. **Post your problem [here](https://github.com/AAndyProgram/SCrawler/issues) or in the [help channel](https://discord.com/channels/1124032649682493462/1124281838056259614) on our Discord server**
|
||||||
A: https://github.com/AAndyProgram/SCrawler/wiki/Settings#how-to-set-up-cookies
|
2. Attach the **profile URLs or links** that you cannot download.
|
||||||
|
3. Attach the **LOG** if it exists.
|
||||||
<!---**ATTENTION! If you need to use cookies but cannot import them, I highly recommend that you don't use SCrawler and use another program. Don't create issues, discussions, or write to me on Discord. Any issue or discussion about cookies will be deleted immediately without a response. Any user who asks me about cookies on Discord will be banned.**--->
|
4. Attach **the environment information** copied from SCrawler (click the top right info button in the main window, then the `Environment` button, then the `Copy` button, and paste the copied text into the message).
|
||||||
|
5. *Add screenshots to illustrate the problem (**optional**)*
|
||||||
----
|
|
||||||
|
|
||||||
#### Q: **Does this program have GUI or CLI.**
|
|
||||||
|
|
||||||
A: This is a GUI program.
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
#### Q: **Will CLI be added in the future?**
|
|
||||||
|
|
||||||
A: NO.
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
#### Q: **I want to add "...." site. How to request.**
|
|
||||||
|
|
||||||
<!---A: How to request a new site you can read [here](CONTRIBUTING.md#how-to-request-a-new-site)--->
|
|
||||||
**I'm currently not accepting requests to develop new sites.**
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
#### Q: **Site download failed.**
|
|
||||||
|
|
||||||
A: Check your credentials and **[SITES REQUIREMENTS](https://github.com/AAndyProgram/SCrawler/wiki/Settings#sites-requirements)**. If all settings are set, but nothing works, go to [create a new issue](https://github.com/AAndyProgram/SCrawler/issues). Don't forget to attach the LOG.
|
|
||||||
|
|
||||||
**ATTENTION! Issues without URLs will be closed without a response!**
|
**ATTENTION! Issues without URLs will be closed without a response!**
|
||||||
|
|
||||||
----
|
# Most frequently questions about SCrawler
|
||||||
|
|
||||||
#### Q: **I have set credentials but still nothing is downloading**
|
**If something doesn't download, always check the [SITE'S REQUIREMENTS](https://github.com/AAndyProgram/SCrawler/wiki/Settings#sites-requirements) before asking questions!**
|
||||||
|
|
||||||
A: Click the ```Start downloading``` button
|
*How to use: find your problem in the list and read the answer.*
|
||||||
|
|
||||||
----
|
## General questions
|
||||||
|
- **PROFILES**
|
||||||
|
- I added a profile but **nothing downloaded** :arrow_forward: check your cookies and [site requirements](https://github.com/AAndyProgram/SCrawler/wiki/Settings#sites-requirements). If there are any optional fields that you don't fill in, do so. Still nothing works - [report it](#how-to-report-a-problem)!
|
||||||
|
- User downloading failed :arrow_forward: check your credentials and **[SITES REQUIREMENTS](https://github.com/AAndyProgram/SCrawler/wiki/Settings#sites-requirements)**. If all settings are set and nothing works, [report it](#how-to-report-a-problem). **Don't forget to attach the LOG.**
|
||||||
|
- [How to redownload user](https://github.com/AAndyProgram/SCrawler/wiki#redownload-user)
|
||||||
|
- How to **add profile** to download :arrow_forward: copy the **[profile URL](https://github.com/AAndyProgram/SCrawler/wiki#add-user)** and press `Insert` or `Ctrl+Insert`. **ALWAYS PASTE THE USER PROFILE URL**. After that select this user and press `F5` or click the `Download selected` button.
|
||||||
|
- How to download **[saved posts](https://github.com/AAndyProgram/SCrawler/wiki#saved-posts)**
|
||||||
|
- **[HOW TO ADD COOKIES](https://github.com/AAndyProgram/SCrawler/wiki/Settings#how-to-set-up-cookies)**
|
||||||
|
- [How to report a problem](#how-to-report-a-problem)
|
||||||
|
- I want you to **add the site** to SCrawler :arrow_forward: **I'm not currently accepting requests to add new sites**, but you can [create a plugin](https://github.com/AAndyProgram/SCrawler/wiki/Plugins) (for your site) for SCrawler.
|
||||||
|
- What language is SCrawler written in :arrow_forward: `vb.net`
|
||||||
|
- I don't know `vb.net` and I can't write a plugin :arrow_forward: you can write a plugin in `C#`
|
||||||
|
- I have a suggestion, will it be added :arrow_forward: maybe if it interested me.
|
||||||
|
- How to name files using a pattern (e.g. `Site_PostID_Name.jpg`) :arrow_forward: **there is no such functionality and there are no such plans**.
|
||||||
|
- **DON'T CHANGE THE DEFAULT SITE SETTINGS UNLESS YOU KNOW EXACTLY WHAT YOU'RE DOING!** SCrawler already has all the default settings to work. You only need to add credentials (where [required](https://github.com/AAndyProgram/SCrawler/wiki/Settings#sites-requirements)).
|
||||||
|
- My computer shut down while SCrawler was running and now **SCrawler won't start or some users are missing** :arrow_forward: restore user settings from [backup](#backup).
|
||||||
|
- Installation, update and configuration
|
||||||
|
- How to install: https://github.com/AAndyProgram/SCrawler#installation
|
||||||
|
- How to update: https://github.com/AAndyProgram/SCrawler#updating
|
||||||
|
- What file executes the program: **`SCrawler.exe`**
|
||||||
|
- Where to find binaries: https://github.com/AAndyProgram/SCrawler/releases/latest
|
||||||
|
- [How to build from source](https://github.com/AAndyProgram/SCrawler/blob/main/CONTRIBUTING.md#how-to-build-from-source)
|
||||||
|
- [Video how to configure](#video-how-to-configure)
|
||||||
|
- **Antivirus**
|
||||||
|
- **Antivirus detects SCrawler as a virus** :arrow_forward: SCrawler doesn't contain any viruses at all. All code is posted on GitHub. You can review it. I have nothing to hide. SCrawler just downloads pictures and videos. That's all. If you trust SCrawler, you should just add it to the antivirus exceptions, as I did. Sometimes antiviruses identify SCawler as a virus. This is usually related to the number of files being edited (users' settings files) and the number of files being downloaded. In this case, the antivirus can also remove these files, which will damage users' settings. **If you don't trust SCrawler, just delete it.**
|
||||||
|
- **Antivirus detects gallery-dl as a virus** :arrow_forward: it's a trustworthy program that is trusted by thousands of people around the world. Antiviruses identify some builds as containing viruses, but this is not true. **If you don't trust gallery-dl, you can simply delete it. But if you delete it, you won't be able to download [Twitter & Pinterest](https://github.com/AAndyProgram/SCrawler/wiki/Settings#gallery-dl).** You should decide for yourself.
|
||||||
|
|
||||||
#### Q: **Where can I find the release?**
|
## Sites questions
|
||||||
|
|
||||||
A: https://github.com/AAndyProgram/SCrawler/releases/latest
|
*How to use: find the site you need in the list and read the answer.*
|
||||||
|
|
||||||
----
|
- Reddit: don't use credentials at all or configure [OAuth](https://github.com/AAndyProgram/SCrawler/wiki/Settings#how-to-get-reddit-credentials). **Reddit profiles can be downloaded without any credentials at all. Subreddits require OAuth! If nothing downloads, use OAuth!** Don't use OAuth token to download saved posts (use cookies only).
|
||||||
|
- **META** (**Instagram**, Threads, Facebook): you need **cookies** and fill in **all fields**
|
||||||
|
- **Instagram [TIPS](https://github.com/AAndyProgram/SCrawler/wiki/Settings#instagram-tips)**
|
||||||
|
- **Instagram saved posts**: I don't consider questions like "I have 10k saved posts and only 1000 were downloaded". Download posts, remove them from saved posts, delete the `Saved posts` **settings folder**, repeat.
|
||||||
|
- TikTok: works via yt-dlp. If something doesn't download, we need to wait until yt-dlp fixes it. TikTok doesn't require cookies to download.
|
||||||
|
- Porn sites: **COOKIES**!
|
||||||
|
- ThisVid: https://github.com/AAndyProgram/SCrawler/wiki/Settings#thisvid-faq
|
||||||
|
- **OnlyFans**: cookies + **all fields** + [OF-Scraper (download the correct version that I pointed)](https://github.com/AAndyProgram/SCrawler/wiki/Settings#of-scraper) & [mp4decrypt](https://www.bento4.com/downloads/) & **DRM keys** to download DRM protected videos. [OF-Scraper support](https://github.com/AAndyProgram/SCrawler/wiki/Settings#of-scraper-support). Also read [this](https://github.com/AAndyProgram/SCrawler/wiki/Settings#onlyfans-faq)
|
||||||
|
- **JustForFans**: **THE VIDEO ISN'T DOWNLOADING AT THE MOMENT** ([Issue](https://discord.com/channels/1124032649682493462/1205547615199039551/1231349555132366870))
|
||||||
|
|
||||||
#### Q: **How to run the program?**
|
## Other questions
|
||||||
|
|
||||||
A: Double-click ```SCrawler.exe```
|
### Does the program remember the last download and check for new posts, downloading only new posts, or does the program download the entire profile every time
|
||||||
|
The program stored posts IDs in users' folders. For the first time, the program downloads the entire profile. All subsequent times the program will check for new posts and download **only new posts**!
|
||||||
|
|
||||||
----
|
### Does this program have a GUI or CLI, and will a CLI be added in the future
|
||||||
|
This is a GUI program and **NO**, <u>CLI will not be added</u>
|
||||||
|
|
||||||
#### Q: **Where to find binaries?**
|
### How to remove the label
|
||||||
|
There is no functionality to remove an individual label. You can open the `Labels.txt` file in the program settings folder and delete any label you want. You also can delete this file (`Labels.txt`). In this case, when SCrawler is launched, the list of labels will be populated only with existing labels (from the user data files).
|
||||||
|
|
||||||
A: https://github.com/AAndyProgram/SCrawler/releases/latest
|
### How to remove a user from the blacklist
|
||||||
|
Just add that user back to the program. In the dialog box that opens, click the `Add and remove from blacklist` button.
|
||||||
|
|
||||||
----
|
### You lost me. Your program is too complicated.
|
||||||
|
**I'm fine with that**. If the program is too complicated for you or you can't configure it, I can only suggest you find another (easier) program. I really don't mind! The program is free. I develop SCrawler for myself and publish it on GitHub because people found my program useful. If someone can't use it or doesn't like it, I'm okay with it.
|
||||||
|
|
||||||
#### Q: **Does the program remember the last download and check for new posts, downloading only new posts? Or does the program download the entire profile every time?**
|
### Add a step-by-step guide or video on how to use the program
|
||||||
|
**NO!** The guide fully covers all the functionality of SCrawler! If you don't respect my work, I don't waste my time. If you want, you can create a video tutorial and send it to me. Then I'll add it. All options and their purposes are described on the wiki. The wiki also contains a description of all the settings and how to configure them. For complex settings there is a step-by-step guide. Read the [main](README.md) information and [GUIDE](https://github.com/AAndyProgram/SCrawler/wiki/) and you won't have any problems. I've developed a program with an intuitive interface. There is a `Settings` button, download buttons, a context menu that appears when you right-click on a user, and other controls. Anyone can use it.
|
||||||
|
|
||||||
A: The program stored posts IDs in users' folders. For the first time, the program downloads the entire profile. All subsequent times the program will check for new posts and download **only new posts**!
|
**There is already a [video](#video-how-to-configure) example of how to configure a site.**
|
||||||
|
|
||||||
----
|
# Video how to configure
|
||||||
|
|
||||||
#### Q: **How to redownload all data**
|
**The following video was recorded by a user who loves SCrawler and demonstrates how to add credentials using Instagram as an example:**
|
||||||
|
|
||||||
A: Double-click on the user you want to redownload. In the opened window open folder setting. Delete the files ending with ```_Data.xml``` and ```_Posts.txt```. Restart SCrawler. Download this user again.
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
#### Q: **How to remove the label**
|
|
||||||
|
|
||||||
A: There is no functionality to remove an individual label. You can open the ```Labels.txt``` file in the program settings folder and delete any label you want. You also can delete this file (```Labels.txt```). In this case, when the program starts, the list of labels list will be updated with only existing labels (from the user data files).
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
#### Q: **How to remove a user from the blacklist**
|
|
||||||
|
|
||||||
A: Just add that user back to the program. In the dialog box that opens, click on the ```Add and remove from blacklist``` button.
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
#### Q: **Why don't you answer how it works**
|
|
||||||
|
|
||||||
A: Because **I don't want to**. I don't want to waste my time explaining things that are already covered in the **[GUIDE](https://github.com/AAndyProgram/SCrawler/wiki)**! If you didn't bother to read the guide, why would I waste my time?! ALL FUNCTIONALITY IS DESCRIBED IN THE GUIDE. Before publishing a new release, I update the guide. If you don't respect my work, I don't waste my time.
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
#### Q: **You lost me. Your program is too complicated.**
|
|
||||||
|
|
||||||
A: **I'm fine with that**. If the program is difficult for you or you can't configure it, I can only suggest you find another (easier) program. I really don't mind! The program is free. I am develop SCrawler for myself and publish on GitHub because people found my program useful. If someone can't use it or doesn't like it, I'm fine.
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
#### Q: **I can't configure something**
|
|
||||||
|
|
||||||
A: I can only [suggest](#q-you-lost-me-your-program-is-too-complicated) you find another (easier) program.
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
#### Q: **Can you add a step-by-step guide or video on how to use the program?**
|
|
||||||
|
|
||||||
A: **NO! NEVER!** The guide fully covers all the functionality of SCrawler! If you don't respect my work, I don't waste my time. If you want, you can create a video tutorial and send it to me. Then I add it. All options and what each option does described on the wiki. The wiki also contains a description of all settings and how-to configure them. For complex settings, there is a steep-by-steep guide. Read the [main](README.md) information and [GUIDE](https://github.com/AAndyProgram/SCrawler/wiki/) and you won't have any problems. I have developed a program with an intuitive interface. There is a Settings button, download buttons, a context menu that drops down when a user is clicked, and other controls. Anyone can use it.
|
|
||||||
|
|
||||||
**The following video shows how to add credentials:**
|
|
||||||
|
|
||||||
[](https://www.youtube.com/watch?v=XDn7zG4I700)
|
[](https://www.youtube.com/watch?v=XDn7zG4I700)
|
||||||
@@ -2,6 +2,8 @@ You can create a plugin for any site you want. **To create a plugin, read [this
|
|||||||
|
|
||||||
If you've created a plugin, you can create a [new issue](https://github.com/AAndyProgram/SCrawler/issues/new?assignees=&labels=New+Plugin&projects=&template=plugin_add.md&title=%5BNEW+PLUGIN%5D) and I'll add your plugin to the list below.
|
If you've created a plugin, you can create a [new issue](https://github.com/AAndyProgram/SCrawler/issues/new?assignees=&labels=New+Plugin&projects=&template=plugin_add.md&title=%5BNEW+PLUGIN%5D) and I'll add your plugin to the list below.
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
List of available plugins:
|
List of available plugins:
|
||||||
|
|
||||||
Tools:
|
Tools:
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 59 KiB |
BIN
ProgramScreenshots/FeedMoveCopyTo.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 491 KiB After Width: | Height: | Size: 472 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 103 KiB After Width: | Height: | Size: 101 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 24 KiB |
BIN
ProgramScreenshots/SettingsGlobalHeaders.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 13 KiB |
BIN
ProgramScreenshots/SettingsSiteBluesky.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 46 KiB |
BIN
ProgramScreenshots/SettingsSiteInstagramData.png
Normal file
|
After Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 31 KiB |
BIN
ProgramScreenshots/SettingsSiteOnlyFansAdditional.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 14 KiB |
@@ -6,11 +6,19 @@ https://github.com/yt-dlp/yt-dlp/
|
|||||||
|
|
||||||
SCrawler has advanced user management, collections, labels, groups, automatic downloads, a beautiful view, GUI, the ability to add plugins for other sites and much more. Just try it and compare.
|
SCrawler has advanced user management, collections, labels, groups, automatic downloads, a beautiful view, GUI, the ability to add plugins for other sites and much more. Just try it and compare.
|
||||||
|
|
||||||
|
# gallery-dl
|
||||||
|
|
||||||
|
https://github.com/mikf/gallery-dl
|
||||||
|
|
||||||
|
**Great powerful CLI tool that supports hundreds of sites.**
|
||||||
|
|
||||||
|
SCrawler has advanced user management, collections, labels, groups, automatic downloads, a beautiful view, GUI, the ability to add plugins for other sites and much more. Just try it and compare.
|
||||||
|
|
||||||
# 4K Video Downloader
|
# 4K Video Downloader
|
||||||
|
|
||||||
https://www.4kdownload.com/-plbrz/video-downloader
|
https://www.4kdownload.com/-plbrz/video-downloader
|
||||||
|
|
||||||
| Option | SCrawler | 4K Stogram |
|
| Option | SCrawler | 4K Video Downloader |
|
||||||
| ---- | ---- | ---- |
|
| ---- | ---- | ---- |
|
||||||
| User managament | **Advanced** | No |
|
| User managament | **Advanced** | No |
|
||||||
| Automatic downloads | **Yes** | No |
|
| Automatic downloads | **Yes** | No |
|
||||||
@@ -121,10 +129,3 @@ https://github.com/RipMeApp/ripme
|
|||||||
| Other sites support | **Yes** | No |
|
| Other sites support | **Yes** | No |
|
||||||
| Still supported | **Yes** | **No (last release date May 4, 2021)** |
|
| Still supported | **Yes** | **No (last release date May 4, 2021)** |
|
||||||
|
|
||||||
# gallery-dl
|
|
||||||
|
|
||||||
https://github.com/mikf/gallery-dl
|
|
||||||
|
|
||||||
**CLI tool**
|
|
||||||
|
|
||||||
SCrawler has advanced user management, collections, labels, groups, automatic downloads, a beautiful view, GUI, the ability to add plugins for other sites and much more. Just try it and compare.
|
|
||||||
57
README.md
@@ -1,5 +1,5 @@
|
|||||||
<!-- # :rainbow_flag: Happy LGBT Pride Month :tada:
|
# 🏳️🌈 Happy LGBT Pride Month 🎉
|
||||||
-->
|
|
||||||
# 🏳️🌈 Social networks crawler 🏳️🌈
|
# 🏳️🌈 Social networks crawler 🏳️🌈
|
||||||
|
|
||||||
[](https://github.com/AAndyProgram/SCrawler/releases/latest)
|
[](https://github.com/AAndyProgram/SCrawler/releases/latest)
|
||||||
@@ -15,6 +15,10 @@
|
|||||||
A program to download photo and video from [any site](#supported-sites) (e.g. YouTube, YouTube Music, OnlyFans, Reddit, Twitter, Mastodon, Instagram, Threads, Facebook, TikTok, RedGifs, JustForFans, PornHub, XHamster, XVIDEOS, ThisVid, LPSG, Pinterest).
|
A program to download photo and video from [any site](#supported-sites) (e.g. YouTube, YouTube Music, OnlyFans, Reddit, Twitter, Mastodon, Instagram, Threads, Facebook, TikTok, RedGifs, JustForFans, PornHub, XHamster, XVIDEOS, ThisVid, LPSG, Pinterest).
|
||||||
|
|
||||||
**If you like SCrawler, please like the program on [this site](https://alternativeto.net/software/scrawler/about/) and/or [this](https://www.softpedia.com/get/Internet/Download-Managers/Social-networks-crawler.shtml)**
|
**If you like SCrawler, please like the program on [this site](https://alternativeto.net/software/scrawler/about/) and/or [this](https://www.softpedia.com/get/Internet/Download-Managers/Social-networks-crawler.shtml)**
|
||||||
|
|
||||||
|
**Join our Discord server**: https://discord.gg/uFNUXvFFmg
|
||||||
|
<br/>*If you have problems using the program, you can get help faster on our Discord server!*
|
||||||
|
|
||||||
<!---Do you like this program? Consider adding to my coffee fund by making a donation to show your support. :blush:
|
<!---Do you like this program? Consider adding to my coffee fund by making a donation to show your support. :blush:
|
||||||
[](https://ko-fi.com/andyprogram)--->
|
[](https://ko-fi.com/andyprogram)--->
|
||||||
**Bitcoin**: BC1Q0NH839FT5TA44DD7L7RLR97XDQAG9V8D6N7XET
|
**Bitcoin**: BC1Q0NH839FT5TA44DD7L7RLR97XDQAG9V8D6N7XET
|
||||||
@@ -29,16 +33,17 @@ A program to download photo and video from [any site](#supported-sites) (e.g. Yo
|
|||||||

|

|
||||||
|
|
||||||
# What can program do:
|
# What can program do:
|
||||||
- Download pictures and videos from users' profiles and subreddits:
|
- Download pictures and videos from user profiles:
|
||||||
- YouTube videos, shorts, community feeds, users, artists, playlists, music, tracks;
|
- YouTube videos, shorts, community feeds, users, artists, playlists, music, tracks;
|
||||||
- Reddit images, galleries of images, videos, saved posts;
|
- Reddit images, galleries of images, videos, saved posts;
|
||||||
- Redgifs videos (https://www.redgifs.com/);
|
- Redgifs images and videos (https://www.redgifs.com/);
|
||||||
- Twitter images and videos, saved (bookmarked) posts;
|
- Twitter images and videos, saved (bookmarked) posts, likes, communities;
|
||||||
- OnlyFans images and videos, saved (bookmarked) posts;
|
- Bluesky images and videos;
|
||||||
|
- OnlyFans images and videos, saved (bookmarked) posts, stories;
|
||||||
- JustForFans images and videos, saved (bookmarked) posts;
|
- JustForFans images and videos, saved (bookmarked) posts;
|
||||||
- Mastodon images and videos, saved (bookmarked) posts;
|
- Mastodon images and videos, saved (bookmarked) posts;
|
||||||
- Instagram images and videos, tagged posts, stories, saved posts;
|
- Instagram images and videos, tagged posts, stories, saved posts;
|
||||||
- Threads images and videos;
|
- Threads images and videos, saved posts;
|
||||||
- Facebook images and videos, stories, saved posts;
|
- Facebook images and videos, stories, saved posts;
|
||||||
- TikTok videos;
|
- TikTok videos;
|
||||||
- Pinterest boards, users, saved posts;
|
- Pinterest boards, users, saved posts;
|
||||||
@@ -53,7 +58,7 @@ A program to download photo and video from [any site](#supported-sites) (e.g. Yo
|
|||||||
- Download [saved posts](https://github.com/AAndyProgram/SCrawler/wiki/Home#saved-posts)
|
- Download [saved posts](https://github.com/AAndyProgram/SCrawler/wiki/Home#saved-posts)
|
||||||
- Add users from parsed channel
|
- Add users from parsed channel
|
||||||
- **Advanced user management**
|
- **Advanced user management**
|
||||||
- **Automation** ([downloading data automatically](https://github.com/AAndyProgram/SCrawler/wiki/Settings#automation) every ```X``` minutes)
|
- **Automation** ([downloading data automatically](https://github.com/AAndyProgram/SCrawler/wiki/Settings#automation) every `X` minutes)
|
||||||
- **Feed** ([feed](https://github.com/AAndyProgram/SCrawler/wiki#feed) of downloaded media files and subscriptions posts)
|
- **Feed** ([feed](https://github.com/AAndyProgram/SCrawler/wiki#feed) of downloaded media files and subscriptions posts)
|
||||||
- Multiple accounts support
|
- Multiple accounts support
|
||||||
- Labeling users
|
- Labeling users
|
||||||
@@ -74,16 +79,17 @@ A program to download photo and video from [any site](#supported-sites) (e.g. Yo
|
|||||||
- **YouTube Music**
|
- **YouTube Music**
|
||||||
- **Reddit**
|
- **Reddit**
|
||||||
- **Twitter**
|
- **Twitter**
|
||||||
- **OnlyFans**
|
- **Bluesky**
|
||||||
- **Mastodon**
|
- **OnlyFans** *(partial support)*[^1]
|
||||||
- **Instagram**
|
- **Instagram**
|
||||||
- **Threads**
|
- **Threads**
|
||||||
- **Facebook**
|
- **Facebook**
|
||||||
- JustForFans
|
- JustForFans *(partial support) ([video issue](https://discord.com/channels/1124032649682493462/1205547615199039551/1231349555132366870))*[^1]
|
||||||
|
- Mastodon *(out of support)*
|
||||||
- TikTok
|
- TikTok
|
||||||
- RedGifs
|
- RedGifs
|
||||||
- Pinterest
|
- Pinterest
|
||||||
- Imgur
|
- Imgur *(out of support)*
|
||||||
- Gfycat
|
- Gfycat
|
||||||
- LPSG
|
- LPSG
|
||||||
- **PornHub**
|
- **PornHub**
|
||||||
@@ -105,7 +111,7 @@ First, the program downloads the full profile. After the program downloads only
|
|||||||
|
|
||||||
# Requirements
|
# Requirements
|
||||||
|
|
||||||
- Windows 10, 11 with NET Framework 4.6.1 or higher (v4.6.1 must be installed). You can check version compatibility with this [tool](Tools/NET.FrameworkVersion.ps1).
|
- **Windows 10, 11** with NET Framework 4.6.1 or higher (v4.6.1 must be installed). You can check version compatibility with this [tool](Tools/NET.FrameworkVersion.ps1).
|
||||||
- **[SITES REQUIREMENTS](https://github.com/AAndyProgram/SCrawler/wiki/Settings#sites-requirements)**
|
- **[SITES REQUIREMENTS](https://github.com/AAndyProgram/SCrawler/wiki/Settings#sites-requirements)**
|
||||||
|
|
||||||
# Guide
|
# Guide
|
||||||
@@ -127,6 +133,7 @@ First, the program downloads the full profile. After the program downloads only
|
|||||||
- **[SITES REQUIREMENTS](https://github.com/AAndyProgram/SCrawler/wiki/Settings#sites-requirements)**
|
- **[SITES REQUIREMENTS](https://github.com/AAndyProgram/SCrawler/wiki/Settings#sites-requirements)**
|
||||||
- [Reddit](https://github.com/AAndyProgram/SCrawler/wiki/Settings#reddit)
|
- [Reddit](https://github.com/AAndyProgram/SCrawler/wiki/Settings#reddit)
|
||||||
- [Twitter](https://github.com/AAndyProgram/SCrawler/wiki/Settings#twitter)
|
- [Twitter](https://github.com/AAndyProgram/SCrawler/wiki/Settings#twitter)
|
||||||
|
- [Bluesky](https://github.com/AAndyProgram/SCrawler/wiki/Settings#bluesky)
|
||||||
- [OnlyFans](https://github.com/AAndyProgram/SCrawler/wiki/Settings#onlyfans)
|
- [OnlyFans](https://github.com/AAndyProgram/SCrawler/wiki/Settings#onlyfans)
|
||||||
- [Mastodon](https://github.com/AAndyProgram/SCrawler/wiki/Settings#mastodon)
|
- [Mastodon](https://github.com/AAndyProgram/SCrawler/wiki/Settings#mastodon)
|
||||||
- [Instagram](https://github.com/AAndyProgram/SCrawler/wiki/Settings#instagram)
|
- [Instagram](https://github.com/AAndyProgram/SCrawler/wiki/Settings#instagram)
|
||||||
@@ -153,11 +160,17 @@ First, the program downloads the full profile. After the program downloads only
|
|||||||
|
|
||||||
**Just download the [latest release](https://github.com/AAndyProgram/SCrawler/releases/latest), unzip the program archive to any folder and enjoy.** :blush:
|
**Just download the [latest release](https://github.com/AAndyProgram/SCrawler/releases/latest), unzip the program archive to any folder and enjoy.** :blush:
|
||||||
|
|
||||||
**Don't put program in the ```Program Files``` system folder (this is portable program and program settings are stored in the program folder)**
|
**Don't put program in the `Program Files` system folder (this is portable program and program settings are stored in the program folder)**
|
||||||
|
|
||||||
|
**I highly doubt you can run SCrawler on Linux or Mac. SCrawler is a program that is heavily dependent on Windows.**
|
||||||
|
|
||||||
# Updating
|
# Updating
|
||||||
|
|
||||||
Just download [latest](https://github.com/AAndyProgram/SCrawler/releases/latest) version and unpack it into the program folder. **Before starting a new version, I recommend making a backup copy of the program settings folder.**
|
Just download [latest](https://github.com/AAndyProgram/SCrawler/releases/latest) version and unpack it into the program folder. **Before launching a new version, I recommend making a backup copy of the program settings folder and user settings/data files.**
|
||||||
|
|
||||||
|
**You can also use the updater included in the release package.**
|
||||||
|
|
||||||
|
# [How to report a problem](CONTRIBUTING.md#how-to-report-a-problem)
|
||||||
|
|
||||||
# [How to build from source](CONTRIBUTING.md#how-to-build-from-source)
|
# [How to build from source](CONTRIBUTING.md#how-to-build-from-source)
|
||||||
|
|
||||||
@@ -173,7 +186,7 @@ The program has an intuitive interface.
|
|||||||
|
|
||||||
[](https://www.youtube.com/watch?v=XDn7zG4I700)
|
[](https://www.youtube.com/watch?v=XDn7zG4I700)
|
||||||
|
|
||||||
Just add a user profile and **click the ```Download``` button**.
|
Just add a user profile and **click the `Download` button**.
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
stateDiagram
|
stateDiagram
|
||||||
@@ -205,14 +218,4 @@ F5-->[*]
|
|||||||
|
|
||||||
Discord server: https://discord.gg/uFNUXvFFmg
|
Discord server: https://discord.gg/uFNUXvFFmg
|
||||||
|
|
||||||
<!--
|
[^1]: Partial support means that I don't have personal accounts on paid porn sites because I don't pay for porn. If this site has stopped downloading and you want me to fix it, please be ready to give me access to an account with at least one active subscription. Otherwise, the download from this site will not be fixed.
|
||||||
[e-mail](mailto:andyprogram@proton.me): andyprogram@proton.me
|
|
||||||
|
|
||||||
Matrix (Element): https://matrix.to/#/@andyprogram:matrix.org
|
|
||||||
|
|
||||||
Discord (contact the developer): andyprogram
|
|
||||||
|
|
||||||
Discord server: https://discord.gg/uFNUXvFFmg
|
|
||||||
|
|
||||||
[Wire](https://account.wire.com/user-profile/?id=93985052-cf2c-4b72-ac75-bbe3231cf544): @andyprogram
|
|
||||||
-->
|
|
||||||
@@ -36,8 +36,24 @@ Namespace Plugin.Attributes
|
|||||||
Public Property IsInformationLabel As Boolean = False
|
Public Property IsInformationLabel As Boolean = False
|
||||||
''' <summary>Label text alignment.<br/>Default: <see cref="Drawing.ContentAlignment.TopCenter"/></summary>
|
''' <summary>Label text alignment.<br/>Default: <see cref="Drawing.ContentAlignment.TopCenter"/></summary>
|
||||||
Public Property LabelTextAlign As Drawing.ContentAlignment = Drawing.ContentAlignment.TopCenter
|
Public Property LabelTextAlign As Drawing.ContentAlignment = Drawing.ContentAlignment.TopCenter
|
||||||
|
Private _IsAuth As Boolean = False
|
||||||
''' <summary>This is an authorization property</summary>
|
''' <summary>This is an authorization property</summary>
|
||||||
Public Property IsAuth As Boolean = False
|
Public Property IsAuth As Boolean
|
||||||
|
Get
|
||||||
|
Return _IsAuth
|
||||||
|
End Get
|
||||||
|
Set(ByVal _IsAuth As Boolean)
|
||||||
|
Me._IsAuth = _IsAuth
|
||||||
|
If _IsAuth And String.IsNullOrEmpty(Category) Then
|
||||||
|
Category = CategoryAuth
|
||||||
|
ElseIf Not _IsAuth AndAlso Not String.IsNullOrEmpty(Category) AndAlso Category = CategoryAuth Then
|
||||||
|
Category = String.Empty
|
||||||
|
End If
|
||||||
|
End Set
|
||||||
|
End Property
|
||||||
|
Public Const CategoryAuth As String = "Authorization"
|
||||||
|
Public Property Category As String = Nothing
|
||||||
|
Public Property InheritanceName As String = Nothing
|
||||||
''' <summary>Initialize a new property option attribute</summary>
|
''' <summary>Initialize a new property option attribute</summary>
|
||||||
''' <param name="PropertyName">Property name</param>
|
''' <param name="PropertyName">Property name</param>
|
||||||
Public Sub New(<CallerMemberName()> Optional ByVal PropertyName As String = Nothing)
|
Public Sub New(<CallerMemberName()> Optional ByVal PropertyName As String = Nothing)
|
||||||
@@ -57,6 +73,7 @@ Namespace Plugin.Attributes
|
|||||||
''' <summary>Store property value in settings XML file</summary>
|
''' <summary>Store property value in settings XML file</summary>
|
||||||
<AttributeUsage(AttributeTargets.Property, AllowMultiple:=False, Inherited:=False)> Public NotInheritable Class PXML : Inherits Attribute
|
<AttributeUsage(AttributeTargets.Property, AllowMultiple:=False, Inherited:=False)> Public NotInheritable Class PXML : Inherits Attribute
|
||||||
Public ReadOnly ElementName As String
|
Public ReadOnly ElementName As String
|
||||||
|
Public Property OnlyForChecked As Boolean = False
|
||||||
''' <summary>Initialize a new XML attribute</summary>
|
''' <summary>Initialize a new XML attribute</summary>
|
||||||
''' <param name="XMLElementName">XML element name</param>
|
''' <param name="XMLElementName">XML element name</param>
|
||||||
Public Sub New(<CallerMemberName()> Optional ByVal XMLElementName As String = Nothing)
|
Public Sub New(<CallerMemberName()> Optional ByVal XMLElementName As String = Nothing)
|
||||||
@@ -188,4 +205,13 @@ Namespace Plugin.Attributes
|
|||||||
Repository = RepoName
|
Repository = RepoName
|
||||||
End Sub
|
End Sub
|
||||||
End Class
|
End Class
|
||||||
|
''' <summary>Replace internal plugin with the current one</summary>
|
||||||
|
<AttributeUsage(AttributeTargets.Class, AllowMultiple:=False, Inherited:=False)> Public NotInheritable Class ReplaceInternalPluginAttribute : Inherits Attribute
|
||||||
|
Public ReadOnly SiteName As String
|
||||||
|
Public ReadOnly PluginKey As String
|
||||||
|
Public Sub New(ByVal PluginKey As String, Optional ByVal SiteName As String = Nothing)
|
||||||
|
Me.PluginKey = PluginKey
|
||||||
|
Me.SiteName = SiteName
|
||||||
|
End Sub
|
||||||
|
End Class
|
||||||
End Namespace
|
End Namespace
|
||||||
@@ -17,6 +17,7 @@ Namespace Plugin
|
|||||||
Property Settings As ISiteSettings
|
Property Settings As ISiteSettings
|
||||||
Property AccountName As String
|
Property AccountName As String
|
||||||
Property Name As String
|
Property Name As String
|
||||||
|
Property NameTrue As String
|
||||||
Property ID As String
|
Property ID As String
|
||||||
Property Options As String
|
Property Options As String
|
||||||
Property ParseUserMediaOnly As Boolean
|
Property ParseUserMediaOnly As Boolean
|
||||||
@@ -40,5 +41,6 @@ Namespace Plugin
|
|||||||
Sub GetMedia(ByVal Token As Threading.CancellationToken)
|
Sub GetMedia(ByVal Token As Threading.CancellationToken)
|
||||||
Sub Download(ByVal Token As Threading.CancellationToken)
|
Sub Download(ByVal Token As Threading.CancellationToken)
|
||||||
Sub DownloadSingleObject(ByVal Data As IDownloadableMedia, ByVal Token As Threading.CancellationToken)
|
Sub DownloadSingleObject(ByVal Data As IDownloadableMedia, ByVal Token As Threading.CancellationToken)
|
||||||
|
Sub ResetHistoryData()
|
||||||
End Interface
|
End Interface
|
||||||
End Namespace
|
End Namespace
|
||||||
@@ -17,6 +17,10 @@ Namespace Plugin
|
|||||||
ReadOnly Property Icon As Icon
|
ReadOnly Property Icon As Icon
|
||||||
ReadOnly Property Image As Image
|
ReadOnly Property Image As Image
|
||||||
ReadOnly Property Site As String
|
ReadOnly Property Site As String
|
||||||
|
Property CMDEncoding As String
|
||||||
|
Property EnvironmentPrograms As IEnumerable(Of String)
|
||||||
|
Property UserAgentDefault As String
|
||||||
|
Sub EnvironmentProgramsUpdated()
|
||||||
Property AccountName As String
|
Property AccountName As String
|
||||||
Property Temporary As Boolean
|
Property Temporary As Boolean
|
||||||
Property DefaultInstance As ISiteSettings
|
Property DefaultInstance As ISiteSettings
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ Imports System.Runtime.InteropServices
|
|||||||
<Assembly: AssemblyDescription("Plugin provider for SCrawler")>
|
<Assembly: AssemblyDescription("Plugin provider for SCrawler")>
|
||||||
<Assembly: AssemblyCompany("AndyProgram")>
|
<Assembly: AssemblyCompany("AndyProgram")>
|
||||||
<Assembly: AssemblyProduct("SCrawler.PluginProvider")>
|
<Assembly: AssemblyProduct("SCrawler.PluginProvider")>
|
||||||
<Assembly: AssemblyCopyright("Copyright © 2024")>
|
<Assembly: AssemblyCopyright("Copyright © 2025")>
|
||||||
<Assembly: AssemblyTrademark("AndyProgram")>
|
<Assembly: AssemblyTrademark("AndyProgram")>
|
||||||
|
|
||||||
<Assembly: ComVisible(False)>
|
<Assembly: ComVisible(False)>
|
||||||
@@ -32,6 +32,6 @@ Imports System.Runtime.InteropServices
|
|||||||
' by using the '*' as shown below:
|
' by using the '*' as shown below:
|
||||||
' <Assembly: AssemblyVersion("1.0.*")>
|
' <Assembly: AssemblyVersion("1.0.*")>
|
||||||
|
|
||||||
<Assembly: AssemblyVersion("2023.11.24.0")>
|
<Assembly: AssemblyVersion("2025.2.25.0")>
|
||||||
<Assembly: AssemblyFileVersion("2023.11.24.0")>
|
<Assembly: AssemblyFileVersion("2025.2.25.0")>
|
||||||
<Assembly: NeutralResourcesLanguage("en")>
|
<Assembly: NeutralResourcesLanguage("en")>
|
||||||
|
|||||||
@@ -9,8 +9,23 @@
|
|||||||
Namespace Plugin
|
Namespace Plugin
|
||||||
Public NotInheritable Class PropertyValue : Implements IPropertyValue
|
Public NotInheritable Class PropertyValue : Implements IPropertyValue
|
||||||
Public Event ValueChanged As IPropertyValue.ValueChangedEventHandler Implements IPropertyValue.ValueChanged
|
Public Event ValueChanged As IPropertyValue.ValueChangedEventHandler Implements IPropertyValue.ValueChanged
|
||||||
|
Public Event CheckedChanged As IPropertyValue.ValueChangedEventHandler
|
||||||
Public Property [Type] As Type Implements IPropertyValue.Type
|
Public Property [Type] As Type Implements IPropertyValue.Type
|
||||||
Public Property OnChangeFunction As IPropertyValue.ValueChangedEventHandler
|
Public Property OnChangeFunction As IPropertyValue.ValueChangedEventHandler
|
||||||
|
Public Property OnCheckboxCheckedChange As EventHandler(Of PropertyValueEventArgs)
|
||||||
|
Private _Checked As Boolean = False
|
||||||
|
Public Property Checked As Boolean
|
||||||
|
Get
|
||||||
|
Return _Checked
|
||||||
|
End Get
|
||||||
|
Set(ByVal IsChecked As Boolean)
|
||||||
|
_Checked = IsChecked
|
||||||
|
If Not _Initialization Then
|
||||||
|
If Not OnCheckboxCheckedChange Is Nothing Then OnCheckboxCheckedChange.Invoke(Me, EventArgs.Empty)
|
||||||
|
RaiseEvent CheckedChanged(_Checked)
|
||||||
|
End If
|
||||||
|
End Set
|
||||||
|
End Property
|
||||||
Private _Initialization As Boolean = False
|
Private _Initialization As Boolean = False
|
||||||
''' <inheritdoc cref="PropertyValue.New(Object, Type, ByRef IPropertyValue.ValueChangedEventHandler)"/>
|
''' <inheritdoc cref="PropertyValue.New(Object, Type, ByRef IPropertyValue.ValueChangedEventHandler)"/>
|
||||||
''' <exception cref="ArgumentNullException"></exception>
|
''' <exception cref="ArgumentNullException"></exception>
|
||||||
@@ -59,6 +74,7 @@ Namespace Plugin
|
|||||||
Type = Source.Type
|
Type = Source.Type
|
||||||
OnChangeFunction = Source.OnChangeFunction
|
OnChangeFunction = Source.OnChangeFunction
|
||||||
_Value = Source._Value
|
_Value = Source._Value
|
||||||
|
_Checked = Source._Checked
|
||||||
_Initialization = False
|
_Initialization = False
|
||||||
End Sub
|
End Sub
|
||||||
End Class
|
End Class
|
||||||
@@ -71,4 +87,8 @@ Namespace Plugin
|
|||||||
''' <summary>Property value</summary>
|
''' <summary>Property value</summary>
|
||||||
Property Value As Object
|
Property Value As Object
|
||||||
End Interface
|
End Interface
|
||||||
|
Public Class PropertyValueEventArgs : Inherits EventArgs
|
||||||
|
Public Property Checked As Boolean = False
|
||||||
|
Public Property ControlEnabled As Boolean = True
|
||||||
|
End Class
|
||||||
End Namespace
|
End Namespace
|
||||||
@@ -23,7 +23,7 @@ Namespace [Shared]
|
|||||||
Next
|
Next
|
||||||
End If
|
End If
|
||||||
End With
|
End With
|
||||||
If versions.Count > 0 Then Return versions.LastOrDefault
|
If versions.Count > 0 Then Return versions.Max
|
||||||
End If
|
End If
|
||||||
Catch
|
Catch
|
||||||
End Try
|
End Try
|
||||||
|
|||||||
@@ -32,6 +32,6 @@ Imports System.Runtime.InteropServices
|
|||||||
' by using the '*' as shown below:
|
' by using the '*' as shown below:
|
||||||
' <Assembly: AssemblyVersion("1.0.*")>
|
' <Assembly: AssemblyVersion("1.0.*")>
|
||||||
|
|
||||||
<Assembly: AssemblyVersion("2023.12.7.0")>
|
<Assembly: AssemblyVersion("2023.12.15.0")>
|
||||||
<Assembly: AssemblyFileVersion("2023.12.7.0")>
|
<Assembly: AssemblyFileVersion("2023.12.15.0")>
|
||||||
<Assembly: NeutralResourcesLanguage("en")>
|
<Assembly: NeutralResourcesLanguage("en")>
|
||||||
|
|||||||
@@ -78,9 +78,21 @@ Namespace API.YouTube.Base
|
|||||||
https = 1
|
https = 1
|
||||||
m3u8 = 2
|
m3u8 = 2
|
||||||
End Enum
|
End Enum
|
||||||
|
<Editor(GetType(EnumDropDownEditor), GetType(UITypeEditor))>
|
||||||
|
Public Enum FileDateMode As Integer
|
||||||
|
None = 0
|
||||||
|
Before = 1
|
||||||
|
After = 2
|
||||||
|
End Enum
|
||||||
|
Public Enum M3U8CreationMode As Integer
|
||||||
|
Relative = 0
|
||||||
|
Absolute = 1
|
||||||
|
Both = 2
|
||||||
|
End Enum
|
||||||
Public Structure MediaObject : Implements IIndexable, IComparable(Of MediaObject)
|
Public Structure MediaObject : Implements IIndexable, IComparable(Of MediaObject)
|
||||||
Public Type As Plugin.UserMediaTypes
|
Public Type As Plugin.UserMediaTypes
|
||||||
Public ID As String
|
Public ID As String
|
||||||
|
Public ID_DRC As Boolean
|
||||||
Public Extension As String
|
Public Extension As String
|
||||||
Public Width As Integer
|
Public Width As Integer
|
||||||
Public Height As Integer
|
Public Height As Integer
|
||||||
@@ -110,10 +122,14 @@ Namespace API.YouTube.Base
|
|||||||
End Function
|
End Function
|
||||||
Private Function CompareTo(ByVal Other As MediaObject) As Integer Implements IComparable(Of MediaObject).CompareTo
|
Private Function CompareTo(ByVal Other As MediaObject) As Integer Implements IComparable(Of MediaObject).CompareTo
|
||||||
If Type = Other.Type Then
|
If Type = Other.Type Then
|
||||||
If Width.CompareTo(Other.Width) = 0 Then
|
If ID_DRC.CompareTo(Other.ID_DRC) = 0 Then
|
||||||
Return Size.CompareTo(Other.Size) * -1
|
If Width.CompareTo(Other.Width) = 0 Then
|
||||||
|
Return Size.CompareTo(Other.Size) * -1
|
||||||
|
Else
|
||||||
|
Return Width.CompareTo(Other.Width) * -1
|
||||||
|
End If
|
||||||
Else
|
Else
|
||||||
Return Width.CompareTo(Other.Width) * -1
|
Return ID_DRC.CompareTo(Other.ID_DRC)
|
||||||
End If
|
End If
|
||||||
Else
|
Else
|
||||||
Return CInt(Type).CompareTo(CInt(Other.Type))
|
Return CInt(Type).CompareTo(CInt(Other.Type))
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ Namespace API.YouTube.Base
|
|||||||
End Sub
|
End Sub
|
||||||
Public Shared Function StandardizeURL(ByVal URL As String) As String
|
Public Shared Function StandardizeURL(ByVal URL As String) As String
|
||||||
Try
|
Try
|
||||||
|
URL = URL.StringTrim
|
||||||
Dim isMusic As Boolean = False, isShorts As Boolean = False
|
Dim isMusic As Boolean = False, isShorts As Boolean = False
|
||||||
If Info_GetUrlType(URL, isMusic, isShorts) = YouTubeMediaType.Single Then
|
If Info_GetUrlType(URL, isMusic, isShorts) = YouTubeMediaType.Single Then
|
||||||
If Not isMusic And Not isShorts Then
|
If Not isMusic And Not isShorts Then
|
||||||
@@ -45,6 +46,7 @@ Namespace API.YouTube.Base
|
|||||||
End Function
|
End Function
|
||||||
Public Shared Function StandardizeURL_Channel(ByVal URL As String, Optional ByVal Process As Boolean = True) As String
|
Public Shared Function StandardizeURL_Channel(ByVal URL As String, Optional ByVal Process As Boolean = True) As String
|
||||||
Try
|
Try
|
||||||
|
URL = URL.StringTrim
|
||||||
Dim ct As YouTubeChannelTab = YouTubeChannelTab.All
|
Dim ct As YouTubeChannelTab = YouTubeChannelTab.All
|
||||||
Dim isMusic As Boolean = False
|
Dim isMusic As Boolean = False
|
||||||
If Process AndAlso Info_GetUrlType(URL, isMusic,,,, ct) = YouTubeMediaType.Channel AndAlso Not isMusic Then
|
If Process AndAlso Info_GetUrlType(URL, isMusic,,,, ct) = YouTubeMediaType.Channel AndAlso Not isMusic Then
|
||||||
@@ -72,6 +74,7 @@ Namespace API.YouTube.Base
|
|||||||
Public Shared Function Info_GetUrlType(ByVal URL As String, Optional ByRef IsMusic As Boolean = False, Optional ByRef IsShorts As Boolean = False,
|
Public Shared Function Info_GetUrlType(ByVal URL As String, Optional ByRef IsMusic As Boolean = False, Optional ByRef IsShorts As Boolean = False,
|
||||||
Optional ByRef IsChannelUser As Boolean = False, Optional ByRef Id As String = Nothing,
|
Optional ByRef IsChannelUser As Boolean = False, Optional ByRef Id As String = Nothing,
|
||||||
Optional ByRef ChannelOptions As YouTubeChannelTab = YouTubeChannelTab.All) As YouTubeMediaType
|
Optional ByRef ChannelOptions As YouTubeChannelTab = YouTubeChannelTab.All) As YouTubeMediaType
|
||||||
|
URL = URL.StringTrim
|
||||||
If Not URL.IsEmptyString Then
|
If Not URL.IsEmptyString Then
|
||||||
IsMusic = URL.Contains("music.youtube.com")
|
IsMusic = URL.Contains("music.youtube.com")
|
||||||
IsChannelUser = False
|
IsChannelUser = False
|
||||||
@@ -118,6 +121,7 @@ Namespace API.YouTube.Base
|
|||||||
Optional ByVal Token As Threading.CancellationToken = Nothing, Optional ByVal Progress As IMyProgress = Nothing,
|
Optional ByVal Token As Threading.CancellationToken = Nothing, Optional ByVal Progress As IMyProgress = Nothing,
|
||||||
Optional ByVal DateAfter As Date? = Nothing, Optional ByVal DateBefore As Date? = Nothing,
|
Optional ByVal DateAfter As Date? = Nothing, Optional ByVal DateBefore As Date? = Nothing,
|
||||||
Optional ByVal ChannelOption As YouTubeChannelTab? = Nothing, Optional ByVal UrlAsIs As Boolean = False) As IYouTubeMediaContainer
|
Optional ByVal ChannelOption As YouTubeChannelTab? = Nothing, Optional ByVal UrlAsIs As Boolean = False) As IYouTubeMediaContainer
|
||||||
|
URL = URL.StringTrim
|
||||||
If URL.IsEmptyString Then Throw New ArgumentNullException("URL", "URL cannot be null")
|
If URL.IsEmptyString Then Throw New ArgumentNullException("URL", "URL cannot be null")
|
||||||
If Not MyYouTubeSettings.YTDLP.Value.Exists Then Throw New IO.FileNotFoundException("Path to 'yt-dlp.exe' not set or program not found at destination", MyYouTubeSettings.YTDLP.Value.ToString)
|
If Not MyYouTubeSettings.YTDLP.Value.Exists Then Throw New IO.FileNotFoundException("Path to 'yt-dlp.exe' not set or program not found at destination", MyYouTubeSettings.YTDLP.Value.ToString)
|
||||||
Dim urlOrig$ = URL
|
Dim urlOrig$ = URL
|
||||||
@@ -162,7 +166,7 @@ Namespace API.YouTube.Base
|
|||||||
|
|
||||||
If result Then
|
If result Then
|
||||||
container.Parse(Nothing, _CachePathDefault, isMusic, Token, Progress)
|
container.Parse(Nothing, _CachePathDefault, isMusic, Token, Progress)
|
||||||
If Not container.HasError Then container.URL = URL : container.IsShorts = isShorts : Return container
|
If Not container.HasError Then container.URL = URL.ToMusicUrl(isMusic) : container.IsShorts = isShorts : Return container
|
||||||
End If
|
End If
|
||||||
container.Dispose()
|
container.Dispose()
|
||||||
End If
|
End If
|
||||||
@@ -174,7 +178,7 @@ Namespace API.YouTube.Base
|
|||||||
ByVal ObjType As YouTubeMediaType, ByVal ChannelTab As YouTubeChannelTab,
|
ByVal ObjType As YouTubeMediaType, ByVal ChannelTab As YouTubeChannelTab,
|
||||||
ByVal IsMusic As Boolean, ByVal UrlAsIs As Boolean) As Boolean
|
ByVal IsMusic As Boolean, ByVal UrlAsIs As Boolean) As Boolean
|
||||||
Try
|
Try
|
||||||
Dim command$ = "yt-dlp --write-info-json --skip-download"
|
Dim command$ = $"{YTDLP_NAME} --write-info-json --skip-download"
|
||||||
command.StringAppend(GetCookiesCommand(UseCookies, CookiesFile), " ")
|
command.StringAppend(GetCookiesCommand(UseCookies, CookiesFile), " ")
|
||||||
If DateAfter.HasValue Then command.StringAppend($"--dateafter {DateAfter.Value:yyyyMMdd}", " ")
|
If DateAfter.HasValue Then command.StringAppend($"--dateafter {DateAfter.Value:yyyyMMdd}", " ")
|
||||||
If DateBefore.HasValue Then command.StringAppend($"--datebefore {DateBefore.Value:yyyyMMdd}", " ")
|
If DateBefore.HasValue Then command.StringAppend($"--datebefore {DateBefore.Value:yyyyMMdd}", " ")
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ Imports PersonalUtilities.Forms
|
|||||||
Imports PersonalUtilities.Functions.XML
|
Imports PersonalUtilities.Functions.XML
|
||||||
Imports PersonalUtilities.Functions.XML.Base
|
Imports PersonalUtilities.Functions.XML.Base
|
||||||
Imports PersonalUtilities.Functions.XML.Objects
|
Imports PersonalUtilities.Functions.XML.Objects
|
||||||
|
Imports PersonalUtilities.Functions.XML.Attributes
|
||||||
Imports PersonalUtilities.Functions.XML.Attributes.Specialized
|
Imports PersonalUtilities.Functions.XML.Attributes.Specialized
|
||||||
Imports PersonalUtilities.Tools
|
Imports PersonalUtilities.Tools
|
||||||
Imports PersonalUtilities.Tools.Grid.Base
|
Imports PersonalUtilities.Tools.Grid.Base
|
||||||
@@ -35,7 +36,9 @@ Namespace API.YouTube.Base
|
|||||||
<Browsable(False)> Private Property Mode As GridUpdateModes = GridUpdateModes.OnConfirm Implements IGridValuesContainer.Mode
|
<Browsable(False)> Private Property Mode As GridUpdateModes = GridUpdateModes.OnConfirm Implements IGridValuesContainer.Mode
|
||||||
<Browsable(False), XMLVV(-1)> Friend ReadOnly Property PlaylistFormSplitterDistance As XMLValue(Of Integer)
|
<Browsable(False), XMLVV(-1)> Friend ReadOnly Property PlaylistFormSplitterDistance As XMLValue(Of Integer)
|
||||||
<Browsable(False)> Friend ReadOnly Property DownloadLocations As DownloadLocationsCollection
|
<Browsable(False)> Friend ReadOnly Property DownloadLocations As DownloadLocationsCollection
|
||||||
|
<Browsable(False)> Friend ReadOnly Property PlaylistsLocations As DownloadLocationsCollection
|
||||||
<Browsable(False)> Public Overridable Property AccountName As String
|
<Browsable(False)> Public Overridable Property AccountName As String
|
||||||
|
<Browsable(False), XMLVV(0)> Private ReadOnly Property SettingsVersion As XMLValue(Of Integer)
|
||||||
#Region "Environment"
|
#Region "Environment"
|
||||||
#Region "Programs"
|
#Region "Programs"
|
||||||
<Browsable(True), GridVisible(False), XMLVN({"Environment"}), Category("Environment programs"), DisplayName("Path to yt-dlp.exe"),
|
<Browsable(True), GridVisible(False), XMLVN({"Environment"}), Category("Environment programs"), DisplayName("Path to yt-dlp.exe"),
|
||||||
@@ -83,6 +86,18 @@ Namespace API.YouTube.Base
|
|||||||
Description("The default output path where files should be downloaded."),
|
Description("The default output path where files should be downloaded."),
|
||||||
Editor(GetType(GridSFileTypeEditorPath), GetType(UITypeEditor))>
|
Editor(GetType(GridSFileTypeEditorPath), GetType(UITypeEditor))>
|
||||||
Public ReadOnly Property OutputPath As XMLValue(Of SFile)
|
Public ReadOnly Property OutputPath As XMLValue(Of SFile)
|
||||||
|
<Browsable(True), GridVisible(False), XMLVN({"Environment"}), Category("Environment"), DisplayName("Playlist file"),
|
||||||
|
Description("Last selected playlist file"),
|
||||||
|
Editor(GetType(GridSFileTypeEditor_M3U8), GetType(UITypeEditor))>
|
||||||
|
Public ReadOnly Property LatestPlaylistFile As XMLValue(Of SFile)
|
||||||
|
Private Class GridSFileTypeEditor_M3U8 : Inherits GridSFileTypeEditor
|
||||||
|
Public Overrides Function EditValue(ByVal Context As ITypeDescriptorContext, ByVal Provider As IServiceProvider, ByVal Value As Object) As Object
|
||||||
|
Dim f As SFile = SFile.SelectFiles(New SFile(CStr(AConvert(Of String)(Value, AModes.Var, String.Empty))), False,
|
||||||
|
"Select playlist file", "Playlists|*.m3u;*.m3u8|All files|*.*", EDP.ReturnValue).FirstOrDefault()
|
||||||
|
If Not f.IsEmptyString() Then Value = f
|
||||||
|
Return Value
|
||||||
|
End Function
|
||||||
|
End Class
|
||||||
<Browsable(True), GridVisible(False), XMLVN({"Environment"}), Category("Environment"), DisplayName("Output path auto change"),
|
<Browsable(True), GridVisible(False), XMLVN({"Environment"}), Category("Environment"), DisplayName("Output path auto change"),
|
||||||
Description("Automatically change the output path when a new destination is selected in the opening forms.")>
|
Description("Automatically change the output path when a new destination is selected in the opening forms.")>
|
||||||
Public ReadOnly Property OutputPathAutoChange As XMLValue(Of Boolean)
|
Public ReadOnly Property OutputPathAutoChange As XMLValue(Of Boolean)
|
||||||
@@ -116,22 +131,28 @@ Namespace API.YouTube.Base
|
|||||||
<Browsable(True), GridVisible(False), Category("EnvironmentFolder"), DisplayName("Open folders in another program"), DefaultValue(False)>
|
<Browsable(True), GridVisible(False), Category("EnvironmentFolder"), DisplayName("Open folders in another program"), DefaultValue(False)>
|
||||||
Private Property IDownloaderSettings_OpenFolderInOtherProgram As Boolean Implements IDownloaderSettings.OpenFolderInOtherProgram
|
Private Property IDownloaderSettings_OpenFolderInOtherProgram As Boolean Implements IDownloaderSettings.OpenFolderInOtherProgram
|
||||||
Get
|
Get
|
||||||
Return OpenFolderInOtherProgram.Use
|
Return OpenFolderInOtherProgram.Attribute.ValueTemp
|
||||||
End Get
|
End Get
|
||||||
Set(ByVal use As Boolean)
|
Set(ByVal use As Boolean)
|
||||||
OpenFolderInOtherProgram.Use = use
|
OpenFolderInOtherProgram.Attribute.ValueTemp = use
|
||||||
End Set
|
End Set
|
||||||
End Property
|
End Property
|
||||||
|
Private Function ShouldSerializeIDownloaderSettings_OpenFolderInOtherProgram() As Boolean
|
||||||
|
Return DirectCast(OpenFolderInOtherProgram.Attribute, IGridValue).ShouldSerializeValue
|
||||||
|
End Function
|
||||||
<Browsable(True), GridVisible(False), Category("EnvironmentFolder"), DisplayName("Open folders in another program (command)"),
|
<Browsable(True), GridVisible(False), Category("EnvironmentFolder"), DisplayName("Open folders in another program (command)"),
|
||||||
Description("The command to open a folder."), DefaultValue("")>
|
Description("The command to open a folder."), DefaultValue("")>
|
||||||
Private Property IDownloaderSettings_OpenFolderInOtherProgram_Command As String Implements IDownloaderSettings.OpenFolderInOtherProgram_Command
|
Private Property IDownloaderSettings_OpenFolderInOtherProgram_Command As String Implements IDownloaderSettings.OpenFolderInOtherProgram_Command
|
||||||
Get
|
Get
|
||||||
Return OpenFolderInOtherProgram
|
Return OpenFolderInOtherProgram.ValueTemp
|
||||||
End Get
|
End Get
|
||||||
Set(ByVal command As String)
|
Set(ByVal command As String)
|
||||||
OpenFolderInOtherProgram.Value = command
|
OpenFolderInOtherProgram.ValueTemp = command
|
||||||
End Set
|
End Set
|
||||||
End Property
|
End Property
|
||||||
|
Private Function ShouldSerializeIDownloaderSettings_OpenFolderInOtherProgram_Command() As Boolean
|
||||||
|
Return DirectCast(OpenFolderInOtherProgram, IGridValue).ShouldSerializeValue
|
||||||
|
End Function
|
||||||
<Browsable(True), GridVisible(False), XMLVN({"Environment"}, True), Category("Environment"), DisplayName("Check new version at start")>
|
<Browsable(True), GridVisible(False), XMLVN({"Environment"}, True), Category("Environment"), DisplayName("Check new version at start")>
|
||||||
Friend ReadOnly Property CheckUpdatesAtStart As XMLValue(Of Boolean)
|
Friend ReadOnly Property CheckUpdatesAtStart As XMLValue(Of Boolean)
|
||||||
#End Region
|
#End Region
|
||||||
@@ -147,6 +168,9 @@ Namespace API.YouTube.Base
|
|||||||
<Browsable(True), GridVisible, XMLVN({"Info"}), Category("Info"), DisplayName("Create description files"),
|
<Browsable(True), GridVisible, XMLVN({"Info"}), Category("Info"), DisplayName("Create description files"),
|
||||||
Description("Create video description files. Default: false.")>
|
Description("Create video description files. Default: false.")>
|
||||||
Public ReadOnly Property CreateDescriptionFiles As XMLValue(Of Boolean)
|
Public ReadOnly Property CreateDescriptionFiles As XMLValue(Of Boolean)
|
||||||
|
<Browsable(True), GridVisible, XMLVN({"Info"}, True), Category("Info"), DisplayName("Create description files: create without description"),
|
||||||
|
Description("Create a description file with the upload date, even if the description does not exist. Default: true.")>
|
||||||
|
Public ReadOnly Property CreateDescriptionFiles_CreateWithNoDescription As XMLValue(Of Boolean)
|
||||||
<Browsable(True), GridVisible, XMLVN({"Info"}, True), Category("Info"), DisplayName("Create thumbnail files (video)"),
|
<Browsable(True), GridVisible, XMLVN({"Info"}, True), Category("Info"), DisplayName("Create thumbnail files (video)"),
|
||||||
Description("Create video thumbnail files. Default: true.")>
|
Description("Create video thumbnail files. Default: true.")>
|
||||||
Public ReadOnly Property CreateThumbnails_Video As XMLValue(Of Boolean)
|
Public ReadOnly Property CreateThumbnails_Video As XMLValue(Of Boolean)
|
||||||
@@ -164,7 +188,7 @@ Namespace API.YouTube.Base
|
|||||||
<Browsable(True), GridVisible, XMLVN({"Defaults"}), Category("Defaults"), DisplayName("Use cookies"),
|
<Browsable(True), GridVisible, XMLVN({"Defaults"}), Category("Defaults"), DisplayName("Use cookies"),
|
||||||
Description("By default, use cookies when downloading from YouTube.")>
|
Description("By default, use cookies when downloading from YouTube.")>
|
||||||
Public ReadOnly Property DefaultUseCookies As XMLValue(Of Boolean)
|
Public ReadOnly Property DefaultUseCookies As XMLValue(Of Boolean)
|
||||||
<Browsable(True), GridVisible, XMLVN({"Defaults"}, Protocols.Any), Category("Defaults"), DisplayName("Protocol"),
|
<Browsable(True), GridVisible, XMLVN({"Defaults"}, Protocols.https), Category("Defaults"), DisplayName("Protocol"),
|
||||||
Description("Priority download protocol. Default: 'Any'")>
|
Description("Priority download protocol. Default: 'Any'")>
|
||||||
Public ReadOnly Property DefaultProtocol As XMLValue(Of Protocols)
|
Public ReadOnly Property DefaultProtocol As XMLValue(Of Protocols)
|
||||||
<Browsable(True), GridVisible(False), XMLVN({"Defaults"}), Category("Defaults"),
|
<Browsable(True), GridVisible(False), XMLVN({"Defaults"}), Category("Defaults"),
|
||||||
@@ -228,6 +252,21 @@ Namespace API.YouTube.Base
|
|||||||
<Browsable(True), GridVisible(False), XMLVN({"Defaults"}), Category("Defaults"), DisplayName("Program description"),
|
<Browsable(True), GridVisible(False), XMLVN({"Defaults"}), Category("Defaults"), DisplayName("Program description"),
|
||||||
Description("Add some additional info to the program info if you need")>
|
Description("Add some additional info to the program info if you need")>
|
||||||
Friend ReadOnly Property ProgramDescription As XMLValue(Of String)
|
Friend ReadOnly Property ProgramDescription As XMLValue(Of String)
|
||||||
|
<Browsable(True), GridVisible, XMLVN({"Defaults"}, "%"""), Category("Defaults"), DisplayName("Remove characters"),
|
||||||
|
Description("Remove specific characters from a file name")>
|
||||||
|
Public ReadOnly Property FileRemoveCharacters As XMLValue(Of String)
|
||||||
|
<Browsable(True), GridVisible, XMLVN({"Defaults"}, FileDateMode.None), Category("Defaults"), DisplayName("Add date to file name"),
|
||||||
|
Description("Add the video upload date before/after the file name")>
|
||||||
|
Public ReadOnly Property FileAddDateToFileName As XMLValue(Of FileDateMode)
|
||||||
|
<Browsable(True), GridVisible, XMLVN({"Defaults"}), Category("Defaults"), DisplayName("Add date to title: video form"),
|
||||||
|
Description("Add video upload date before video title (visual only) in the video form")>
|
||||||
|
Public ReadOnly Property FileAddDateToFileName_VideoForm As XMLValue(Of Boolean)
|
||||||
|
<Browsable(True), GridVisible, XMLVN({"Defaults"}), Category("Defaults"), DisplayName("Add date to title: video list"),
|
||||||
|
Description("Add video upload date before video title (visual only) in the video list")>
|
||||||
|
Public ReadOnly Property FileAddDateToFileName_VideoList As XMLValue(Of Boolean)
|
||||||
|
<Browsable(True), GridVisible, XMLVN({"Defaults"}, FileDateMode.None), Category("Defaults"), DisplayName("Add channel to file name"),
|
||||||
|
Description("Add channel name before/after the file name")>
|
||||||
|
Public ReadOnly Property FileAddChannelToFileName As XMLValue(Of FileDateMode)
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Defaults ChannelsDownload"
|
#Region "Defaults ChannelsDownload"
|
||||||
<Browsable(True), GridVisible, XMLVN({"Defaults", "Channels"}), Category("Defaults"), DisplayName("Default download tabs for channels"),
|
<Browsable(True), GridVisible, XMLVN({"Defaults", "Channels"}), Category("Defaults"), DisplayName("Default download tabs for channels"),
|
||||||
@@ -272,9 +311,92 @@ Namespace API.YouTube.Base
|
|||||||
<Browsable(True), GridVisible, XMLVN({"DefaultsVideo"}, 1080), Category("Defaults Video"), DisplayName("Default definition"),
|
<Browsable(True), GridVisible, XMLVN({"DefaultsVideo"}, 1080), Category("Defaults Video"), DisplayName("Default definition"),
|
||||||
Description("The default maximum video resolution. -1 for max definition")>
|
Description("The default maximum video resolution. -1 for max definition")>
|
||||||
Public ReadOnly Property DefaultVideoDefinition As XMLValue(Of Integer)
|
Public ReadOnly Property DefaultVideoDefinition As XMLValue(Of Integer)
|
||||||
|
<Browsable(True), GridVisible, XMLVN({"DefaultsVideo"}, True), Category("Defaults Video"), DisplayName("Allow webm formats"),
|
||||||
|
Description("Allow webm formats over http if mp4 formats are not available. Default: true.")>
|
||||||
|
Public ReadOnly Property DefaultVideoAllowWebm As XMLValue(Of Boolean)
|
||||||
|
<Browsable(True), GridVisible, XMLVN({"DefaultsVideo"}), Category("Defaults Video"), DisplayName("Convert non-AVC codecs to AVC"),
|
||||||
|
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.")>
|
||||||
|
Public ReadOnly Property DefaultVideoEmbedThumbnail As XMLValue(Of Boolean)
|
||||||
<Browsable(True), GridVisible, XMLVN({"DefaultsVideo"}), Category("Defaults Video"), DisplayName("Include zero size formats"),
|
<Browsable(True), GridVisible, XMLVN({"DefaultsVideo"}), Category("Defaults Video"), DisplayName("Include zero size formats"),
|
||||||
Description("Include formats with zero size (or undefined size).")>
|
Description("Include formats with zero size (or undefined size).")>
|
||||||
Public ReadOnly Property DefaultVideoIncludeNullSize As XMLValue(Of Boolean)
|
Public ReadOnly Property DefaultVideoIncludeNullSize As XMLValue(Of Boolean)
|
||||||
|
<Browsable(False), XMLV("DefaultVideoFPS", {"DefaultsVideo"}, -1)>
|
||||||
|
Private ReadOnly Property DefaultVideoFPS_XML As XMLValue(Of Double)
|
||||||
|
<Browsable(True), GridVisible, Category("Defaults Video"), DisplayName("Default video FPS"),
|
||||||
|
Description("Set default video FPS (only to reduce video FPS). Default: -1 (disabled)."),
|
||||||
|
TypeConverter(GetType(FieldsTypeConverter)), GridFormatProvider(GetType(FpsFormatProvider))>
|
||||||
|
Public Property DefaultVideoFPS As Double
|
||||||
|
Get
|
||||||
|
Return DefaultVideoFPS_XML
|
||||||
|
End Get
|
||||||
|
Set(ByVal fps As Double)
|
||||||
|
DefaultVideoFPS_XML.Value = fps
|
||||||
|
End Set
|
||||||
|
End Property
|
||||||
|
Private Function ShouldSerializeDefaultVideoFPS() As Boolean
|
||||||
|
Return DefaultVideoFPS <> DefaultVideoFPS_XML.Value
|
||||||
|
End Function
|
||||||
|
Private Sub ResetDefaultVideoFPS()
|
||||||
|
DefaultVideoFPS = -1
|
||||||
|
End Sub
|
||||||
|
Friend Class FpsFormatProvider : Implements IGridConversionProvider
|
||||||
|
Private Property Converter As TypeConverter Implements IGridConversionProvider.Converter
|
||||||
|
Private Property Context As ITypeDescriptorContext Implements IGridConversionProvider.Context
|
||||||
|
Private Property DataType As Type Implements IGridConversionProvider.DataType
|
||||||
|
Private Property Instance As Object Implements IGridConversionProvider.Instance
|
||||||
|
Friend Shared ReadOnly Property MyProviderDefault As ANumbers
|
||||||
|
Get
|
||||||
|
Return New ANumbers(ANumbers.Cultures.Primitive) With {.DecimalDigits = 5, .TrimDecimalDigits = True}
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
|
Friend Const ErrorMessageDefault As String = "The fps value must be a number"
|
||||||
|
Private ReadOnly MyProvider As ANumbers = MyProviderDefault
|
||||||
|
Friend Function ToObject(ByVal Context As ITypeDescriptorContext, ByVal Culture As CultureInfo, ByVal Value As Object) As Object Implements IGridConversionProvider.ToObject
|
||||||
|
Return AConvert(Of Double)(Value, MyProvider, -1)
|
||||||
|
End Function
|
||||||
|
Friend Overloads Function ToString(ByVal Context As ITypeDescriptorContext, ByVal Culture As CultureInfo, ByVal Value As Object,
|
||||||
|
ByVal DestinationType As Type) As Object Implements IGridConversionProvider.ToString
|
||||||
|
If ACheck(Of Double)(Value, AModes.Var, MyProvider) Then
|
||||||
|
Return Value.ToString
|
||||||
|
Else
|
||||||
|
Return -1
|
||||||
|
End If
|
||||||
|
End Function
|
||||||
|
Friend Function CreateInstance(ByVal Context As ITypeDescriptorContext, ByVal NewValue As Object, ByRef RefreshGrid As Boolean) As Object Implements IGridConversionProvider.CreateInstance
|
||||||
|
If ACheck(Of Double)(NewValue, AModes.Var, MyProvider) Then
|
||||||
|
Return NewValue
|
||||||
|
Else
|
||||||
|
RefreshGrid = True
|
||||||
|
Return -1
|
||||||
|
End If
|
||||||
|
End Function
|
||||||
|
Friend Function Convert(ByVal Value As Object, ByVal DestinationType As Type, ByVal Provider As IFormatProvider,
|
||||||
|
Optional ByVal NothingArg As Object = Nothing, Optional ByVal e As ErrorsDescriber = Nothing) As Object Implements ICustomProvider.Convert
|
||||||
|
Return AConvert(Value, AModes.Var, DestinationType,, True, -1, MyProvider, EDP.ReturnValue)
|
||||||
|
End Function
|
||||||
|
Friend Function IsValid(ByVal Context As ITypeDescriptorContext, ByVal Value As Object, ByVal DestinationType As Type) As Boolean Implements IGridValidator.IsValid
|
||||||
|
If ACheck(Of Double)(Value, AModes.Var, MyProvider) Then
|
||||||
|
Return True
|
||||||
|
Else
|
||||||
|
Throw New FormatException(ErrorMessageDefault)
|
||||||
|
End If
|
||||||
|
End Function
|
||||||
|
Private Function GetFormat(ByVal FormatType As Type) As Object Implements IFormatProvider.GetFormat
|
||||||
|
Throw New NotImplementedException("'GetFormat' is not available in 'FpsFormatProvider'")
|
||||||
|
End Function
|
||||||
|
End Class
|
||||||
|
<Browsable(True), GridVisible, XMLVN({"DefaultsVideo"}, 30), Category("Defaults Video"), DisplayName("Highlight FPS (higher)"),
|
||||||
|
Description("Highlight frame rates higher than this value." & vbCr & "Default: 30" & vbCr & "-1 to disable")>
|
||||||
|
Public ReadOnly Property DefaultVideoHighlightFPS_H As XMLValue(Of Integer)
|
||||||
|
<Browsable(True), GridVisible, XMLVN({"DefaultsVideo"}, -1), Category("Defaults Video"), DisplayName("Highlight FPS (lower)"),
|
||||||
|
Description("Highlight frame rates lower than this value." & vbCr & "Default: -1" & vbCr & "-1 to disable")>
|
||||||
|
Public ReadOnly Property DefaultVideoHighlightFPS_L As XMLValue(Of Integer)
|
||||||
|
<Browsable(True), GridVisible, XMLVN({"DefaultsVideo"}), Category("Defaults Video"), DisplayName("Add extracted MP3 to playlist"),
|
||||||
|
Description("If you also extract MP3 when download the video, add the extracted MP3 to the playlist. Default: false.")>
|
||||||
|
Public ReadOnly Property VideoPlaylist_AddExtractedMP3 As XMLValue(Of Boolean)
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Defaults Audio"
|
#Region "Defaults Audio"
|
||||||
<Browsable(True), GridVisible, XMLVN({"DefaultsAudio"}, "AAC"), Category("Defaults Audio"), DisplayName("Default codec"),
|
<Browsable(True), GridVisible, XMLVN({"DefaultsAudio"}, "AAC"), Category("Defaults Audio"), DisplayName("Default codec"),
|
||||||
@@ -294,6 +416,41 @@ Namespace API.YouTube.Base
|
|||||||
TypeConverter(GetType(ValueCollectionConverter)),
|
TypeConverter(GetType(ValueCollectionConverter)),
|
||||||
Description("Additional audio format for downloading videos. This means that the audio will be extracted and saved as a separate file in these formats.")>
|
Description("Additional audio format for downloading videos. This means that the audio will be extracted and saved as a separate file in these formats.")>
|
||||||
Public ReadOnly Property DefaultAudioCodecAddit As XMLValuesCollection(Of String)
|
Public ReadOnly Property DefaultAudioCodecAddit As XMLValuesCollection(Of String)
|
||||||
|
<Browsable(True), GridVisible, XMLVN({"DefaultsAudio"}, True), Category("Defaults Audio"), DisplayName("Embed thumbnail"),
|
||||||
|
Description("Embed thumbnail in the audio as cover art. Default: true.")>
|
||||||
|
Public ReadOnly Property DefaultAudioEmbedThumbnail As XMLValue(Of Boolean)
|
||||||
|
<Browsable(True), GridVisible, XMLVN({"DefaultsAudio"}, True), Category("Defaults Audio"), DisplayName("Embed thumbnail (cover)"),
|
||||||
|
Description("Try embedding the playlist cover (if it exists) as cover art. Default: true.")>
|
||||||
|
Public ReadOnly Property DefaultAudioEmbedThumbnail_Cover As XMLValue(Of Boolean)
|
||||||
|
<Browsable(True), GridVisible, XMLVN({"DefaultsAudio"}, True), Category("Defaults Audio"), DisplayName("Embed thumbnail (extracted files)"),
|
||||||
|
Description("Embed thumbnail in the extracted (additional file ('mp3' only)) audio as cover art. Default: true.")>
|
||||||
|
Public ReadOnly Property DefaultAudioEmbedThumbnail_ExtractedFiles As XMLValue(Of Boolean)
|
||||||
|
<Browsable(True), GridVisible, XMLVN({"DefaultsAudio"}, -1), Category("Defaults Audio"), DisplayName("Bitrate"),
|
||||||
|
Description("Default audio bitrate if you want to change it during download. -1 to disable. Default: -1.")>
|
||||||
|
Public ReadOnly Property DefaultAudioBitrate As XMLValue(Of Integer)
|
||||||
|
<Browsable(True), GridVisible, XMLVN({"DefaultsAudio"}, 20), Category("Defaults Audio"), DisplayName("Bitrate: ffmpeg crf"),
|
||||||
|
Description("This is the ffmpeg argument. Change it only if you know what you're doing. Default: 20.")>
|
||||||
|
Public ReadOnly Property DefaultAudioBitrate_crf As XMLValue(Of Integer)
|
||||||
|
#Region "Music"
|
||||||
|
<Browsable(True), GridVisible, XMLVN({"Playlists"}, True), Category("Music"), DisplayName("Create M3U8"),
|
||||||
|
Description("Create M3U8 playlist for music. Default: true.")>
|
||||||
|
Public ReadOnly Property MusicPlaylistCreate_M3U8 As XMLValue(Of Boolean)
|
||||||
|
<Browsable(True), GridVisible, XMLVN({"Playlists"}), Category("Music"), DisplayName("Create M3U"),
|
||||||
|
Description("Create M3U playlist for music. Default: false.")>
|
||||||
|
Public ReadOnly Property MusicPlaylistCreate_M3U As XMLValue(Of Boolean)
|
||||||
|
<Browsable(True), GridVisible, XMLVN({"Playlists"}), Category("Music"), DisplayName("M3U8 Append artist"),
|
||||||
|
Description("Add artist to file name. Default: false.")>
|
||||||
|
Public ReadOnly Property MusicPlaylistCreate_M3U8_AppendArtist As XMLValue(Of Boolean)
|
||||||
|
<Browsable(True), GridVisible, XMLVN({"Playlists"}), Category("Music"), DisplayName("M3U8 Append file extension"),
|
||||||
|
Description("Add file extension to file name. Default: false.")>
|
||||||
|
Public ReadOnly Property MusicPlaylistCreate_M3U8_AppendExt As XMLValue(Of Boolean)
|
||||||
|
<Browsable(True), GridVisible, XMLVN({"Playlists"}), Category("Music"), DisplayName("M3U8 Append file number"),
|
||||||
|
Description("Add file number to file name. Default: false.")>
|
||||||
|
Public ReadOnly Property MusicPlaylistCreate_M3U8_AppendNumber As XMLValue(Of Boolean)
|
||||||
|
<Browsable(True), GridVisible, XMLVN({"Playlists"}, M3U8CreationMode.Relative), Category("Music"), DisplayName("Create M3U8: creation mode"),
|
||||||
|
Description("Set the playlist creation mode: absolute links, relative links, or both. If 'Both' is selected, two playlists will be created. Default: 'Relative'.")>
|
||||||
|
Public ReadOnly Property MusicPlaylistCreate_CreationMode As XMLValue(Of M3U8CreationMode)
|
||||||
|
#End Region
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Defaults Subtitles"
|
#Region "Defaults Subtitles"
|
||||||
<XMLVN({"DefaultsSubtitles"}, {"en"}, CollectionMode:=IXMLValuesCollection.Modes.String)>
|
<XMLVN({"DefaultsSubtitles"}, {"en"}, CollectionMode:=IXMLValuesCollection.Modes.String)>
|
||||||
@@ -346,7 +503,9 @@ Namespace API.YouTube.Base
|
|||||||
Public Sub New(ByVal AccountName As String)
|
Public Sub New(ByVal AccountName As String)
|
||||||
Me.AccountName = AccountName
|
Me.AccountName = AccountName
|
||||||
DownloadLocations = New DownloadLocationsCollection
|
DownloadLocations = New DownloadLocationsCollection
|
||||||
|
PlaylistsLocations = New DownloadLocationsCollection
|
||||||
DownloadLocations.Load(False, True)
|
DownloadLocations.Load(False, True)
|
||||||
|
PlaylistsLocations.Load(True, True, $"{XmlFile.SettingsFolder}\DownloadLocations_Playlists.xml")
|
||||||
Dim acc$ = String.Empty
|
Dim acc$ = String.Empty
|
||||||
If Not AccountName.IsEmptyString Then acc = $"_{AccountName}"
|
If Not AccountName.IsEmptyString Then acc = $"_{AccountName}"
|
||||||
Dim f As SFile = YouTubeSettingsFile
|
Dim f As SFile = YouTubeSettingsFile
|
||||||
|
|||||||
23
SCrawler.YouTube/Controls/ButtonRC.vb
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
' 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
|
||||||
|
Public Class ButtonRC : Inherits Button
|
||||||
|
Private Const WM_CONTEXTMENU As Integer = 123 '&H7B
|
||||||
|
Private Const WM_CANCELMODE As Integer = 31 '&H1F
|
||||||
|
Private Const WM_INITMENUPOPUP As Integer = 279 '&H117
|
||||||
|
Private Const SMTO_NOTIMEOUTIFNOTHUNG As Integer = 8
|
||||||
|
Protected Overrides Sub WndProc(ByRef m As Message)
|
||||||
|
If m.Msg = WM_CONTEXTMENU Or m.Msg = WM_CANCELMODE Or m.Msg = WM_INITMENUPOPUP Or m.Msg = SMTO_NOTIMEOUTIFNOTHUNG Then
|
||||||
|
m.Result = IntPtr.Zero
|
||||||
|
Else
|
||||||
|
MyBase.WndProc(m)
|
||||||
|
End If
|
||||||
|
End Sub
|
||||||
|
End Class
|
||||||
|
End Namespace
|
||||||
136
SCrawler.YouTube/Controls/MusicPlaylistsForm.Designer.vb
generated
@@ -43,8 +43,16 @@ Namespace API.YouTube.Controls
|
|||||||
Dim ActionButton8 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
Dim ActionButton8 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||||
Dim ActionButton9 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
Dim ActionButton9 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||||
Dim ActionButton10 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
Dim ActionButton10 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||||
|
Dim ActionButton11 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||||
Dim ListColumn1 As PersonalUtilities.Forms.Controls.Base.ListColumn = New PersonalUtilities.Forms.Controls.Base.ListColumn()
|
Dim ListColumn1 As PersonalUtilities.Forms.Controls.Base.ListColumn = New PersonalUtilities.Forms.Controls.Base.ListColumn()
|
||||||
Dim ListColumn2 As PersonalUtilities.Forms.Controls.Base.ListColumn = New PersonalUtilities.Forms.Controls.Base.ListColumn()
|
Dim ListColumn2 As PersonalUtilities.Forms.Controls.Base.ListColumn = New PersonalUtilities.Forms.Controls.Base.ListColumn()
|
||||||
|
Dim ActionButton12 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||||
|
Dim ActionButton13 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||||
|
Dim ActionButton14 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||||
|
Dim ActionButton15 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||||
|
Dim ActionButton16 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||||
|
Dim ActionButton17 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||||
|
Dim ActionButton18 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||||
Dim TT_MAIN As System.Windows.Forms.ToolTip
|
Dim TT_MAIN As System.Windows.Forms.ToolTip
|
||||||
Me.BTT_DOWN = New System.Windows.Forms.Button()
|
Me.BTT_DOWN = New System.Windows.Forms.Button()
|
||||||
Me.BTT_CANCEL = New System.Windows.Forms.Button()
|
Me.BTT_CANCEL = New System.Windows.Forms.Button()
|
||||||
@@ -58,6 +66,8 @@ Namespace API.YouTube.Controls
|
|||||||
Me.TXT_SUBS = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
Me.TXT_SUBS = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
||||||
Me.CH_DOWN_LYRICS = New System.Windows.Forms.CheckBox()
|
Me.CH_DOWN_LYRICS = New System.Windows.Forms.CheckBox()
|
||||||
Me.TXT_OUTPUT_PATH = New PersonalUtilities.Forms.Controls.ComboBoxExtended()
|
Me.TXT_OUTPUT_PATH = New PersonalUtilities.Forms.Controls.ComboBoxExtended()
|
||||||
|
Me.CMB_PLS = New PersonalUtilities.Forms.Controls.ComboBoxExtended()
|
||||||
|
Me.TXT_AUDIO_BITRATE = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
||||||
TP_MAIN = New System.Windows.Forms.TableLayoutPanel()
|
TP_MAIN = New System.Windows.Forms.TableLayoutPanel()
|
||||||
TP_BUTTONS = New System.Windows.Forms.TableLayoutPanel()
|
TP_BUTTONS = New System.Windows.Forms.TableLayoutPanel()
|
||||||
TP_PLS = New System.Windows.Forms.TableLayoutPanel()
|
TP_PLS = New System.Windows.Forms.TableLayoutPanel()
|
||||||
@@ -83,6 +93,8 @@ Namespace API.YouTube.Controls
|
|||||||
TP_LYRICS.SuspendLayout()
|
TP_LYRICS.SuspendLayout()
|
||||||
CType(Me.TXT_SUBS, System.ComponentModel.ISupportInitialize).BeginInit()
|
CType(Me.TXT_SUBS, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||||
CType(Me.TXT_OUTPUT_PATH, System.ComponentModel.ISupportInitialize).BeginInit()
|
CType(Me.TXT_OUTPUT_PATH, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||||
|
CType(Me.CMB_PLS, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||||
|
CType(Me.TXT_AUDIO_BITRATE, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||||
Me.SuspendLayout()
|
Me.SuspendLayout()
|
||||||
'
|
'
|
||||||
'TP_MAIN
|
'TP_MAIN
|
||||||
@@ -97,10 +109,10 @@ Namespace API.YouTube.Controls
|
|||||||
TP_MAIN.Margin = New System.Windows.Forms.Padding(0)
|
TP_MAIN.Margin = New System.Windows.Forms.Padding(0)
|
||||||
TP_MAIN.Name = "TP_MAIN"
|
TP_MAIN.Name = "TP_MAIN"
|
||||||
TP_MAIN.RowCount = 3
|
TP_MAIN.RowCount = 3
|
||||||
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 84.0!))
|
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 140.0!))
|
||||||
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
|
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
|
||||||
TP_MAIN.Size = New System.Drawing.Size(434, 261)
|
TP_MAIN.Size = New System.Drawing.Size(434, 317)
|
||||||
TP_MAIN.TabIndex = 0
|
TP_MAIN.TabIndex = 0
|
||||||
'
|
'
|
||||||
'TP_BUTTONS
|
'TP_BUTTONS
|
||||||
@@ -112,14 +124,14 @@ Namespace API.YouTube.Controls
|
|||||||
TP_BUTTONS.Controls.Add(Me.BTT_DOWN, 1, 0)
|
TP_BUTTONS.Controls.Add(Me.BTT_DOWN, 1, 0)
|
||||||
TP_BUTTONS.Controls.Add(Me.BTT_CANCEL, 2, 0)
|
TP_BUTTONS.Controls.Add(Me.BTT_CANCEL, 2, 0)
|
||||||
TP_BUTTONS.Dock = System.Windows.Forms.DockStyle.Fill
|
TP_BUTTONS.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
TP_BUTTONS.Location = New System.Drawing.Point(0, 236)
|
TP_BUTTONS.Location = New System.Drawing.Point(0, 292)
|
||||||
TP_BUTTONS.Margin = New System.Windows.Forms.Padding(0)
|
TP_BUTTONS.Margin = New System.Windows.Forms.Padding(0)
|
||||||
TP_BUTTONS.Name = "TP_BUTTONS"
|
TP_BUTTONS.Name = "TP_BUTTONS"
|
||||||
TP_BUTTONS.RowCount = 1
|
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.Percent, 100.0!))
|
||||||
TP_BUTTONS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
|
TP_BUTTONS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
|
||||||
TP_BUTTONS.Size = New System.Drawing.Size(434, 25)
|
TP_BUTTONS.Size = New System.Drawing.Size(434, 25)
|
||||||
TP_BUTTONS.TabIndex = 2
|
TP_BUTTONS.TabIndex = 1
|
||||||
'
|
'
|
||||||
'BTT_DOWN
|
'BTT_DOWN
|
||||||
'
|
'
|
||||||
@@ -147,7 +159,7 @@ Namespace API.YouTube.Controls
|
|||||||
'SPLITTER_MAIN
|
'SPLITTER_MAIN
|
||||||
'
|
'
|
||||||
Me.SPLITTER_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
|
Me.SPLITTER_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
Me.SPLITTER_MAIN.Location = New System.Drawing.Point(3, 87)
|
Me.SPLITTER_MAIN.Location = New System.Drawing.Point(3, 143)
|
||||||
Me.SPLITTER_MAIN.Name = "SPLITTER_MAIN"
|
Me.SPLITTER_MAIN.Name = "SPLITTER_MAIN"
|
||||||
'
|
'
|
||||||
'SPLITTER_MAIN.Panel1
|
'SPLITTER_MAIN.Panel1
|
||||||
@@ -263,16 +275,20 @@ Namespace API.YouTube.Controls
|
|||||||
TP_SETTINGS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
TP_SETTINGS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
TP_SETTINGS.Controls.Add(TP_FORMATS, 0, 1)
|
TP_SETTINGS.Controls.Add(TP_FORMATS, 0, 1)
|
||||||
TP_SETTINGS.Controls.Add(TP_LYRICS, 0, 0)
|
TP_SETTINGS.Controls.Add(TP_LYRICS, 0, 0)
|
||||||
TP_SETTINGS.Controls.Add(Me.TXT_OUTPUT_PATH, 0, 2)
|
TP_SETTINGS.Controls.Add(Me.TXT_OUTPUT_PATH, 0, 3)
|
||||||
|
TP_SETTINGS.Controls.Add(Me.CMB_PLS, 0, 4)
|
||||||
|
TP_SETTINGS.Controls.Add(Me.TXT_AUDIO_BITRATE, 0, 2)
|
||||||
TP_SETTINGS.Dock = System.Windows.Forms.DockStyle.Fill
|
TP_SETTINGS.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
TP_SETTINGS.Location = New System.Drawing.Point(0, 0)
|
TP_SETTINGS.Location = New System.Drawing.Point(0, 0)
|
||||||
TP_SETTINGS.Margin = New System.Windows.Forms.Padding(0)
|
TP_SETTINGS.Margin = New System.Windows.Forms.Padding(0)
|
||||||
TP_SETTINGS.Name = "TP_SETTINGS"
|
TP_SETTINGS.Name = "TP_SETTINGS"
|
||||||
TP_SETTINGS.RowCount = 3
|
TP_SETTINGS.RowCount = 5
|
||||||
TP_SETTINGS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 33.33333!))
|
TP_SETTINGS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 20.0!))
|
||||||
TP_SETTINGS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 33.33333!))
|
TP_SETTINGS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 20.0!))
|
||||||
TP_SETTINGS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 33.33333!))
|
TP_SETTINGS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 20.0!))
|
||||||
TP_SETTINGS.Size = New System.Drawing.Size(434, 84)
|
TP_SETTINGS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 20.0!))
|
||||||
|
TP_SETTINGS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 20.0!))
|
||||||
|
TP_SETTINGS.Size = New System.Drawing.Size(434, 140)
|
||||||
TP_SETTINGS.TabIndex = 1
|
TP_SETTINGS.TabIndex = 1
|
||||||
'
|
'
|
||||||
'TP_FORMATS
|
'TP_FORMATS
|
||||||
@@ -291,7 +307,7 @@ Namespace API.YouTube.Controls
|
|||||||
TP_FORMATS.RowCount = 1
|
TP_FORMATS.RowCount = 1
|
||||||
TP_FORMATS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
TP_FORMATS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
TP_FORMATS.Size = New System.Drawing.Size(434, 28)
|
TP_FORMATS.Size = New System.Drawing.Size(434, 28)
|
||||||
TP_FORMATS.TabIndex = 1
|
TP_FORMATS.TabIndex = 5
|
||||||
'
|
'
|
||||||
'TXT_FORMATS_ADDIT
|
'TXT_FORMATS_ADDIT
|
||||||
'
|
'
|
||||||
@@ -360,7 +376,7 @@ Namespace API.YouTube.Controls
|
|||||||
TP_LYRICS.RowCount = 1
|
TP_LYRICS.RowCount = 1
|
||||||
TP_LYRICS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
TP_LYRICS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
TP_LYRICS.Size = New System.Drawing.Size(434, 28)
|
TP_LYRICS.Size = New System.Drawing.Size(434, 28)
|
||||||
TP_LYRICS.TabIndex = 0
|
TP_LYRICS.TabIndex = 6
|
||||||
'
|
'
|
||||||
'TXT_SUBS
|
'TXT_SUBS
|
||||||
'
|
'
|
||||||
@@ -410,23 +426,28 @@ Namespace API.YouTube.Controls
|
|||||||
'TXT_OUTPUT_PATH
|
'TXT_OUTPUT_PATH
|
||||||
'
|
'
|
||||||
ActionButton7.BackgroundImage = CType(resources.GetObject("ActionButton7.BackgroundImage"), System.Drawing.Image)
|
ActionButton7.BackgroundImage = CType(resources.GetObject("ActionButton7.BackgroundImage"), System.Drawing.Image)
|
||||||
ActionButton7.Name = "Open"
|
ActionButton7.Name = "Save"
|
||||||
ActionButton7.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Open
|
ActionButton7.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Save
|
||||||
ActionButton7.ToolTipText = "Choose a new location (Ctrl+O)"
|
ActionButton7.ToolTipText = "Save destination"
|
||||||
ActionButton8.BackgroundImage = CType(resources.GetObject("ActionButton8.BackgroundImage"), System.Drawing.Image)
|
ActionButton8.BackgroundImage = CType(resources.GetObject("ActionButton8.BackgroundImage"), System.Drawing.Image)
|
||||||
ActionButton8.Name = "Add"
|
ActionButton8.Name = "Open"
|
||||||
ActionButton8.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Add
|
ActionButton8.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Open
|
||||||
ActionButton8.ToolTipText = "Choose a new location and add it to the list (Alt+O)"
|
ActionButton8.ToolTipText = "Choose a new location (Ctrl+O)"
|
||||||
ActionButton9.BackgroundImage = CType(resources.GetObject("ActionButton9.BackgroundImage"), System.Drawing.Image)
|
ActionButton9.BackgroundImage = CType(resources.GetObject("ActionButton9.BackgroundImage"), System.Drawing.Image)
|
||||||
ActionButton9.Name = "Clear"
|
ActionButton9.Name = "Add"
|
||||||
ActionButton9.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
|
ActionButton9.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Add
|
||||||
|
ActionButton9.ToolTipText = "Choose a new location and add it to the list (Alt+O)"
|
||||||
ActionButton10.BackgroundImage = CType(resources.GetObject("ActionButton10.BackgroundImage"), System.Drawing.Image)
|
ActionButton10.BackgroundImage = CType(resources.GetObject("ActionButton10.BackgroundImage"), System.Drawing.Image)
|
||||||
ActionButton10.Name = "ArrowDown"
|
ActionButton10.Name = "Clear"
|
||||||
ActionButton10.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.ArrowDown
|
ActionButton10.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
|
||||||
|
ActionButton11.BackgroundImage = CType(resources.GetObject("ActionButton11.BackgroundImage"), System.Drawing.Image)
|
||||||
|
ActionButton11.Name = "ArrowDown"
|
||||||
|
ActionButton11.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.ArrowDown
|
||||||
Me.TXT_OUTPUT_PATH.Buttons.Add(ActionButton7)
|
Me.TXT_OUTPUT_PATH.Buttons.Add(ActionButton7)
|
||||||
Me.TXT_OUTPUT_PATH.Buttons.Add(ActionButton8)
|
Me.TXT_OUTPUT_PATH.Buttons.Add(ActionButton8)
|
||||||
Me.TXT_OUTPUT_PATH.Buttons.Add(ActionButton9)
|
Me.TXT_OUTPUT_PATH.Buttons.Add(ActionButton9)
|
||||||
Me.TXT_OUTPUT_PATH.Buttons.Add(ActionButton10)
|
Me.TXT_OUTPUT_PATH.Buttons.Add(ActionButton10)
|
||||||
|
Me.TXT_OUTPUT_PATH.Buttons.Add(ActionButton11)
|
||||||
Me.TXT_OUTPUT_PATH.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.CheckBox
|
Me.TXT_OUTPUT_PATH.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.CheckBox
|
||||||
Me.TXT_OUTPUT_PATH.CaptionText = "Output path"
|
Me.TXT_OUTPUT_PATH.CaptionText = "Output path"
|
||||||
Me.TXT_OUTPUT_PATH.CaptionToolTipEnabled = True
|
Me.TXT_OUTPUT_PATH.CaptionToolTipEnabled = True
|
||||||
@@ -446,23 +467,82 @@ Namespace API.YouTube.Controls
|
|||||||
Me.TXT_OUTPUT_PATH.Columns.Add(ListColumn1)
|
Me.TXT_OUTPUT_PATH.Columns.Add(ListColumn1)
|
||||||
Me.TXT_OUTPUT_PATH.Columns.Add(ListColumn2)
|
Me.TXT_OUTPUT_PATH.Columns.Add(ListColumn2)
|
||||||
Me.TXT_OUTPUT_PATH.Dock = System.Windows.Forms.DockStyle.Fill
|
Me.TXT_OUTPUT_PATH.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
Me.TXT_OUTPUT_PATH.Location = New System.Drawing.Point(3, 59)
|
Me.TXT_OUTPUT_PATH.Location = New System.Drawing.Point(3, 87)
|
||||||
Me.TXT_OUTPUT_PATH.Name = "TXT_OUTPUT_PATH"
|
Me.TXT_OUTPUT_PATH.Name = "TXT_OUTPUT_PATH"
|
||||||
Me.TXT_OUTPUT_PATH.Size = New System.Drawing.Size(428, 22)
|
Me.TXT_OUTPUT_PATH.Size = New System.Drawing.Size(428, 22)
|
||||||
Me.TXT_OUTPUT_PATH.TabIndex = 2
|
Me.TXT_OUTPUT_PATH.TabIndex = 2
|
||||||
Me.TXT_OUTPUT_PATH.TextBoxBorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
|
Me.TXT_OUTPUT_PATH.TextBoxBorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
|
||||||
'
|
'
|
||||||
|
'CMB_PLS
|
||||||
|
'
|
||||||
|
ActionButton12.BackgroundImage = CType(resources.GetObject("ActionButton12.BackgroundImage"), System.Drawing.Image)
|
||||||
|
ActionButton12.Name = "Save"
|
||||||
|
ActionButton12.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Save
|
||||||
|
ActionButton12.ToolTipText = "Save playlist"
|
||||||
|
ActionButton13.BackgroundImage = CType(resources.GetObject("ActionButton13.BackgroundImage"), System.Drawing.Image)
|
||||||
|
ActionButton13.Name = "List"
|
||||||
|
ActionButton13.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.List
|
||||||
|
ActionButton13.ToolTipText = "Select multiple playlists"
|
||||||
|
ActionButton14.BackgroundImage = CType(resources.GetObject("ActionButton14.BackgroundImage"), System.Drawing.Image)
|
||||||
|
ActionButton14.Name = "Open"
|
||||||
|
ActionButton14.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Open
|
||||||
|
ActionButton14.ToolTipText = "Choose an output file"
|
||||||
|
ActionButton15.BackgroundImage = CType(resources.GetObject("ActionButton15.BackgroundImage"), System.Drawing.Image)
|
||||||
|
ActionButton15.Name = "Add"
|
||||||
|
ActionButton15.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Add
|
||||||
|
ActionButton15.ToolTipText = "Choose an output file (add a new location to the list)"
|
||||||
|
ActionButton16.BackgroundImage = CType(resources.GetObject("ActionButton16.BackgroundImage"), System.Drawing.Image)
|
||||||
|
ActionButton16.Name = "Clear"
|
||||||
|
ActionButton16.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
|
||||||
|
ActionButton17.BackgroundImage = CType(resources.GetObject("ActionButton17.BackgroundImage"), System.Drawing.Image)
|
||||||
|
ActionButton17.Name = "ArrowDown"
|
||||||
|
ActionButton17.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.ArrowDown
|
||||||
|
Me.CMB_PLS.Buttons.Add(ActionButton12)
|
||||||
|
Me.CMB_PLS.Buttons.Add(ActionButton13)
|
||||||
|
Me.CMB_PLS.Buttons.Add(ActionButton14)
|
||||||
|
Me.CMB_PLS.Buttons.Add(ActionButton15)
|
||||||
|
Me.CMB_PLS.Buttons.Add(ActionButton16)
|
||||||
|
Me.CMB_PLS.Buttons.Add(ActionButton17)
|
||||||
|
Me.CMB_PLS.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.Label
|
||||||
|
Me.CMB_PLS.CaptionText = "Playlist"
|
||||||
|
Me.CMB_PLS.CaptionToolTipEnabled = True
|
||||||
|
Me.CMB_PLS.CaptionToolTipText = "Add downloaded item(s) to playlist"
|
||||||
|
Me.CMB_PLS.CaptionVisible = True
|
||||||
|
Me.CMB_PLS.CaptionWidth = 50.0R
|
||||||
|
Me.CMB_PLS.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.CMB_PLS.Location = New System.Drawing.Point(3, 115)
|
||||||
|
Me.CMB_PLS.Name = "CMB_PLS"
|
||||||
|
Me.CMB_PLS.Size = New System.Drawing.Size(428, 22)
|
||||||
|
Me.CMB_PLS.TabIndex = 3
|
||||||
|
Me.CMB_PLS.TextBoxBorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
|
||||||
|
'
|
||||||
|
'TXT_AUDIO_BITRATE
|
||||||
|
'
|
||||||
|
ActionButton18.BackgroundImage = CType(resources.GetObject("ActionButton18.BackgroundImage"), System.Drawing.Image)
|
||||||
|
ActionButton18.Name = "Clear"
|
||||||
|
ActionButton18.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
|
||||||
|
Me.TXT_AUDIO_BITRATE.Buttons.Add(ActionButton18)
|
||||||
|
Me.TXT_AUDIO_BITRATE.CaptionText = "Audio bitrate"
|
||||||
|
Me.TXT_AUDIO_BITRATE.CaptionToolTipEnabled = True
|
||||||
|
Me.TXT_AUDIO_BITRATE.CaptionToolTipText = "Default audio bitrate if you want to change it during download"
|
||||||
|
Me.TXT_AUDIO_BITRATE.CaptionWidth = 112.0R
|
||||||
|
Me.TXT_AUDIO_BITRATE.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.TXT_AUDIO_BITRATE.Location = New System.Drawing.Point(3, 59)
|
||||||
|
Me.TXT_AUDIO_BITRATE.Name = "TXT_AUDIO_BITRATE"
|
||||||
|
Me.TXT_AUDIO_BITRATE.Size = New System.Drawing.Size(428, 22)
|
||||||
|
Me.TXT_AUDIO_BITRATE.TabIndex = 4
|
||||||
|
'
|
||||||
'MusicPlaylistsForm
|
'MusicPlaylistsForm
|
||||||
'
|
'
|
||||||
Me.AcceptButton = Me.BTT_DOWN
|
Me.AcceptButton = Me.BTT_DOWN
|
||||||
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
|
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
|
||||||
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
|
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
|
||||||
Me.CancelButton = Me.BTT_CANCEL
|
Me.CancelButton = Me.BTT_CANCEL
|
||||||
Me.ClientSize = New System.Drawing.Size(434, 261)
|
Me.ClientSize = New System.Drawing.Size(434, 317)
|
||||||
Me.Controls.Add(TP_MAIN)
|
Me.Controls.Add(TP_MAIN)
|
||||||
Me.Icon = Global.SCrawler.My.Resources.SiteYouTube.YouTubeMusicIcon_32
|
Me.Icon = Global.SCrawler.My.Resources.SiteYouTube.YouTubeMusicIcon_32
|
||||||
Me.KeyPreview = True
|
Me.KeyPreview = True
|
||||||
Me.MinimumSize = New System.Drawing.Size(450, 300)
|
Me.MinimumSize = New System.Drawing.Size(450, 356)
|
||||||
Me.Name = "MusicPlaylistsForm"
|
Me.Name = "MusicPlaylistsForm"
|
||||||
Me.Text = "Albums"
|
Me.Text = "Albums"
|
||||||
TP_MAIN.ResumeLayout(False)
|
TP_MAIN.ResumeLayout(False)
|
||||||
@@ -481,6 +561,8 @@ Namespace API.YouTube.Controls
|
|||||||
TP_LYRICS.PerformLayout()
|
TP_LYRICS.PerformLayout()
|
||||||
CType(Me.TXT_SUBS, System.ComponentModel.ISupportInitialize).EndInit()
|
CType(Me.TXT_SUBS, System.ComponentModel.ISupportInitialize).EndInit()
|
||||||
CType(Me.TXT_OUTPUT_PATH, System.ComponentModel.ISupportInitialize).EndInit()
|
CType(Me.TXT_OUTPUT_PATH, System.ComponentModel.ISupportInitialize).EndInit()
|
||||||
|
CType(Me.CMB_PLS, System.ComponentModel.ISupportInitialize).EndInit()
|
||||||
|
CType(Me.TXT_AUDIO_BITRATE, System.ComponentModel.ISupportInitialize).EndInit()
|
||||||
Me.ResumeLayout(False)
|
Me.ResumeLayout(False)
|
||||||
|
|
||||||
End Sub
|
End Sub
|
||||||
@@ -496,5 +578,7 @@ Namespace API.YouTube.Controls
|
|||||||
Private WithEvents SPLITTER_MAIN As SplitContainer
|
Private WithEvents SPLITTER_MAIN As SplitContainer
|
||||||
Private WithEvents CH_DOWN_LYRICS As CheckBox
|
Private WithEvents CH_DOWN_LYRICS As CheckBox
|
||||||
Private WithEvents TXT_OUTPUT_PATH As PersonalUtilities.Forms.Controls.ComboBoxExtended
|
Private WithEvents TXT_OUTPUT_PATH As PersonalUtilities.Forms.Controls.ComboBoxExtended
|
||||||
|
Private WithEvents CMB_PLS As PersonalUtilities.Forms.Controls.ComboBoxExtended
|
||||||
|
Private WithEvents TXT_AUDIO_BITRATE As PersonalUtilities.Forms.Controls.TextBoxExtended
|
||||||
End Class
|
End Class
|
||||||
End Namespace
|
End Namespace
|
||||||
@@ -222,6 +222,13 @@
|
|||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ActionButton7.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ActionButton7.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>
|
||||||
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
|
wwAADsMBx2+oZAAAAFFJREFUOE9joAr49u3bf1Lw169f50O1QgBI0MnJCY4/vP8Ix8hiILqtrQ3TEFIM
|
||||||
|
AGGYIVDtpBsAwkQbgIyR1dDWAGLwqAGD0gByMFQ7JYCBAQChNviRiQ8ETwAAAABJRU5ErkJggg==
|
||||||
|
</value>
|
||||||
|
</data>
|
||||||
|
<data name="ActionButton8.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP
|
wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP
|
||||||
@@ -232,7 +239,7 @@
|
|||||||
cMaRN0UdBBkAAAAASUVORK5CYII=
|
cMaRN0UdBBkAAAAASUVORK5CYII=
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ActionButton8.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ActionButton9.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
|
iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
|
||||||
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAADmUlE
|
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAADmUlE
|
||||||
@@ -254,7 +261,7 @@
|
|||||||
0AUyNxOP1DOwcaG/8I+/LRB+At7psBnyDBG0AAAAAElFTkSuQmCC
|
0AUyNxOP1DOwcaG/8I+/LRB+At7psBnyDBG0AAAAAElFTkSuQmCC
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ActionButton9.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ActionButton10.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
|
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
|
||||||
@@ -262,7 +269,7 @@
|
|||||||
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
|
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ActionButton10.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ActionButton11.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAYAAAD0eNT6AAAABGdBTUEAALGPC/xhBQAAE65JREFUeF7t
|
iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAYAAAD0eNT6AAAABGdBTUEAALGPC/xhBQAAE65JREFUeF7t
|
||||||
3X2sJWddB/DdLi2lQG2hdOHuvfM887J7Cxca4ELTQMDWKigIFpBAEAgi9g+CJpJo9Q8NJhgBiYZIYspL
|
3X2sJWddB/DdLi2lQG2hdOHuvfM887J7Cxca4ELTQMDWKigIFpBAEAgi9g+CJpJo9Q8NJhgBiYZIYspL
|
||||||
@@ -350,6 +357,161 @@
|
|||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6LEtW/4flgYiLD1qeX0A
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6LEtW/4flgYiLD1qeX0A
|
||||||
AAAASUVORK5CYII=
|
AAAASUVORK5CYII=
|
||||||
|
</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+oZAAAAFFJREFUOE9joAr49u3bf1Lw169f50O1QgBI0MnJCY4/vP8Ix8hiILqtrQ3TEFIM
|
||||||
|
AGGYIVDtpBsAwkQbgIyR1dDWAGLwqAGD0gByMFQ7JYCBAQChNviRiQ8ETwAAAABJRU5ErkJggg==
|
||||||
|
</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+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAeElE
|
||||||
|
QVQ4T2P4//8/RRhMFHQfKgDi/yAaXQEhDCZAmkNbnvyXta4CciESLEws//FhmDqYAQUgzUBMngsowVgF
|
||||||
|
ScFgYjQQsUsQi8FEYsXyAiD+D6LRFRDCYAKk2bPo6H9J40wgFyKBLeCQMUwdzIACkGYgHnKB+J8BAD5Q
|
||||||
|
tqhi4tzWAAAAAElFTkSuQmCC
|
||||||
|
</value>
|
||||||
|
</data>
|
||||||
|
<data name="ActionButton14.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>
|
||||||
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
|
wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP
|
||||||
|
WQwhyWIyJIUW5NqyPb7oCVtIlhVTwYf8nv7/t2zJagel9KmqKsIACYL9RjI8UHz5zshougZr/AEvbxEP
|
||||||
|
aZCDBY3VslixaJvX3wzkkDiOwbZtDRGA5vdNAg+TL27qgmt5XkBG/gTdAG7Gt+3PP9oOaEGFCVEC6rp+
|
||||||
|
5g9MfM/c5e4OsEZMZkQEtGL5H2DdZ5JRArDwPA+iKII0TfkC9vroC9j5vq8JTWw3WzWgLMtZGIaa0MR8
|
||||||
|
vlAD8PYlSaIJTTiOowY0p0Bc19XEJo6HE59FAPuMzyAINKGJ1XLFZxHALtMrnkBXOIQIIIQ8YvF/KrgB
|
||||||
|
cMaRN0UdBBkAAAAASUVORK5CYII=
|
||||||
|
</value>
|
||||||
|
</data>
|
||||||
|
<data name="ActionButton15.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>
|
||||||
|
iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
|
||||||
|
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAADmUlE
|
||||||
|
QVRIS62WWWxMURjHL220JW1HausmlFrDFKUhnUGH6bRFzJ2idImlC0Vp2mlji1A8iNhCPIjIRES8EU+W
|
||||||
|
h2oEtbSDTk3HNNM7S01VKsXjkb/vXBo3k1Ee7sMvmZzzzf//ne/+z50RAAxL1MUIG4G/YAv3HSVhF5Vw
|
||||||
|
IYNdz3LadVj9RgdTB+HQYYPHIJuE1ocSdlEJFzG+1bPRLQLinglIeCkg+XUkKvz56hnkOfQs/rmA8S9H
|
||||||
|
YEp7FDI64tAQtKhnsMapZ7zzNHsUFnbGY4VzIk70l6hnIH4wsDR7NBZ3apDrSqL5T8eFgUr1DLZ78lim
|
||||||
|
Q4N8VzK29MxEpZSBa4M16hnU+c3M9CEFpdJsVHsXos63DDcHrf9nQEXD5VymwW/5USLNwl5vJhp7dTgW
|
||||||
|
NML2pR7jbsUMS+KdMTa5Q8NQxinfBU4dRFcOyjy52OtbhwOBDTgZLKPPmTgY0ON4MBdNfSbYBupxY8Aq
|
||||||
|
G10dqMG5/nIc7ytGQ6CQRliAamkTN/g1Ai4e95Qy3iogpX0UtBRDnhRzdxq2SXOxz5eFQ70rScCEU335
|
||||||
|
ssGxj0YS06HSm4GN3ekwdE2C1hGH1LZR0JDOJof5jwHvnIvzTa0jlooTYfktvt+fhcOBHDQFTWRgxJGP
|
||||||
|
ObAGsulZLMLWnjlY756K5c4JmNcRi6T2SGheCIihS2l5ozAo6NRhMolnUAcGV6IcwwqvFrX+JTjYuwKH
|
||||||
|
SfRAYDms/mzs9y1GFe2VSnOw1j0FejqpLN4WCX4ZufiIBwLMLxQGm12rsLQzgWKYgmLPLNTQw6ynpDSS
|
||||||
|
IBet8y+TqaVRVdFIeJrWuCcj+/0EzH43BomvIhBLI45uFiDcJ+6QwROFwa6+Amb9bGFNg6Xs9Ncd7Oy3
|
||||||
|
Knb2eyU7/20nu9y/m136tIvEl6BC0qKoZwby3alo9JVhj7T5R7m/kJVIIityi8zyXmTiW+I10SqyIQNb
|
||||||
|
uIgNwYuuf25kFd75KPKkI49OmUWnrfYWyXv/wBb2cijhhVf6a9lGei65XclYRDd6mj0GWz2iLBJaH0rY
|
||||||
|
RSVc5Eywmhm7kuQXHX+bJlBStrh+zTi0PpSwi0q4yNFAOVvgiEcKJWUsxZn/NhT+znlofShhF5VwkRpv
|
||||||
|
MUtti4KGYjj6sYCIh5QSu4oG27stjItHU+cjeQzvkcFzFQ2KnSKLoc4FukDCXeI2GbSoaFD4ziyPxNxK
|
||||||
|
0AUyNxOP1DOwcaG/8I+/LRB+At7psBnyDBG0AAAAAElFTkSuQmCC
|
||||||
|
</value>
|
||||||
|
</data>
|
||||||
|
<data name="ActionButton16.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>
|
||||||
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
|
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
|
||||||
|
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
|
||||||
|
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
|
||||||
|
</value>
|
||||||
|
</data>
|
||||||
|
<data name="ActionButton17.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="ActionButton18.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>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
</root>
|
</root>
|
||||||
@@ -19,10 +19,17 @@ Namespace API.YouTube.Controls
|
|||||||
Friend Class MusicPlaylistsForm : Implements IDesignXMLContainer
|
Friend Class MusicPlaylistsForm : Implements IDesignXMLContainer
|
||||||
#Region "Declarations"
|
#Region "Declarations"
|
||||||
Private MyView As FormView
|
Private MyView As FormView
|
||||||
|
Private ReadOnly MyFieldsChecker As FieldsChecker
|
||||||
Friend Property DesignXML As EContainer Implements IDesignXMLContainer.DesignXML
|
Friend Property DesignXML As EContainer Implements IDesignXMLContainer.DesignXML
|
||||||
Private Property DesignXMLNodes As String() Implements IDesignXMLContainer.DesignXMLNodes
|
Private Property DesignXMLNodes As String() Implements IDesignXMLContainer.DesignXMLNodes
|
||||||
Private Property DesignXMLNodeName As String Implements IDesignXMLContainer.DesignXMLNodeName
|
Private Property DesignXMLNodeName As String Implements IDesignXMLContainer.DesignXMLNodeName
|
||||||
Private ReadOnly MyContainer As IYouTubeMediaContainer
|
Private ReadOnly MyContainer As IYouTubeMediaContainer
|
||||||
|
Private ReadOnly M3U8Files As List(Of SFile)
|
||||||
|
Private ReadOnly Property M3U8FilesFull As List(Of SFile)
|
||||||
|
Get
|
||||||
|
Return ListAddList(Nothing, M3U8Files, LAP.NotContainsOnly).ListAddValue(CMB_PLS.Text, LAP.NotContainsOnly)
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
Private Initializing As Boolean = True
|
Private Initializing As Boolean = True
|
||||||
Private ReadOnly Property Current As IYouTubeMediaContainer
|
Private ReadOnly Property Current As IYouTubeMediaContainer
|
||||||
Get
|
Get
|
||||||
@@ -40,7 +47,9 @@ Namespace API.YouTube.Controls
|
|||||||
#Region "Initializer"
|
#Region "Initializer"
|
||||||
Friend Sub New(ByVal Container As IYouTubeMediaContainer)
|
Friend Sub New(ByVal Container As IYouTubeMediaContainer)
|
||||||
InitializeComponent()
|
InitializeComponent()
|
||||||
|
M3U8Files = New List(Of SFile)
|
||||||
MyContainer = Container
|
MyContainer = Container
|
||||||
|
MyFieldsChecker = New FieldsChecker
|
||||||
End Sub
|
End Sub
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Form handlers"
|
#Region "Form handlers"
|
||||||
@@ -52,6 +61,9 @@ Namespace API.YouTube.Controls
|
|||||||
End If
|
End If
|
||||||
|
|
||||||
MyYouTubeSettings.DownloadLocations.PopulateComboBox(TXT_OUTPUT_PATH)
|
MyYouTubeSettings.DownloadLocations.PopulateComboBox(TXT_OUTPUT_PATH)
|
||||||
|
MyYouTubeSettings.PlaylistsLocations.PopulateComboBox(CMB_PLS,, True)
|
||||||
|
CMB_PLS.Text = MyYouTubeSettings.LatestPlaylistFile.Value
|
||||||
|
If MyYouTubeSettings.DefaultAudioBitrate > 0 Then TXT_AUDIO_BITRATE.Text = MyYouTubeSettings.DefaultAudioBitrate.Value
|
||||||
|
|
||||||
CMB_FORMATS.Items.AddRange(AvailableAudioFormats)
|
CMB_FORMATS.Items.AddRange(AvailableAudioFormats)
|
||||||
If MyYouTubeSettings.PlaylistFormSplitterDistance > 0 Then SPLITTER_MAIN.SplitterDistancePercentageSet(MyYouTubeSettings.PlaylistFormSplitterDistance)
|
If MyYouTubeSettings.PlaylistFormSplitterDistance > 0 Then SPLITTER_MAIN.SplitterDistancePercentageSet(MyYouTubeSettings.PlaylistFormSplitterDistance)
|
||||||
@@ -104,6 +116,9 @@ Namespace API.YouTube.Controls
|
|||||||
Text = .PlaylistTitle
|
Text = .PlaylistTitle
|
||||||
End If
|
End If
|
||||||
|
|
||||||
|
MyFieldsChecker.AddControl(Of Integer)(TXT_AUDIO_BITRATE, TXT_AUDIO_BITRATE.CaptionText, True)
|
||||||
|
MyFieldsChecker.EndLoaderOperations()
|
||||||
|
|
||||||
UpdateSizeText()
|
UpdateSizeText()
|
||||||
End With
|
End With
|
||||||
RefillAddit()
|
RefillAddit()
|
||||||
@@ -111,7 +126,9 @@ Namespace API.YouTube.Controls
|
|||||||
End Sub
|
End Sub
|
||||||
Private Sub MusicPlaylistsForm_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
|
Private Sub MusicPlaylistsForm_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
|
||||||
MyYouTubeSettings.PlaylistFormSplitterDistance.Value = SPLITTER_MAIN.SplitterDistancePercentageGet
|
MyYouTubeSettings.PlaylistFormSplitterDistance.Value = SPLITTER_MAIN.SplitterDistancePercentageGet
|
||||||
MyView.DisposeIfReady()
|
MyView.DisposeIfReady
|
||||||
|
MyFieldsChecker.DisposeIfReady
|
||||||
|
M3U8Files.Clear()
|
||||||
End Sub
|
End Sub
|
||||||
Private Sub MusicPlaylistsForm_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
|
Private Sub MusicPlaylistsForm_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
|
||||||
Dim b As Boolean = True
|
Dim b As Boolean = True
|
||||||
@@ -181,8 +198,52 @@ Namespace API.YouTube.Controls
|
|||||||
End With
|
End With
|
||||||
End Sub
|
End Sub
|
||||||
Private Sub TXT_OUTPUT_PATH_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As ActionButtonEventArgs) Handles TXT_OUTPUT_PATH.ActionOnButtonClick
|
Private Sub TXT_OUTPUT_PATH_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As ActionButtonEventArgs) Handles TXT_OUTPUT_PATH.ActionOnButtonClick
|
||||||
If Sender.DefaultButton = ADB.Open Or Sender.DefaultButton = ADB.Add Then _
|
Select Case e.DefaultButton
|
||||||
MyYouTubeSettings.DownloadLocations.ChooseNewLocation(TXT_OUTPUT_PATH, Sender.DefaultButton = ADB.Add, MyDownloaderSettings.OutputPathAskForName)
|
Case ADB.Open, ADB.Add
|
||||||
|
MyYouTubeSettings.DownloadLocations.ChooseNewLocation(TXT_OUTPUT_PATH, e.DefaultButton = ADB.Add, MyDownloaderSettings.OutputPathAskForName)
|
||||||
|
Case ADB.Save
|
||||||
|
If Not TXT_OUTPUT_PATH.Text.IsEmptyString Then
|
||||||
|
With MyYouTubeSettings.PlaylistsLocations
|
||||||
|
.Add(TXT_OUTPUT_PATH.Text, True)
|
||||||
|
.PopulateComboBox(TXT_OUTPUT_PATH, TXT_OUTPUT_PATH.Text)
|
||||||
|
End With
|
||||||
|
End If
|
||||||
|
End Select
|
||||||
|
End Sub
|
||||||
|
Private Sub CMB_PLS_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As ActionButtonEventArgs) Handles CMB_PLS.ActionOnButtonClick
|
||||||
|
Try
|
||||||
|
Select Case e.DefaultButton
|
||||||
|
Case ADB.Add, ADB.Open
|
||||||
|
Dim f As SFile = Nothing
|
||||||
|
If Not CMB_PLS.Text.IsEmptyString Then
|
||||||
|
f = CMB_PLS.Text
|
||||||
|
ElseIf Not TXT_OUTPUT_PATH.Text.IsEmptyString Then
|
||||||
|
f = TXT_OUTPUT_PATH.Text
|
||||||
|
End If
|
||||||
|
f = SFile.SelectFiles(f, False, "Select a playlist...", "Playlists|*.m3u;*.m3u8|All files|*.*", EDP.ReturnValue).FirstOrDefault
|
||||||
|
If Not f.IsEmptyString Then
|
||||||
|
If Sender.DefaultButton = ADB.Add Then
|
||||||
|
MyYouTubeSettings.PlaylistsLocations.Add(f.ToString, True, True)
|
||||||
|
MyYouTubeSettings.PlaylistsLocations.PopulateComboBox(CMB_PLS, f, True)
|
||||||
|
End If
|
||||||
|
CMB_PLS.Text = f
|
||||||
|
End If
|
||||||
|
Case ADB.List
|
||||||
|
Dim result As Boolean = False
|
||||||
|
Dim selectedFiles As IEnumerable(Of SFile) = MyYouTubeSettings.PlaylistsLocations.ChooseNewPlaylistArray(CMB_PLS, result)
|
||||||
|
If result Then M3U8Files.ListAddList(selectedFiles, LAP.NotContainsOnly, LAP.ClearBeforeAdd)
|
||||||
|
Case ADB.Save
|
||||||
|
With MyYouTubeSettings.PlaylistsLocations
|
||||||
|
If Not CMB_PLS.Text.IsEmptyString AndAlso .IndexOf(CMB_PLS.Text,, True) = -1 Then
|
||||||
|
.Add(CMB_PLS.Text, True, True)
|
||||||
|
.PopulateComboBox(CMB_PLS, CMB_PLS.Text, True)
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
Case ADB.Clear : M3U8Files.Clear()
|
||||||
|
End Select
|
||||||
|
Catch ex As Exception
|
||||||
|
ErrorsDescriber.Execute(EDP.SendToLog, ex, "[API.YouTube.Controls.MusicPlaylistsForm.SelectPlaylist]")
|
||||||
|
End Try
|
||||||
End Sub
|
End Sub
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Lists' handlers"
|
#Region "Lists' handlers"
|
||||||
@@ -268,7 +329,7 @@ Namespace API.YouTube.Controls
|
|||||||
Private Sub BTT_DOWN_Click(sender As Object, e As EventArgs) Handles BTT_DOWN.Click
|
Private Sub BTT_DOWN_Click(sender As Object, e As EventArgs) Handles BTT_DOWN.Click
|
||||||
If TXT_OUTPUT_PATH.IsEmptyString Then
|
If TXT_OUTPUT_PATH.IsEmptyString Then
|
||||||
MsgBoxE({"The output path cannot be null.", "Download music"}, vbCritical)
|
MsgBoxE({"The output path cannot be null.", "Download music"}, vbCritical)
|
||||||
Else
|
ElseIf MyFieldsChecker.AllParamsOK Then
|
||||||
With DirectCast(MyContainer, YouTubeMediaContainerBase)
|
With DirectCast(MyContainer, YouTubeMediaContainerBase)
|
||||||
.OutputSubtitlesFormat = IIf(CH_DOWN_LYRICS.Checked, "LRC", String.Empty)
|
.OutputSubtitlesFormat = IIf(CH_DOWN_LYRICS.Checked, "LRC", String.Empty)
|
||||||
If Not TXT_SUBS.Checked Then .PostProcessing_OutputSubtitlesFormats.Clear()
|
If Not TXT_SUBS.Checked Then .PostProcessing_OutputSubtitlesFormats.Clear()
|
||||||
@@ -276,8 +337,12 @@ Namespace API.YouTube.Controls
|
|||||||
If Not TXT_FORMATS_ADDIT.Checked Then .PostProcessing_OutputAudioFormats.Clear()
|
If Not TXT_FORMATS_ADDIT.Checked Then .PostProcessing_OutputAudioFormats.Clear()
|
||||||
.AbsolutePath = TXT_OUTPUT_PATH.Checked
|
.AbsolutePath = TXT_OUTPUT_PATH.Checked
|
||||||
.File = TXT_OUTPUT_PATH.Text.CSFileP
|
.File = TXT_OUTPUT_PATH.Text.CSFileP
|
||||||
|
.M3U8_PlaylistFiles = M3U8FilesFull
|
||||||
|
.OutputAudioBitrate = AConvert(Of Integer)(TXT_AUDIO_BITRATE.Text, -1)
|
||||||
If MyYouTubeSettings.OutputPathAutoChange Then MyYouTubeSettings.OutputPath.Value = .File
|
If MyYouTubeSettings.OutputPathAutoChange Then MyYouTubeSettings.OutputPath.Value = .File
|
||||||
If MyDownloaderSettings.OutputPathAutoAddPaths Then MyYouTubeSettings.DownloadLocations.Add(.File, False)
|
If MyDownloaderSettings.OutputPathAutoAddPaths Then MyYouTubeSettings.DownloadLocations.Add(.File, False)
|
||||||
|
If Not CMB_PLS.Text.IsEmptyString Then MyYouTubeSettings.PlaylistsLocations.Add(CMB_PLS.Text, False, True)
|
||||||
|
MyYouTubeSettings.LatestPlaylistFile.Value = CMB_PLS.Text
|
||||||
End With
|
End With
|
||||||
DialogResult = DialogResult.OK
|
DialogResult = DialogResult.OK
|
||||||
Close()
|
Close()
|
||||||
|
|||||||
@@ -121,9 +121,10 @@ Namespace API.YouTube.Controls
|
|||||||
Me.TXT_LIMIT.Location = New System.Drawing.Point(3, 3)
|
Me.TXT_LIMIT.Location = New System.Drawing.Point(3, 3)
|
||||||
Me.TXT_LIMIT.Name = "TXT_LIMIT"
|
Me.TXT_LIMIT.Name = "TXT_LIMIT"
|
||||||
Me.TXT_LIMIT.PlaceholderEnabled = True
|
Me.TXT_LIMIT.PlaceholderEnabled = True
|
||||||
Me.TXT_LIMIT.PlaceholderText = "e.g. ABCDE"
|
Me.TXT_LIMIT.PlaceholderText = "e.g. RDAMP"
|
||||||
Me.TXT_LIMIT.Size = New System.Drawing.Size(378, 22)
|
Me.TXT_LIMIT.Size = New System.Drawing.Size(378, 22)
|
||||||
Me.TXT_LIMIT.TabIndex = 2
|
Me.TXT_LIMIT.TabIndex = 2
|
||||||
|
Me.TXT_LIMIT.Text = "RDAMP"
|
||||||
'
|
'
|
||||||
'CONTAINER_MAIN
|
'CONTAINER_MAIN
|
||||||
'
|
'
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ Namespace API.YouTube.Controls
|
|||||||
Me.TXT_URLS.MaxLength = 2147483647
|
Me.TXT_URLS.MaxLength = 2147483647
|
||||||
Me.TXT_URLS.Multiline = True
|
Me.TXT_URLS.Multiline = True
|
||||||
Me.TXT_URLS.Name = "TXT_URLS"
|
Me.TXT_URLS.Name = "TXT_URLS"
|
||||||
|
Me.TXT_URLS.ScrollBars = System.Windows.Forms.ScrollBars.Both
|
||||||
Me.TXT_URLS.Size = New System.Drawing.Size(372, 261)
|
Me.TXT_URLS.Size = New System.Drawing.Size(372, 261)
|
||||||
Me.TXT_URLS.TabIndex = 0
|
Me.TXT_URLS.TabIndex = 0
|
||||||
'
|
'
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ Namespace API.YouTube.Controls
|
|||||||
Friend Sub New(ByVal m As MediaObject, Optional ByVal SelectedAudio As MediaObject = Nothing)
|
Friend Sub New(ByVal m As MediaObject, Optional ByVal SelectedAudio As MediaObject = Nothing)
|
||||||
Me.New
|
Me.New
|
||||||
Const d$ = " " & ChrW(183) & " "
|
Const d$ = " " & ChrW(183) & " "
|
||||||
|
Const DRC$ = Objects.YouTubeMediaContainerBase.DRC
|
||||||
MyMedia = m
|
MyMedia = m
|
||||||
If m.Type = Plugin.UserMediaTypes.Audio Then
|
If m.Type = Plugin.UserMediaTypes.Audio Then
|
||||||
If m.Bitrate >= 320 Then
|
If m.Bitrate >= 320 Then
|
||||||
@@ -38,6 +39,7 @@ Namespace API.YouTube.Controls
|
|||||||
End If
|
End If
|
||||||
LBL_DEFINITION.Text = $"{m.Bitrate}k"
|
LBL_DEFINITION.Text = $"{m.Bitrate}k"
|
||||||
LBL_CODECS.Text = $"{m.Extension} {d} {m.Codec} {d} {m.Bitrate}k"
|
LBL_CODECS.Text = $"{m.Extension} {d} {m.Codec} {d} {m.Bitrate}k"
|
||||||
|
If Not m.ID.IsEmptyString AndAlso m.ID.StringToLower.Contains(DRC) Then LBL_CODECS.Text &= $" {d} DRC"
|
||||||
Else
|
Else
|
||||||
If m.Height >= 1440 Then
|
If m.Height >= 1440 Then
|
||||||
LBL_DEFINITION_INFO.Text = "Ultra High Definition"
|
LBL_DEFINITION_INFO.Text = "Ultra High Definition"
|
||||||
@@ -53,7 +55,14 @@ Namespace API.YouTube.Controls
|
|||||||
LBL_DEFINITION.Text = $"{m.Height}p"
|
LBL_DEFINITION.Text = $"{m.Height}p"
|
||||||
LBL_CODECS.Text = $"{m.Extension.StringToUpper}{d}{m.Codec.StringToUpper}{d}{m.FPS}fps{d}{m.Bitrate}k"
|
LBL_CODECS.Text = $"{m.Extension.StringToUpper}{d}{m.Codec.StringToUpper}{d}{m.FPS}fps{d}{m.Bitrate}k"
|
||||||
If Not m.Protocol.IsEmptyString Then LBL_CODECS.Text &= $" ({m.Protocol})"
|
If Not m.Protocol.IsEmptyString Then LBL_CODECS.Text &= $" ({m.Protocol})"
|
||||||
|
If Not m.ID.IsEmptyString AndAlso m.ID.StringToLower.Contains(DRC) Then LBL_CODECS.Text &= $"{d}DRC"
|
||||||
If Not SelectedAudio.ID.IsEmptyString Then LBL_CODECS.Text &= $" / {SelectedAudio.Extension}{d}{SelectedAudio.Codec}{d}{SelectedAudio.Bitrate}k"
|
If Not SelectedAudio.ID.IsEmptyString Then LBL_CODECS.Text &= $" / {SelectedAudio.Extension}{d}{SelectedAudio.Codec}{d}{SelectedAudio.Bitrate}k"
|
||||||
|
If Not SelectedAudio.ID.IsEmptyString AndAlso SelectedAudio.ID.StringToLower.Contains(DRC) Then LBL_CODECS.Text &= $"{d}DRC"
|
||||||
|
|
||||||
|
If MyYouTubeSettings.DefaultVideoHighlightFPS_H > 0 AndAlso m.FPS > MyYouTubeSettings.DefaultVideoHighlightFPS_H Then _
|
||||||
|
BackColor = MyColor.DeleteBack : ForeColor = MyColor.DeleteFore
|
||||||
|
If MyYouTubeSettings.DefaultVideoHighlightFPS_L > 0 AndAlso m.FPS < MyYouTubeSettings.DefaultVideoHighlightFPS_L Then _
|
||||||
|
BackColor = MyColor.UpdateBack : ForeColor = MyColor.UpdateFore
|
||||||
End If
|
End If
|
||||||
|
|
||||||
Dim sv% = m.Size / 1024
|
Dim sv% = m.Size / 1024
|
||||||
|
|||||||
343
SCrawler.YouTube/Controls/VideoOptionsForm.Designer.vb
generated
@@ -31,9 +31,15 @@ Namespace API.YouTube.Controls
|
|||||||
Dim TP_DESTINATION As System.Windows.Forms.TableLayoutPanel
|
Dim TP_DESTINATION As System.Windows.Forms.TableLayoutPanel
|
||||||
Dim ActionButton1 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
Dim ActionButton1 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||||
Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(VideoOptionsForm))
|
Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(VideoOptionsForm))
|
||||||
|
Dim ActionButton2 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||||
Dim ListColumn1 As PersonalUtilities.Forms.Controls.Base.ListColumn = New PersonalUtilities.Forms.Controls.Base.ListColumn()
|
Dim ListColumn1 As PersonalUtilities.Forms.Controls.Base.ListColumn = New PersonalUtilities.Forms.Controls.Base.ListColumn()
|
||||||
Dim ListColumn2 As PersonalUtilities.Forms.Controls.Base.ListColumn = New PersonalUtilities.Forms.Controls.Base.ListColumn()
|
Dim ListColumn2 As PersonalUtilities.Forms.Controls.Base.ListColumn = New PersonalUtilities.Forms.Controls.Base.ListColumn()
|
||||||
Dim TP_OK_CANCEL As System.Windows.Forms.TableLayoutPanel
|
Dim TP_OK_CANCEL As System.Windows.Forms.TableLayoutPanel
|
||||||
|
Dim TP_PLS As System.Windows.Forms.TableLayoutPanel
|
||||||
|
Dim ActionButton3 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||||
|
Dim ActionButton4 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||||
|
Dim ActionButton5 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||||
|
Dim ActionButton6 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||||
Dim LB_SEP_1 As System.Windows.Forms.Label
|
Dim LB_SEP_1 As System.Windows.Forms.Label
|
||||||
Dim LB_SEP_2 As System.Windows.Forms.Label
|
Dim LB_SEP_2 As System.Windows.Forms.Label
|
||||||
Dim TP_WHAT As System.Windows.Forms.TableLayoutPanel
|
Dim TP_WHAT As System.Windows.Forms.TableLayoutPanel
|
||||||
@@ -41,27 +47,34 @@ Namespace API.YouTube.Controls
|
|||||||
Dim LBL_FORMAT As System.Windows.Forms.Label
|
Dim LBL_FORMAT As System.Windows.Forms.Label
|
||||||
Dim LBL_SUBS_FORMAT As System.Windows.Forms.Label
|
Dim LBL_SUBS_FORMAT As System.Windows.Forms.Label
|
||||||
Dim TT_MAIN As System.Windows.Forms.ToolTip
|
Dim TT_MAIN As System.Windows.Forms.ToolTip
|
||||||
Dim ActionButton2 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
Dim TP_FPS_BITRATE As System.Windows.Forms.TableLayoutPanel
|
||||||
Dim ActionButton3 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
|
||||||
Dim ActionButton4 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
|
||||||
Dim ActionButton5 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
|
||||||
Dim ActionButton6 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
|
||||||
Dim ActionButton7 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
Dim ActionButton7 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||||
Dim ActionButton8 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
Dim ActionButton8 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||||
Dim ActionButton9 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
Dim ActionButton9 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||||
Dim ActionButton10 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
Dim ActionButton10 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||||
|
Dim ActionButton11 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||||
|
Dim ActionButton12 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||||
|
Dim ActionButton13 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||||
|
Dim ActionButton14 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||||
|
Dim ActionButton15 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||||
|
Dim ActionButton16 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||||
|
Dim ActionButton17 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||||
Me.ICON_VIDEO = New System.Windows.Forms.PictureBox()
|
Me.ICON_VIDEO = New System.Windows.Forms.PictureBox()
|
||||||
Me.LBL_TITLE = New System.Windows.Forms.Label()
|
Me.LBL_TITLE = New System.Windows.Forms.Label()
|
||||||
Me.TP_HEADER_INFO_2 = New System.Windows.Forms.TableLayoutPanel()
|
Me.TP_HEADER_INFO_2 = New System.Windows.Forms.TableLayoutPanel()
|
||||||
Me.LBL_TIME = New System.Windows.Forms.Label()
|
Me.LBL_TIME = New System.Windows.Forms.Label()
|
||||||
Me.LBL_URL = New System.Windows.Forms.LinkLabel()
|
Me.LBL_URL = New System.Windows.Forms.LinkLabel()
|
||||||
Me.TXT_FILE = New PersonalUtilities.Forms.Controls.ComboBoxExtended()
|
Me.TXT_FILE = New PersonalUtilities.Forms.Controls.ComboBoxExtended()
|
||||||
Me.BTT_BROWSE = New System.Windows.Forms.Button()
|
Me.BTT_BROWSE = New SCrawler.API.YouTube.Controls.ButtonRC()
|
||||||
Me.BTT_DOWN = New System.Windows.Forms.Button()
|
Me.BTT_DOWN = New System.Windows.Forms.Button()
|
||||||
Me.BTT_CANCEL = New System.Windows.Forms.Button()
|
Me.BTT_CANCEL = New System.Windows.Forms.Button()
|
||||||
|
Me.CMB_PLS = New PersonalUtilities.Forms.Controls.ComboBoxExtended()
|
||||||
|
Me.BTT_PLS_BROWSE = New SCrawler.API.YouTube.Controls.ButtonRC()
|
||||||
Me.OPT_VIDEO = New System.Windows.Forms.RadioButton()
|
Me.OPT_VIDEO = New System.Windows.Forms.RadioButton()
|
||||||
Me.OPT_AUDIO = New System.Windows.Forms.RadioButton()
|
Me.OPT_AUDIO = New System.Windows.Forms.RadioButton()
|
||||||
Me.LBL_AUDIO_CODEC = New System.Windows.Forms.Label()
|
Me.LBL_AUDIO_CODEC = New System.Windows.Forms.Label()
|
||||||
|
Me.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()
|
Me.TP_HEADER_BASE = New System.Windows.Forms.TableLayoutPanel()
|
||||||
Me.TP_SUBS = New System.Windows.Forms.TableLayoutPanel()
|
Me.TP_SUBS = New System.Windows.Forms.TableLayoutPanel()
|
||||||
Me.TXT_SUBS = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
Me.TXT_SUBS = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
||||||
@@ -81,6 +94,7 @@ Namespace API.YouTube.Controls
|
|||||||
TP_FOOTER = New System.Windows.Forms.TableLayoutPanel()
|
TP_FOOTER = New System.Windows.Forms.TableLayoutPanel()
|
||||||
TP_DESTINATION = New System.Windows.Forms.TableLayoutPanel()
|
TP_DESTINATION = New System.Windows.Forms.TableLayoutPanel()
|
||||||
TP_OK_CANCEL = New System.Windows.Forms.TableLayoutPanel()
|
TP_OK_CANCEL = New System.Windows.Forms.TableLayoutPanel()
|
||||||
|
TP_PLS = New System.Windows.Forms.TableLayoutPanel()
|
||||||
LB_SEP_1 = New System.Windows.Forms.Label()
|
LB_SEP_1 = New System.Windows.Forms.Label()
|
||||||
LB_SEP_2 = New System.Windows.Forms.Label()
|
LB_SEP_2 = New System.Windows.Forms.Label()
|
||||||
TP_WHAT = New System.Windows.Forms.TableLayoutPanel()
|
TP_WHAT = New System.Windows.Forms.TableLayoutPanel()
|
||||||
@@ -88,6 +102,7 @@ Namespace API.YouTube.Controls
|
|||||||
LBL_FORMAT = New System.Windows.Forms.Label()
|
LBL_FORMAT = New System.Windows.Forms.Label()
|
||||||
LBL_SUBS_FORMAT = New System.Windows.Forms.Label()
|
LBL_SUBS_FORMAT = New System.Windows.Forms.Label()
|
||||||
TT_MAIN = New System.Windows.Forms.ToolTip(Me.components)
|
TT_MAIN = New System.Windows.Forms.ToolTip(Me.components)
|
||||||
|
TP_FPS_BITRATE = New System.Windows.Forms.TableLayoutPanel()
|
||||||
TP_HEADER.SuspendLayout()
|
TP_HEADER.SuspendLayout()
|
||||||
CType(Me.ICON_VIDEO, System.ComponentModel.ISupportInitialize).BeginInit()
|
CType(Me.ICON_VIDEO, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||||
TP_HEADER_INFO.SuspendLayout()
|
TP_HEADER_INFO.SuspendLayout()
|
||||||
@@ -98,7 +113,12 @@ Namespace API.YouTube.Controls
|
|||||||
TP_DESTINATION.SuspendLayout()
|
TP_DESTINATION.SuspendLayout()
|
||||||
CType(Me.TXT_FILE, System.ComponentModel.ISupportInitialize).BeginInit()
|
CType(Me.TXT_FILE, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||||
TP_OK_CANCEL.SuspendLayout()
|
TP_OK_CANCEL.SuspendLayout()
|
||||||
|
TP_PLS.SuspendLayout()
|
||||||
|
CType(Me.CMB_PLS, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||||
TP_WHAT.SuspendLayout()
|
TP_WHAT.SuspendLayout()
|
||||||
|
TP_FPS_BITRATE.SuspendLayout()
|
||||||
|
CType(Me.TXT_FPS, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||||
|
CType(Me.TXT_AUDIO_BITRATE, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||||
Me.TP_HEADER_BASE.SuspendLayout()
|
Me.TP_HEADER_BASE.SuspendLayout()
|
||||||
Me.TP_SUBS.SuspendLayout()
|
Me.TP_SUBS.SuspendLayout()
|
||||||
CType(Me.TXT_SUBS, System.ComponentModel.ISupportInitialize).BeginInit()
|
CType(Me.TXT_SUBS, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||||
@@ -240,17 +260,18 @@ Namespace API.YouTube.Controls
|
|||||||
'
|
'
|
||||||
TP_FOOTER.ColumnCount = 1
|
TP_FOOTER.ColumnCount = 1
|
||||||
TP_FOOTER.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
TP_FOOTER.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
TP_FOOTER.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20.0!))
|
TP_FOOTER.Controls.Add(TP_DESTINATION, 0, 1)
|
||||||
TP_FOOTER.Controls.Add(TP_DESTINATION, 0, 0)
|
TP_FOOTER.Controls.Add(TP_OK_CANCEL, 0, 2)
|
||||||
TP_FOOTER.Controls.Add(TP_OK_CANCEL, 0, 1)
|
TP_FOOTER.Controls.Add(TP_PLS, 0, 0)
|
||||||
TP_FOOTER.Dock = System.Windows.Forms.DockStyle.Fill
|
TP_FOOTER.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
TP_FOOTER.Location = New System.Drawing.Point(6, 215)
|
TP_FOOTER.Location = New System.Drawing.Point(6, 243)
|
||||||
TP_FOOTER.Margin = New System.Windows.Forms.Padding(6, 3, 6, 3)
|
TP_FOOTER.Margin = New System.Windows.Forms.Padding(6, 3, 6, 3)
|
||||||
TP_FOOTER.Name = "TP_FOOTER"
|
TP_FOOTER.Name = "TP_FOOTER"
|
||||||
TP_FOOTER.RowCount = 2
|
TP_FOOTER.RowCount = 3
|
||||||
TP_FOOTER.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
|
TP_FOOTER.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 33.33333!))
|
||||||
TP_FOOTER.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
|
TP_FOOTER.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 33.33333!))
|
||||||
TP_FOOTER.Size = New System.Drawing.Size(589, 52)
|
TP_FOOTER.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 33.33333!))
|
||||||
|
TP_FOOTER.Size = New System.Drawing.Size(589, 81)
|
||||||
TP_FOOTER.TabIndex = 5
|
TP_FOOTER.TabIndex = 5
|
||||||
'
|
'
|
||||||
'TP_DESTINATION
|
'TP_DESTINATION
|
||||||
@@ -261,20 +282,25 @@ Namespace API.YouTube.Controls
|
|||||||
TP_DESTINATION.Controls.Add(Me.TXT_FILE, 0, 0)
|
TP_DESTINATION.Controls.Add(Me.TXT_FILE, 0, 0)
|
||||||
TP_DESTINATION.Controls.Add(Me.BTT_BROWSE, 1, 0)
|
TP_DESTINATION.Controls.Add(Me.BTT_BROWSE, 1, 0)
|
||||||
TP_DESTINATION.Dock = System.Windows.Forms.DockStyle.Fill
|
TP_DESTINATION.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
TP_DESTINATION.Location = New System.Drawing.Point(0, 0)
|
TP_DESTINATION.Location = New System.Drawing.Point(0, 27)
|
||||||
TP_DESTINATION.Margin = New System.Windows.Forms.Padding(0)
|
TP_DESTINATION.Margin = New System.Windows.Forms.Padding(0)
|
||||||
TP_DESTINATION.Name = "TP_DESTINATION"
|
TP_DESTINATION.Name = "TP_DESTINATION"
|
||||||
TP_DESTINATION.RowCount = 1
|
TP_DESTINATION.RowCount = 1
|
||||||
TP_DESTINATION.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
TP_DESTINATION.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
TP_DESTINATION.Size = New System.Drawing.Size(589, 26)
|
TP_DESTINATION.Size = New System.Drawing.Size(589, 27)
|
||||||
TP_DESTINATION.TabIndex = 0
|
TP_DESTINATION.TabIndex = 0
|
||||||
'
|
'
|
||||||
'TXT_FILE
|
'TXT_FILE
|
||||||
'
|
'
|
||||||
ActionButton1.BackgroundImage = CType(resources.GetObject("ActionButton1.BackgroundImage"), System.Drawing.Image)
|
ActionButton1.BackgroundImage = CType(resources.GetObject("ActionButton1.BackgroundImage"), System.Drawing.Image)
|
||||||
ActionButton1.Name = "ArrowDown"
|
ActionButton1.Name = "Save"
|
||||||
ActionButton1.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.ArrowDown
|
ActionButton1.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Save
|
||||||
|
ActionButton1.ToolTipText = "Save destination"
|
||||||
|
ActionButton2.BackgroundImage = CType(resources.GetObject("ActionButton2.BackgroundImage"), System.Drawing.Image)
|
||||||
|
ActionButton2.Name = "ArrowDown"
|
||||||
|
ActionButton2.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.ArrowDown
|
||||||
Me.TXT_FILE.Buttons.Add(ActionButton1)
|
Me.TXT_FILE.Buttons.Add(ActionButton1)
|
||||||
|
Me.TXT_FILE.Buttons.Add(ActionButton2)
|
||||||
Me.TXT_FILE.ChangeControlsEnableOnCheckedChange = False
|
Me.TXT_FILE.ChangeControlsEnableOnCheckedChange = False
|
||||||
ListColumn1.Name = "COL_NAME"
|
ListColumn1.Name = "COL_NAME"
|
||||||
ListColumn1.Text = "Name"
|
ListColumn1.Text = "Name"
|
||||||
@@ -300,7 +326,7 @@ Namespace API.YouTube.Controls
|
|||||||
Me.BTT_BROWSE.Location = New System.Drawing.Point(512, 2)
|
Me.BTT_BROWSE.Location = New System.Drawing.Point(512, 2)
|
||||||
Me.BTT_BROWSE.Margin = New System.Windows.Forms.Padding(3, 2, 3, 2)
|
Me.BTT_BROWSE.Margin = New System.Windows.Forms.Padding(3, 2, 3, 2)
|
||||||
Me.BTT_BROWSE.Name = "BTT_BROWSE"
|
Me.BTT_BROWSE.Name = "BTT_BROWSE"
|
||||||
Me.BTT_BROWSE.Size = New System.Drawing.Size(74, 22)
|
Me.BTT_BROWSE.Size = New System.Drawing.Size(74, 23)
|
||||||
Me.BTT_BROWSE.TabIndex = 1
|
Me.BTT_BROWSE.TabIndex = 1
|
||||||
Me.BTT_BROWSE.Text = "Browse"
|
Me.BTT_BROWSE.Text = "Browse"
|
||||||
TT_MAIN.SetToolTip(Me.BTT_BROWSE, "Choose an output file (Right click for add a new location to the list)")
|
TT_MAIN.SetToolTip(Me.BTT_BROWSE, "Choose an output file (Right click for add a new location to the list)")
|
||||||
@@ -315,13 +341,13 @@ Namespace API.YouTube.Controls
|
|||||||
TP_OK_CANCEL.Controls.Add(Me.BTT_DOWN, 1, 0)
|
TP_OK_CANCEL.Controls.Add(Me.BTT_DOWN, 1, 0)
|
||||||
TP_OK_CANCEL.Controls.Add(Me.BTT_CANCEL, 2, 0)
|
TP_OK_CANCEL.Controls.Add(Me.BTT_CANCEL, 2, 0)
|
||||||
TP_OK_CANCEL.Dock = System.Windows.Forms.DockStyle.Fill
|
TP_OK_CANCEL.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
TP_OK_CANCEL.Location = New System.Drawing.Point(0, 26)
|
TP_OK_CANCEL.Location = New System.Drawing.Point(0, 54)
|
||||||
TP_OK_CANCEL.Margin = New System.Windows.Forms.Padding(0)
|
TP_OK_CANCEL.Margin = New System.Windows.Forms.Padding(0)
|
||||||
TP_OK_CANCEL.Name = "TP_OK_CANCEL"
|
TP_OK_CANCEL.Name = "TP_OK_CANCEL"
|
||||||
TP_OK_CANCEL.RowCount = 1
|
TP_OK_CANCEL.RowCount = 1
|
||||||
TP_OK_CANCEL.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
TP_OK_CANCEL.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
TP_OK_CANCEL.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 26.0!))
|
TP_OK_CANCEL.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 27.0!))
|
||||||
TP_OK_CANCEL.Size = New System.Drawing.Size(589, 26)
|
TP_OK_CANCEL.Size = New System.Drawing.Size(589, 27)
|
||||||
TP_OK_CANCEL.TabIndex = 1
|
TP_OK_CANCEL.TabIndex = 1
|
||||||
'
|
'
|
||||||
'BTT_DOWN
|
'BTT_DOWN
|
||||||
@@ -330,7 +356,7 @@ Namespace API.YouTube.Controls
|
|||||||
Me.BTT_DOWN.Location = New System.Drawing.Point(432, 2)
|
Me.BTT_DOWN.Location = New System.Drawing.Point(432, 2)
|
||||||
Me.BTT_DOWN.Margin = New System.Windows.Forms.Padding(3, 2, 3, 2)
|
Me.BTT_DOWN.Margin = New System.Windows.Forms.Padding(3, 2, 3, 2)
|
||||||
Me.BTT_DOWN.Name = "BTT_DOWN"
|
Me.BTT_DOWN.Name = "BTT_DOWN"
|
||||||
Me.BTT_DOWN.Size = New System.Drawing.Size(74, 22)
|
Me.BTT_DOWN.Size = New System.Drawing.Size(74, 23)
|
||||||
Me.BTT_DOWN.TabIndex = 0
|
Me.BTT_DOWN.TabIndex = 0
|
||||||
Me.BTT_DOWN.Text = "Download"
|
Me.BTT_DOWN.Text = "Download"
|
||||||
Me.BTT_DOWN.UseVisualStyleBackColor = True
|
Me.BTT_DOWN.UseVisualStyleBackColor = True
|
||||||
@@ -342,16 +368,79 @@ Namespace API.YouTube.Controls
|
|||||||
Me.BTT_CANCEL.Location = New System.Drawing.Point(512, 2)
|
Me.BTT_CANCEL.Location = New System.Drawing.Point(512, 2)
|
||||||
Me.BTT_CANCEL.Margin = New System.Windows.Forms.Padding(3, 2, 3, 2)
|
Me.BTT_CANCEL.Margin = New System.Windows.Forms.Padding(3, 2, 3, 2)
|
||||||
Me.BTT_CANCEL.Name = "BTT_CANCEL"
|
Me.BTT_CANCEL.Name = "BTT_CANCEL"
|
||||||
Me.BTT_CANCEL.Size = New System.Drawing.Size(74, 22)
|
Me.BTT_CANCEL.Size = New System.Drawing.Size(74, 23)
|
||||||
Me.BTT_CANCEL.TabIndex = 1
|
Me.BTT_CANCEL.TabIndex = 1
|
||||||
Me.BTT_CANCEL.Text = "Cancel"
|
Me.BTT_CANCEL.Text = "Cancel"
|
||||||
Me.BTT_CANCEL.UseVisualStyleBackColor = True
|
Me.BTT_CANCEL.UseVisualStyleBackColor = True
|
||||||
'
|
'
|
||||||
|
'TP_PLS
|
||||||
|
'
|
||||||
|
TP_PLS.ColumnCount = 2
|
||||||
|
TP_PLS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
|
TP_PLS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 80.0!))
|
||||||
|
TP_PLS.Controls.Add(Me.CMB_PLS, 0, 0)
|
||||||
|
TP_PLS.Controls.Add(Me.BTT_PLS_BROWSE, 1, 0)
|
||||||
|
TP_PLS.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
TP_PLS.Location = New System.Drawing.Point(0, 0)
|
||||||
|
TP_PLS.Margin = New System.Windows.Forms.Padding(0)
|
||||||
|
TP_PLS.Name = "TP_PLS"
|
||||||
|
TP_PLS.RowCount = 1
|
||||||
|
TP_PLS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
|
TP_PLS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 27.0!))
|
||||||
|
TP_PLS.Size = New System.Drawing.Size(589, 27)
|
||||||
|
TP_PLS.TabIndex = 2
|
||||||
|
'
|
||||||
|
'CMB_PLS
|
||||||
|
'
|
||||||
|
ActionButton3.BackgroundImage = CType(resources.GetObject("ActionButton3.BackgroundImage"), System.Drawing.Image)
|
||||||
|
ActionButton3.Name = "Save"
|
||||||
|
ActionButton3.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Save
|
||||||
|
ActionButton3.ToolTipText = "Save playlist"
|
||||||
|
ActionButton4.BackgroundImage = CType(resources.GetObject("ActionButton4.BackgroundImage"), System.Drawing.Image)
|
||||||
|
ActionButton4.Name = "List"
|
||||||
|
ActionButton4.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.List
|
||||||
|
ActionButton4.ToolTipText = "Select multiple playlists"
|
||||||
|
ActionButton5.BackgroundImage = CType(resources.GetObject("ActionButton5.BackgroundImage"), System.Drawing.Image)
|
||||||
|
ActionButton5.Name = "Clear"
|
||||||
|
ActionButton5.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
|
||||||
|
ActionButton6.BackgroundImage = CType(resources.GetObject("ActionButton6.BackgroundImage"), System.Drawing.Image)
|
||||||
|
ActionButton6.Name = "ArrowDown"
|
||||||
|
ActionButton6.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.ArrowDown
|
||||||
|
Me.CMB_PLS.Buttons.Add(ActionButton3)
|
||||||
|
Me.CMB_PLS.Buttons.Add(ActionButton4)
|
||||||
|
Me.CMB_PLS.Buttons.Add(ActionButton5)
|
||||||
|
Me.CMB_PLS.Buttons.Add(ActionButton6)
|
||||||
|
Me.CMB_PLS.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.Label
|
||||||
|
Me.CMB_PLS.CaptionText = "Playlist"
|
||||||
|
Me.CMB_PLS.CaptionToolTipEnabled = True
|
||||||
|
Me.CMB_PLS.CaptionToolTipText = "Add downloaded item(s) to playlist"
|
||||||
|
Me.CMB_PLS.CaptionVisible = True
|
||||||
|
Me.CMB_PLS.CaptionWidth = 50.0R
|
||||||
|
Me.CMB_PLS.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.CMB_PLS.Location = New System.Drawing.Point(1, 1)
|
||||||
|
Me.CMB_PLS.Margin = New System.Windows.Forms.Padding(1)
|
||||||
|
Me.CMB_PLS.Name = "CMB_PLS"
|
||||||
|
Me.CMB_PLS.Size = New System.Drawing.Size(507, 22)
|
||||||
|
Me.CMB_PLS.TabIndex = 0
|
||||||
|
Me.CMB_PLS.TextBoxBorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
|
||||||
|
'
|
||||||
|
'BTT_PLS_BROWSE
|
||||||
|
'
|
||||||
|
Me.BTT_PLS_BROWSE.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.BTT_PLS_BROWSE.Location = New System.Drawing.Point(512, 2)
|
||||||
|
Me.BTT_PLS_BROWSE.Margin = New System.Windows.Forms.Padding(3, 2, 3, 2)
|
||||||
|
Me.BTT_PLS_BROWSE.Name = "BTT_PLS_BROWSE"
|
||||||
|
Me.BTT_PLS_BROWSE.Size = New System.Drawing.Size(74, 23)
|
||||||
|
Me.BTT_PLS_BROWSE.TabIndex = 1
|
||||||
|
Me.BTT_PLS_BROWSE.Text = "Browse"
|
||||||
|
TT_MAIN.SetToolTip(Me.BTT_PLS_BROWSE, "Choose an output file (Right click for add a new location to the list)")
|
||||||
|
Me.BTT_PLS_BROWSE.UseVisualStyleBackColor = True
|
||||||
|
'
|
||||||
'LB_SEP_1
|
'LB_SEP_1
|
||||||
'
|
'
|
||||||
LB_SEP_1.Anchor = CType((System.Windows.Forms.AnchorStyles.Left Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
|
LB_SEP_1.Anchor = CType((System.Windows.Forms.AnchorStyles.Left Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
|
||||||
LB_SEP_1.BackColor = System.Drawing.SystemColors.ControlDark
|
LB_SEP_1.BackColor = System.Drawing.SystemColors.ControlDark
|
||||||
LB_SEP_1.Location = New System.Drawing.Point(6, 179)
|
LB_SEP_1.Location = New System.Drawing.Point(6, 207)
|
||||||
LB_SEP_1.Margin = New System.Windows.Forms.Padding(6, 0, 6, 0)
|
LB_SEP_1.Margin = New System.Windows.Forms.Padding(6, 0, 6, 0)
|
||||||
LB_SEP_1.Name = "LB_SEP_1"
|
LB_SEP_1.Name = "LB_SEP_1"
|
||||||
LB_SEP_1.Size = New System.Drawing.Size(589, 1)
|
LB_SEP_1.Size = New System.Drawing.Size(589, 1)
|
||||||
@@ -361,7 +450,7 @@ Namespace API.YouTube.Controls
|
|||||||
'
|
'
|
||||||
LB_SEP_2.Anchor = CType((System.Windows.Forms.AnchorStyles.Left Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
|
LB_SEP_2.Anchor = CType((System.Windows.Forms.AnchorStyles.Left Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
|
||||||
LB_SEP_2.BackColor = System.Drawing.SystemColors.ControlDark
|
LB_SEP_2.BackColor = System.Drawing.SystemColors.ControlDark
|
||||||
LB_SEP_2.Location = New System.Drawing.Point(6, 209)
|
LB_SEP_2.Location = New System.Drawing.Point(6, 237)
|
||||||
LB_SEP_2.Margin = New System.Windows.Forms.Padding(6, 0, 6, 0)
|
LB_SEP_2.Margin = New System.Windows.Forms.Padding(6, 0, 6, 0)
|
||||||
LB_SEP_2.Name = "LB_SEP_2"
|
LB_SEP_2.Name = "LB_SEP_2"
|
||||||
LB_SEP_2.Size = New System.Drawing.Size(589, 1)
|
LB_SEP_2.Size = New System.Drawing.Size(589, 1)
|
||||||
@@ -456,6 +545,59 @@ Namespace API.YouTube.Controls
|
|||||||
Me.LBL_AUDIO_CODEC.TextAlign = System.Drawing.ContentAlignment.MiddleRight
|
Me.LBL_AUDIO_CODEC.TextAlign = System.Drawing.ContentAlignment.MiddleRight
|
||||||
TT_MAIN.SetToolTip(Me.LBL_AUDIO_CODEC, "Output Audio Codec")
|
TT_MAIN.SetToolTip(Me.LBL_AUDIO_CODEC, "Output Audio Codec")
|
||||||
'
|
'
|
||||||
|
'TP_FPS_BITRATE
|
||||||
|
'
|
||||||
|
TP_FPS_BITRATE.ColumnCount = 2
|
||||||
|
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.Controls.Add(Me.TXT_FPS, 0, 0)
|
||||||
|
TP_FPS_BITRATE.Controls.Add(Me.TXT_AUDIO_BITRATE, 1, 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
|
||||||
|
'
|
||||||
|
'TXT_FPS
|
||||||
|
'
|
||||||
|
ActionButton7.BackgroundImage = CType(resources.GetObject("ActionButton7.BackgroundImage"), System.Drawing.Image)
|
||||||
|
ActionButton7.Name = "Clear"
|
||||||
|
ActionButton7.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
|
||||||
|
Me.TXT_FPS.Buttons.Add(ActionButton7)
|
||||||
|
Me.TXT_FPS.CaptionText = "Video FPS"
|
||||||
|
Me.TXT_FPS.CaptionToolTipEnabled = True
|
||||||
|
Me.TXT_FPS.CaptionToolTipText = "Set the video FPS by setting the FPS value in this field. Leave blank so as not t" &
|
||||||
|
"o change"
|
||||||
|
Me.TXT_FPS.CaptionWidth = 60.0R
|
||||||
|
Me.TXT_FPS.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
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.TabIndex = 0
|
||||||
|
Me.TXT_FPS.TextBoxWidthMinimal = 30
|
||||||
|
'
|
||||||
|
'TXT_AUDIO_BITRATE
|
||||||
|
'
|
||||||
|
ActionButton8.BackgroundImage = CType(resources.GetObject("ActionButton8.BackgroundImage"), System.Drawing.Image)
|
||||||
|
ActionButton8.Name = "Clear"
|
||||||
|
ActionButton8.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
|
||||||
|
Me.TXT_AUDIO_BITRATE.Buttons.Add(ActionButton8)
|
||||||
|
Me.TXT_AUDIO_BITRATE.CaptionText = "Audio bitrate"
|
||||||
|
Me.TXT_AUDIO_BITRATE.CaptionToolTipEnabled = True
|
||||||
|
Me.TXT_AUDIO_BITRATE.CaptionToolTipText = "Set the video FPS if you want to change it during download. Leave blank so as not" &
|
||||||
|
" 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.Name = "TXT_AUDIO_BITRATE"
|
||||||
|
Me.TXT_AUDIO_BITRATE.Size = New System.Drawing.Size(289, 22)
|
||||||
|
Me.TXT_AUDIO_BITRATE.TabIndex = 1
|
||||||
|
'
|
||||||
'TP_HEADER_BASE
|
'TP_HEADER_BASE
|
||||||
'
|
'
|
||||||
Me.TP_HEADER_BASE.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single]
|
Me.TP_HEADER_BASE.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single]
|
||||||
@@ -471,7 +613,7 @@ Namespace API.YouTube.Controls
|
|||||||
Me.TP_HEADER_BASE.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
Me.TP_HEADER_BASE.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
Me.TP_HEADER_BASE.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 64.0!))
|
Me.TP_HEADER_BASE.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 64.0!))
|
||||||
Me.TP_HEADER_BASE.Size = New System.Drawing.Size(601, 65)
|
Me.TP_HEADER_BASE.Size = New System.Drawing.Size(601, 65)
|
||||||
Me.TP_HEADER_BASE.TabIndex = 6
|
Me.TP_HEADER_BASE.TabIndex = 7
|
||||||
'
|
'
|
||||||
'TP_SUBS
|
'TP_SUBS
|
||||||
'
|
'
|
||||||
@@ -483,7 +625,7 @@ Namespace API.YouTube.Controls
|
|||||||
Me.TP_SUBS.Controls.Add(LBL_SUBS_FORMAT, 1, 0)
|
Me.TP_SUBS.Controls.Add(LBL_SUBS_FORMAT, 1, 0)
|
||||||
Me.TP_SUBS.Controls.Add(Me.CMB_SUBS_FORMAT, 2, 0)
|
Me.TP_SUBS.Controls.Add(Me.CMB_SUBS_FORMAT, 2, 0)
|
||||||
Me.TP_SUBS.Dock = System.Windows.Forms.DockStyle.Fill
|
Me.TP_SUBS.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
Me.TP_SUBS.Location = New System.Drawing.Point(6, 93)
|
Me.TP_SUBS.Location = New System.Drawing.Point(6, 121)
|
||||||
Me.TP_SUBS.Margin = New System.Windows.Forms.Padding(6, 0, 6, 0)
|
Me.TP_SUBS.Margin = New System.Windows.Forms.Padding(6, 0, 6, 0)
|
||||||
Me.TP_SUBS.Name = "TP_SUBS"
|
Me.TP_SUBS.Name = "TP_SUBS"
|
||||||
Me.TP_SUBS.RowCount = 1
|
Me.TP_SUBS.RowCount = 1
|
||||||
@@ -493,21 +635,21 @@ Namespace API.YouTube.Controls
|
|||||||
'
|
'
|
||||||
'TXT_SUBS
|
'TXT_SUBS
|
||||||
'
|
'
|
||||||
ActionButton2.BackgroundImage = CType(resources.GetObject("ActionButton2.BackgroundImage"), System.Drawing.Image)
|
ActionButton9.BackgroundImage = CType(resources.GetObject("ActionButton9.BackgroundImage"), System.Drawing.Image)
|
||||||
ActionButton2.Name = "Open"
|
ActionButton9.Name = "Open"
|
||||||
ActionButton2.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Open
|
ActionButton9.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Open
|
||||||
ActionButton2.ToolTipText = "Choose subtitles"
|
ActionButton9.ToolTipText = "Choose subtitles"
|
||||||
ActionButton3.BackgroundImage = CType(resources.GetObject("ActionButton3.BackgroundImage"), System.Drawing.Image)
|
ActionButton10.BackgroundImage = CType(resources.GetObject("ActionButton10.BackgroundImage"), System.Drawing.Image)
|
||||||
ActionButton3.Name = "Refresh"
|
ActionButton10.Name = "Refresh"
|
||||||
ActionButton3.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Refresh
|
ActionButton10.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Refresh
|
||||||
ActionButton3.ToolTipText = "Reset subtitles to initial selected"
|
ActionButton10.ToolTipText = "Reset subtitles to initial selected"
|
||||||
ActionButton4.BackgroundImage = CType(resources.GetObject("ActionButton4.BackgroundImage"), System.Drawing.Image)
|
ActionButton11.BackgroundImage = CType(resources.GetObject("ActionButton11.BackgroundImage"), System.Drawing.Image)
|
||||||
ActionButton4.Name = "Clear"
|
ActionButton11.Name = "Clear"
|
||||||
ActionButton4.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
|
ActionButton11.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
|
||||||
ActionButton4.ToolTipText = "Clear subtitles selection (don't download subtitles)"
|
ActionButton11.ToolTipText = "Clear subtitles selection (don't download subtitles)"
|
||||||
Me.TXT_SUBS.Buttons.Add(ActionButton2)
|
Me.TXT_SUBS.Buttons.Add(ActionButton9)
|
||||||
Me.TXT_SUBS.Buttons.Add(ActionButton3)
|
Me.TXT_SUBS.Buttons.Add(ActionButton10)
|
||||||
Me.TXT_SUBS.Buttons.Add(ActionButton4)
|
Me.TXT_SUBS.Buttons.Add(ActionButton11)
|
||||||
Me.TXT_SUBS.CaptionText = "Subtitles"
|
Me.TXT_SUBS.CaptionText = "Subtitles"
|
||||||
Me.TXT_SUBS.CaptionToolTipEnabled = True
|
Me.TXT_SUBS.CaptionToolTipEnabled = True
|
||||||
Me.TXT_SUBS.CaptionToolTipText = "The selected subtitles will also be downloaded"
|
Me.TXT_SUBS.CaptionToolTipText = "The selected subtitles will also be downloaded"
|
||||||
@@ -535,29 +677,31 @@ Namespace API.YouTube.Controls
|
|||||||
Me.TP_MAIN.ColumnCount = 1
|
Me.TP_MAIN.ColumnCount = 1
|
||||||
Me.TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
Me.TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
Me.TP_MAIN.Controls.Add(Me.TP_HEADER_BASE, 0, 0)
|
Me.TP_MAIN.Controls.Add(Me.TP_HEADER_BASE, 0, 0)
|
||||||
Me.TP_MAIN.Controls.Add(TP_FOOTER, 0, 8)
|
Me.TP_MAIN.Controls.Add(TP_FOOTER, 0, 9)
|
||||||
Me.TP_MAIN.Controls.Add(Me.TP_OPTIONS, 0, 1)
|
Me.TP_MAIN.Controls.Add(Me.TP_OPTIONS, 0, 1)
|
||||||
Me.TP_MAIN.Controls.Add(Me.TP_CONTROLS, 0, 6)
|
Me.TP_MAIN.Controls.Add(Me.TP_CONTROLS, 0, 7)
|
||||||
Me.TP_MAIN.Controls.Add(LB_SEP_1, 0, 5)
|
Me.TP_MAIN.Controls.Add(LB_SEP_1, 0, 6)
|
||||||
Me.TP_MAIN.Controls.Add(LB_SEP_2, 0, 7)
|
Me.TP_MAIN.Controls.Add(LB_SEP_2, 0, 8)
|
||||||
Me.TP_MAIN.Controls.Add(Me.TP_SUBS, 0, 2)
|
Me.TP_MAIN.Controls.Add(Me.TP_SUBS, 0, 3)
|
||||||
Me.TP_MAIN.Controls.Add(Me.TXT_SUBS_ADDIT, 0, 3)
|
Me.TP_MAIN.Controls.Add(Me.TXT_SUBS_ADDIT, 0, 4)
|
||||||
Me.TP_MAIN.Controls.Add(Me.TXT_EXTRA_AUDIO_FORMATS, 0, 4)
|
Me.TP_MAIN.Controls.Add(Me.TXT_EXTRA_AUDIO_FORMATS, 0, 5)
|
||||||
|
Me.TP_MAIN.Controls.Add(TP_FPS_BITRATE, 0, 2)
|
||||||
Me.TP_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
|
Me.TP_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
Me.TP_MAIN.Location = New System.Drawing.Point(0, 0)
|
Me.TP_MAIN.Location = New System.Drawing.Point(0, 0)
|
||||||
Me.TP_MAIN.Name = "TP_MAIN"
|
Me.TP_MAIN.Name = "TP_MAIN"
|
||||||
Me.TP_MAIN.RowCount = 10
|
Me.TP_MAIN.RowCount = 11
|
||||||
Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 65.0!))
|
Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 65.0!))
|
||||||
Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
|
Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
|
||||||
Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
|
Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
|
||||||
Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
|
Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
|
||||||
Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
|
Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
|
||||||
|
Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
|
||||||
Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 5.0!))
|
Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 5.0!))
|
||||||
Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
|
Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
|
||||||
Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 5.0!))
|
Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 5.0!))
|
||||||
Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 58.0!))
|
Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 87.0!))
|
||||||
Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle())
|
Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle())
|
||||||
Me.TP_MAIN.Size = New System.Drawing.Size(601, 271)
|
Me.TP_MAIN.Size = New System.Drawing.Size(601, 328)
|
||||||
Me.TP_MAIN.TabIndex = 0
|
Me.TP_MAIN.TabIndex = 0
|
||||||
'
|
'
|
||||||
'TP_OPTIONS
|
'TP_OPTIONS
|
||||||
@@ -569,6 +713,7 @@ Namespace API.YouTube.Controls
|
|||||||
Me.TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 80.0!))
|
Me.TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 80.0!))
|
||||||
Me.TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 80.0!))
|
Me.TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 80.0!))
|
||||||
Me.TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 80.0!))
|
Me.TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 80.0!))
|
||||||
|
Me.TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20.0!))
|
||||||
Me.TP_OPTIONS.Controls.Add(LBL_FORMAT, 1, 0)
|
Me.TP_OPTIONS.Controls.Add(LBL_FORMAT, 1, 0)
|
||||||
Me.TP_OPTIONS.Controls.Add(TP_WHAT, 0, 0)
|
Me.TP_OPTIONS.Controls.Add(TP_WHAT, 0, 0)
|
||||||
Me.TP_OPTIONS.Controls.Add(Me.CMB_FORMAT, 2, 0)
|
Me.TP_OPTIONS.Controls.Add(Me.CMB_FORMAT, 2, 0)
|
||||||
@@ -621,7 +766,7 @@ Namespace API.YouTube.Controls
|
|||||||
Me.TP_CONTROLS.ColumnCount = 1
|
Me.TP_CONTROLS.ColumnCount = 1
|
||||||
Me.TP_CONTROLS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
Me.TP_CONTROLS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
Me.TP_CONTROLS.Dock = System.Windows.Forms.DockStyle.Fill
|
Me.TP_CONTROLS.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
Me.TP_CONTROLS.Location = New System.Drawing.Point(3, 182)
|
Me.TP_CONTROLS.Location = New System.Drawing.Point(3, 210)
|
||||||
Me.TP_CONTROLS.Margin = New System.Windows.Forms.Padding(3, 0, 3, 0)
|
Me.TP_CONTROLS.Margin = New System.Windows.Forms.Padding(3, 0, 3, 0)
|
||||||
Me.TP_CONTROLS.Name = "TP_CONTROLS"
|
Me.TP_CONTROLS.Name = "TP_CONTROLS"
|
||||||
Me.TP_CONTROLS.RowCount = 1
|
Me.TP_CONTROLS.RowCount = 1
|
||||||
@@ -631,24 +776,24 @@ Namespace API.YouTube.Controls
|
|||||||
'
|
'
|
||||||
'TXT_SUBS_ADDIT
|
'TXT_SUBS_ADDIT
|
||||||
'
|
'
|
||||||
ActionButton5.BackgroundImage = CType(resources.GetObject("ActionButton5.BackgroundImage"), System.Drawing.Image)
|
ActionButton12.BackgroundImage = CType(resources.GetObject("ActionButton12.BackgroundImage"), System.Drawing.Image)
|
||||||
ActionButton5.Enabled = False
|
ActionButton12.Enabled = False
|
||||||
ActionButton5.Name = "Open"
|
ActionButton12.Name = "Open"
|
||||||
ActionButton5.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Open
|
ActionButton12.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Open
|
||||||
ActionButton5.ToolTipText = "Choose additional formats"
|
ActionButton12.ToolTipText = "Choose additional formats"
|
||||||
ActionButton6.BackgroundImage = CType(resources.GetObject("ActionButton6.BackgroundImage"), System.Drawing.Image)
|
ActionButton13.BackgroundImage = CType(resources.GetObject("ActionButton13.BackgroundImage"), System.Drawing.Image)
|
||||||
ActionButton6.Enabled = False
|
ActionButton13.Enabled = False
|
||||||
ActionButton6.Name = "Refresh"
|
ActionButton13.Name = "Refresh"
|
||||||
ActionButton6.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Refresh
|
ActionButton13.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Refresh
|
||||||
ActionButton6.ToolTipText = "Fill in additional formats from the defaults"
|
ActionButton13.ToolTipText = "Fill in additional formats from the defaults"
|
||||||
ActionButton7.BackgroundImage = CType(resources.GetObject("ActionButton7.BackgroundImage"), System.Drawing.Image)
|
ActionButton14.BackgroundImage = CType(resources.GetObject("ActionButton14.BackgroundImage"), System.Drawing.Image)
|
||||||
ActionButton7.Enabled = False
|
ActionButton14.Enabled = False
|
||||||
ActionButton7.Name = "Clear"
|
ActionButton14.Name = "Clear"
|
||||||
ActionButton7.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
|
ActionButton14.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
|
||||||
ActionButton7.ToolTipText = "Remove all additional formats"
|
ActionButton14.ToolTipText = "Remove all additional formats"
|
||||||
Me.TXT_SUBS_ADDIT.Buttons.Add(ActionButton5)
|
Me.TXT_SUBS_ADDIT.Buttons.Add(ActionButton12)
|
||||||
Me.TXT_SUBS_ADDIT.Buttons.Add(ActionButton6)
|
Me.TXT_SUBS_ADDIT.Buttons.Add(ActionButton13)
|
||||||
Me.TXT_SUBS_ADDIT.Buttons.Add(ActionButton7)
|
Me.TXT_SUBS_ADDIT.Buttons.Add(ActionButton14)
|
||||||
Me.TXT_SUBS_ADDIT.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.CheckBox
|
Me.TXT_SUBS_ADDIT.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.CheckBox
|
||||||
Me.TXT_SUBS_ADDIT.CaptionText = "Additional subtitle formats"
|
Me.TXT_SUBS_ADDIT.CaptionText = "Additional subtitle formats"
|
||||||
Me.TXT_SUBS_ADDIT.CaptionToolTipEnabled = True
|
Me.TXT_SUBS_ADDIT.CaptionToolTipEnabled = True
|
||||||
@@ -656,7 +801,7 @@ Namespace API.YouTube.Controls
|
|||||||
Me.TXT_SUBS_ADDIT.CaptionWidth = 150.0R
|
Me.TXT_SUBS_ADDIT.CaptionWidth = 150.0R
|
||||||
Me.TXT_SUBS_ADDIT.ClearTextByButtonClear = False
|
Me.TXT_SUBS_ADDIT.ClearTextByButtonClear = False
|
||||||
Me.TXT_SUBS_ADDIT.Dock = System.Windows.Forms.DockStyle.Fill
|
Me.TXT_SUBS_ADDIT.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
Me.TXT_SUBS_ADDIT.Location = New System.Drawing.Point(6, 124)
|
Me.TXT_SUBS_ADDIT.Location = New System.Drawing.Point(6, 152)
|
||||||
Me.TXT_SUBS_ADDIT.Margin = New System.Windows.Forms.Padding(6, 3, 6, 3)
|
Me.TXT_SUBS_ADDIT.Margin = New System.Windows.Forms.Padding(6, 3, 6, 3)
|
||||||
Me.TXT_SUBS_ADDIT.Name = "TXT_SUBS_ADDIT"
|
Me.TXT_SUBS_ADDIT.Name = "TXT_SUBS_ADDIT"
|
||||||
Me.TXT_SUBS_ADDIT.Size = New System.Drawing.Size(589, 22)
|
Me.TXT_SUBS_ADDIT.Size = New System.Drawing.Size(589, 22)
|
||||||
@@ -666,31 +811,31 @@ Namespace API.YouTube.Controls
|
|||||||
'
|
'
|
||||||
'TXT_EXTRA_AUDIO_FORMATS
|
'TXT_EXTRA_AUDIO_FORMATS
|
||||||
'
|
'
|
||||||
ActionButton8.BackgroundImage = CType(resources.GetObject("ActionButton8.BackgroundImage"), System.Drawing.Image)
|
ActionButton15.BackgroundImage = CType(resources.GetObject("ActionButton15.BackgroundImage"), System.Drawing.Image)
|
||||||
ActionButton8.Enabled = False
|
ActionButton15.Enabled = False
|
||||||
ActionButton8.Name = "Open"
|
ActionButton15.Name = "Open"
|
||||||
ActionButton8.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Open
|
ActionButton15.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Open
|
||||||
ActionButton8.ToolTipText = "Choose additional formats"
|
ActionButton15.ToolTipText = "Choose additional formats"
|
||||||
ActionButton9.BackgroundImage = CType(resources.GetObject("ActionButton9.BackgroundImage"), System.Drawing.Image)
|
ActionButton16.BackgroundImage = CType(resources.GetObject("ActionButton16.BackgroundImage"), System.Drawing.Image)
|
||||||
ActionButton9.Enabled = False
|
ActionButton16.Enabled = False
|
||||||
ActionButton9.Name = "Refresh"
|
ActionButton16.Name = "Refresh"
|
||||||
ActionButton9.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Refresh
|
ActionButton16.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Refresh
|
||||||
ActionButton9.ToolTipText = "Fill in additional formats from the defaults"
|
ActionButton16.ToolTipText = "Fill in additional formats from the defaults"
|
||||||
ActionButton10.BackgroundImage = CType(resources.GetObject("ActionButton10.BackgroundImage"), System.Drawing.Image)
|
ActionButton17.BackgroundImage = CType(resources.GetObject("ActionButton17.BackgroundImage"), System.Drawing.Image)
|
||||||
ActionButton10.Enabled = False
|
ActionButton17.Enabled = False
|
||||||
ActionButton10.Name = "Clear"
|
ActionButton17.Name = "Clear"
|
||||||
ActionButton10.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
|
ActionButton17.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
|
||||||
ActionButton10.ToolTipText = "Choose additional formats"
|
ActionButton17.ToolTipText = "Choose additional formats"
|
||||||
Me.TXT_EXTRA_AUDIO_FORMATS.Buttons.Add(ActionButton8)
|
Me.TXT_EXTRA_AUDIO_FORMATS.Buttons.Add(ActionButton15)
|
||||||
Me.TXT_EXTRA_AUDIO_FORMATS.Buttons.Add(ActionButton9)
|
Me.TXT_EXTRA_AUDIO_FORMATS.Buttons.Add(ActionButton16)
|
||||||
Me.TXT_EXTRA_AUDIO_FORMATS.Buttons.Add(ActionButton10)
|
Me.TXT_EXTRA_AUDIO_FORMATS.Buttons.Add(ActionButton17)
|
||||||
Me.TXT_EXTRA_AUDIO_FORMATS.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.CheckBox
|
Me.TXT_EXTRA_AUDIO_FORMATS.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.CheckBox
|
||||||
Me.TXT_EXTRA_AUDIO_FORMATS.CaptionText = "Additional audio formats"
|
Me.TXT_EXTRA_AUDIO_FORMATS.CaptionText = "Additional audio formats"
|
||||||
Me.TXT_EXTRA_AUDIO_FORMATS.CaptionToolTipEnabled = True
|
Me.TXT_EXTRA_AUDIO_FORMATS.CaptionToolTipEnabled = True
|
||||||
Me.TXT_EXTRA_AUDIO_FORMATS.CaptionWidth = 150.0R
|
Me.TXT_EXTRA_AUDIO_FORMATS.CaptionWidth = 150.0R
|
||||||
Me.TXT_EXTRA_AUDIO_FORMATS.ClearTextByButtonClear = False
|
Me.TXT_EXTRA_AUDIO_FORMATS.ClearTextByButtonClear = False
|
||||||
Me.TXT_EXTRA_AUDIO_FORMATS.Dock = System.Windows.Forms.DockStyle.Fill
|
Me.TXT_EXTRA_AUDIO_FORMATS.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
Me.TXT_EXTRA_AUDIO_FORMATS.Location = New System.Drawing.Point(6, 152)
|
Me.TXT_EXTRA_AUDIO_FORMATS.Location = New System.Drawing.Point(6, 180)
|
||||||
Me.TXT_EXTRA_AUDIO_FORMATS.Margin = New System.Windows.Forms.Padding(6, 3, 6, 3)
|
Me.TXT_EXTRA_AUDIO_FORMATS.Margin = New System.Windows.Forms.Padding(6, 3, 6, 3)
|
||||||
Me.TXT_EXTRA_AUDIO_FORMATS.Name = "TXT_EXTRA_AUDIO_FORMATS"
|
Me.TXT_EXTRA_AUDIO_FORMATS.Name = "TXT_EXTRA_AUDIO_FORMATS"
|
||||||
Me.TXT_EXTRA_AUDIO_FORMATS.Size = New System.Drawing.Size(589, 22)
|
Me.TXT_EXTRA_AUDIO_FORMATS.Size = New System.Drawing.Size(589, 22)
|
||||||
@@ -704,13 +849,14 @@ Namespace API.YouTube.Controls
|
|||||||
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
|
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
|
||||||
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
|
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
|
||||||
Me.CancelButton = Me.BTT_CANCEL
|
Me.CancelButton = Me.BTT_CANCEL
|
||||||
Me.ClientSize = New System.Drawing.Size(601, 271)
|
Me.ClientSize = New System.Drawing.Size(601, 328)
|
||||||
Me.Controls.Add(Me.TP_MAIN)
|
Me.Controls.Add(Me.TP_MAIN)
|
||||||
Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle
|
Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle
|
||||||
Me.Icon = Global.SCrawler.My.Resources.SiteYouTube.YouTubeIcon_32
|
Me.Icon = Global.SCrawler.My.Resources.SiteYouTube.YouTubeIcon_32
|
||||||
Me.KeyPreview = True
|
Me.KeyPreview = True
|
||||||
Me.MaximizeBox = False
|
Me.MaximizeBox = False
|
||||||
Me.MinimizeBox = False
|
Me.MinimizeBox = False
|
||||||
|
Me.MinimumSize = New System.Drawing.Size(617, 367)
|
||||||
Me.Name = "VideoOptionsForm"
|
Me.Name = "VideoOptionsForm"
|
||||||
Me.ShowInTaskbar = False
|
Me.ShowInTaskbar = False
|
||||||
Me.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide
|
Me.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide
|
||||||
@@ -726,8 +872,13 @@ Namespace API.YouTube.Controls
|
|||||||
TP_DESTINATION.ResumeLayout(False)
|
TP_DESTINATION.ResumeLayout(False)
|
||||||
CType(Me.TXT_FILE, System.ComponentModel.ISupportInitialize).EndInit()
|
CType(Me.TXT_FILE, System.ComponentModel.ISupportInitialize).EndInit()
|
||||||
TP_OK_CANCEL.ResumeLayout(False)
|
TP_OK_CANCEL.ResumeLayout(False)
|
||||||
|
TP_PLS.ResumeLayout(False)
|
||||||
|
CType(Me.CMB_PLS, System.ComponentModel.ISupportInitialize).EndInit()
|
||||||
TP_WHAT.ResumeLayout(False)
|
TP_WHAT.ResumeLayout(False)
|
||||||
TP_WHAT.PerformLayout()
|
TP_WHAT.PerformLayout()
|
||||||
|
TP_FPS_BITRATE.ResumeLayout(False)
|
||||||
|
CType(Me.TXT_FPS, System.ComponentModel.ISupportInitialize).EndInit()
|
||||||
|
CType(Me.TXT_AUDIO_BITRATE, System.ComponentModel.ISupportInitialize).EndInit()
|
||||||
Me.TP_HEADER_BASE.ResumeLayout(False)
|
Me.TP_HEADER_BASE.ResumeLayout(False)
|
||||||
Me.TP_SUBS.ResumeLayout(False)
|
Me.TP_SUBS.ResumeLayout(False)
|
||||||
Me.TP_SUBS.PerformLayout()
|
Me.TP_SUBS.PerformLayout()
|
||||||
@@ -761,9 +912,13 @@ Namespace API.YouTube.Controls
|
|||||||
Private WithEvents TXT_SUBS_ADDIT As PersonalUtilities.Forms.Controls.TextBoxExtended
|
Private WithEvents TXT_SUBS_ADDIT As PersonalUtilities.Forms.Controls.TextBoxExtended
|
||||||
Private WithEvents TXT_EXTRA_AUDIO_FORMATS As PersonalUtilities.Forms.Controls.TextBoxExtended
|
Private WithEvents TXT_EXTRA_AUDIO_FORMATS As PersonalUtilities.Forms.Controls.TextBoxExtended
|
||||||
Private WithEvents TXT_FILE As PersonalUtilities.Forms.Controls.ComboBoxExtended
|
Private WithEvents TXT_FILE As PersonalUtilities.Forms.Controls.ComboBoxExtended
|
||||||
Private WithEvents BTT_BROWSE As Button
|
Private WithEvents BTT_BROWSE As SCrawler.API.YouTube.Controls.ButtonRC
|
||||||
Private WithEvents BTT_DOWN As Button
|
Private WithEvents BTT_DOWN As Button
|
||||||
Private WithEvents BTT_CANCEL As Button
|
Private WithEvents BTT_CANCEL As Button
|
||||||
Private WithEvents TP_HEADER_INFO_2 As TableLayoutPanel
|
Private WithEvents TP_HEADER_INFO_2 As TableLayoutPanel
|
||||||
|
Private WithEvents TXT_FPS As PersonalUtilities.Forms.Controls.TextBoxExtended
|
||||||
|
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
|
||||||
End Class
|
End Class
|
||||||
End Namespace
|
End Namespace
|
||||||
@@ -137,6 +137,13 @@
|
|||||||
</metadata>
|
</metadata>
|
||||||
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||||
<data name="ActionButton1.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ActionButton1.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>
|
||||||
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
|
wwAADsMBx2+oZAAAAFFJREFUOE9joAr49u3bf1Lw169f50O1QgBI0MnJCY4/vP8Ix8hiILqtrQ3TEFIM
|
||||||
|
AGGYIVDtpBsAwkQbgIyR1dDWAGLwqAGD0gByMFQ7JYCBAQChNviRiQ8ETwAAAABJRU5ErkJggg==
|
||||||
|
</value>
|
||||||
|
</data>
|
||||||
|
<data name="ActionButton2.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAYAAAD0eNT6AAAABGdBTUEAALGPC/xhBQAAE65JREFUeF7t
|
iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAYAAAD0eNT6AAAABGdBTUEAALGPC/xhBQAAE65JREFUeF7t
|
||||||
3X2sJWddB/DdLi2lQG2hdOHuvfM887J7Cxca4ELTQMDWKigIFpBAEAgi9g+CJpJo9Q8NJhgBiYZIYspL
|
3X2sJWddB/DdLi2lQG2hdOHuvfM887J7Cxca4ELTQMDWKigIFpBAEAgi9g+CJpJo9Q8NJhgBiYZIYspL
|
||||||
@@ -235,6 +242,123 @@
|
|||||||
<metadata name="TP_OK_CANCEL.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
<metadata name="TP_OK_CANCEL.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
<value>False</value>
|
<value>False</value>
|
||||||
</metadata>
|
</metadata>
|
||||||
|
<metadata name="TP_PLS.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</metadata>
|
||||||
|
<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==
|
||||||
|
</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
|
||||||
|
</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
|
||||||
|
</value>
|
||||||
|
</data>
|
||||||
|
<data name="ActionButton6.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>
|
||||||
|
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
|
||||||
|
AAAASUVORK5CYII=
|
||||||
|
</value>
|
||||||
|
</data>
|
||||||
<metadata name="LB_SEP_1.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
<metadata name="LB_SEP_1.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
<value>False</value>
|
<value>False</value>
|
||||||
</metadata>
|
</metadata>
|
||||||
@@ -253,68 +377,9 @@
|
|||||||
<metadata name="LBL_SUBS_FORMAT.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
<metadata name="LBL_SUBS_FORMAT.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
<value>False</value>
|
<value>False</value>
|
||||||
</metadata>
|
</metadata>
|
||||||
<data name="ActionButton2.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<metadata name="TP_FPS_BITRATE.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
<value>
|
<value>False</value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
</metadata>
|
||||||
wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP
|
|
||||||
WQwhyWIyJIUW5NqyPb7oCVtIlhVTwYf8nv7/t2zJagel9KmqKsIACYL9RjI8UHz5zshougZr/AEvbxEP
|
|
||||||
aZCDBY3VslixaJvX3wzkkDiOwbZtDRGA5vdNAg+TL27qgmt5XkBG/gTdAG7Gt+3PP9oOaEGFCVEC6rp+
|
|
||||||
5g9MfM/c5e4OsEZMZkQEtGL5H2DdZ5JRArDwPA+iKII0TfkC9vroC9j5vq8JTWw3WzWgLMtZGIaa0MR8
|
|
||||||
vlAD8PYlSaIJTTiOowY0p0Bc19XEJo6HE59FAPuMzyAINKGJ1XLFZxHALtMrnkBXOIQIIIQ8YvF/KrgB
|
|
||||||
cMaRN0UdBBkAAAAASUVORK5CYII=
|
|
||||||
</value>
|
|
||||||
</data>
|
|
||||||
<data name="ActionButton3.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==
|
|
||||||
</value>
|
|
||||||
</data>
|
|
||||||
<data name="ActionButton4.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
|
||||||
<value>
|
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
|
||||||
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
|
|
||||||
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
|
|
||||||
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
|
|
||||||
</value>
|
|
||||||
</data>
|
|
||||||
<data name="ActionButton5.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
|
||||||
<value>
|
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
|
||||||
wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP
|
|
||||||
WQwhyWIyJIUW5NqyPb7oCVtIlhVTwYf8nv7/t2zJagel9KmqKsIACYL9RjI8UHz5zshougZr/AEvbxEP
|
|
||||||
aZCDBY3VslixaJvX3wzkkDiOwbZtDRGA5vdNAg+TL27qgmt5XkBG/gTdAG7Gt+3PP9oOaEGFCVEC6rp+
|
|
||||||
5g9MfM/c5e4OsEZMZkQEtGL5H2DdZ5JRArDwPA+iKII0TfkC9vroC9j5vq8JTWw3WzWgLMtZGIaa0MR8
|
|
||||||
vlAD8PYlSaIJTTiOowY0p0Bc19XEJo6HE59FAPuMzyAINKGJ1XLFZxHALtMrnkBXOIQIIIQ8YvF/KrgB
|
|
||||||
cMaRN0UdBBkAAAAASUVORK5CYII=
|
|
||||||
</value>
|
|
||||||
</data>
|
|
||||||
<data name="ActionButton6.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==
|
|
||||||
</value>
|
|
||||||
</data>
|
|
||||||
<data name="ActionButton7.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ActionButton7.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
@@ -324,6 +389,14 @@
|
|||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ActionButton8.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ActionButton8.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>
|
||||||
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
|
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
|
||||||
|
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
|
||||||
|
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
|
||||||
|
</value>
|
||||||
|
</data>
|
||||||
|
<data name="ActionButton9.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP
|
wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP
|
||||||
@@ -334,7 +407,7 @@
|
|||||||
cMaRN0UdBBkAAAAASUVORK5CYII=
|
cMaRN0UdBBkAAAAASUVORK5CYII=
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ActionButton9.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ActionButton10.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
|
||||||
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOElE
|
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOElE
|
||||||
@@ -350,7 +423,77 @@
|
|||||||
VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg==
|
VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg==
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ActionButton10.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ActionButton11.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>
|
||||||
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
|
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
|
||||||
|
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
|
||||||
|
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
|
||||||
|
</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=
|
||||||
|
</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==
|
||||||
|
</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
|
||||||
|
</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=
|
||||||
|
</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==
|
||||||
|
</value>
|
||||||
|
</data>
|
||||||
|
<data name="ActionButton17.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
|
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
|
||||||
|
|||||||
@@ -22,21 +22,51 @@ Namespace API.YouTube.Controls
|
|||||||
Friend Class VideoOptionsForm : Implements IDesignXMLContainer
|
Friend Class VideoOptionsForm : Implements IDesignXMLContainer
|
||||||
#Region "Declarations"
|
#Region "Declarations"
|
||||||
Private MyView As FormView
|
Private MyView As FormView
|
||||||
|
Private ReadOnly MyFieldsChecker As FieldsChecker
|
||||||
Friend Property DesignXML As EContainer Implements IDesignXMLContainer.DesignXML
|
Friend Property DesignXML As EContainer Implements IDesignXMLContainer.DesignXML
|
||||||
Private Property DesignXMLNodes As String() Implements IDesignXMLContainer.DesignXMLNodes
|
Private Property DesignXMLNodes As String() Implements IDesignXMLContainer.DesignXMLNodes
|
||||||
Private Property DesignXMLNodeName As String Implements IDesignXMLContainer.DesignXMLNodeName
|
Private Property DesignXMLNodeName As String Implements IDesignXMLContainer.DesignXMLNodeName
|
||||||
Private Const ControlsRow As Integer = 6
|
Private Const ControlsRow As Integer = 7
|
||||||
Private ReadOnly Property CNT_PROCESSOR As TableControlsProcessor
|
Private ReadOnly Property CNT_PROCESSOR As TableControlsProcessor
|
||||||
Friend Property MyContainer As YouTubeMediaContainerBase
|
Friend Property MyContainer As YouTubeMediaContainerBase
|
||||||
Private Initialization As Boolean = True
|
Private Initialization As Boolean = True
|
||||||
Private ReadOnly IsSavedObject As Boolean
|
Private ReadOnly InheritsFromContainer As Boolean
|
||||||
|
Private ReadOnly M3U8Files As List(Of SFile)
|
||||||
|
Friend Property UseCookies As Boolean = False
|
||||||
|
Private ReadOnly Property M3U8FilesFull As List(Of SFile)
|
||||||
|
Get
|
||||||
|
Return ListAddList(Nothing, M3U8Files, LAP.NotContainsOnly).ListAddValue(CMB_PLS.Text, LAP.NotContainsOnly)
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
|
Private Class FpsFieldChecker : Inherits FieldsCheckerProviderBase
|
||||||
|
Private ReadOnly MyProvider As ANumbers = YouTubeSettings.FpsFormatProvider.MyProviderDefault
|
||||||
|
Public Overrides Property ErrorMessage As String
|
||||||
|
Get
|
||||||
|
Return IIf(HasError, YouTubeSettings.FpsFormatProvider.ErrorMessageDefault, String.Empty)
|
||||||
|
End Get
|
||||||
|
Set : End Set
|
||||||
|
End Property
|
||||||
|
Public Overrides Function Convert(ByVal Value As Object, ByVal DestinationType As Type, ByVal Provider As IFormatProvider,
|
||||||
|
Optional ByVal NothingArg As Object = Nothing, Optional ByVal e As ErrorsDescriber = Nothing) As Object
|
||||||
|
If ACheck(Of Double)(Value, AModes.Var, MyProvider) Then
|
||||||
|
Return Value
|
||||||
|
Else
|
||||||
|
HasError = True
|
||||||
|
TypeError = True
|
||||||
|
Return Nothing
|
||||||
|
End If
|
||||||
|
End Function
|
||||||
|
End Class
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Initializers"
|
#Region "Initializers"
|
||||||
Friend Sub New(ByVal Container As YouTubeMediaContainerBase, Optional ByVal IsSavedObject As Boolean = False)
|
Friend Sub New(ByVal Container As YouTubeMediaContainerBase, Optional ByVal InheritsFromContainer As Boolean = False)
|
||||||
InitializeComponent()
|
InitializeComponent()
|
||||||
|
M3U8Files = New List(Of SFile)
|
||||||
MyContainer = Container
|
MyContainer = Container
|
||||||
CNT_PROCESSOR = New TableControlsProcessor(TP_CONTROLS)
|
CNT_PROCESSOR = New TableControlsProcessor(TP_CONTROLS)
|
||||||
Me.IsSavedObject = IsSavedObject
|
Me.InheritsFromContainer = InheritsFromContainer
|
||||||
|
MyFieldsChecker = New FieldsChecker
|
||||||
|
UseCookies = MyYouTubeSettings.DefaultUseCookies
|
||||||
End Sub
|
End Sub
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Form handlers"
|
#Region "Form handlers"
|
||||||
@@ -48,6 +78,8 @@ Namespace API.YouTube.Controls
|
|||||||
End If
|
End If
|
||||||
|
|
||||||
MyYouTubeSettings.DownloadLocations.PopulateComboBox(TXT_FILE)
|
MyYouTubeSettings.DownloadLocations.PopulateComboBox(TXT_FILE)
|
||||||
|
MyYouTubeSettings.PlaylistsLocations.PopulateComboBox(CMB_PLS,, True)
|
||||||
|
CMB_PLS.Text = MyYouTubeSettings.LatestPlaylistFile.Value
|
||||||
|
|
||||||
If Not MyContainer Is Nothing Then
|
If Not MyContainer Is Nothing Then
|
||||||
With MyContainer
|
With MyContainer
|
||||||
@@ -68,8 +100,8 @@ Namespace API.YouTube.Controls
|
|||||||
If Not .PlaylistTitle.IsEmptyString Or Not .Title.IsEmptyString Then Text &= $" - { .PlaylistTitle.IfNullOrEmpty(.Title)}"
|
If Not .PlaylistTitle.IsEmptyString Or Not .Title.IsEmptyString Then Text &= $" - { .PlaylistTitle.IfNullOrEmpty(.Title)}"
|
||||||
TP_MAIN.Controls.Remove(TP_HEADER_BASE)
|
TP_MAIN.Controls.Remove(TP_HEADER_BASE)
|
||||||
TP_MAIN.RowStyles(0).Height = 0
|
TP_MAIN.RowStyles(0).Height = 0
|
||||||
Dim def% = If(IsSavedObject, .ArrayMaxResolution, MyYouTubeSettings.DefaultVideoDefinition.Value)
|
Dim def% = If(InheritsFromContainer, .ArrayMaxResolution, MyYouTubeSettings.DefaultVideoDefinition.Value)
|
||||||
If IsSavedObject Then
|
If InheritsFromContainer Then
|
||||||
__audioOnly = def = -2
|
__audioOnly = def = -2
|
||||||
If def <= 0 Then def = MyYouTubeSettings.DefaultVideoDefinition
|
If def <= 0 Then def = MyYouTubeSettings.DefaultVideoDefinition
|
||||||
Else
|
Else
|
||||||
@@ -91,14 +123,14 @@ Namespace API.YouTube.Controls
|
|||||||
img = ImageRenderer.GetImage(SFile.GetBytesFromNet(imgUrl, EDP.ReturnValue), EDP.ReturnValue)
|
img = ImageRenderer.GetImage(SFile.GetBytesFromNet(imgUrl, EDP.ReturnValue), EDP.ReturnValue)
|
||||||
If Not img Is Nothing Then ICON_VIDEO.Image = img : ICON_VIDEO.InitialImage = img
|
If Not img Is Nothing Then ICON_VIDEO.Image = img : ICON_VIDEO.InitialImage = img
|
||||||
End If
|
End If
|
||||||
LBL_TITLE.Text = .Title
|
LBL_TITLE.Text = $"{If(MyYouTubeSettings.FileAddDateToFileName_VideoForm.Value, $"[{ .DateAdded:yyyy-MM-dd}] ", String.Empty)}{ .Title}"
|
||||||
LBL_TIME.Text = AConvert(Of String)(.Duration, TimeToStringProvider, String.Empty)
|
LBL_TIME.Text = AConvert(Of String)(.Duration, TimeToStringProvider, String.Empty)
|
||||||
TP_HEADER_INFO_2.ColumnStyles(1).Width = MeasureTextDefault(LBL_TIME.Text, LBL_TIME.Font).Width + PaddingE.GetOf({LBL_TIME}).Horizontal
|
TP_HEADER_INFO_2.ColumnStyles(1).Width = MeasureTextDefault(LBL_TIME.Text, LBL_TIME.Font).Width + PaddingE.GetOf({LBL_TIME}).Horizontal
|
||||||
TP_HEADER_INFO_2.Refresh()
|
TP_HEADER_INFO_2.Refresh()
|
||||||
LBL_URL.Text = .URL
|
LBL_URL.Text = .URL
|
||||||
End If
|
End If
|
||||||
|
|
||||||
If .IsMusic Or __audioOnly Then
|
If .IsMusic Or __audioOnly Or (InheritsFromContainer And .IsAudioSelected) Then
|
||||||
OPT_AUDIO.Checked = True
|
OPT_AUDIO.Checked = True
|
||||||
Else
|
Else
|
||||||
OPT_VIDEO.Checked = True
|
OPT_VIDEO.Checked = True
|
||||||
@@ -107,7 +139,7 @@ Namespace API.YouTube.Controls
|
|||||||
|
|
||||||
arr = AvailableVideoFormats
|
arr = AvailableVideoFormats
|
||||||
CMB_FORMAT.Items.AddRange(arr)
|
CMB_FORMAT.Items.AddRange(arr)
|
||||||
If IsSavedObject Then
|
If InheritsFromContainer Then
|
||||||
__optionValue = .OutputVideoExtension.IfNullOrEmpty(MyYouTubeSettings.DefaultVideoFormat.Value)
|
__optionValue = .OutputVideoExtension.IfNullOrEmpty(MyYouTubeSettings.DefaultVideoFormat.Value)
|
||||||
Else
|
Else
|
||||||
__optionValue = MyYouTubeSettings.DefaultVideoFormat.Value
|
__optionValue = MyYouTubeSettings.DefaultVideoFormat.Value
|
||||||
@@ -116,7 +148,7 @@ Namespace API.YouTube.Controls
|
|||||||
|
|
||||||
arr = AvailableAudioFormats
|
arr = AvailableAudioFormats
|
||||||
CMB_AUDIO_CODEC.Items.AddRange(arr)
|
CMB_AUDIO_CODEC.Items.AddRange(arr)
|
||||||
If IsSavedObject Then
|
If InheritsFromContainer Then
|
||||||
__optionValue = .OutputAudioCodec.IfNullOrEmpty(IIf(.IsMusic, MyYouTubeSettings.DefaultAudioCodecMusic.Value, MyYouTubeSettings.DefaultAudioCodec.Value))
|
__optionValue = .OutputAudioCodec.IfNullOrEmpty(IIf(.IsMusic, MyYouTubeSettings.DefaultAudioCodecMusic.Value, MyYouTubeSettings.DefaultAudioCodec.Value))
|
||||||
Else
|
Else
|
||||||
__optionValue = IIf(.IsMusic, MyYouTubeSettings.DefaultAudioCodecMusic.Value, MyYouTubeSettings.DefaultAudioCodec.Value)
|
__optionValue = IIf(.IsMusic, MyYouTubeSettings.DefaultAudioCodecMusic.Value, MyYouTubeSettings.DefaultAudioCodec.Value)
|
||||||
@@ -125,13 +157,25 @@ Namespace API.YouTube.Controls
|
|||||||
|
|
||||||
arr = AvailableSubtitlesFormats
|
arr = AvailableSubtitlesFormats
|
||||||
CMB_SUBS_FORMAT.Items.AddRange(arr)
|
CMB_SUBS_FORMAT.Items.AddRange(arr)
|
||||||
If IsSavedObject Then
|
If InheritsFromContainer Then
|
||||||
__optionValue = .OutputSubtitlesFormat.IfNullOrEmpty(IIf(.IsMusic, "LRC", MyYouTubeSettings.DefaultSubtitlesFormat.Value))
|
__optionValue = .OutputSubtitlesFormat.IfNullOrEmpty(IIf(.IsMusic, "LRC", MyYouTubeSettings.DefaultSubtitlesFormat.Value))
|
||||||
Else
|
Else
|
||||||
__optionValue = IIf(.IsMusic, "LRC", MyYouTubeSettings.DefaultSubtitlesFormat.Value)
|
__optionValue = IIf(.IsMusic, "LRC", MyYouTubeSettings.DefaultSubtitlesFormat.Value)
|
||||||
End If
|
End If
|
||||||
setDef(CMB_SUBS_FORMAT, __optionValue)
|
setDef(CMB_SUBS_FORMAT, __optionValue)
|
||||||
|
|
||||||
|
If InheritsFromContainer Then
|
||||||
|
If .OutputVideoFPS > 0 Then TXT_FPS.Text = .OutputVideoFPS
|
||||||
|
If .OutputAudioBitrate > 0 Then TXT_AUDIO_BITRATE.Text = .OutputAudioBitrate
|
||||||
|
Else
|
||||||
|
If MyYouTubeSettings.DefaultVideoFPS > 0 Then TXT_FPS.Text = MyYouTubeSettings.DefaultVideoFPS
|
||||||
|
If MyYouTubeSettings.DefaultAudioBitrate > 0 Then TXT_AUDIO_BITRATE.Text = MyYouTubeSettings.DefaultAudioBitrate.Value
|
||||||
|
End If
|
||||||
|
With MyFieldsChecker
|
||||||
|
.AddControl(Of Double)(TXT_FPS, TXT_FPS.CaptionText, True, New FpsFieldChecker)
|
||||||
|
.AddControl(Of Integer)(TXT_AUDIO_BITRATE, TXT_AUDIO_BITRATE.CaptionText, True)
|
||||||
|
.EndLoaderOperations()
|
||||||
|
End With
|
||||||
TP_SUBS.Enabled = .Subtitles.Count > 0
|
TP_SUBS.Enabled = .Subtitles.Count > 0
|
||||||
TXT_SUBS_ADDIT.Enabled = .Subtitles.Count > 0
|
TXT_SUBS_ADDIT.Enabled = .Subtitles.Count > 0
|
||||||
RefillTextBoxes()
|
RefillTextBoxes()
|
||||||
@@ -151,6 +195,8 @@ Namespace API.YouTube.Controls
|
|||||||
End Sub
|
End Sub
|
||||||
Private Sub VideoOptionsForm_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
|
Private Sub VideoOptionsForm_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
|
||||||
MyView.DisposeIfReady()
|
MyView.DisposeIfReady()
|
||||||
|
MyFieldsChecker.DisposeIfReady()
|
||||||
|
M3U8Files.Clear()
|
||||||
End Sub
|
End Sub
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Refill"
|
#Region "Refill"
|
||||||
@@ -183,7 +229,7 @@ Namespace API.YouTube.Controls
|
|||||||
Dim data As IEnumerable(Of Control)
|
Dim data As IEnumerable(Of Control)
|
||||||
|
|
||||||
If .HasElements Then
|
If .HasElements Then
|
||||||
data = .Elements.Select(Function(ee) New MediaItem(ee) With {.Dock = DockStyle.Fill, .Checked = ee.Checked, .IgnoreDownloadState = True})
|
data = .Elements.Select(Function(ee) New MediaItem(ee, True) With {.Dock = DockStyle.Fill, .Checked = ee.Checked, .UseCookies = UseCookies})
|
||||||
Else
|
Else
|
||||||
data = (From m As MediaObject In .Self.MediaObjects
|
data = (From m As MediaObject In .Self.MediaObjects
|
||||||
Where m.Type = __contentType
|
Where m.Type = __contentType
|
||||||
@@ -204,6 +250,8 @@ Namespace API.YouTube.Controls
|
|||||||
If MyContainer.HasElements Then
|
If MyContainer.HasElements Then
|
||||||
With DirectCast(d, MediaItem)
|
With DirectCast(d, MediaItem)
|
||||||
AddHandler .CheckedChanged, AddressOf MediaItem_CheckedChanged
|
AddHandler .CheckedChanged, AddressOf MediaItem_CheckedChanged
|
||||||
|
AddHandler .BeforeOpenEditor, AddressOf MediaItem_BeforeOpenEditor
|
||||||
|
AddHandler .BeforeOpenEditorFull, AddressOf MediaItem_BeforeOpenEditorFull
|
||||||
AddHandler .Click, AddressOf CNT_PROCESSOR.MediaItem_Click
|
AddHandler .Click, AddressOf CNT_PROCESSOR.MediaItem_Click
|
||||||
AddHandler .KeyDown, AddressOf CNT_PROCESSOR.MediaItem_KeyDown
|
AddHandler .KeyDown, AddressOf CNT_PROCESSOR.MediaItem_KeyDown
|
||||||
End With
|
End With
|
||||||
@@ -271,21 +319,50 @@ Namespace API.YouTube.Controls
|
|||||||
Private Sub MediaItem_CheckedChanged(ByVal Sender As MediaItem, ByVal Container As IYouTubeMediaContainer)
|
Private Sub MediaItem_CheckedChanged(ByVal Sender As MediaItem, ByVal Container As IYouTubeMediaContainer)
|
||||||
ControlInvokeFast(TP_CONTROLS, Sub() Container.Checked = Sender.Checked, EDP.None)
|
ControlInvokeFast(TP_CONTROLS, Sub() Container.Checked = Sender.Checked, EDP.None)
|
||||||
End Sub
|
End Sub
|
||||||
|
Private Sub MediaItem_BeforeOpenEditor(ByVal Sender As MediaItem, ByVal Container As IYouTubeMediaContainer)
|
||||||
|
MediaItem_BeforeOpenEditorImpl(Sender, Container, False)
|
||||||
|
End Sub
|
||||||
|
Private Sub MediaItem_BeforeOpenEditorFull(ByVal Sender As MediaItem, ByVal Container As IYouTubeMediaContainer)
|
||||||
|
MediaItem_BeforeOpenEditorImpl(Sender, Container, True)
|
||||||
|
End Sub
|
||||||
|
Private Sub MediaItem_BeforeOpenEditorImpl(ByVal Sender As MediaItem, ByVal Container As IYouTubeMediaContainer, ByVal Full As Boolean)
|
||||||
|
If MyContainer.HasElements Then
|
||||||
|
ControlInvokeFast(TP_CONTROLS, Sub()
|
||||||
|
With DirectCast(Container, YouTubeMediaContainerBase)
|
||||||
|
.File = $"{TXT_FILE.Text.CSFilePS}{ .File.File}"
|
||||||
|
.M3U8_PlaylistFiles = M3U8FilesFull
|
||||||
|
If Full Then
|
||||||
|
.OutputVideoExtension = CMB_FORMAT.Text.StringToLower
|
||||||
|
.OutputVideoFPS = AConvert(Of Double)(TXT_FPS.Text, YouTubeSettings.FpsFormatProvider.MyProviderDefault, -1)
|
||||||
|
.OutputAudioBitrate = AConvert(Of Integer)(TXT_AUDIO_BITRATE.Text, -1)
|
||||||
|
.OutputAudioCodec = CMB_AUDIO_CODEC.Text.StringToLower
|
||||||
|
.OutputSubtitlesFormat = CMB_SUBS_FORMAT.Text.StringToLower
|
||||||
|
.IsAudioSelected = OPT_AUDIO.Checked
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
End Sub, EDP.None)
|
||||||
|
End If
|
||||||
|
End Sub
|
||||||
#End Region
|
#End Region
|
||||||
#Region "OK, Cancel"
|
#Region "OK, Cancel"
|
||||||
Private Sub BTT_DOWN_Click(sender As Object, e As EventArgs) Handles BTT_DOWN.Click
|
Private Sub BTT_DOWN_Click(sender As Object, e As EventArgs) Handles BTT_DOWN.Click
|
||||||
Try
|
Try
|
||||||
|
If Not MyFieldsChecker.AllParamsOK Then Exit Sub
|
||||||
Dim f As SFile
|
Dim f As SFile
|
||||||
If MyContainer.HasElements Then
|
If MyContainer.HasElements Then
|
||||||
f = TXT_FILE.Text.CSFileP
|
f = TXT_FILE.Text.CSFileP
|
||||||
Else
|
Else
|
||||||
f = TXT_FILE.Text
|
f = TXT_FILE.Text
|
||||||
End If
|
End If
|
||||||
|
f = CleanFileName(f)
|
||||||
If f.IsEmptyString Then Throw New ArgumentNullException("File", "The output file cannot be null")
|
If f.IsEmptyString Then Throw New ArgumentNullException("File", "The output file cannot be null")
|
||||||
With MyContainer
|
With MyContainer
|
||||||
.OutputVideoExtension = CMB_FORMAT.Text.StringToLower
|
.OutputVideoExtension = CMB_FORMAT.Text.StringToLower
|
||||||
|
.OutputVideoFPS = AConvert(Of Double)(TXT_FPS.Text, YouTubeSettings.FpsFormatProvider.MyProviderDefault, -1)
|
||||||
|
.OutputAudioBitrate = AConvert(Of Integer)(TXT_AUDIO_BITRATE.Text, -1)
|
||||||
.OutputAudioCodec = CMB_AUDIO_CODEC.Text.StringToLower
|
.OutputAudioCodec = CMB_AUDIO_CODEC.Text.StringToLower
|
||||||
.OutputSubtitlesFormat = CMB_SUBS_FORMAT.Text.StringToLower
|
.OutputSubtitlesFormat = CMB_SUBS_FORMAT.Text.StringToLower
|
||||||
|
.M3U8_PlaylistFiles = M3U8FilesFull
|
||||||
|
|
||||||
If Not .HasElements Then
|
If Not .HasElements Then
|
||||||
Dim cntIndex% = -1
|
Dim cntIndex% = -1
|
||||||
@@ -302,6 +379,7 @@ Namespace API.YouTube.Controls
|
|||||||
Else
|
Else
|
||||||
.SelectedVideoIndex = -1
|
.SelectedVideoIndex = -1
|
||||||
.SelectedAudioIndex = cntIndex
|
.SelectedAudioIndex = cntIndex
|
||||||
|
.MediaType = UMTypes.Audio
|
||||||
End If
|
End If
|
||||||
.FileSetManually = True
|
.FileSetManually = True
|
||||||
.File = f
|
.File = f
|
||||||
@@ -312,6 +390,7 @@ Namespace API.YouTube.Controls
|
|||||||
Else
|
Else
|
||||||
If OPT_AUDIO.Checked Then
|
If OPT_AUDIO.Checked Then
|
||||||
.SetMaxResolution(-2)
|
.SetMaxResolution(-2)
|
||||||
|
.MediaType = UMTypes.Audio
|
||||||
Else
|
Else
|
||||||
.SetMaxResolution(NUM_RES.Value)
|
.SetMaxResolution(NUM_RES.Value)
|
||||||
End If
|
End If
|
||||||
@@ -322,6 +401,8 @@ Namespace API.YouTube.Controls
|
|||||||
|
|
||||||
If MyYouTubeSettings.OutputPathAutoChange Then MyYouTubeSettings.OutputPath.Value = f
|
If MyYouTubeSettings.OutputPathAutoChange Then MyYouTubeSettings.OutputPath.Value = f
|
||||||
If MyDownloaderSettings.OutputPathAutoAddPaths Then MyYouTubeSettings.DownloadLocations.Add(f, False)
|
If MyDownloaderSettings.OutputPathAutoAddPaths Then MyYouTubeSettings.DownloadLocations.Add(f, False)
|
||||||
|
If Not CMB_PLS.Text.IsEmptyString Then MyYouTubeSettings.PlaylistsLocations.Add(CMB_PLS.Text, False, True)
|
||||||
|
MyYouTubeSettings.LatestPlaylistFile.Value = CMB_PLS.Text
|
||||||
|
|
||||||
DialogResult = DialogResult.OK
|
DialogResult = DialogResult.OK
|
||||||
Close()
|
Close()
|
||||||
@@ -346,6 +427,19 @@ Namespace API.YouTube.Controls
|
|||||||
Private Sub OPT_VIDEO_AUDIO_CheckedChanged(sender As Object, e As EventArgs) Handles OPT_VIDEO.CheckedChanged, OPT_AUDIO.CheckedChanged
|
Private Sub OPT_VIDEO_AUDIO_CheckedChanged(sender As Object, e As EventArgs) Handles OPT_VIDEO.CheckedChanged, OPT_AUDIO.CheckedChanged
|
||||||
If Not Initialization Then
|
If Not Initialization Then
|
||||||
CMB_FORMAT.Enabled = OPT_VIDEO.Checked
|
CMB_FORMAT.Enabled = OPT_VIDEO.Checked
|
||||||
|
Dim upFormat As Action(Of String) = Sub(ByVal format As String)
|
||||||
|
If Not format.IsEmptyString Then
|
||||||
|
format = format.ToLower
|
||||||
|
Dim fIndex% = CMB_AUDIO_CODEC.Items.Cast(Of String).ListIndexOf(Function(f) f.ToLower = format)
|
||||||
|
If fIndex >= 0 Then CMB_AUDIO_CODEC.SelectedIndex = fIndex
|
||||||
|
End If
|
||||||
|
End Sub
|
||||||
|
If OPT_VIDEO.Checked Then
|
||||||
|
upFormat(MyYouTubeSettings.DefaultAudioCodec)
|
||||||
|
Else
|
||||||
|
upFormat(MyYouTubeSettings.DefaultAudioCodecMusic)
|
||||||
|
End If
|
||||||
|
|
||||||
If MyContainer.HasElements Then
|
If MyContainer.HasElements Then
|
||||||
NUM_RES.Enabled = OPT_VIDEO.Checked
|
NUM_RES.Enabled = OPT_VIDEO.Checked
|
||||||
Else
|
Else
|
||||||
@@ -440,6 +534,42 @@ Namespace API.YouTube.Controls
|
|||||||
End Sub
|
End Sub
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Footer"
|
#Region "Footer"
|
||||||
|
Private Sub CMB_PLS_ActionOnButtonClick(ByVal Sender As Object, ByVal e As ActionButtonEventArgs) Handles CMB_PLS.ActionOnButtonClick
|
||||||
|
Select Case e.DefaultButton
|
||||||
|
Case ADB.List
|
||||||
|
Dim result As Boolean = False
|
||||||
|
Dim selectedFiles As IEnumerable(Of SFile) = MyYouTubeSettings.PlaylistsLocations.ChooseNewPlaylistArray(CMB_PLS, result)
|
||||||
|
If result And selectedFiles.ListExists Then M3U8Files.ListAddList(selectedFiles, LAP.NotContainsOnly, LAP.ClearBeforeAdd)
|
||||||
|
Case ADB.Save
|
||||||
|
With MyYouTubeSettings.PlaylistsLocations
|
||||||
|
If Not CMB_PLS.Text.IsEmptyString AndAlso .IndexOf(CMB_PLS.Text,, True) = -1 Then
|
||||||
|
.Add(CMB_PLS.Text, True, True)
|
||||||
|
.PopulateComboBox(CMB_PLS, CMB_PLS.Text, True)
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
Case ADB.Clear : M3U8Files.Clear()
|
||||||
|
End Select
|
||||||
|
End Sub
|
||||||
|
Private Sub BTT_PLS_BROWSE_MouseDown(sender As Object, e As MouseEventArgs) Handles BTT_PLS_BROWSE.MouseDown
|
||||||
|
Try
|
||||||
|
Dim f As SFile = Nothing
|
||||||
|
If Not CMB_PLS.Text.IsEmptyString Then
|
||||||
|
f = CMB_PLS.Text
|
||||||
|
ElseIf Not TXT_FILE.Text.IsEmptyString Then
|
||||||
|
f = TXT_FILE.Text
|
||||||
|
End If
|
||||||
|
f = SFile.SelectFiles(f, False, "Select a playlist...", "Playlists|*.m3u;*.m3u8|All files|*.*", EDP.ReturnValue).FirstOrDefault
|
||||||
|
If Not f.IsEmptyString Then
|
||||||
|
If e.Button = MouseButtons.Right Then
|
||||||
|
MyYouTubeSettings.PlaylistsLocations.Add(f.ToString, True, True)
|
||||||
|
MyYouTubeSettings.PlaylistsLocations.PopulateComboBox(CMB_PLS, f, True)
|
||||||
|
End If
|
||||||
|
CMB_PLS.Text = f
|
||||||
|
End If
|
||||||
|
Catch ex As Exception
|
||||||
|
ErrorsDescriber.Execute(EDP.SendToLog, ex, "[API.YouTube.Controls.VideoOptionsForm.SelectPlaylist]")
|
||||||
|
End Try
|
||||||
|
End Sub
|
||||||
Private _FilePathBeforeItemChange As SFile = Nothing
|
Private _FilePathBeforeItemChange As SFile = Nothing
|
||||||
Private Sub TXT_FILE_ActionSelectedItemBeforeChanged(ByVal Sender As Object, ByVal e As EventArgs, ByVal Item As ListViewItem) Handles TXT_FILE.ActionSelectedItemBeforeChanged
|
Private Sub TXT_FILE_ActionSelectedItemBeforeChanged(ByVal Sender As Object, ByVal e As EventArgs, ByVal Item As ListViewItem) Handles TXT_FILE.ActionSelectedItemBeforeChanged
|
||||||
If Not TXT_FILE.Text.IsEmptyString Then _FilePathBeforeItemChange = TXT_FILE.Text Else _FilePathBeforeItemChange = Nothing
|
If Not TXT_FILE.Text.IsEmptyString Then _FilePathBeforeItemChange = TXT_FILE.Text Else _FilePathBeforeItemChange = Nothing
|
||||||
@@ -461,6 +591,14 @@ Namespace API.YouTube.Controls
|
|||||||
_FilePathBeforeItemChange = Nothing
|
_FilePathBeforeItemChange = Nothing
|
||||||
End Try
|
End Try
|
||||||
End Sub
|
End Sub
|
||||||
|
Private Sub TXT_FILE_ActionOnButtonClick(ByVal Sender As Object, ByVal e As ActionButtonEventArgs) Handles TXT_FILE.ActionOnButtonClick
|
||||||
|
If e.DefaultButton = ADB.Save And Not TXT_FILE.Text.IsEmptyString Then
|
||||||
|
With MyYouTubeSettings.PlaylistsLocations
|
||||||
|
.Add(TXT_FILE.Text, True)
|
||||||
|
.PopulateComboBox(TXT_FILE, TXT_FILE.Text)
|
||||||
|
End With
|
||||||
|
End If
|
||||||
|
End Sub
|
||||||
Private Sub BTT_BROWSE_MouseDown(sender As Object, e As MouseEventArgs) Handles BTT_BROWSE.MouseDown
|
Private Sub BTT_BROWSE_MouseDown(sender As Object, e As MouseEventArgs) Handles BTT_BROWSE.MouseDown
|
||||||
Dim f As SFile
|
Dim f As SFile
|
||||||
#Disable Warning BC40000
|
#Disable Warning BC40000
|
||||||
@@ -469,12 +607,15 @@ Namespace API.YouTube.Controls
|
|||||||
f = SFile.SelectPath(f, "Select the destination of the video files", EDP.ReturnValue)
|
f = SFile.SelectPath(f, "Select the destination of the video files", EDP.ReturnValue)
|
||||||
Else
|
Else
|
||||||
f = TXT_FILE.Text
|
f = TXT_FILE.Text
|
||||||
Dim sPattern$ = $"Video|{AvailableVideoFormats.Select(Function(vf) $"*.{vf.ToLower}").ListToString(";")}" &
|
Dim ext$ = f.Extension
|
||||||
$"|Audio|{AvailableAudioFormats.Select(Function(af) $"*.{af.ToLower}").ListToString(";")}" &
|
Dim sPattern$ = "All Files|*.*|" &
|
||||||
"|All Files|*.*"
|
$"Video|{AvailableVideoFormats.Select(Function(vf) $"*.{vf.ToLower}").ListToString(";")}" &
|
||||||
f = SFile.SaveAs(f, "Select the destination of the video file",,, sPattern, EDP.ReturnValue)
|
$"|Audio|{AvailableAudioFormats.Select(Function(af) $"*.{af.ToLower}").ListToString(";")}"
|
||||||
|
f = SFile.SaveAs(f, "Select the destination of the video file",, ext, sPattern, EDP.ReturnValue)
|
||||||
|
If Not f.IsEmptyString Then f.Extension = ext
|
||||||
End If
|
End If
|
||||||
#Enable Warning
|
#Enable Warning
|
||||||
|
f = CleanFileName(f)
|
||||||
If Not f.IsEmptyString Then
|
If Not f.IsEmptyString Then
|
||||||
If e.Button = MouseButtons.Right Then
|
If e.Button = MouseButtons.Right Then
|
||||||
MyYouTubeSettings.DownloadLocations.Add(f, MyDownloaderSettings.OutputPathAskForName)
|
MyYouTubeSettings.DownloadLocations.Add(f, MyDownloaderSettings.OutputPathAskForName)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
'
|
'
|
||||||
' This program is distributed in the hope that it will be useful,
|
' This program is distributed in the hope that it will be useful,
|
||||||
' but WITHOUT ANY WARRANTY
|
' but WITHOUT ANY WARRANTY
|
||||||
|
Imports System.Runtime.CompilerServices
|
||||||
Imports PersonalUtilities.Tools
|
Imports PersonalUtilities.Tools
|
||||||
Imports PersonalUtilities.Forms.Toolbars
|
Imports PersonalUtilities.Forms.Toolbars
|
||||||
Imports PersonalUtilities.Functions.RegularExpressions
|
Imports PersonalUtilities.Functions.RegularExpressions
|
||||||
@@ -17,10 +18,21 @@ Namespace API.YouTube
|
|||||||
Public Const DownloaderDataFolderYouTube As String = DownloadObjects.STDownloader.DownloaderDataFolder & "YouTube\"
|
Public Const DownloaderDataFolderYouTube As String = DownloadObjects.STDownloader.DownloaderDataFolder & "YouTube\"
|
||||||
Friend Const YouTubeDownloadPathDefault As String = "YouTubeDownloads\"
|
Friend Const YouTubeDownloadPathDefault As String = "YouTubeDownloads\"
|
||||||
Friend Const SimpleArraysFormNode As String = "SimpleFormatsChooserForm"
|
Friend Const SimpleArraysFormNode As String = "SimpleFormatsChooserForm"
|
||||||
|
Private Const YTDLP_DefaultName As String = "yt-dlp"
|
||||||
Public Property MyYouTubeSettings As Base.YouTubeSettings
|
Public Property MyYouTubeSettings As Base.YouTubeSettings
|
||||||
Public Property MyCache As CacheKeeper
|
Public Property MyCache As CacheKeeper
|
||||||
Friend ReadOnly Property MyCacheSettings As New CacheKeeper(DownloaderDataFolderYouTube) With {.DeleteCacheOnDispose = False, .DeleteRootOnDispose = False}
|
Friend ReadOnly Property MyCacheSettings As New CacheKeeper(DownloaderDataFolderYouTube) With {.DeleteCacheOnDispose = False, .DeleteRootOnDispose = False}
|
||||||
Public ReadOnly Property YouTubeCookieNetscapeFile As New SFile($"Settings\Responser_{YouTubeSite}_Cookies_Netscape.txt")
|
Public ReadOnly Property YouTubeCookieNetscapeFile As New SFile($"Settings\Responser_{YouTubeSite}_Cookies_Netscape.txt")
|
||||||
|
Friend ReadOnly Property YTDLP_NAME As String
|
||||||
|
Get
|
||||||
|
Dim n$ = MyYouTubeSettings.YTDLP.Value.Name
|
||||||
|
If Not n.IsEmptyString Then
|
||||||
|
Return If(n.ToLower = YTDLP_DefaultName, n, $"""{n}""")
|
||||||
|
Else
|
||||||
|
Return YTDLP_DefaultName
|
||||||
|
End If
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
Friend ReadOnly Property AvailableSubtitlesFormats As String()
|
Friend ReadOnly Property AvailableSubtitlesFormats As String()
|
||||||
Get
|
Get
|
||||||
Return {"ASS", "LRC", "SRT", "VTT"}
|
Return {"ASS", "LRC", "SRT", "VTT"}
|
||||||
@@ -45,6 +57,26 @@ Namespace API.YouTube
|
|||||||
Friend ReadOnly TitleHtmlConverter As Func(Of String, String) = Function(Input) Input.StringRemoveWinForbiddenSymbols().StringTrim()
|
Friend ReadOnly TitleHtmlConverter As Func(Of String, String) = Function(Input) Input.StringRemoveWinForbiddenSymbols().StringTrim()
|
||||||
Friend ReadOnly ProgressProvider As IMyProgressNumberProvider = MyProgressNumberProvider.Percentage
|
Friend ReadOnly ProgressProvider As IMyProgressNumberProvider = MyProgressNumberProvider.Percentage
|
||||||
Public ReadOnly TrueUrlRegEx As RParams = RParams.DM(Base.YouTubeFunctions.TrueUrlPattern, 0, EDP.ReturnValue)
|
Public ReadOnly TrueUrlRegEx As RParams = RParams.DM(Base.YouTubeFunctions.TrueUrlPattern, 0, EDP.ReturnValue)
|
||||||
|
Friend ReadOnly MusicUrlApply As RParams = RParams.DMS("https://([w\.]*)youtube.com.+", 1, RegexReturn.Replace, EDP.ReturnValue,
|
||||||
|
CType(Function(input$) "music.", Func(Of String, String)), String.Empty)
|
||||||
|
Friend ReadOnly M3U8ExcludedSymbols As String() = {".", ",", ":", "/", "\", "(", ")", "[", "]"}
|
||||||
|
<Extension> Friend Function ToMusicUrl(ByVal URL As String, ByVal IsMusic As Boolean) As String
|
||||||
|
Try : Return If(IsMusic And Not URL.IsEmptyString, CStr(RegexReplace(URL, MusicUrlApply)).IfNullOrEmpty(URL), URL) : Catch : Return URL : End Try
|
||||||
|
End Function
|
||||||
|
Friend Function CleanFileName(ByVal f As SFile) As SFile
|
||||||
|
If Not f.IsEmptyString And Not f.Name.IsEmptyString Then
|
||||||
|
Dim ff As SFile = f
|
||||||
|
ff.Name = ff.Name.StringRemoveWinForbiddenSymbols.StringTrim
|
||||||
|
ff.Name = ff.Name.StringReplaceSymbols({vbLf, vbCr, vbCrLf}, String.Empty, EDP.ReturnValue)
|
||||||
|
ff.Name = ff.Name.StringTrimEnd(".")
|
||||||
|
If Not ff.Name.IsEmptyString And Not MyYouTubeSettings.FileRemoveCharacters.IsEmptyString Then _
|
||||||
|
ff.Name = ff.Name.StringReplaceSymbols(MyYouTubeSettings.FileRemoveCharacters.Value.AsList.ListCast(Of String).ToArray, String.Empty, EDP.ReturnValue)
|
||||||
|
If ff.Name.IsEmptyString Then ff.Name = "file"
|
||||||
|
Return ff
|
||||||
|
Else
|
||||||
|
Return f
|
||||||
|
End If
|
||||||
|
End Function
|
||||||
Private Class TimeToStringConverter : Implements ICustomProvider
|
Private Class TimeToStringConverter : Implements ICustomProvider
|
||||||
Private ReadOnly _Provider As New ADateTime("mm\:ss") With {.TimeParseMode = ADateTime.TimeModes.TimeSpan}
|
Private ReadOnly _Provider As New ADateTime("mm\:ss") With {.TimeParseMode = ADateTime.TimeModes.TimeSpan}
|
||||||
Private ReadOnly _ProviderWithHours As New ADateTime("h\:mm\:ss") With {.TimeParseMode = ADateTime.TimeModes.TimeSpan}
|
Private ReadOnly _ProviderWithHours As New ADateTime("h\:mm\:ss") With {.TimeParseMode = ADateTime.TimeModes.TimeSpan}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
Imports PersonalUtilities.Functions.XML
|
Imports PersonalUtilities.Functions.XML
|
||||||
Imports PersonalUtilities.Functions.XML.Base
|
Imports PersonalUtilities.Functions.XML.Base
|
||||||
Imports PersonalUtilities.Functions.XML.Attributes
|
Imports PersonalUtilities.Functions.XML.Attributes
|
||||||
|
Imports PersonalUtilities.Forms
|
||||||
Imports PersonalUtilities.Forms.Controls
|
Imports PersonalUtilities.Forms.Controls
|
||||||
Imports PersonalUtilities.Forms.Controls.Base
|
Imports PersonalUtilities.Forms.Controls.Base
|
||||||
Imports PersonalUtilities.Tools
|
Imports PersonalUtilities.Tools
|
||||||
@@ -103,7 +104,7 @@ Namespace DownloadObjects.STDownloader
|
|||||||
If UseUpdate Then .EndUpdate(True)
|
If UseUpdate Then .EndUpdate(True)
|
||||||
End With
|
End With
|
||||||
End Sub
|
End Sub
|
||||||
Public Sub PopulateComboBox(ByRef CMB As ComboBoxExtended, Optional ByVal Current As SFile = Nothing)
|
Public Sub PopulateComboBox(ByRef CMB As ComboBoxExtended, Optional ByVal Current As SFile = Nothing, Optional ByVal IsFile As Boolean = False)
|
||||||
Locations.Sort()
|
Locations.Sort()
|
||||||
With CMB
|
With CMB
|
||||||
.BeginUpdate()
|
.BeginUpdate()
|
||||||
@@ -124,7 +125,7 @@ Namespace DownloadObjects.STDownloader
|
|||||||
.EndUpdate()
|
.EndUpdate()
|
||||||
|
|
||||||
If Not Current.IsEmptyString And Locations.Count > 0 Then
|
If Not Current.IsEmptyString And Locations.Count > 0 Then
|
||||||
Dim i% = IndexOf(Current.PathWithSeparator)
|
Dim i% = IndexOf(If(IsFile, Current.ToString, Current.PathWithSeparator),, IsFile)
|
||||||
If i.ValueBetween(0, .Items.Count - 1) Then .SelectedIndex = i
|
If i.ValueBetween(0, .Items.Count - 1) Then .SelectedIndex = i
|
||||||
If Current.File.IsEmptyString Then CMB.Text = Current.PathWithSeparator Else CMB.Text = Current
|
If Current.File.IsEmptyString Then CMB.Text = Current.PathWithSeparator Else CMB.Text = Current
|
||||||
End If
|
End If
|
||||||
@@ -141,6 +142,44 @@ Namespace DownloadObjects.STDownloader
|
|||||||
End If
|
End If
|
||||||
Return f
|
Return f
|
||||||
End Function
|
End Function
|
||||||
|
Friend Function ChooseNewPlaylistArray(ByRef CMB As ComboBoxExtended, ByRef Result As Boolean) As IEnumerable(Of SFile)
|
||||||
|
Try
|
||||||
|
Dim initFiles As IEnumerable(Of SFile) = Nothing
|
||||||
|
Dim selectedFiles As IEnumerable(Of SFile) = Nothing
|
||||||
|
If Count > 0 Then initFiles = Me.Select(Function(l) l.Path.CSFile)
|
||||||
|
Dim addh As New EventHandler(Of SimpleListFormEventArgs)(Sub(ByVal s As Object, ByVal ee As SimpleListFormEventArgs)
|
||||||
|
Dim ff As List(Of SFile) = SFile.SelectFiles(,, "Select playlist files", "Playlist|*.m3u;*.m3u8|AllFiles|*.*", EDP.ReturnValue)
|
||||||
|
If ff.ListExists Then
|
||||||
|
ee.AddItem(ff.Cast(Of Object))
|
||||||
|
ee.Result = True
|
||||||
|
Else
|
||||||
|
ee.Result = False
|
||||||
|
End If
|
||||||
|
End Sub)
|
||||||
|
Using f As New SimpleListForm(Of SFile)(initFiles, API.YouTube.MyYouTubeSettings.DesignXml) With {
|
||||||
|
.DesignXMLNodeName = "M3U8SelectorForm",
|
||||||
|
.FormText = "Playlists",
|
||||||
|
.Buttons = {ActionButton.DefaultButtons.Add},
|
||||||
|
.Icon = ImageRenderer.GetIcon(My.Resources.StartPic_Green_16, EDP.ReturnValue),
|
||||||
|
.AddFunction = addh
|
||||||
|
}
|
||||||
|
If f.ShowDialog = DialogResult.OK Then Result = True : selectedFiles = ListAddList(Nothing, f.DataResult, LAP.NotContainsOnly)
|
||||||
|
End Using
|
||||||
|
If selectedFiles.ListExists Then
|
||||||
|
Dim added As Boolean = False
|
||||||
|
selectedFiles.ListForEach(Sub(ByVal plsFile As SFile, ByVal ii As Integer)
|
||||||
|
If IndexOf(plsFile.ToString,, True) = -1 Then Add(plsFile.ToString, True, True) : added = True
|
||||||
|
End Sub)
|
||||||
|
If added Then PopulateComboBox(CMB, selectedFiles(0).ToString, True)
|
||||||
|
CMB.Text = selectedFiles(0)
|
||||||
|
Return selectedFiles
|
||||||
|
Else
|
||||||
|
Return Nothing
|
||||||
|
End If
|
||||||
|
Catch ex As Exception
|
||||||
|
Return ErrorsDescriber.Execute(EDP.LogMessageValue, ex, "Select playlist array")
|
||||||
|
End Try
|
||||||
|
End Function
|
||||||
Private Sub Update()
|
Private Sub Update()
|
||||||
If Locations.Count > 0 Then
|
If Locations.Count > 0 Then
|
||||||
Using x As New XmlFile With {.AllowSameNames = True}
|
Using x As New XmlFile With {.AllowSameNames = True}
|
||||||
@@ -158,9 +197,9 @@ Namespace DownloadObjects.STDownloader
|
|||||||
Public Overloads Sub Add(ByVal Item As DownloadLocation) Implements ICollection(Of DownloadLocation).Add
|
Public Overloads Sub Add(ByVal Item As DownloadLocation) Implements ICollection(Of DownloadLocation).Add
|
||||||
Add(Item, True)
|
Add(Item, True)
|
||||||
End Sub
|
End Sub
|
||||||
Public Overloads Sub Add(ByVal Item As DownloadLocation, ByVal AskForName As Boolean)
|
Public Overloads Sub Add(ByVal Item As DownloadLocation, ByVal AskForName As Boolean, Optional ByVal IsFile As Boolean = False)
|
||||||
If Not Item.Path.IsEmptyString Then
|
If Not Item.Path.IsEmptyString Then
|
||||||
Dim i% = IndexOf(Item)
|
Dim i% = IndexOf(Item,, IsFile)
|
||||||
Dim processUpdate As Boolean = True
|
Dim processUpdate As Boolean = True
|
||||||
If i >= 0 Then
|
If i >= 0 Then
|
||||||
If Locations(i).Model = Item.Model Then
|
If Locations(i).Model = Item.Model Then
|
||||||
@@ -183,8 +222,12 @@ Namespace DownloadObjects.STDownloader
|
|||||||
Public Function Contains(ByVal Item As DownloadLocation) As Boolean Implements ICollection(Of DownloadLocation).Contains
|
Public Function Contains(ByVal Item As DownloadLocation) As Boolean Implements ICollection(Of DownloadLocation).Contains
|
||||||
Return Not Item.Path.IsEmptyString AndAlso Locations.Contains(Item)
|
Return Not Item.Path.IsEmptyString AndAlso Locations.Contains(Item)
|
||||||
End Function
|
End Function
|
||||||
Public Function IndexOf(ByVal Item As DownloadLocation, Optional ByVal IgnoreModel As Boolean = False) As Integer
|
Public Function IndexOf(ByVal Item As DownloadLocation, Optional ByVal IgnoreModel As Boolean = False, Optional ByVal IsFile As Boolean = False) As Integer
|
||||||
Return Locations.FindIndex(Function(d) d.Path = Item.Path And (d.Model = Item.Model Or IgnoreModel))
|
If Not IsFile Then
|
||||||
|
Return Locations.FindIndex(Function(d) d.Path = Item.Path And (d.Model = Item.Model Or IgnoreModel))
|
||||||
|
Else
|
||||||
|
Return Locations.FindIndex(Function(d) d.Path = Item.Path)
|
||||||
|
End If
|
||||||
End Function
|
End Function
|
||||||
Public Function Remove(ByVal Item As DownloadLocation) As Boolean Implements ICollection(Of DownloadLocation).Remove
|
Public Function Remove(ByVal Item As DownloadLocation) As Boolean Implements ICollection(Of DownloadLocation).Remove
|
||||||
If Locations.Remove(Item) Then
|
If Locations.Remove(Item) Then
|
||||||
|
|||||||
59
SCrawler.YouTube/Downloader/MediaItem.Designer.vb
generated
@@ -30,11 +30,16 @@ Namespace DownloadObjects.STDownloader
|
|||||||
Me.BTT_DOWN = New System.Windows.Forms.ToolStripMenuItem()
|
Me.BTT_DOWN = New System.Windows.Forms.ToolStripMenuItem()
|
||||||
Me.SEP_DOWN = New System.Windows.Forms.ToolStripSeparator()
|
Me.SEP_DOWN = New System.Windows.Forms.ToolStripSeparator()
|
||||||
Me.BTT_OPEN_FOLDER = New System.Windows.Forms.ToolStripMenuItem()
|
Me.BTT_OPEN_FOLDER = New System.Windows.Forms.ToolStripMenuItem()
|
||||||
|
Me.BTT_OPEN_FILE = New System.Windows.Forms.ToolStripMenuItem()
|
||||||
Me.SEP_FOLDER = New System.Windows.Forms.ToolStripSeparator()
|
Me.SEP_FOLDER = New System.Windows.Forms.ToolStripSeparator()
|
||||||
|
Me.BTT_PLS_ITEM_EDIT = New System.Windows.Forms.ToolStripMenuItem()
|
||||||
|
Me.BTT_PLS_ITEM_EDIT_FULL = New System.Windows.Forms.ToolStripMenuItem()
|
||||||
|
Me.SEP_PLS_ITEM_EDIT = New System.Windows.Forms.ToolStripSeparator()
|
||||||
Me.BTT_COPY_LINK = New System.Windows.Forms.ToolStripMenuItem()
|
Me.BTT_COPY_LINK = New System.Windows.Forms.ToolStripMenuItem()
|
||||||
Me.BTT_OPEN_IN_BROWSER = New System.Windows.Forms.ToolStripMenuItem()
|
Me.BTT_OPEN_IN_BROWSER = New System.Windows.Forms.ToolStripMenuItem()
|
||||||
Me.SEP_DOWN_AGAIN = New System.Windows.Forms.ToolStripSeparator()
|
Me.SEP_DOWN_AGAIN = New System.Windows.Forms.ToolStripSeparator()
|
||||||
Me.BTT_DOWN_AGAIN = New System.Windows.Forms.ToolStripMenuItem()
|
Me.BTT_DOWN_AGAIN = New System.Windows.Forms.ToolStripMenuItem()
|
||||||
|
Me.BTT_VIEW_SETTINGS = New System.Windows.Forms.ToolStripMenuItem()
|
||||||
Me.SEP_DEL = New System.Windows.Forms.ToolStripSeparator()
|
Me.SEP_DEL = New System.Windows.Forms.ToolStripSeparator()
|
||||||
Me.BTT_REMOVE_FROM_LIST = New System.Windows.Forms.ToolStripMenuItem()
|
Me.BTT_REMOVE_FROM_LIST = New System.Windows.Forms.ToolStripMenuItem()
|
||||||
Me.BTT_DELETE_FILE = New System.Windows.Forms.ToolStripMenuItem()
|
Me.BTT_DELETE_FILE = New System.Windows.Forms.ToolStripMenuItem()
|
||||||
@@ -42,7 +47,6 @@ Namespace DownloadObjects.STDownloader
|
|||||||
Me.TP_CHECKED_TITLE = New System.Windows.Forms.TableLayoutPanel()
|
Me.TP_CHECKED_TITLE = New System.Windows.Forms.TableLayoutPanel()
|
||||||
Me.LBL_TITLE = New System.Windows.Forms.Label()
|
Me.LBL_TITLE = New System.Windows.Forms.Label()
|
||||||
Me.CH_CHECKED = New System.Windows.Forms.CheckBox()
|
Me.CH_CHECKED = New System.Windows.Forms.CheckBox()
|
||||||
Me.BTT_VIEW_SETTINGS = New System.Windows.Forms.ToolStripMenuItem()
|
|
||||||
TP_MAIN = New System.Windows.Forms.TableLayoutPanel()
|
TP_MAIN = New System.Windows.Forms.TableLayoutPanel()
|
||||||
TP_MAIN.SuspendLayout()
|
TP_MAIN.SuspendLayout()
|
||||||
CType(Me.ICON_VIDEO, System.ComponentModel.ISupportInitialize).BeginInit()
|
CType(Me.ICON_VIDEO, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||||
@@ -83,10 +87,10 @@ Namespace DownloadObjects.STDownloader
|
|||||||
'
|
'
|
||||||
'CONTEXT_MAIN
|
'CONTEXT_MAIN
|
||||||
'
|
'
|
||||||
Me.CONTEXT_MAIN.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.BTT_DOWN, Me.SEP_DOWN, Me.BTT_OPEN_FOLDER, Me.SEP_FOLDER, Me.BTT_COPY_LINK, Me.BTT_OPEN_IN_BROWSER, Me.SEP_DOWN_AGAIN, Me.BTT_DOWN_AGAIN, Me.BTT_VIEW_SETTINGS, Me.SEP_DEL, Me.BTT_REMOVE_FROM_LIST, Me.BTT_DELETE_FILE})
|
Me.CONTEXT_MAIN.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.BTT_DOWN, Me.SEP_DOWN, Me.BTT_OPEN_FOLDER, Me.BTT_OPEN_FILE, Me.SEP_FOLDER, Me.BTT_PLS_ITEM_EDIT, Me.BTT_PLS_ITEM_EDIT_FULL, Me.SEP_PLS_ITEM_EDIT, Me.BTT_COPY_LINK, Me.BTT_OPEN_IN_BROWSER, Me.SEP_DOWN_AGAIN, Me.BTT_DOWN_AGAIN, Me.BTT_VIEW_SETTINGS, Me.SEP_DEL, Me.BTT_REMOVE_FROM_LIST, Me.BTT_DELETE_FILE})
|
||||||
Me.CONTEXT_MAIN.Name = "CONTEXT_MAIN"
|
Me.CONTEXT_MAIN.Name = "CONTEXT_MAIN"
|
||||||
Me.CONTEXT_MAIN.ShowItemToolTips = False
|
Me.CONTEXT_MAIN.ShowItemToolTips = False
|
||||||
Me.CONTEXT_MAIN.Size = New System.Drawing.Size(185, 226)
|
Me.CONTEXT_MAIN.Size = New System.Drawing.Size(185, 298)
|
||||||
'
|
'
|
||||||
'BTT_DOWN
|
'BTT_DOWN
|
||||||
'
|
'
|
||||||
@@ -107,11 +111,42 @@ Namespace DownloadObjects.STDownloader
|
|||||||
Me.BTT_OPEN_FOLDER.Size = New System.Drawing.Size(184, 22)
|
Me.BTT_OPEN_FOLDER.Size = New System.Drawing.Size(184, 22)
|
||||||
Me.BTT_OPEN_FOLDER.Text = "Open folder"
|
Me.BTT_OPEN_FOLDER.Text = "Open folder"
|
||||||
'
|
'
|
||||||
|
'BTT_OPEN_FILE
|
||||||
|
'
|
||||||
|
Me.BTT_OPEN_FILE.Image = CType(resources.GetObject("BTT_OPEN_FILE.Image"), System.Drawing.Image)
|
||||||
|
Me.BTT_OPEN_FILE.Name = "BTT_OPEN_FILE"
|
||||||
|
Me.BTT_OPEN_FILE.Size = New System.Drawing.Size(184, 22)
|
||||||
|
Me.BTT_OPEN_FILE.Text = "Open file"
|
||||||
|
'
|
||||||
'SEP_FOLDER
|
'SEP_FOLDER
|
||||||
'
|
'
|
||||||
Me.SEP_FOLDER.Name = "SEP_FOLDER"
|
Me.SEP_FOLDER.Name = "SEP_FOLDER"
|
||||||
Me.SEP_FOLDER.Size = New System.Drawing.Size(181, 6)
|
Me.SEP_FOLDER.Size = New System.Drawing.Size(181, 6)
|
||||||
'
|
'
|
||||||
|
'BTT_PLS_ITEM_EDIT
|
||||||
|
'
|
||||||
|
Me.BTT_PLS_ITEM_EDIT.Image = CType(resources.GetObject("BTT_PLS_ITEM_EDIT.Image"), System.Drawing.Image)
|
||||||
|
Me.BTT_PLS_ITEM_EDIT.Name = "BTT_PLS_ITEM_EDIT"
|
||||||
|
Me.BTT_PLS_ITEM_EDIT.Size = New System.Drawing.Size(184, 22)
|
||||||
|
Me.BTT_PLS_ITEM_EDIT.Text = "Edit"
|
||||||
|
Me.BTT_PLS_ITEM_EDIT.Visible = False
|
||||||
|
'
|
||||||
|
'BTT_PLS_ITEM_EDIT_FULL
|
||||||
|
'
|
||||||
|
Me.BTT_PLS_ITEM_EDIT_FULL.AutoToolTip = True
|
||||||
|
Me.BTT_PLS_ITEM_EDIT_FULL.Image = CType(resources.GetObject("BTT_PLS_ITEM_EDIT_FULL.Image"), System.Drawing.Image)
|
||||||
|
Me.BTT_PLS_ITEM_EDIT_FULL.Name = "BTT_PLS_ITEM_EDIT_FULL"
|
||||||
|
Me.BTT_PLS_ITEM_EDIT_FULL.Size = New System.Drawing.Size(184, 22)
|
||||||
|
Me.BTT_PLS_ITEM_EDIT_FULL.Text = "Edit (inherit settings)"
|
||||||
|
Me.BTT_PLS_ITEM_EDIT_FULL.ToolTipText = "Inherit settings selected in the form"
|
||||||
|
Me.BTT_PLS_ITEM_EDIT_FULL.Visible = False
|
||||||
|
'
|
||||||
|
'SEP_PLS_ITEM_EDIT
|
||||||
|
'
|
||||||
|
Me.SEP_PLS_ITEM_EDIT.Name = "SEP_PLS_ITEM_EDIT"
|
||||||
|
Me.SEP_PLS_ITEM_EDIT.Size = New System.Drawing.Size(181, 6)
|
||||||
|
Me.SEP_PLS_ITEM_EDIT.Visible = False
|
||||||
|
'
|
||||||
'BTT_COPY_LINK
|
'BTT_COPY_LINK
|
||||||
'
|
'
|
||||||
Me.BTT_COPY_LINK.Image = Global.SCrawler.My.Resources.Resources.LinkPic_32
|
Me.BTT_COPY_LINK.Image = Global.SCrawler.My.Resources.Resources.LinkPic_32
|
||||||
@@ -138,6 +173,13 @@ Namespace DownloadObjects.STDownloader
|
|||||||
Me.BTT_DOWN_AGAIN.Size = New System.Drawing.Size(184, 22)
|
Me.BTT_DOWN_AGAIN.Size = New System.Drawing.Size(184, 22)
|
||||||
Me.BTT_DOWN_AGAIN.Text = "Download again"
|
Me.BTT_DOWN_AGAIN.Text = "Download again"
|
||||||
'
|
'
|
||||||
|
'BTT_VIEW_SETTINGS
|
||||||
|
'
|
||||||
|
Me.BTT_VIEW_SETTINGS.Image = Global.SCrawler.My.Resources.Resources.SettingsPic_16
|
||||||
|
Me.BTT_VIEW_SETTINGS.Name = "BTT_VIEW_SETTINGS"
|
||||||
|
Me.BTT_VIEW_SETTINGS.Size = New System.Drawing.Size(184, 22)
|
||||||
|
Me.BTT_VIEW_SETTINGS.Text = "View settings"
|
||||||
|
'
|
||||||
'SEP_DEL
|
'SEP_DEL
|
||||||
'
|
'
|
||||||
Me.SEP_DEL.Name = "SEP_DEL"
|
Me.SEP_DEL.Name = "SEP_DEL"
|
||||||
@@ -212,13 +254,6 @@ Namespace DownloadObjects.STDownloader
|
|||||||
Me.CH_CHECKED.TabIndex = 0
|
Me.CH_CHECKED.TabIndex = 0
|
||||||
Me.CH_CHECKED.UseVisualStyleBackColor = True
|
Me.CH_CHECKED.UseVisualStyleBackColor = True
|
||||||
'
|
'
|
||||||
'BTT_VIEW_SETTINGS
|
|
||||||
'
|
|
||||||
Me.BTT_VIEW_SETTINGS.Image = Global.SCrawler.My.Resources.Resources.SettingsPic_16
|
|
||||||
Me.BTT_VIEW_SETTINGS.Name = "BTT_VIEW_SETTINGS"
|
|
||||||
Me.BTT_VIEW_SETTINGS.Size = New System.Drawing.Size(184, 22)
|
|
||||||
Me.BTT_VIEW_SETTINGS.Text = "View settings"
|
|
||||||
'
|
|
||||||
'MediaItem
|
'MediaItem
|
||||||
'
|
'
|
||||||
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
|
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
|
||||||
@@ -253,5 +288,9 @@ Namespace DownloadObjects.STDownloader
|
|||||||
Private WithEvents SEP_DOWN_AGAIN As ToolStripSeparator
|
Private WithEvents SEP_DOWN_AGAIN As ToolStripSeparator
|
||||||
Private WithEvents SEP_DEL As ToolStripSeparator
|
Private WithEvents SEP_DEL As ToolStripSeparator
|
||||||
Private WithEvents BTT_VIEW_SETTINGS As ToolStripMenuItem
|
Private WithEvents BTT_VIEW_SETTINGS As ToolStripMenuItem
|
||||||
|
Private WithEvents BTT_OPEN_FILE As ToolStripMenuItem
|
||||||
|
Private WithEvents BTT_PLS_ITEM_EDIT As ToolStripMenuItem
|
||||||
|
Private WithEvents SEP_PLS_ITEM_EDIT As ToolStripSeparator
|
||||||
|
Private WithEvents BTT_PLS_ITEM_EDIT_FULL As ToolStripMenuItem
|
||||||
End Class
|
End Class
|
||||||
End Namespace
|
End Namespace
|
||||||
@@ -138,6 +138,138 @@
|
|||||||
PNWfb/GWbyQQ2Z/pgjaJ9XsI91sIjr1H+fgUVeYh/KVrFs8Itp6O1B2RR+fAdhzupEHDXnw3U3GVpuAq
|
PNWfb/GWbyQQ2Z/pgjaJ9XsI91sIjr1H+fgUVeYh/KVrFs8Itp6O1B2RR+fAdhzupEHDXnw3U3GVpuAq
|
||||||
+w/y3l2wnHCNxMrhGIGMcp2WpkyYWeqcC30Co5OYu0gvwZIRtc4b606cpoUYtF9y3BgvNkFSmhcSO25a
|
+w/y3l2wnHCNxMrhGIGMcp2WpkyYWeqcC30Co5OYu0gvwZIRtc4b606cpoUYtF9y3BgvNkFSmhcSO25a
|
||||||
TGCkk99shOQwl9bXawAAAABJRU5ErkJggg==
|
TGCkk99shOQwl9bXawAAAABJRU5ErkJggg==
|
||||||
|
</value>
|
||||||
|
</data>
|
||||||
|
<data name="BTT_OPEN_FILE.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>
|
||||||
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
|
wwAADsMBx2+oZAAAAk9JREFUOE+Nk0tIVGEUgKcWZlZWEK1aZEmZUlmpEQUtrF1Q0WNfUUgtCqKZLMXQ
|
||||||
|
UPJRmuY4TYYKmbPJcVSCAkuFQislzCx7rSo3Oc5T7zzu17njdZosxMXH/bn/+b97zn/ONfBjAJoPQctR
|
||||||
|
sB2bH1rsw8OEvnVj0BbUbdNJ19HW2+fmbgZO4wIR2MRm3irIQcsO2RA0Qe3mf9EOajGRuEycuXEiaDky
|
||||||
|
vdlXTfjrc0Kfu1BfVkJjtqR68G80cfRDIrgSL4Km/fCinFC/GU9JEs7CTUy25hAafYIy8hhl2IEy2Iwy
|
||||||
|
0IzacRaq1kNNClizdEHjPhiw4nFcRClKFLukWZvG1PWVuI0GPMVr8LYb8XZcRvX/gqEH0HZSskmPEbyu
|
||||||
|
w9N+CaV41bS9/Qx86oQPdhh1EOwuwesw4bGdY7LvPoHhNgIlq5nIS5gl0DLoyIF3LfgbDjBhFap348uL
|
||||||
|
Q5EDyrVEgvZT+Htv4ytYiit/WYzAfh6lIgl1bBB/xQYmi1YQqkomVJmMapbLswhN2ajfX+ErW8dU+Vpc
|
||||||
|
eUtiBRcIPDpBoKcU99V4uJf1p2Va+2q3QE8hSvcN3PkJUL9r5g6kXW8sUoKRqSE7vlupBCUTrJl6u3SB
|
||||||
|
PNWfb/GWbyQQ2Z/pgjaJ9XsI91sIjr1H+fgUVeYh/KVrFs8Itp6O1B2RR+fAdhzupEHDXnw3U3GVpuAq
|
||||||
|
+w/y3l2wnHCNxMrhGIGMcp2WpkyYWeqcC30Co5OYu0gvwZIRtc4b606cpoUYtF9y3BgvNkFSmhcSO25a
|
||||||
|
TGCkk99shOQwl9bXawAAAABJRU5ErkJggg==
|
||||||
|
</value>
|
||||||
|
</data>
|
||||||
|
<data name="BTT_PLS_ITEM_EDIT.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>
|
||||||
|
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
|
||||||
|
AAAASUVORK5CYII=
|
||||||
|
</value>
|
||||||
|
</data>
|
||||||
|
<data name="BTT_PLS_ITEM_EDIT_FULL.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>
|
||||||
|
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
|
||||||
|
AAAASUVORK5CYII=
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="BTT_OPEN_IN_BROWSER.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="BTT_OPEN_IN_BROWSER.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ Imports SCrawler.API.YouTube.Objects
|
|||||||
Imports SCrawler.API.YouTube.Controls
|
Imports SCrawler.API.YouTube.Controls
|
||||||
Imports PersonalUtilities.Tools
|
Imports PersonalUtilities.Tools
|
||||||
Imports PersonalUtilities.Forms.Toolbars
|
Imports PersonalUtilities.Forms.Toolbars
|
||||||
|
Imports PersonalUtilities.Functions.Messaging
|
||||||
Namespace DownloadObjects.STDownloader
|
Namespace DownloadObjects.STDownloader
|
||||||
Public Delegate Sub MediaItemEventHandler(ByVal Sender As MediaItem, ByVal Container As IYouTubeMediaContainer)
|
Public Delegate Sub MediaItemEventHandler(ByVal Sender As MediaItem, ByVal Container As IYouTubeMediaContainer)
|
||||||
<DefaultEvent("DoubleClick"), DesignTimeVisible(False), ToolboxItem(False)>
|
<DefaultEvent("DoubleClick"), DesignTimeVisible(False), ToolboxItem(False)>
|
||||||
@@ -23,6 +24,8 @@ Namespace DownloadObjects.STDownloader
|
|||||||
Public Event DownloadAgain As MediaItemEventHandler
|
Public Event DownloadAgain As MediaItemEventHandler
|
||||||
Public Event DownloadRequested As MediaItemEventHandler
|
Public Event DownloadRequested As MediaItemEventHandler
|
||||||
Public Event CheckedChanged As MediaItemEventHandler
|
Public Event CheckedChanged As MediaItemEventHandler
|
||||||
|
Public Event BeforeOpenEditor As MediaItemEventHandler
|
||||||
|
Public Event BeforeOpenEditorFull As MediaItemEventHandler
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Declarations"
|
#Region "Declarations"
|
||||||
#Region "Controls"
|
#Region "Controls"
|
||||||
@@ -51,8 +54,8 @@ Namespace DownloadObjects.STDownloader
|
|||||||
ControlInvokeFast(CH_CHECKED, Sub() CH_CHECKED.Checked = _Checked, EDP.None)
|
ControlInvokeFast(CH_CHECKED, Sub() CH_CHECKED.Checked = _Checked, EDP.None)
|
||||||
End Set
|
End Set
|
||||||
End Property
|
End Property
|
||||||
<Browsable(False)> Public Property IgnoreDownloadState As Boolean = False
|
|
||||||
Private ReadOnly FileOption As SFO = SFO.File
|
Private ReadOnly FileOption As SFO = SFO.File
|
||||||
|
Private ReadOnly ContainerHasElements As Boolean = False
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Initializers"
|
#Region "Initializers"
|
||||||
Public Sub New()
|
Public Sub New()
|
||||||
@@ -111,16 +114,18 @@ Namespace DownloadObjects.STDownloader
|
|||||||
.ContextMenuStrip = CONTEXT_MAIN
|
.ContextMenuStrip = CONTEXT_MAIN
|
||||||
}
|
}
|
||||||
End Sub
|
End Sub
|
||||||
Public Sub New(ByVal Container As IYouTubeMediaContainer)
|
Public Sub New(ByVal Container As IYouTubeMediaContainer, Optional ByVal HasElements As Boolean = False)
|
||||||
Me.New
|
Me.New
|
||||||
Const d$ = " " & ChrW(183) & " "
|
Const d$ = " " & ChrW(183) & " "
|
||||||
MyContainer = Container
|
MyContainer = Container
|
||||||
|
ContainerHasElements = HasElements
|
||||||
With MyContainer
|
With MyContainer
|
||||||
.Progress = MyProgress
|
.Progress = MyProgress
|
||||||
|
If HasElements Then BTT_PLS_ITEM_EDIT.Visible = True : BTT_PLS_ITEM_EDIT_FULL.Visible = True : SEP_PLS_ITEM_EDIT.Visible = True
|
||||||
If .HasElements Then FileOption = SFO.Path Else FileOption = SFO.File
|
If .HasElements Then FileOption = SFO.Path Else FileOption = SFO.File
|
||||||
If .DownloadState = Plugin.UserMediaStates.Downloaded AndAlso
|
If .DownloadState = Plugin.UserMediaStates.Downloaded AndAlso
|
||||||
(.ObjectType = Base.YouTubeMediaType.Channel Or .ObjectType = Base.YouTubeMediaType.PlayList) AndAlso FileOption = SFO.File AndAlso
|
(.ObjectType = Base.YouTubeMediaType.Channel Or .ObjectType = Base.YouTubeMediaType.PlayList) AndAlso FileOption = SFO.File AndAlso
|
||||||
Not .File.Exists AndAlso .File.Exists(SFO.Path, False) Then FileOption = SFO.Path
|
Not .File.Exists AndAlso .File.Exists(SFO.Path, False) Then FileOption = SFO.Path : BTT_OPEN_FILE.Visible = False
|
||||||
If Not .SiteKey = YouTubeSiteKey Then
|
If Not .SiteKey = YouTubeSiteKey Then
|
||||||
BTT_DOWN_AGAIN.Visible = False
|
BTT_DOWN_AGAIN.Visible = False
|
||||||
SEP_DOWN_AGAIN.Visible = False
|
SEP_DOWN_AGAIN.Visible = False
|
||||||
@@ -128,18 +133,25 @@ Namespace DownloadObjects.STDownloader
|
|||||||
|
|
||||||
ICON_SITE.Image = .SiteIcon
|
ICON_SITE.Image = .SiteIcon
|
||||||
LBL_TIME.Text = AConvert(Of String)(.Duration, TimeToStringProvider, String.Empty)
|
LBL_TIME.Text = AConvert(Of String)(.Duration, TimeToStringProvider, String.Empty)
|
||||||
LBL_TITLE.Text = .ToString(True)
|
LBL_TITLE.Text = $"{If(MyYouTubeSettings.FileAddDateToFileName_VideoList.Value, $"[{ .DateAdded:yyyy-MM-dd}] ", String.Empty)}{ .ToString(True)}"
|
||||||
|
Dim h%, b%
|
||||||
|
If .Self.GetType Is GetType(YouTubeMediaContainerBase) OrElse (Not .Self.GetType.BaseType Is Nothing AndAlso .Self.GetType.BaseType Is GetType(YouTubeMediaContainerBase)) Then
|
||||||
|
With DirectCast(.Self, YouTubeMediaContainerBase) : h = .HeightBase : b = .BitrateBase : End With
|
||||||
|
Else
|
||||||
|
h = .Height
|
||||||
|
b = .Bitrate
|
||||||
|
End If
|
||||||
If Not .SiteKey = YouTubeSiteKey And .ContentType = Plugin.UserMediaTypes.Picture Then
|
If Not .SiteKey = YouTubeSiteKey And .ContentType = Plugin.UserMediaTypes.Picture Then
|
||||||
LBL_INFO.Text = .File.Extension.StringToUpper
|
LBL_INFO.Text = .File.Extension.StringToUpper
|
||||||
ElseIf Not .IsMusic Then
|
ElseIf Not .IsMusic And Not (.MediaType = Plugin.UserMediaTypes.Audio Or .MediaType = Plugin.UserMediaTypes.AudioPre) Then
|
||||||
If .Height > 0 Then
|
If h > 0 Then
|
||||||
LBL_INFO.Text = $"{ .File.Extension.StringToUpper}{d}{ .Height}p"
|
LBL_INFO.Text = $"{ .File.Extension.StringToUpper}{d}{h}p"
|
||||||
Else
|
Else
|
||||||
LBL_INFO.Text = .File.Extension.StringToUpper
|
LBL_INFO.Text = .File.Extension.StringToUpper
|
||||||
End If
|
End If
|
||||||
Else
|
Else
|
||||||
If .Bitrate > 0 Then
|
If b > 0 Then
|
||||||
LBL_INFO.Text = $"{ .File.Extension.StringToUpper}{d}{ .Bitrate}k"
|
LBL_INFO.Text = $"{ .File.Extension.StringToUpper}{d}{b}k"
|
||||||
Else
|
Else
|
||||||
LBL_INFO.Text = .File.Extension.StringToUpper
|
LBL_INFO.Text = .File.Extension.StringToUpper
|
||||||
End If
|
End If
|
||||||
@@ -176,10 +188,10 @@ Namespace DownloadObjects.STDownloader
|
|||||||
With MyContainer
|
With MyContainer
|
||||||
If Not .SiteKey = YouTubeSiteKey And .ContentType = Plugin.UserMediaTypes.Picture Then
|
If Not .SiteKey = YouTubeSiteKey And .ContentType = Plugin.UserMediaTypes.Picture Then
|
||||||
ICON_WHAT.Image = My.Resources.ImagePic_32
|
ICON_WHAT.Image = My.Resources.ImagePic_32
|
||||||
ElseIf Not .IsMusic Then
|
ElseIf .IsMusic Or .MediaType = Plugin.UserMediaTypes.Audio Or .MediaType = Plugin.UserMediaTypes.AudioPre Then
|
||||||
ICON_WHAT.Image = My.Resources.VideoCamera_32
|
|
||||||
Else
|
|
||||||
ICON_WHAT.Image = My.Resources.AudioMusic_32
|
ICON_WHAT.Image = My.Resources.AudioMusic_32
|
||||||
|
Else
|
||||||
|
ICON_WHAT.Image = My.Resources.VideoCamera_32
|
||||||
End If
|
End If
|
||||||
End With
|
End With
|
||||||
End Sub, EDP.None)
|
End Sub, EDP.None)
|
||||||
@@ -216,7 +228,7 @@ Namespace DownloadObjects.STDownloader
|
|||||||
t = 0
|
t = 0
|
||||||
End If
|
End If
|
||||||
|
|
||||||
LBL_TITLE.Text = MyContainer.ToString(True)
|
LBL_TITLE.Text = $"{If(MyYouTubeSettings.FileAddDateToFileName_VideoList.Value, $"[{ .DateAdded:yyyy-MM-dd}] ", String.Empty)}{ .ToString(True)}"
|
||||||
|
|
||||||
If Not .SiteKey = YouTubeSiteKey Then BTT_VIEW_SETTINGS.Visible = False
|
If Not .SiteKey = YouTubeSiteKey Then BTT_VIEW_SETTINGS.Visible = False
|
||||||
|
|
||||||
@@ -224,11 +236,17 @@ Namespace DownloadObjects.STDownloader
|
|||||||
.Controls.Clear()
|
.Controls.Clear()
|
||||||
.ColumnStyles.Clear()
|
.ColumnStyles.Clear()
|
||||||
.ColumnCount = 0
|
.ColumnCount = 0
|
||||||
If IgnoreDownloadState Or MyContainer.MediaState = Plugin.UserMediaStates.Downloaded Then
|
If ContainerHasElements Or MyContainer.MediaState = Plugin.UserMediaStates.Downloaded Then
|
||||||
If Not MyContainer.SiteKey = YouTubeSiteKey Then UpdateMediaIcon()
|
UpdateMediaIcon()
|
||||||
If IgnoreDownloadState Then
|
If ContainerHasElements Then
|
||||||
BTT_OPEN_FOLDER.Visible = False
|
BTT_OPEN_FOLDER.Visible = False
|
||||||
|
BTT_OPEN_FILE.Visible = False
|
||||||
SEP_FOLDER.Visible = False
|
SEP_FOLDER.Visible = False
|
||||||
|
If Not ContainerHasElements Then
|
||||||
|
BTT_PLS_ITEM_EDIT.Visible = False
|
||||||
|
BTT_PLS_ITEM_EDIT_FULL.Visible = False
|
||||||
|
SEP_PLS_ITEM_EDIT.Visible = False
|
||||||
|
End If
|
||||||
BTT_DOWN_AGAIN.Visible = False
|
BTT_DOWN_AGAIN.Visible = False
|
||||||
SEP_DOWN_AGAIN.Visible = False
|
SEP_DOWN_AGAIN.Visible = False
|
||||||
BTT_REMOVE_FROM_LIST.Visible = False
|
BTT_REMOVE_FROM_LIST.Visible = False
|
||||||
@@ -369,7 +387,7 @@ Namespace DownloadObjects.STDownloader
|
|||||||
ICON_WHAT.DoubleClick, LBL_TIME.DoubleClick, ICON_SIZE.DoubleClick, LBL_INFO.DoubleClick,
|
ICON_WHAT.DoubleClick, LBL_TIME.DoubleClick, ICON_SIZE.DoubleClick, LBL_INFO.DoubleClick,
|
||||||
LBL_PROGRESS.DoubleClick, PR_MAIN.DoubleClick
|
LBL_PROGRESS.DoubleClick, PR_MAIN.DoubleClick
|
||||||
Controls_Click(sender, e)
|
Controls_Click(sender, e)
|
||||||
If Not IgnoreDownloadState AndAlso Not MyDownloaderSettings.OnItemDoubleClick = DoubleClickBehavior.None Then
|
If Not ContainerHasElements AndAlso Not MyDownloaderSettings.OnItemDoubleClick = DoubleClickBehavior.None Then
|
||||||
Dim m As New MMessage("The specified path was not found.", "Open file/folder",, vbExclamation)
|
Dim m As New MMessage("The specified path was not found.", "Open file/folder",, vbExclamation)
|
||||||
If MyDownloaderSettings.OnItemDoubleClick = DoubleClickBehavior.File Then
|
If MyDownloaderSettings.OnItemDoubleClick = DoubleClickBehavior.File Then
|
||||||
If FileOption = SFO.File And MyContainer.File.Exists(SFO.File, False) Then
|
If FileOption = SFO.File And MyContainer.File.Exists(SFO.File, False) Then
|
||||||
@@ -405,6 +423,27 @@ Namespace DownloadObjects.STDownloader
|
|||||||
Private Sub BTT_OPEN_FOLDER_Click(sender As Object, e As EventArgs) Handles BTT_OPEN_FOLDER.Click
|
Private Sub BTT_OPEN_FOLDER_Click(sender As Object, e As EventArgs) Handles BTT_OPEN_FOLDER.Click
|
||||||
If MyContainer.File.Exists(FileOption, False) Then GlobalOpenPath(MyContainer.File)
|
If MyContainer.File.Exists(FileOption, False) Then GlobalOpenPath(MyContainer.File)
|
||||||
End Sub
|
End Sub
|
||||||
|
Private Sub BTT_OPEN_FILE_Click(sender As Object, e As EventArgs) Handles BTT_OPEN_FILE.Click
|
||||||
|
If MyContainer.File.Exists(SFO.File) Then MyContainer.File.Open(,, EDP.ShowAllMsg)
|
||||||
|
End Sub
|
||||||
|
Private Sub BTT_PLS_ITEM_EDIT_Click(sender As Object, e As EventArgs) Handles BTT_PLS_ITEM_EDIT.Click, BTT_PLS_ITEM_EDIT_FULL.Click
|
||||||
|
If ContainerHasElements Then
|
||||||
|
With DirectCast(MyContainer, YouTubeMediaContainerBase)
|
||||||
|
Dim initProtected As Boolean = .Protected
|
||||||
|
Dim isFull As Boolean = sender Is BTT_PLS_ITEM_EDIT_FULL
|
||||||
|
.Protected = False
|
||||||
|
If isFull Then
|
||||||
|
RaiseEvent BeforeOpenEditorFull(Me, MyContainer)
|
||||||
|
Else
|
||||||
|
RaiseEvent BeforeOpenEditor(Me, MyContainer)
|
||||||
|
End If
|
||||||
|
Using f As New VideoOptionsForm(MyContainer, initProtected Or isFull) With {.UseCookies = UseCookies}
|
||||||
|
f.ShowDialog()
|
||||||
|
.Protected = IIf(f.DialogResult = DialogResult.OK, True, initProtected)
|
||||||
|
End Using
|
||||||
|
End With
|
||||||
|
End If
|
||||||
|
End Sub
|
||||||
Private Sub BTT_COPY_LINK_Click(sender As Object, e As EventArgs) Handles BTT_COPY_LINK.Click
|
Private Sub BTT_COPY_LINK_Click(sender As Object, e As EventArgs) Handles BTT_COPY_LINK.Click
|
||||||
If Not MyContainer.URL.IsEmptyString Then
|
If Not MyContainer.URL.IsEmptyString Then
|
||||||
BufferText = MyContainer.URL
|
BufferText = MyContainer.URL
|
||||||
@@ -426,12 +465,12 @@ Namespace DownloadObjects.STDownloader
|
|||||||
If Not MyContainer Is Nothing Then
|
If Not MyContainer Is Nothing Then
|
||||||
Dim f As Form = Nothing
|
Dim f As Form = Nothing
|
||||||
Select Case MyContainer.ObjectType
|
Select Case MyContainer.ObjectType
|
||||||
Case Base.YouTubeMediaType.Single : f = New VideoOptionsForm(MyContainer, True)
|
Case Base.YouTubeMediaType.Single : f = New VideoOptionsForm(MyContainer, True) With {.UseCookies = UseCookies}
|
||||||
Case Base.YouTubeMediaType.Channel, Base.YouTubeMediaType.PlayList
|
Case Base.YouTubeMediaType.Channel, Base.YouTubeMediaType.PlayList
|
||||||
If MyContainer.IsMusic Then
|
If MyContainer.IsMusic Then
|
||||||
f = New MusicPlaylistsForm(MyContainer)
|
f = New MusicPlaylistsForm(MyContainer)
|
||||||
Else
|
Else
|
||||||
f = New VideoOptionsForm(MyContainer, True)
|
f = New VideoOptionsForm(MyContainer, True) With {.UseCookies = UseCookies}
|
||||||
End If
|
End If
|
||||||
End Select
|
End Select
|
||||||
If Not f Is Nothing Then
|
If Not f Is Nothing Then
|
||||||
@@ -445,12 +484,28 @@ Namespace DownloadObjects.STDownloader
|
|||||||
RaiseEvent Removal(Me, MyContainer)
|
RaiseEvent Removal(Me, MyContainer)
|
||||||
End Sub
|
End Sub
|
||||||
Private Sub BTT_DELETE_FILE_Click(sender As Object, e As EventArgs) Handles BTT_DELETE_FILE.Click
|
Private Sub BTT_DELETE_FILE_Click(sender As Object, e As EventArgs) Handles BTT_DELETE_FILE.Click
|
||||||
If MsgBoxE({$"Are you sure you want to delete the following {FileOption.ToString.ToLower}:{vbCr}" &
|
Dim opt$
|
||||||
If(FileOption = SFO.File, MyContainer.File.ToString, MyContainer.File.PathWithSeparator),
|
Dim opt2$ = String.Empty
|
||||||
$"Deleting a {FileOption.ToString.ToLower}"}, vbExclamation,,, {"Process", "Cancel"}) = 0 Then
|
If FileOption = SFO.File Then
|
||||||
|
opt = "file"
|
||||||
|
Else
|
||||||
|
opt = "item"
|
||||||
|
opt2 = "THE ITEM MAY CONTAIN MULTIPLE FILES" & vbCr
|
||||||
|
End If
|
||||||
|
Dim b As New List(Of MsgBoxButton) From {New MsgBoxButton("Process")}
|
||||||
|
If Not opt2.IsEmptyString Then _
|
||||||
|
b.Add(New MsgBoxButton("Show files", "Show files to delete") With {
|
||||||
|
.IsDialogResultButton = False,
|
||||||
|
.CallBack = Function(r, m, bb) MsgBoxE(New MMessage($"The following files will be deleted:{vbCr}{vbCr}{MyContainer.Files.ListToString(vbCr)}",
|
||||||
|
"Files to delete",, vbExclamation) With {.Editable = True})})
|
||||||
|
b.Add(New MsgBoxButton("Cancel"))
|
||||||
|
If MsgBoxE({$"Are you sure you want to delete the following {opt}:{vbCr}{opt2}" &
|
||||||
|
If(FileOption = SFO.File, MyContainer.File.ToString, MyContainer.ToString(True)),
|
||||||
|
$"Deleting {opt}"}, vbExclamation,,, b) = 0 Then
|
||||||
MyContainer.Delete(True)
|
MyContainer.Delete(True)
|
||||||
RaiseEvent Removal(Me, MyContainer)
|
RaiseEvent Removal(Me, MyContainer)
|
||||||
End If
|
End If
|
||||||
|
b.Clear()
|
||||||
End Sub
|
End Sub
|
||||||
#End Region
|
#End Region
|
||||||
#Region "ISupportInitialize Support"
|
#Region "ISupportInitialize Support"
|
||||||
|
|||||||
@@ -57,6 +57,12 @@ Namespace DownloadObjects.STDownloader
|
|||||||
End If
|
End If
|
||||||
MyNotificator = New YTNotificator(Me)
|
MyNotificator = New YTNotificator(Me)
|
||||||
MyDownloaderSettings = MyYouTubeSettings
|
MyDownloaderSettings = MyYouTubeSettings
|
||||||
|
ProgramLogInitialize()
|
||||||
|
With ProgramLog
|
||||||
|
AddHandler .TextAdded, AddressOf ProgramLog_TextAdded
|
||||||
|
AddHandler .TextCleared, AddressOf ProgramLog_TextCleared
|
||||||
|
End With
|
||||||
|
UpdateLogButton()
|
||||||
End If
|
End If
|
||||||
|
|
||||||
With MyView : .Import() : .SetFormSize() : End With
|
With MyView : .Import() : .SetFormSize() : End With
|
||||||
@@ -126,7 +132,8 @@ Namespace DownloadObjects.STDownloader
|
|||||||
#End Region
|
#End Region
|
||||||
#Region "Controls"
|
#Region "Controls"
|
||||||
Protected Sub ControlCreateAndAdd(ByVal Container As IYouTubeMediaContainer, Optional ByVal DisableDownload As Boolean = False,
|
Protected Sub ControlCreateAndAdd(ByVal Container As IYouTubeMediaContainer, Optional ByVal DisableDownload As Boolean = False,
|
||||||
Optional ByVal PerformClick As Boolean = True, Optional ByVal IsLoading As Boolean = False)
|
Optional ByVal PerformClick As Boolean = True, Optional ByVal IsLoading As Boolean = False,
|
||||||
|
Optional ByVal UseCookies As Boolean = False)
|
||||||
ControlInvokeFast(TP_CONTROLS, Sub()
|
ControlInvokeFast(TP_CONTROLS, Sub()
|
||||||
With TP_CONTROLS
|
With TP_CONTROLS
|
||||||
.SuspendLayout()
|
.SuspendLayout()
|
||||||
@@ -136,7 +143,7 @@ Namespace DownloadObjects.STDownloader
|
|||||||
.RowStyles.Insert(0, New RowStyle(SizeType.Absolute, 60))
|
.RowStyles.Insert(0, New RowStyle(SizeType.Absolute, 60))
|
||||||
.RowCount = .RowStyles.Count
|
.RowCount = .RowStyles.Count
|
||||||
OffsetControls(0, True)
|
OffsetControls(0, True)
|
||||||
Dim cnt As New MediaItem(Container) With {.Dock = DockStyle.Fill, .Margin = New Padding(0)}
|
Dim cnt As New MediaItem(Container) With {.Dock = DockStyle.Fill, .Margin = New Padding(0), .UseCookies = UseCookies}
|
||||||
AddHandler cnt.FileDownloaded, AddressOf MediaControl_FileDownloaded
|
AddHandler cnt.FileDownloaded, AddressOf MediaControl_FileDownloaded
|
||||||
AddHandler cnt.Removal, AddressOf MediaControl_Removal
|
AddHandler cnt.Removal, AddressOf MediaControl_Removal
|
||||||
AddHandler cnt.DownloadAgain, AddressOf MediaControl_DownloadAgain
|
AddHandler cnt.DownloadAgain, AddressOf MediaControl_DownloadAgain
|
||||||
@@ -157,7 +164,7 @@ Namespace DownloadObjects.STDownloader
|
|||||||
If PerformClick Then cnt.PerformClick()
|
If PerformClick Then cnt.PerformClick()
|
||||||
If Not DisableDownload And MyDownloaderSettings.DownloadAutomatically Then AddToDownload(cnt, True)
|
If Not DisableDownload And MyDownloaderSettings.DownloadAutomatically Then AddToDownload(cnt, True)
|
||||||
End With
|
End With
|
||||||
End Sub, EDP.None)
|
End Sub, EDP.SendToLog)
|
||||||
End Sub
|
End Sub
|
||||||
#Region "Controls rendering"
|
#Region "Controls rendering"
|
||||||
Private Overloads Sub OffsetControls()
|
Private Overloads Sub OffsetControls()
|
||||||
@@ -247,7 +254,7 @@ Namespace DownloadObjects.STDownloader
|
|||||||
Dim useCookiesParse As Boolean? = Nothing
|
Dim useCookiesParse As Boolean? = Nothing
|
||||||
If useCookies Then useCookiesParse = True
|
If useCookies Then useCookiesParse = True
|
||||||
Dim standardizeUrls As Boolean = MyYouTubeSettings.StandardizeURLs
|
Dim standardizeUrls As Boolean = MyYouTubeSettings.StandardizeURLs
|
||||||
Dim standardize As Func(Of String, String) = Function(input) If(standardizeUrls, YouTubeFunctions.StandardizeURL(input), input)
|
Dim standardize As Func(Of String, String) = Function(input) If(standardizeUrls, YouTubeFunctions.StandardizeURL(input), input.StringTrim)
|
||||||
|
|
||||||
Dim c As IYouTubeMediaContainer = Nothing
|
Dim c As IYouTubeMediaContainer = Nothing
|
||||||
Dim url$ = String.Empty
|
Dim url$ = String.Empty
|
||||||
@@ -327,19 +334,19 @@ Namespace DownloadObjects.STDownloader
|
|||||||
If Not c Is Nothing Then
|
If Not c Is Nothing Then
|
||||||
Dim f As Form
|
Dim f As Form
|
||||||
Select Case c.ObjectType
|
Select Case c.ObjectType
|
||||||
Case YouTubeMediaType.Single : f = New VideoOptionsForm(c)
|
Case YouTubeMediaType.Single : f = New VideoOptionsForm(c) With {.UseCookies = useCookies}
|
||||||
Case YouTubeMediaType.Channel, YouTubeMediaType.PlayList
|
Case YouTubeMediaType.Channel, YouTubeMediaType.PlayList
|
||||||
If c.IsMusic Then
|
If c.IsMusic Then
|
||||||
f = New MusicPlaylistsForm(c)
|
f = New MusicPlaylistsForm(c)
|
||||||
Else
|
Else
|
||||||
f = New VideoOptionsForm(c)
|
f = New VideoOptionsForm(c) With {.UseCookies = useCookies}
|
||||||
End If
|
End If
|
||||||
Case Else : c.Dispose() : Throw New ArgumentException($"Object type {c.ObjectType} not implemented", "IYouTubeMediaContainer.ObjectType")
|
Case Else : c.Dispose() : Throw New ArgumentException($"Object type {c.ObjectType} not implemented", "IYouTubeMediaContainer.ObjectType")
|
||||||
End Select
|
End Select
|
||||||
If Not f Is Nothing Then
|
If Not f Is Nothing Then
|
||||||
If TypeOf f Is IDesignXMLContainer Then DirectCast(f, IDesignXMLContainer).DesignXML = DesignXML
|
If TypeOf f Is IDesignXMLContainer Then DirectCast(f, IDesignXMLContainer).DesignXML = DesignXML
|
||||||
f.ShowDialog()
|
f.ShowDialog()
|
||||||
If f.DialogResult = DialogResult.OK AndAlso ValidateContainerURL(c) Then ControlCreateAndAdd(c, disableDown)
|
If f.DialogResult = DialogResult.OK AndAlso ValidateContainerURL(c) Then ControlCreateAndAdd(c, disableDown,,, useCookies)
|
||||||
f.Dispose()
|
f.Dispose()
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
@@ -449,12 +456,26 @@ Namespace DownloadObjects.STDownloader
|
|||||||
End Try
|
End Try
|
||||||
End Sub
|
End Sub
|
||||||
#End Region
|
#End Region
|
||||||
|
#Region "LOG"
|
||||||
Private Sub BTT_LOG_Click(sender As Object, e As EventArgs) Handles BTT_LOG.Click
|
Private Sub BTT_LOG_Click(sender As Object, e As EventArgs) Handles BTT_LOG.Click
|
||||||
MyMainLOG_ShowForm(DesignXML,,,, AddressOf UpdateLogButton)
|
MyMainLOG_ShowForm(DesignXML,,,, AddressOf UpdateLogButton)
|
||||||
End Sub
|
End Sub
|
||||||
Friend Sub UpdateLogButton()
|
Private Sub UpdateLogButton()
|
||||||
If AppMode Then MyMainLOG_UpdateLogButton(BTT_LOG, TOOLBAR_TOP)
|
If AppMode Then
|
||||||
|
Try : MyMainLOG_UpdateLogButton(BTT_LOG, TOOLBAR_TOP) : Catch : End Try
|
||||||
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
|
Private _LogUpdateButtonSuspended As Boolean = False
|
||||||
|
Private Sub ProgramLog_TextAdded(ByVal Sender As Object, ByVal e As EventArgs)
|
||||||
|
If Not _LogUpdateButtonSuspended Then
|
||||||
|
_LogUpdateButtonSuspended = True
|
||||||
|
Try : ControlInvokeFast(TOOLBAR_TOP, BTT_LOG, AddressOf UpdateLogButton, EDP.None) : Catch : End Try
|
||||||
|
End If
|
||||||
|
End Sub
|
||||||
|
Private Sub ProgramLog_TextCleared(ByVal Sender As Object, ByVal e As EventArgs)
|
||||||
|
_LogUpdateButtonSuspended = False
|
||||||
|
End Sub
|
||||||
|
#End Region
|
||||||
Private Sub BTT_BUG_REPORT_Click(sender As Object, e As EventArgs) Handles BTT_BUG_REPORT.Click
|
Private Sub BTT_BUG_REPORT_Click(sender As Object, e As EventArgs) Handles BTT_BUG_REPORT.Click
|
||||||
Try
|
Try
|
||||||
With MyYouTubeSettings
|
With MyYouTubeSettings
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ Imports System.Runtime.InteropServices
|
|||||||
<Assembly: AssemblyDescription("YouTube plugin environment")>
|
<Assembly: AssemblyDescription("YouTube plugin environment")>
|
||||||
<Assembly: AssemblyCompany("AndyProgram")>
|
<Assembly: AssemblyCompany("AndyProgram")>
|
||||||
<Assembly: AssemblyProduct("SCrawler.YouTube")>
|
<Assembly: AssemblyProduct("SCrawler.YouTube")>
|
||||||
<Assembly: AssemblyCopyright("Copyright © 2024")>
|
<Assembly: AssemblyCopyright("Copyright © 2025")>
|
||||||
<Assembly: AssemblyTrademark("AndyProgram")>
|
<Assembly: AssemblyTrademark("AndyProgram")>
|
||||||
|
|
||||||
<Assembly: ComVisible(False)>
|
<Assembly: ComVisible(False)>
|
||||||
@@ -32,6 +32,6 @@ Imports System.Runtime.InteropServices
|
|||||||
' by using the '*' as shown below:
|
' by using the '*' as shown below:
|
||||||
' <Assembly: AssemblyVersion("1.0.*")>
|
' <Assembly: AssemblyVersion("1.0.*")>
|
||||||
|
|
||||||
<Assembly: AssemblyVersion("2023.12.14.0")>
|
<Assembly: AssemblyVersion("2025.2.25.0")>
|
||||||
<Assembly: AssemblyFileVersion("2023.12.14.0")>
|
<Assembly: AssemblyFileVersion("2025.2.25.0")>
|
||||||
<Assembly: NeutralResourcesLanguage("en")>
|
<Assembly: NeutralResourcesLanguage("en")>
|
||||||
|
|||||||
@@ -19,17 +19,18 @@ Namespace API.YouTube.Objects
|
|||||||
Dim __title$ = $" - {Title}"
|
Dim __title$ = $" - {Title}"
|
||||||
If Not s.IsEmptyString Then s = $" [{s}]"
|
If Not s.IsEmptyString Then s = $" [{s}]"
|
||||||
If Not PlaylistTitle.IsEmptyString And Not ForMediaItem Then t = $"{PlaylistTitle} - "
|
If Not PlaylistTitle.IsEmptyString And Not ForMediaItem Then t = $"{PlaylistTitle} - "
|
||||||
|
Dim c% = {Count, ElementsNumber}.Max
|
||||||
If IsMusic Then
|
If IsMusic Then
|
||||||
If Count <= 1 Then t &= "Single" Else t &= "Album"
|
If c <= 1 Then t &= "Single" Else t &= "Album"
|
||||||
Else
|
Else
|
||||||
t &= "Playlist"
|
t &= "Playlist"
|
||||||
End If
|
End If
|
||||||
If Not PlaylistTitle.IsEmptyString And Not ForMediaItem Then t &= $" - {PlaylistTitle}"
|
If Not PlaylistTitle.IsEmptyString And Not ForMediaItem Then t &= $" - {PlaylistTitle}"
|
||||||
If PlaylistTitle = Title Then __title = String.Empty
|
If PlaylistTitle = Title Then __title = String.Empty
|
||||||
If ForMediaItem Then
|
If ForMediaItem Then
|
||||||
Return $"{t} ({Count}){__title}"
|
Return $"{t} ({c}){__title}"
|
||||||
Else
|
Else
|
||||||
Return $"{t} ({Count}){__title} ({AConvert(Of String)(Duration, TimeToStringProvider)}){s}"
|
Return $"{t} ({c}){__title} ({AConvert(Of String)(Duration, TimeToStringProvider)}){s}"
|
||||||
End If
|
End If
|
||||||
End Function
|
End Function
|
||||||
Public Overrides Function Parse(ByVal Container As EContainer, ByVal Path As SFile, ByVal IsMusic As Boolean,
|
Public Overrides Function Parse(ByVal Container As EContainer, ByVal Path As SFile, ByVal IsMusic As Boolean,
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ Namespace API.YouTube.Objects
|
|||||||
Else
|
Else
|
||||||
_File.Extension = mp3
|
_File.Extension = mp3
|
||||||
End If
|
End If
|
||||||
|
_File = CleanFileName(_File)
|
||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
Public Overrides Function ToString(ByVal ForMediaItem As Boolean) As String
|
Public Overrides Function ToString(ByVal ForMediaItem As Boolean) As String
|
||||||
@@ -46,12 +47,17 @@ Namespace API.YouTube.Objects
|
|||||||
_ObjectType = Base.YouTubeMediaType.Single
|
_ObjectType = Base.YouTubeMediaType.Single
|
||||||
Me.IsMusic = IsMusic
|
Me.IsMusic = IsMusic
|
||||||
If MyBase.Parse(Container, Path, IsMusic, Token, Progress) Then
|
If MyBase.Parse(Container, Path, IsMusic, Token, Progress) Then
|
||||||
Dim f As SFile = MyYouTubeSettings.OutputPath
|
With MyYouTubeSettings
|
||||||
If f.IsEmptyString Then f = "YouTubeDownloads\OutputFile.mp3"
|
Dim f As SFile = .OutputPath
|
||||||
Dim ext$ = MyYouTubeSettings.DefaultAudioCodec.Value.StringToLower
|
If f.IsEmptyString Then f = "YouTubeDownloads\OutputFile.mp3"
|
||||||
If ext.IsEmptyString Then ext = "mp3"
|
Dim ext$ = .DefaultAudioCodecMusic.Value.StringToLower.IfNullOrEmpty(.DefaultAudioCodec.Value.StringToLower)
|
||||||
f.Extension = ext
|
If ext.IsEmptyString Then ext = "mp3"
|
||||||
File = f
|
f.Extension = ext
|
||||||
|
'If f.Name.IsEmptyString Then f.Name = File.Name
|
||||||
|
File = f
|
||||||
|
If _File.Extension.IsEmptyString Then _File.Extension = ext
|
||||||
|
_File = CleanFileName(_File)
|
||||||
|
End With
|
||||||
Return True
|
Return True
|
||||||
Else
|
Else
|
||||||
Return False
|
Return False
|
||||||
|
|||||||
@@ -115,6 +115,9 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Attributes\GridVisibleAttribute.vb" />
|
<Compile Include="Attributes\GridVisibleAttribute.vb" />
|
||||||
<Compile Include="Base\TableControlsProcessor.vb" />
|
<Compile Include="Base\TableControlsProcessor.vb" />
|
||||||
|
<Compile Include="Controls\ButtonRC.vb">
|
||||||
|
<SubType>Component</SubType>
|
||||||
|
</Compile>
|
||||||
<Compile Include="Controls\ChannelTabsChooserForm.Designer.vb">
|
<Compile Include="Controls\ChannelTabsChooserForm.Designer.vb">
|
||||||
<DependentUpon>ChannelTabsChooserForm.vb</DependentUpon>
|
<DependentUpon>ChannelTabsChooserForm.vb</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ Imports System.Runtime.InteropServices
|
|||||||
<Assembly: AssemblyDescription("SCrawler YouTube downloader")>
|
<Assembly: AssemblyDescription("SCrawler YouTube downloader")>
|
||||||
<Assembly: AssemblyCompany("AndyProgram")>
|
<Assembly: AssemblyCompany("AndyProgram")>
|
||||||
<Assembly: AssemblyProduct("SCrawler.YouTubeDownloader")>
|
<Assembly: AssemblyProduct("SCrawler.YouTubeDownloader")>
|
||||||
<Assembly: AssemblyCopyright("Copyright © 2024")>
|
<Assembly: AssemblyCopyright("Copyright © 2025")>
|
||||||
<Assembly: AssemblyTrademark("AndyProgram")>
|
<Assembly: AssemblyTrademark("AndyProgram")>
|
||||||
|
|
||||||
<Assembly: ComVisible(False)>
|
<Assembly: ComVisible(False)>
|
||||||
@@ -32,6 +32,6 @@ Imports System.Runtime.InteropServices
|
|||||||
' by using the '*' as shown below:
|
' by using the '*' as shown below:
|
||||||
' <Assembly: AssemblyVersion("1.0.*")>
|
' <Assembly: AssemblyVersion("1.0.*")>
|
||||||
|
|
||||||
<Assembly: AssemblyVersion("2023.12.14.0")>
|
<Assembly: AssemblyVersion("2025.2.25.0")>
|
||||||
<Assembly: AssemblyFileVersion("2023.12.14.0")>
|
<Assembly: AssemblyFileVersion("2025.2.25.0")>
|
||||||
<Assembly: NeutralResourcesLanguage("en")>
|
<Assembly: NeutralResourcesLanguage("en")>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
'
|
'
|
||||||
' This program is distributed in the hope that it will be useful,
|
' This program is distributed in the hope that it will be useful,
|
||||||
' but WITHOUT ANY WARRANTY
|
' but WITHOUT ANY WARRANTY
|
||||||
|
Imports System.Runtime.CompilerServices
|
||||||
Imports PersonalUtilities.Forms
|
Imports PersonalUtilities.Forms
|
||||||
Imports PersonalUtilities.Functions.RegularExpressions
|
Imports PersonalUtilities.Functions.RegularExpressions
|
||||||
Namespace API.Base
|
Namespace API.Base
|
||||||
@@ -49,7 +50,7 @@ Namespace API.Base
|
|||||||
End Sub
|
End Sub
|
||||||
Public Overrides Function Convert(ByVal Value As Object, ByVal DestinationType As Type, ByVal Provider As IFormatProvider,
|
Public Overrides Function Convert(ByVal Value As Object, ByVal DestinationType As Type, ByVal Provider As IFormatProvider,
|
||||||
Optional ByVal NothingArg As Object = Nothing, Optional ByVal e As ErrorsDescriber = Nothing) As Object
|
Optional ByVal NothingArg As Object = Nothing, Optional ByVal e As ErrorsDescriber = Nothing) As Object
|
||||||
Dim v% = AConvert(Of Integer)(Value, -1)
|
Dim v% = AConvert(Of Integer)(Value, -1, EDP.ReturnValue)
|
||||||
If v > 0 Then
|
If v > 0 Then
|
||||||
Return Value
|
Return Value
|
||||||
ElseIf Not ACheck(Of Integer)(Value) Then
|
ElseIf Not ACheck(Of Integer)(Value) Then
|
||||||
@@ -72,5 +73,12 @@ Namespace API.Base
|
|||||||
$"Current query: [{CurrentQuery}]{vbCr}New query: [{NewQuery}]",
|
$"Current query: [{CurrentQuery}]{vbCr}New query: [{NewQuery}]",
|
||||||
"Changing a query"}, vbExclamation,,, {"Process", "Cancel"}) = 0
|
"Changing a query"}, vbExclamation,,, {"Process", "Cancel"}) = 0
|
||||||
End Function
|
End Function
|
||||||
|
<Extension> Friend Function GetCookieValue(ByVal Cookies As IEnumerable(Of System.Net.Cookie), ByVal CookieName As String) As String
|
||||||
|
If Cookies.ListExists Then Return If(Cookies.FirstOrDefault(Function(c) c.Name.ToLower = CookieName.ToLower)?.Value, String.Empty) Else Return String.Empty
|
||||||
|
End Function
|
||||||
|
<Extension> Friend Function GetCookieValue(ByVal Cookies As IEnumerable(Of System.Net.Cookie), ByVal CookieName As String,
|
||||||
|
ByVal PropName As String, ByVal PropNameComp As String) As String
|
||||||
|
Return If(PropName = PropNameComp, Cookies.GetCookieValue(CookieName), String.Empty)
|
||||||
|
End Function
|
||||||
End Module
|
End Module
|
||||||
End Namespace
|
End Namespace
|
||||||
@@ -11,7 +11,8 @@ Namespace API.Base
|
|||||||
Friend Const Header_Authorization As String = "authorization"
|
Friend Const Header_Authorization As String = "authorization"
|
||||||
Friend Const Header_CSRFToken As String = "x-csrf-token"
|
Friend Const Header_CSRFToken As String = "x-csrf-token"
|
||||||
|
|
||||||
Friend Const Header_FB_FRIENDLY_NAME As String = "x-fb-friendly-name"
|
Friend Const CAT_UserDefs As String = "New user defaults"
|
||||||
|
Friend Const CAT_Timers As String = "Timers"
|
||||||
|
|
||||||
Friend Const ConcurrentDownloadsCaption As String = "Concurrent downloads"
|
Friend Const ConcurrentDownloadsCaption As String = "Concurrent downloads"
|
||||||
Friend Const ConcurrentDownloadsToolTip As String = "The number of concurrent downloads."
|
Friend Const ConcurrentDownloadsToolTip As String = "The number of concurrent downloads."
|
||||||
@@ -27,6 +28,8 @@ Namespace API.Base
|
|||||||
Friend Const GifsDownloadCaption As String = "Download GIFs"
|
Friend Const GifsDownloadCaption As String = "Download GIFs"
|
||||||
Friend Const UseMD5ComparisonCaption As String = "Use MD5 comparison"
|
Friend Const UseMD5ComparisonCaption As String = "Use MD5 comparison"
|
||||||
Friend Const UseMD5ComparisonToolTip As String = "Each image will be checked for existence using MD5"
|
Friend Const UseMD5ComparisonToolTip As String = "Each image will be checked for existence using MD5"
|
||||||
|
Friend Const UserNameChangeCaption As String = "UserName"
|
||||||
|
Friend Const UserNameChangeToolTip As String = "If the user has changed their UserName, you can set a new name here. Not required for new users."
|
||||||
Private Sub New()
|
Private Sub New()
|
||||||
End Sub
|
End Sub
|
||||||
End Class
|
End Class
|
||||||
|
|||||||
@@ -6,8 +6,9 @@
|
|||||||
'
|
'
|
||||||
' This program is distributed in the hope that it will be useful,
|
' This program is distributed in the hope that it will be useful,
|
||||||
' but WITHOUT ANY WARRANTY
|
' but WITHOUT ANY WARRANTY
|
||||||
Imports System.Net
|
Imports SCrawler.Plugin
|
||||||
Imports PersonalUtilities.Functions.RegularExpressions
|
Imports PersonalUtilities.Functions.RegularExpressions
|
||||||
|
Imports Download = SCrawler.Plugin.ISiteSettings.Download
|
||||||
Namespace API.Base
|
Namespace API.Base
|
||||||
Friend NotInheritable Class DownDetector
|
Friend NotInheritable Class DownDetector
|
||||||
Private Shared ReadOnly Property Params As New RParams("x:.'([\S]+?)',.y:.(\d+)", -1, Nothing, RegexReturn.List)
|
Private Shared ReadOnly Property Params As New RParams("x:.'([\S]+?)',.y:.(\d+)", -1, Nothing, RegexReturn.List)
|
||||||
@@ -34,34 +35,106 @@ Namespace API.Base
|
|||||||
Try
|
Try
|
||||||
Dim l As List(Of Data) = Nothing
|
Dim l As List(Of Data) = Nothing
|
||||||
Dim l2 As List(Of Data) = Nothing
|
Dim l2 As List(Of Data) = Nothing
|
||||||
Using w As New WebClient
|
Dim r$ = GetWebString($"https://downdetector.co.uk/status/{Site}/",, EDP.ThrowException)
|
||||||
Dim r$ = w.DownloadString($"https://downdetector.co.uk/status/{Site}/")
|
If Not r.IsEmptyString Then
|
||||||
If Not r.IsEmptyString Then
|
l = RegexFields(Of Data)(r, {Params}, {1, 2})
|
||||||
l = RegexFields(Of Data)(r, {Params}, {1, 2})
|
If l.ListExists(2) Then
|
||||||
If l.ListExists(2) Then
|
l.Sort()
|
||||||
l.Sort()
|
l2 = New List(Of Data)
|
||||||
l2 = New List(Of Data)
|
Dim d As Data
|
||||||
Dim d As Data
|
Dim eDates As New List(Of Date)
|
||||||
Dim eDates As New List(Of Date)
|
Dim MaxValue As Func(Of Date, Integer) = Function(dd) (From ddd As Data In l Where ddd.Date = dd Select ddd.Value).DefaultIfEmpty(0).Max
|
||||||
Dim MaxValue As Func(Of Date, Integer) = Function(dd) (From ddd In l Where ddd.Date = dd Select ddd.Value).DefaultIfEmpty(0).Max
|
For i% = 0 To l.Count - 1
|
||||||
For i% = 0 To l.Count - 1
|
If Not eDates.Contains(l(i).Date) Then
|
||||||
If Not eDates.Contains(l(i).Date) Then
|
d = l(i)
|
||||||
d = l(i)
|
d.Value = MaxValue(d.Date)
|
||||||
d.Value = MaxValue(d.Date)
|
l2.Add(d)
|
||||||
l2.Add(d)
|
eDates.Add(d.Date)
|
||||||
eDates.Add(d.Date)
|
End If
|
||||||
End If
|
Next
|
||||||
Next
|
eDates.Clear()
|
||||||
eDates.Clear()
|
l.Clear()
|
||||||
l.Clear()
|
l2.Sort()
|
||||||
l2.Sort()
|
|
||||||
End If
|
|
||||||
End If
|
End If
|
||||||
End Using
|
End If
|
||||||
Return l2
|
Return l2
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
Return ErrorsDescriber.Execute(EDP.SendToLog + EDP.ReturnValue, ex, $"[DownDetector.GetData({Site})]")
|
Return ErrorsDescriber.Execute(EDP.SendToLog + EDP.ReturnValue, ex, $"[DownDetector.GetData({Site})]")
|
||||||
End Try
|
End Try
|
||||||
End Function
|
End Function
|
||||||
|
Friend Interface IDownDetector
|
||||||
|
ReadOnly Property Value As Integer
|
||||||
|
ReadOnly Property AddToLog As Boolean
|
||||||
|
ReadOnly Property CheckSite As String
|
||||||
|
Function Available(ByVal What As Download, ByVal Silent As Boolean) As Boolean
|
||||||
|
End Interface
|
||||||
|
Friend Class Checker(Of T As {ISiteSettings, IDownDetector})
|
||||||
|
Protected ReadOnly Property Source As T
|
||||||
|
Private ReadOnly NP As New ANumbers With {.FormatOptions = ANumbers.Options.GroupIntegral}
|
||||||
|
Friend Sub New(ByRef _Source As T)
|
||||||
|
Source = _Source
|
||||||
|
End Sub
|
||||||
|
Private ____AvailableChecked As Boolean = False
|
||||||
|
Private ____AvailableResult As Boolean = False
|
||||||
|
Friend Overridable Function Available(ByVal What As Download, ByVal Silent As Boolean) As Boolean
|
||||||
|
If Settings.DownDetectorEnabled And Source.Value >= 0 Then
|
||||||
|
If Not ____AvailableChecked Then
|
||||||
|
____AvailableResult = AvailableImpl(What, Silent)
|
||||||
|
____AvailableChecked = True
|
||||||
|
End If
|
||||||
|
Return ____AvailableResult
|
||||||
|
Else
|
||||||
|
Return True
|
||||||
|
End If
|
||||||
|
End Function
|
||||||
|
Protected Overridable Function AvailableImpl(ByVal What As Download, ByVal Silent As Boolean) As Boolean
|
||||||
|
Try
|
||||||
|
Source.AvailableText = String.Empty
|
||||||
|
If Source.Value < 0 Then
|
||||||
|
Return True
|
||||||
|
Else
|
||||||
|
Dim dl As List(Of Data) = GetData(Source.CheckSite)
|
||||||
|
If dl.ListExists Then
|
||||||
|
dl = dl.Take(4).ToList
|
||||||
|
Dim avg% = dl.Average(Function(d) d.Value)
|
||||||
|
If avg > Source.Value Then
|
||||||
|
Source.AvailableText = $"Over the past hour, {Source.Site} has received an average of {avg.NumToString(NP)} outage reports:{vbCr}{dl.ListToString(vbCr)}"
|
||||||
|
If Source.AddToLog Then MyMainLOG = Source.AvailableText
|
||||||
|
If Silent Then
|
||||||
|
Return AvailableImpl_FALSE_SILENT()
|
||||||
|
Else
|
||||||
|
If MsgBoxE({$"{Source.AvailableText}{vbCr}{vbCr}Do you want to continue parsing {Source.Site} data?",
|
||||||
|
$"There are outage reports on {Source.Site}"}, vbYesNo) = vbYes Then
|
||||||
|
Return AvailableImpl_FALSE_SILENT_NOT_MSG_YES()
|
||||||
|
Else
|
||||||
|
Return AvailableImpl_FALSE_SILENT_NOT_MSG_NO()
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
Return AvailableImpl_TRUE()
|
||||||
|
End If
|
||||||
|
Catch ex As Exception
|
||||||
|
Return ErrorsDescriber.Execute(EDP.SendToLog + EDP.ReturnValue, ex, $"[API.{Source.Site}.SiteSettings.Available([DownDetector])]", True)
|
||||||
|
End Try
|
||||||
|
End Function
|
||||||
|
Protected Overridable Function AvailableImpl_TRUE() As Boolean
|
||||||
|
Return True
|
||||||
|
End Function
|
||||||
|
Protected Overridable Function AvailableImpl_FALSE_SILENT() As Boolean
|
||||||
|
Return False
|
||||||
|
End Function
|
||||||
|
Protected Overridable Function AvailableImpl_FALSE_SILENT_NOT_MSG_YES() As Boolean
|
||||||
|
Return True
|
||||||
|
End Function
|
||||||
|
Protected Overridable Function AvailableImpl_FALSE_SILENT_NOT_MSG_NO() As Boolean
|
||||||
|
Return False
|
||||||
|
End Function
|
||||||
|
Friend Overridable Sub Reset()
|
||||||
|
____AvailableChecked = False
|
||||||
|
____AvailableResult = False
|
||||||
|
Source.AvailableText = String.Empty
|
||||||
|
End Sub
|
||||||
|
End Class
|
||||||
End Class
|
End Class
|
||||||
End Namespace
|
End Namespace
|
||||||
22
SCrawler/API/Base/EditorExchangeOptionsBase.vb
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
' Copyright (C) Andy https://github.com/AAndyProgram
|
||||||
|
' This program is free software: you can redistribute it and/or modify
|
||||||
|
' it under the terms of the GNU General Public License as published by
|
||||||
|
' the Free Software Foundation, either version 3 of the License, or
|
||||||
|
' (at your option) any later version.
|
||||||
|
'
|
||||||
|
' This program is distributed in the hope that it will be useful,
|
||||||
|
' but WITHOUT ANY WARRANTY
|
||||||
|
Imports SCrawler.Plugin.Attributes
|
||||||
|
Imports DN = SCrawler.API.Base.DeclaredNames
|
||||||
|
Namespace API.Base
|
||||||
|
Friend Class EditorExchangeOptionsBase
|
||||||
|
Friend Overridable Property SiteKey As String
|
||||||
|
<PSetting(Address:=SettingAddress.User, Caption:=DN.UserNameChangeCaption, ToolTip:=DN.UserNameChangeToolTip)>
|
||||||
|
Friend Overridable Property UserName As String = String.Empty
|
||||||
|
Friend Sub New(ByVal u As UserDataBase)
|
||||||
|
UserName = u.NameTrue(True)
|
||||||
|
End Sub
|
||||||
|
Friend Sub New()
|
||||||
|
End Sub
|
||||||
|
End Class
|
||||||
|
End Namespace
|
||||||
@@ -6,66 +6,7 @@
|
|||||||
'
|
'
|
||||||
' This program is distributed in the hope that it will be useful,
|
' This program is distributed in the hope that it will be useful,
|
||||||
' but WITHOUT ANY WARRANTY
|
' but WITHOUT ANY WARRANTY
|
||||||
Imports PersonalUtilities.Tools
|
|
||||||
Imports PersonalUtilities.Functions.RegularExpressions
|
|
||||||
Namespace API.Base.GDL
|
Namespace API.Base.GDL
|
||||||
Friend Module Declarations
|
|
||||||
Private Structure GDLURL : Implements IRegExCreator
|
|
||||||
Private _URL As String
|
|
||||||
Friend ReadOnly Property URL As String
|
|
||||||
Get
|
|
||||||
Return _URL
|
|
||||||
End Get
|
|
||||||
End Property
|
|
||||||
Public Shared Widening Operator CType(ByVal u As String) As GDLURL
|
|
||||||
Return New GDLURL With {._URL = u}
|
|
||||||
End Operator
|
|
||||||
Public Shared Widening Operator CType(ByVal u As GDLURL) As String
|
|
||||||
Return u.URL
|
|
||||||
End Operator
|
|
||||||
Private Function CreateFromArray(ByVal ParamsArray() As String) As Object Implements IRegExCreator.CreateFromArray
|
|
||||||
If ParamsArray.ListExists(2) Then
|
|
||||||
Dim u$ = ParamsArray(0).StringTrim.StringTrimEnd("/"), u2$
|
|
||||||
If Not u.IsEmptyString Then
|
|
||||||
u2 = ParamsArray(1).StringTrim
|
|
||||||
If Not u2.IsEmptyString AndAlso u2.StartsWith("GET", StringComparison.OrdinalIgnoreCase) Then
|
|
||||||
u2 = u2.Remove(0, 3).StringTrim.StringTrimStart("/")
|
|
||||||
If Not u2.IsEmptyString Then _URL = $"{u}/{u2}"
|
|
||||||
End If
|
|
||||||
End If
|
|
||||||
End If
|
|
||||||
Return Me
|
|
||||||
End Function
|
|
||||||
Public Shared Operator =(ByVal x As GDLURL, ByVal y As GDLURL) As Boolean
|
|
||||||
Return x.URL = y.URL
|
|
||||||
End Operator
|
|
||||||
Public Shared Operator <>(ByVal x As GDLURL, ByVal y As GDLURL) As Boolean
|
|
||||||
Return Not x.URL = y.URL
|
|
||||||
End Operator
|
|
||||||
Public Overrides Function ToString() As String
|
|
||||||
Return URL
|
|
||||||
End Function
|
|
||||||
Public Overrides Function Equals(ByVal Obj As Object) As Boolean
|
|
||||||
Return URL = CType(Obj, String)
|
|
||||||
End Function
|
|
||||||
End Structure
|
|
||||||
Private ReadOnly Property GdlUrlPattern As RParams = RParams.DM(GDLBatch.UrlLibStart.Replace("[", "\[").Replace("]", "\]") &
|
|
||||||
"([^""]+?)""(GET [^""]+)""", 0, EDP.ReturnValue)
|
|
||||||
Friend Function GetUrlsFromGalleryDl(ByVal Batch As BatchExecutor, ByVal Command As String) As List(Of String)
|
|
||||||
Dim urls As New List(Of String)
|
|
||||||
Dim u As GDLURL
|
|
||||||
With Batch
|
|
||||||
.Execute(Command)
|
|
||||||
If .ErrorOutputData.Count > 0 Then
|
|
||||||
For Each eValue$ In .ErrorOutputData
|
|
||||||
u = RegexFields(Of GDLURL)(eValue, {GdlUrlPattern}, {1, 2}, EDP.ReturnValue).ListIfNothing.FirstOrDefault
|
|
||||||
If Not u.URL.IsEmptyString Then urls.ListAddValue(u, LNC)
|
|
||||||
Next
|
|
||||||
End If
|
|
||||||
End With
|
|
||||||
Return urls
|
|
||||||
End Function
|
|
||||||
End Module
|
|
||||||
Friend Class GDLBatch : Inherits TokenBatch
|
Friend Class GDLBatch : Inherits TokenBatch
|
||||||
Friend Const UrlLibStart As String = "[urllib3.connectionpool][debug]"
|
Friend Const UrlLibStart As String = "[urllib3.connectionpool][debug]"
|
||||||
Friend Const UrlTextStart As String = UrlLibStart & " https"
|
Friend Const UrlTextStart As String = UrlLibStart & " https"
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ Namespace API.Base
|
|||||||
End Enum
|
End Enum
|
||||||
ReadOnly Property Site As String
|
ReadOnly Property Site As String
|
||||||
ReadOnly Property Name As String
|
ReadOnly Property Name As String
|
||||||
|
Property NameTrue As String
|
||||||
Property ID As String
|
Property ID As String
|
||||||
Property Options As String
|
Property Options As String
|
||||||
Property FriendlyName As String
|
Property FriendlyName As String
|
||||||
@@ -59,7 +60,6 @@ Namespace API.Base
|
|||||||
ReadOnly Property DownloadedTotal(Optional ByVal Total As Boolean = True) As Integer
|
ReadOnly Property DownloadedTotal(Optional ByVal Total As Boolean = True) As Integer
|
||||||
ReadOnly Property DownloadedInformation As String
|
ReadOnly Property DownloadedInformation As String
|
||||||
Property HasError As Boolean
|
Property HasError As Boolean
|
||||||
ReadOnly Property FitToAddParams As Boolean
|
|
||||||
ReadOnly Property Key As String
|
ReadOnly Property Key As String
|
||||||
Property DownloadImages As Boolean
|
Property DownloadImages As Boolean
|
||||||
Property DownloadVideos As Boolean
|
Property DownloadVideos As Boolean
|
||||||
@@ -78,7 +78,7 @@ Namespace API.Base
|
|||||||
''' </summary>
|
''' </summary>
|
||||||
Function Delete(Optional ByVal Multiple As Boolean = False, Optional ByVal CollectionValue As Integer = -1) As Integer
|
Function Delete(Optional ByVal Multiple As Boolean = False, Optional ByVal CollectionValue As Integer = -1) As Integer
|
||||||
Function EraseData(ByVal Mode As EraseMode) As Boolean
|
Function EraseData(ByVal Mode As EraseMode) As Boolean
|
||||||
Function MoveFiles(ByVal CollectionName As String, ByVal SpecialCollectionPath As SFile) As Boolean
|
Function MoveFiles(ByVal CollectionName As String, ByVal SpecialCollectionPath As SFile, Optional ByVal NewUser As SplitCollectionUserInfo? = Nothing) As Boolean
|
||||||
Function CopyFiles(ByVal DestinationPath As SFile, Optional ByVal e As ErrorsDescriber = Nothing) As Boolean
|
Function CopyFiles(ByVal DestinationPath As SFile, Optional ByVal e As ErrorsDescriber = Nothing) As Boolean
|
||||||
Sub OpenFolder()
|
Sub OpenFolder()
|
||||||
Property DownloadTopCount As Integer?
|
Property DownloadTopCount As Integer?
|
||||||
|
|||||||
@@ -42,6 +42,13 @@ Namespace API.Base
|
|||||||
Friend NotInheritable Class M3U8Base
|
Friend NotInheritable Class M3U8Base
|
||||||
Friend Const TempCacheFolderName As String = "tmpCache"
|
Friend Const TempCacheFolderName As String = "tmpCache"
|
||||||
Friend Const TempFilePrefix As String = "ConPart_"
|
Friend Const TempFilePrefix As String = "ConPart_"
|
||||||
|
Friend Const TempFileDefaultExtension As String = "ts"
|
||||||
|
''' <summary><c>SFileNumbers.NumberProviderDefault</c></summary>
|
||||||
|
Friend Shared ReadOnly Property NumberProviderDefault As ANumbers
|
||||||
|
Get
|
||||||
|
Return SFileNumbers.NumberProviderDefault
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
Private Sub New()
|
Private Sub New()
|
||||||
End Sub
|
End Sub
|
||||||
Friend Shared Function CreateUrl(ByVal Appender As String, ByVal File As String) As String
|
Friend Shared Function CreateUrl(ByVal Appender As String, ByVal File As String) As String
|
||||||
@@ -63,8 +70,7 @@ Namespace API.Base
|
|||||||
Friend Overloads Shared Function Download(ByVal URLs As List(Of M3U8URL), ByVal DestinationFile As SFile, Optional ByVal Responser As Responser = Nothing,
|
Friend Overloads Shared Function Download(ByVal URLs As List(Of M3U8URL), ByVal DestinationFile As SFile, Optional ByVal Responser As Responser = Nothing,
|
||||||
Optional ByVal Token As CancellationToken = Nothing, Optional ByVal Progress As MyProgress = Nothing,
|
Optional ByVal Token As CancellationToken = Nothing, Optional ByVal Progress As MyProgress = Nothing,
|
||||||
Optional ByVal UsePreProgress As Boolean = True, Optional ByVal ExistingCache As CacheKeeper = Nothing,
|
Optional ByVal UsePreProgress As Boolean = True, Optional ByVal ExistingCache As CacheKeeper = Nothing,
|
||||||
Optional ByVal OnlyDownload As Boolean = False) As SFile
|
Optional ByVal OnlyDownload As Boolean = False, Optional ByVal SkipBroken As Boolean = False) As SFile
|
||||||
Const defaultExtension$ = "ts"
|
|
||||||
Dim Cache As CacheKeeper = Nothing
|
Dim Cache As CacheKeeper = Nothing
|
||||||
Using tmpPr As New PreProgress(Progress)
|
Using tmpPr As New PreProgress(Progress)
|
||||||
Try
|
Try
|
||||||
@@ -89,13 +95,13 @@ Namespace API.Base
|
|||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
Dim p As SFileNumbers = SFileNumbers.Default(ConcatFile.Name)
|
Dim p As SFileNumbers = SFileNumbers.Default(ConcatFile.Name)
|
||||||
Dim pNum As ANumbers = SFileNumbers.NumberProviderDefault
|
Dim pNum As ANumbers = NumberProviderDefault
|
||||||
p.NumberProvider = pNum
|
p.NumberProvider = pNum
|
||||||
DirectCast(p.NumberProvider, ANumbers).GroupSize = {URLs.Count.ToString.Length, 3}.Max
|
DirectCast(p.NumberProvider, ANumbers).GroupSize = {URLs.Count.ToString.Length, 3}.Max
|
||||||
ConcatFile = SFile.IndexReindex(ConcatFile,,, p, EDP.ReturnValue)
|
ConcatFile = SFile.IndexReindex(ConcatFile,,, p, EDP.ReturnValue)
|
||||||
Dim i%
|
Dim i%
|
||||||
Dim dFile As SFile = cache2.RootDirectory
|
Dim dFile As SFile = cache2.RootDirectory
|
||||||
dFile.Extension = defaultExtension
|
dFile.Extension = TempFileDefaultExtension
|
||||||
Using w As New DownloadObjects.WebClient2(Responser)
|
Using w As New DownloadObjects.WebClient2(Responser)
|
||||||
For i = 0 To URLs.Count - 1
|
For i = 0 To URLs.Count - 1
|
||||||
If progressExists Then
|
If progressExists Then
|
||||||
@@ -107,9 +113,13 @@ Namespace API.Base
|
|||||||
End If
|
End If
|
||||||
Token.ThrowIfCancellationRequested()
|
Token.ThrowIfCancellationRequested()
|
||||||
dFile.Name = $"{TempFilePrefix}{i.NumToString(pNum)}"
|
dFile.Name = $"{TempFilePrefix}{i.NumToString(pNum)}"
|
||||||
dFile.Extension = URLs(i).Extension.IfNullOrEmpty(defaultExtension)
|
dFile.Extension = URLs(i).Extension.IfNullOrEmpty(TempFileDefaultExtension)
|
||||||
w.DownloadFile(URLs(i).URL, dFile)
|
Try
|
||||||
cache2.AddFile(dFile, True)
|
w.DownloadFile(URLs(i).URL, dFile)
|
||||||
|
cache2.AddFile(dFile, True)
|
||||||
|
Catch ex As Exception
|
||||||
|
If Not SkipBroken Then Throw ex
|
||||||
|
End Try
|
||||||
Next
|
Next
|
||||||
End Using
|
End Using
|
||||||
If Not OnlyDownload Then _
|
If Not OnlyDownload Then _
|
||||||
|
|||||||
@@ -47,16 +47,15 @@ Namespace API.Base
|
|||||||
Progress.InformationTemporary = $"{HOST.Name} ({c - s}/{c}) Images: {_TotalImages}; Videos: {_TotalVideos}"
|
Progress.InformationTemporary = $"{HOST.Name} ({c - s}/{c}) Images: {_TotalImages}; Videos: {_TotalVideos}"
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
If _FeedDataExists Then Downloader.Files.Sort()
|
If _FeedDataExists Then Downloader.Files.Sort() : Downloader.FilesSave()
|
||||||
End Sub
|
End Sub
|
||||||
Private Overloads Sub Download(ByVal Host As SettingsHost, ByVal Number As Integer, ByVal Count As Integer,
|
Private Overloads Sub Download(ByVal Host As SettingsHost, ByVal Number As Integer, ByVal Count As Integer,
|
||||||
ByVal Token As CancellationToken, ByVal Multiple As Boolean)
|
ByVal Token As CancellationToken, ByVal Multiple As Boolean)
|
||||||
Dim aStr$ = String.Empty
|
Dim aStr$ = String.Empty
|
||||||
If Count > 1 Then aStr = $" ({Number}/{Count})"
|
If Count > 1 Then aStr = $" ({Number}/{Count})"
|
||||||
Try
|
Try
|
||||||
If Host.Source.ReadyToDownload(PDownload.SavedPosts) Then
|
If Host.Available(PDownload.SavedPosts, Multiple Or Count > 1) Then
|
||||||
If Host.Available(PDownload.SavedPosts, Multiple Or Count > 1) Then
|
If Host.Source.ReadyToDownload(PDownload.SavedPosts) Then
|
||||||
Host.DownloadStarted(PDownload.SavedPosts)
|
|
||||||
If Count > 1 Then Progress.Information = $"{Host.Name} - {Host.AccountName.IfNullOrEmpty(SettingsHost.NameAccountNameDefault)}"
|
If Count > 1 Then Progress.Information = $"{Host.Name} - {Host.AccountName.IfNullOrEmpty(SettingsHost.NameAccountNameDefault)}"
|
||||||
Using user As IUserData = Host.GetInstance(PDownload.SavedPosts, Nothing, False, False)
|
Using user As IUserData = Host.GetInstance(PDownload.SavedPosts, Nothing, False, False)
|
||||||
If Not user Is Nothing Then
|
If Not user Is Nothing Then
|
||||||
@@ -83,11 +82,11 @@ Namespace API.Base
|
|||||||
End Using
|
End Using
|
||||||
Else
|
Else
|
||||||
_Unavailable += 1
|
_Unavailable += 1
|
||||||
Progress.InformationTemporary = $"Host [{Host.Name}{aStr}] is unavailable"
|
Progress.InformationTemporary = $"Host [{Host.Name}{aStr}] is not ready"
|
||||||
End If
|
End If
|
||||||
Else
|
Else
|
||||||
_NotReady += 1
|
_NotReady += 1
|
||||||
Progress.InformationTemporary = $"Host [{Host.Name}{aStr}] is not ready"
|
Progress.InformationTemporary = $"Host [{Host.Name}{aStr}] is unavailable"
|
||||||
End If
|
End If
|
||||||
Catch oex As OperationCanceledException When Token.IsCancellationRequested
|
Catch oex As OperationCanceledException When Token.IsCancellationRequested
|
||||||
_ErrorCount += 1
|
_ErrorCount += 1
|
||||||
@@ -96,9 +95,6 @@ Namespace API.Base
|
|||||||
_ErrorCount += 1
|
_ErrorCount += 1
|
||||||
Progress.InformationTemporary = $"{Host.Name}{aStr} downloading error"
|
Progress.InformationTemporary = $"{Host.Name}{aStr} downloading error"
|
||||||
ErrorsDescriber.Execute(EDP.SendToLog, ex, $"[API.Base.ProfileSaved.Download({Host.Key}{aStr})]")
|
ErrorsDescriber.Execute(EDP.SendToLog, ex, $"[API.Base.ProfileSaved.Download({Host.Key}{aStr})]")
|
||||||
Finally
|
|
||||||
Host.DownloadDone(PDownload.SavedPosts)
|
|
||||||
MainFrameObj.UpdateLogButton()
|
|
||||||
End Try
|
End Try
|
||||||
End Sub
|
End Sub
|
||||||
End Class
|
End Class
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ Imports Download = SCrawler.Plugin.ISiteSettings.Download
|
|||||||
Namespace API.Base
|
Namespace API.Base
|
||||||
Friend MustInherit Class SiteSettingsBase : Implements ISiteSettings, IResponserContainer
|
Friend MustInherit Class SiteSettingsBase : Implements ISiteSettings, IResponserContainer
|
||||||
#Region "Declarations"
|
#Region "Declarations"
|
||||||
|
<PXML> Protected ReadOnly Property SettingsVersion As PropertyValue
|
||||||
Friend ReadOnly Property Site As String Implements ISiteSettings.Site
|
Friend ReadOnly Property Site As String Implements ISiteSettings.Site
|
||||||
Protected _Icon As Icon = Nothing
|
Protected _Icon As Icon = Nothing
|
||||||
Friend Overridable ReadOnly Property Icon As Icon Implements ISiteSettings.Icon
|
Friend Overridable ReadOnly Property Icon As Icon Implements ISiteSettings.Icon
|
||||||
@@ -32,7 +33,17 @@ Namespace API.Base
|
|||||||
End Property
|
End Property
|
||||||
Friend Property AccountName As String Implements ISiteSettings.AccountName
|
Friend Property AccountName As String Implements ISiteSettings.AccountName
|
||||||
Friend Property Temporary As Boolean = False Implements ISiteSettings.Temporary
|
Friend Property Temporary As Boolean = False Implements ISiteSettings.Temporary
|
||||||
Friend Property DefaultInstance As ISiteSettings = Nothing Implements ISiteSettings.DefaultInstance
|
Friend Overridable Property DefaultInstance As ISiteSettings = Nothing Implements ISiteSettings.DefaultInstance
|
||||||
|
Protected _UserAgentDefault As String = String.Empty
|
||||||
|
Friend Overridable Property UserAgentDefault As String Implements ISiteSettings.UserAgentDefault
|
||||||
|
Get
|
||||||
|
Return _UserAgentDefault
|
||||||
|
End Get
|
||||||
|
Set(ByVal _UserAgentDefault As String)
|
||||||
|
Me._UserAgentDefault = _UserAgentDefault
|
||||||
|
If _AllowUserAgentUpdate And Not Responser Is Nothing And Not _UserAgentDefault.IsEmptyString Then Responser.UserAgent = _UserAgentDefault
|
||||||
|
End Set
|
||||||
|
End Property
|
||||||
Protected _AllowUserAgentUpdate As Boolean = True
|
Protected _AllowUserAgentUpdate As Boolean = True
|
||||||
Protected _SubscriptionsAllowed As Boolean = False
|
Protected _SubscriptionsAllowed As Boolean = False
|
||||||
Friend ReadOnly Property SubscriptionsAllowed As Boolean Implements ISiteSettings.SubscriptionsAllowed
|
Friend ReadOnly Property SubscriptionsAllowed As Boolean Implements ISiteSettings.SubscriptionsAllowed
|
||||||
@@ -44,6 +55,11 @@ Namespace API.Base
|
|||||||
Friend Overridable ReadOnly Property Responser As Responser
|
Friend Overridable ReadOnly Property Responser As Responser
|
||||||
Private _UserOptionsExists As Boolean = False
|
Private _UserOptionsExists As Boolean = False
|
||||||
Private _UserOptionsType As Type = Nothing
|
Private _UserOptionsType As Type = Nothing
|
||||||
|
Protected Overridable Function UserOptionsValid(ByVal Options As Object) As Boolean
|
||||||
|
Return True
|
||||||
|
End Function
|
||||||
|
Protected Overridable Sub UserOptionsSetParameters(ByRef Options As Object)
|
||||||
|
End Sub
|
||||||
Protected Property UserOptionsType As Type
|
Protected Property UserOptionsType As Type
|
||||||
Get
|
Get
|
||||||
Return _UserOptionsType
|
Return _UserOptionsType
|
||||||
@@ -54,7 +70,14 @@ Namespace API.Base
|
|||||||
End Set
|
End Set
|
||||||
End Property
|
End Property
|
||||||
#End Region
|
#End Region
|
||||||
|
#Region "EnvironmentPrograms"
|
||||||
|
Private Property CMDEncoding As String Implements ISiteSettings.CMDEncoding
|
||||||
|
Private Property EnvironmentPrograms As IEnumerable(Of String) Implements ISiteSettings.EnvironmentPrograms
|
||||||
|
Private Sub EnvironmentProgramsUpdated() Implements ISiteSettings.EnvironmentProgramsUpdated
|
||||||
|
End Sub
|
||||||
|
#End Region
|
||||||
#Region "Responser and cookies support"
|
#Region "Responser and cookies support"
|
||||||
|
Friend Const ResponserFilePrefix As String = "Responser_"
|
||||||
Private _CookiesNetscapeFile As SFile = Nothing
|
Private _CookiesNetscapeFile As SFile = Nothing
|
||||||
Friend ReadOnly Property CookiesNetscapeFile As SFile
|
Friend ReadOnly Property CookiesNetscapeFile As SFile
|
||||||
Get
|
Get
|
||||||
@@ -85,7 +108,7 @@ Namespace API.Base
|
|||||||
End Property
|
End Property
|
||||||
Protected Sub UpdateResponserFile()
|
Protected Sub UpdateResponserFile()
|
||||||
Dim acc$ = If(AccountName.IsEmptyString OrElse AccountName = Hosts.SettingsHost.NameAccountNameDefault, String.Empty, $"_{AccountName}")
|
Dim acc$ = If(AccountName.IsEmptyString OrElse AccountName = Hosts.SettingsHost.NameAccountNameDefault, String.Empty, $"_{AccountName}")
|
||||||
Responser.File = $"{SettingsFolderName}\Responser_{Site}{acc}.xml"
|
Responser.File = $"{SettingsFolderName}\{ResponserFilePrefix}{Site}{acc}.xml"
|
||||||
_CookiesNetscapeFile = Responser.File
|
_CookiesNetscapeFile = Responser.File
|
||||||
_CookiesNetscapeFile.Name &= "_Cookies_Netscape"
|
_CookiesNetscapeFile.Name &= "_Cookies_Netscape"
|
||||||
_CookiesNetscapeFile.Extension = "txt"
|
_CookiesNetscapeFile.Extension = "txt"
|
||||||
@@ -100,6 +123,7 @@ Namespace API.Base
|
|||||||
_Icon = __Icon
|
_Icon = __Icon
|
||||||
_Image = __Image
|
_Image = __Image
|
||||||
Responser = New Responser With {.DeclaredError = EDP.ThrowException}
|
Responser = New Responser With {.DeclaredError = EDP.ThrowException}
|
||||||
|
SettingsVersion = New PropertyValue(0)
|
||||||
UpdateResponserFile()
|
UpdateResponserFile()
|
||||||
End Sub
|
End Sub
|
||||||
Friend Sub New(ByVal SiteName As String, ByVal CookiesDomain As String, ByVal AccName As String, ByVal Temp As Boolean,
|
Friend Sub New(ByVal SiteName As String, ByVal CookiesDomain As String, ByVal AccName As String, ByVal Temp As Boolean,
|
||||||
@@ -129,7 +153,6 @@ Namespace API.Base
|
|||||||
Friend Overridable Sub BeginInit() Implements ISiteSettings.BeginInit
|
Friend Overridable Sub BeginInit() Implements ISiteSettings.BeginInit
|
||||||
End Sub
|
End Sub
|
||||||
Friend Overridable Sub EndInit() Implements ISiteSettings.EndInit
|
Friend Overridable Sub EndInit() Implements ISiteSettings.EndInit
|
||||||
If _AllowUserAgentUpdate And Not DefaultUserAgent.IsEmptyString And Not Responser Is Nothing Then Responser.UserAgent = DefaultUserAgent
|
|
||||||
If CheckNetscapeCookiesOnEndInit Then Update_SaveCookiesNetscape(, True)
|
If CheckNetscapeCookiesOnEndInit Then Update_SaveCookiesNetscape(, True)
|
||||||
End Sub
|
End Sub
|
||||||
#End Region
|
#End Region
|
||||||
@@ -225,7 +248,7 @@ Namespace API.Base
|
|||||||
#Region "User info"
|
#Region "User info"
|
||||||
Protected UrlPatternUser As String = String.Empty
|
Protected UrlPatternUser As String = String.Empty
|
||||||
Friend Overridable Function GetUserUrl(ByVal User As IPluginContentProvider) As String Implements ISiteSettings.GetUserUrl
|
Friend Overridable Function GetUserUrl(ByVal User As IPluginContentProvider) As String Implements ISiteSettings.GetUserUrl
|
||||||
If Not UrlPatternUser.IsEmptyString Then Return String.Format(UrlPatternUser, User.Name)
|
If Not UrlPatternUser.IsEmptyString Then Return String.Format(UrlPatternUser, User.NameTrue.IfNullOrEmpty(User.Name))
|
||||||
Return String.Empty
|
Return String.Empty
|
||||||
End Function
|
End Function
|
||||||
Private Function ISiteSettings_GetUserPostUrl(ByVal User As IPluginContentProvider, ByVal Media As IUserMedia) As String Implements ISiteSettings.GetUserPostUrl
|
Private Function ISiteSettings_GetUserPostUrl(ByVal User As IPluginContentProvider, ByVal Media As IUserMedia) As String Implements ISiteSettings.GetUserPostUrl
|
||||||
@@ -362,11 +385,40 @@ Namespace API.Base
|
|||||||
End Sub
|
End Sub
|
||||||
Friend Overridable Sub UserOptions(ByRef Options As Object, ByVal OpenForm As Boolean) Implements ISiteSettings.UserOptions
|
Friend Overridable Sub UserOptions(ByRef Options As Object, ByVal OpenForm As Boolean) Implements ISiteSettings.UserOptions
|
||||||
If _UserOptionsExists Then
|
If _UserOptionsExists Then
|
||||||
If Options Is Nothing OrElse Not Options.GetType Is _UserOptionsType Then
|
If Options Is Nothing OrElse (Not Options.GetType Is _UserOptionsType OrElse Not UserOptionsValid(Options)) Then
|
||||||
Options = AConvert(Me, AModes.Var, _UserOptionsType,, True, Nothing)
|
Dim args% = 0
|
||||||
|
Dim constructor As ConstructorInfo = Nothing
|
||||||
|
With _UserOptionsType.GetTypeInfo.DeclaredConstructors
|
||||||
|
If .ListExists Then
|
||||||
|
With .Where(Function(ByVal c As ConstructorInfo) As Boolean
|
||||||
|
With c.GetParameters
|
||||||
|
If .ListExists Then
|
||||||
|
If .Count = 1 Then
|
||||||
|
Return .Self()(0).ParameterType.GetInterfaces.ListIfNothing.Where(Function(i) i Is Me.GetType).Count = 1
|
||||||
|
Else
|
||||||
|
Return False
|
||||||
|
End If
|
||||||
|
Else
|
||||||
|
Return True
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
Return If(c.GetParameters?.Count, 0).ValueBetween(0, 1)
|
||||||
|
End Function)
|
||||||
|
If .ListExists Then
|
||||||
|
args = .Max(Of Integer)(Function(c) If(c.GetParameters?.Count, 0))
|
||||||
|
constructor = .First(Function(c) If(c.GetParameters?.Count, 0) = args)
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
If Not constructor Is Nothing Then
|
||||||
|
If args > 0 AndAlso Not constructor.GetParameters()(0).ParameterType Is GetType(ISiteSettings) Then Throw New Exception
|
||||||
|
If args = 0 Then Options = constructor.Invoke(Nothing) Else Options = constructor.Invoke({Me})
|
||||||
|
End If
|
||||||
If Options Is Nothing Then Options = Activator.CreateInstance(_UserOptionsType)
|
If Options Is Nothing Then Options = Activator.CreateInstance(_UserOptionsType)
|
||||||
|
If Not Options Is Nothing Then UserOptionsSetParameters(Options)
|
||||||
End If
|
End If
|
||||||
If OpenForm Then
|
If Not Options Is Nothing And OpenForm Then
|
||||||
Using f As New InternalSettingsForm(Options, Me, False) : f.ShowDialog() : End Using
|
Using f As New InternalSettingsForm(Options, Me, False) : f.ShowDialog() : End Using
|
||||||
End If
|
End If
|
||||||
Else
|
Else
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ Imports PersonalUtilities.Tools.Web.Clients
|
|||||||
Imports PersonalUtilities.Tools.ImageRenderer
|
Imports PersonalUtilities.Tools.ImageRenderer
|
||||||
Imports UStates = SCrawler.API.Base.UserMedia.States
|
Imports UStates = SCrawler.API.Base.UserMedia.States
|
||||||
Imports UTypes = SCrawler.API.Base.UserMedia.Types
|
Imports UTypes = SCrawler.API.Base.UserMedia.Types
|
||||||
|
Imports CookieUpdateModes = PersonalUtilities.Tools.Web.Cookies.CookieKeeper.UpdateModes
|
||||||
Namespace API.Base
|
Namespace API.Base
|
||||||
Friend MustInherit Class UserDataBase : Implements IUserData, IPluginContentProvider, IThrower
|
Friend MustInherit Class UserDataBase : Implements IUserData, IPluginContentProvider, IThrower
|
||||||
Friend Const UserFileAppender As String = "User"
|
Friend Const UserFileAppender As String = "User"
|
||||||
@@ -79,6 +80,8 @@ Namespace API.Base
|
|||||||
Private _CollectionButtonsExists As Boolean = False
|
Private _CollectionButtonsExists As Boolean = False
|
||||||
Private _CollectionButtonsColorsSet As Boolean = False
|
Private _CollectionButtonsColorsSet As Boolean = False
|
||||||
Friend WithEvents BTT_CONTEXT_DOWN As ToolStripKeyMenuItem
|
Friend WithEvents BTT_CONTEXT_DOWN As ToolStripKeyMenuItem
|
||||||
|
Friend WithEvents BTT_CONTEXT_DOWN_LIMIT As ToolStripKeyMenuItem
|
||||||
|
Friend WithEvents BTT_CONTEXT_DOWN_DATE As ToolStripKeyMenuItem
|
||||||
Friend WithEvents BTT_CONTEXT_EDIT As ToolStripMenuItem
|
Friend WithEvents BTT_CONTEXT_EDIT As ToolStripMenuItem
|
||||||
Friend WithEvents BTT_CONTEXT_DELETE As ToolStripMenuItem
|
Friend WithEvents BTT_CONTEXT_DELETE As ToolStripMenuItem
|
||||||
Friend WithEvents BTT_CONTEXT_ERASE As ToolStripMenuItem
|
Friend WithEvents BTT_CONTEXT_ERASE As ToolStripMenuItem
|
||||||
@@ -97,6 +100,8 @@ Namespace API.Base
|
|||||||
End If
|
End If
|
||||||
End With
|
End With
|
||||||
BTT_CONTEXT_DOWN = New ToolStripKeyMenuItem(tn, i) With {.Name = tnn("DOWN"), .Tag = Me}
|
BTT_CONTEXT_DOWN = New ToolStripKeyMenuItem(tn, i) With {.Name = tnn("DOWN"), .Tag = Me}
|
||||||
|
BTT_CONTEXT_DOWN_LIMIT = New ToolStripKeyMenuItem(tn, i) With {.Name = tnn("DOWN_LIMIT"), .Tag = Me}
|
||||||
|
BTT_CONTEXT_DOWN_DATE = New ToolStripKeyMenuItem(tn, i) With {.Name = tnn("DOWN_DATE"), .Tag = Me}
|
||||||
BTT_CONTEXT_EDIT = New ToolStripMenuItem(tn, i) With {.Name = tnn("EDIT"), .Tag = Me}
|
BTT_CONTEXT_EDIT = New ToolStripMenuItem(tn, i) With {.Name = tnn("EDIT"), .Tag = Me}
|
||||||
BTT_CONTEXT_DELETE = New ToolStripMenuItem(tn, i) With {.Name = tnn("DELETE"), .Tag = Me}
|
BTT_CONTEXT_DELETE = New ToolStripMenuItem(tn, i) With {.Name = tnn("DELETE"), .Tag = Me}
|
||||||
BTT_CONTEXT_ERASE = New ToolStripMenuItem(tn, i) With {.Name = tnn("ERASE"), .Tag = Me}
|
BTT_CONTEXT_ERASE = New ToolStripMenuItem(tn, i) With {.Name = tnn("ERASE"), .Tag = Me}
|
||||||
@@ -116,7 +121,8 @@ Namespace API.Base
|
|||||||
cb = MyColor.EditBack
|
cb = MyColor.EditBack
|
||||||
cf = MyColor.EditFore
|
cf = MyColor.EditFore
|
||||||
End If
|
End If
|
||||||
For Each b As ToolStripMenuItem In {BTT_CONTEXT_DOWN, BTT_CONTEXT_EDIT, BTT_CONTEXT_DELETE, BTT_CONTEXT_ERASE,
|
For Each b As ToolStripMenuItem In {BTT_CONTEXT_DOWN, BTT_CONTEXT_DOWN_LIMIT, BTT_CONTEXT_DOWN_DATE,
|
||||||
|
BTT_CONTEXT_EDIT, BTT_CONTEXT_DELETE, BTT_CONTEXT_ERASE,
|
||||||
BTT_CONTEXT_OPEN_PATH, BTT_CONTEXT_OPEN_SITE}
|
BTT_CONTEXT_OPEN_PATH, BTT_CONTEXT_OPEN_SITE}
|
||||||
If Not b Is Nothing Then b.BackColor = cb : b.ForeColor = cf
|
If Not b Is Nothing Then b.BackColor = cb : b.ForeColor = cf
|
||||||
Next
|
Next
|
||||||
@@ -142,7 +148,7 @@ Namespace API.Base
|
|||||||
Protected Const Name_UserID As String = "UserID"
|
Protected Const Name_UserID As String = "UserID"
|
||||||
Protected Const Name_Options As String = "Options"
|
Protected Const Name_Options As String = "Options"
|
||||||
Protected Const Name_Description As String = "Description"
|
Protected Const Name_Description As String = "Description"
|
||||||
Private Const Name_ParseUserMediaOnly As String = "ParseUserMediaOnly"
|
Protected Const Name_ParseUserMediaOnly As String = "ParseUserMediaOnly"
|
||||||
Private Const Name_IsSubscription As String = UserInfo.Name_IsSubscription
|
Private Const Name_IsSubscription As String = UserInfo.Name_IsSubscription
|
||||||
Private Const Name_Temporary As String = "Temporary"
|
Private Const Name_Temporary As String = "Temporary"
|
||||||
Private Const Name_Favorite As String = "Favorite"
|
Private Const Name_Favorite As String = "Favorite"
|
||||||
@@ -172,6 +178,8 @@ Namespace API.Base
|
|||||||
#Region "Additional names"
|
#Region "Additional names"
|
||||||
Protected Const Name_SiteMode As String = "SiteMode"
|
Protected Const Name_SiteMode As String = "SiteMode"
|
||||||
Protected Const Name_TrueName As String = "TrueName"
|
Protected Const Name_TrueName As String = "TrueName"
|
||||||
|
'TODELETE Name_TrueName2
|
||||||
|
<Obsolete> Protected Const Name_TrueName2 As String = "NameTrue"
|
||||||
Protected Const Name_Arguments As String = "Arguments"
|
Protected Const Name_Arguments As String = "Arguments"
|
||||||
#End Region
|
#End Region
|
||||||
#End Region
|
#End Region
|
||||||
@@ -205,7 +213,7 @@ Namespace API.Base
|
|||||||
If Not h Is Nothing Then _HostKey = h.Key
|
If Not h Is Nothing Then _HostKey = h.Key
|
||||||
End Set
|
End Set
|
||||||
End Property
|
End Property
|
||||||
Private Sub ResetHost()
|
Friend Sub ResetHost()
|
||||||
_HostObtained = False
|
_HostObtained = False
|
||||||
End Sub
|
End Sub
|
||||||
Friend Property HostStatic As Boolean = False Implements IUserData.HostStatic
|
Friend Property HostStatic As Boolean = False Implements IUserData.HostStatic
|
||||||
@@ -272,6 +280,21 @@ Namespace API.Base
|
|||||||
Return User.Name
|
Return User.Name
|
||||||
End Get
|
End Get
|
||||||
End Property
|
End Property
|
||||||
|
Private _NameTrue As String = String.Empty
|
||||||
|
Friend Overridable Overloads Property NameTrue As String Implements IUserData.NameTrue, IPluginContentProvider.NameTrue
|
||||||
|
Get
|
||||||
|
Return NameTrue(False)
|
||||||
|
End Get
|
||||||
|
Set(ByVal NewName As String)
|
||||||
|
If Not _NameTrue = NewName Then EnvirChanged(NewName)
|
||||||
|
_NameTrue = NewName
|
||||||
|
End Set
|
||||||
|
End Property
|
||||||
|
Friend Overloads ReadOnly Property NameTrue(ByVal Exact As Boolean) As String
|
||||||
|
Get
|
||||||
|
Return If(Exact, _NameTrue, _NameTrue.IfNullOrEmpty(Name))
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
Friend Overridable Property ID As String = String.Empty Implements IUserData.ID, IPluginContentProvider.ID
|
Friend Overridable Property ID As String = String.Empty Implements IUserData.ID, IPluginContentProvider.ID
|
||||||
Protected _FriendlyName As String = String.Empty
|
Protected _FriendlyName As String = String.Empty
|
||||||
Friend Overridable Property FriendlyName As String Implements IUserData.FriendlyName
|
Friend Overridable Property FriendlyName As String Implements IUserData.FriendlyName
|
||||||
@@ -311,7 +334,7 @@ Namespace API.Base
|
|||||||
End Set
|
End Set
|
||||||
End Property
|
End Property
|
||||||
Protected Sub UserSiteNameUpdate(ByVal NewName As String)
|
Protected Sub UserSiteNameUpdate(ByVal NewName As String)
|
||||||
If Not NewName.IsEmptyString And (UserSiteName.IsEmptyString Or Settings.UserSiteNameUpdateEveryTime) Then UserSiteName = NewName
|
If Not NewName.IsEmptyString And (UserSiteName.IsEmptyString Or Settings.UpdateUserSiteNameEveryTime) Then UserSiteName = NewName
|
||||||
End Sub
|
End Sub
|
||||||
Friend ReadOnly Property UserModel As UsageModel Implements IUserData.UserModel
|
Friend ReadOnly Property UserModel As UsageModel Implements IUserData.UserModel
|
||||||
Get
|
Get
|
||||||
@@ -342,12 +365,20 @@ Namespace API.Base
|
|||||||
Protected Function UserDescriptionNeedToUpdate() As Boolean
|
Protected Function UserDescriptionNeedToUpdate() As Boolean
|
||||||
Return (UserDescription.IsEmptyString Or _DescriptionEveryTime) And Not _DescriptionChecked
|
Return (UserDescription.IsEmptyString Or _DescriptionEveryTime) And Not _DescriptionChecked
|
||||||
End Function
|
End Function
|
||||||
Protected Sub UserDescriptionUpdate(ByVal Descr As String)
|
Protected Sub UserDescriptionUpdate(ByVal Descr As String, Optional ByVal Force As Boolean = False,
|
||||||
If UserDescriptionNeedToUpdate() Then
|
Optional ByVal InsertFirst As Boolean = False, Optional ByVal AppendDate As Boolean = False)
|
||||||
|
If UserDescriptionNeedToUpdate() Or Force Then
|
||||||
|
If AppendDate Then Descr = $"{Now.ToStringDateDef}: {Descr}"
|
||||||
If UserDescription.IsEmptyString Then
|
If UserDescription.IsEmptyString Then
|
||||||
UserDescription = Descr
|
UserDescription = Descr
|
||||||
|
_ForceSaveUserInfo = True
|
||||||
ElseIf Not UserDescription.Contains(Descr) Then
|
ElseIf Not UserDescription.Contains(Descr) Then
|
||||||
UserDescription &= $"{vbNewLine}----{vbNewLine}{Descr}"
|
If InsertFirst Then
|
||||||
|
UserDescription = $"{Descr}{vbNewLine}{UserDescription}"
|
||||||
|
Else
|
||||||
|
UserDescription &= $"{vbNewLine}----{vbNewLine}{Descr}"
|
||||||
|
End If
|
||||||
|
_ForceSaveUserInfo = True
|
||||||
End If
|
End If
|
||||||
_DescriptionChecked = True
|
_DescriptionChecked = True
|
||||||
End If
|
End If
|
||||||
@@ -409,9 +440,7 @@ Namespace API.Base
|
|||||||
End Function
|
End Function
|
||||||
Friend Overridable Sub SetPicture(ByVal f As SFile) Implements IUserData.SetPicture
|
Friend Overridable Sub SetPicture(ByVal f As SFile) Implements IUserData.SetPicture
|
||||||
Try
|
Try
|
||||||
If f.Exists Then
|
If f.Exists Then UserImage.NewUserPicture(f, MyFile)
|
||||||
Using p As New UserImage(f, MyFile) : p.Save() : End Using
|
|
||||||
End If
|
|
||||||
Catch
|
Catch
|
||||||
End Try
|
End Try
|
||||||
End Sub
|
End Sub
|
||||||
@@ -450,11 +479,7 @@ BlockPictureScan:
|
|||||||
New ErrorsDescriber(EDP.ReturnValue) With {
|
New ErrorsDescriber(EDP.ReturnValue) With {
|
||||||
.ReturnValue = New List(Of SFile),
|
.ReturnValue = New List(Of SFile),
|
||||||
.ReturnValueExists = True}).FirstOrDefault
|
.ReturnValueExists = True}).FirstOrDefault
|
||||||
If NewPicFile.Exists Then
|
If NewPicFile.Exists Then p = UserImage.NewUserPicture(NewPicFile, MyFile,, True) : GoTo BlockReturn
|
||||||
p = New UserImage(NewPicFile, MyFile)
|
|
||||||
p.Save()
|
|
||||||
GoTo BlockReturn
|
|
||||||
End If
|
|
||||||
BlockDeletePictureFolder:
|
BlockDeletePictureFolder:
|
||||||
On Error GoTo BlockReturn
|
On Error GoTo BlockReturn
|
||||||
If DelPath Then
|
If DelPath Then
|
||||||
@@ -653,6 +678,7 @@ BlockNullPicture:
|
|||||||
End Sub
|
End Sub
|
||||||
Protected ReadOnly _TempMediaList As List(Of UserMedia)
|
Protected ReadOnly _TempMediaList As List(Of UserMedia)
|
||||||
Protected ReadOnly _TempPostsList As List(Of String)
|
Protected ReadOnly _TempPostsList As List(Of String)
|
||||||
|
Private ReadOnly _MD5List As List(Of String)
|
||||||
Friend Function GetLastImageAddress() As SFile
|
Friend Function GetLastImageAddress() As SFile
|
||||||
If _ContentList.Count > 0 Then
|
If _ContentList.Count > 0 Then
|
||||||
Return _ContentList.LastOrDefault(Function(c) c.Type = UTypes.Picture And Not c.File.IsEmptyString And Not c.File.Extension = "gif").File
|
Return _ContentList.LastOrDefault(Function(c) c.Type = UTypes.Picture And Not c.File.IsEmptyString And Not c.File.Extension = "gif").File
|
||||||
@@ -678,6 +704,7 @@ BlockNullPicture:
|
|||||||
Protected MyFileSettings As SFile
|
Protected MyFileSettings As SFile
|
||||||
Protected MyFileData As SFile
|
Protected MyFileData As SFile
|
||||||
Protected MyFilePosts As SFile
|
Protected MyFilePosts As SFile
|
||||||
|
Private MyMD5File As SFile
|
||||||
Friend Overridable Property FileExists As Boolean = False Implements IUserData.FileExists
|
Friend Overridable Property FileExists As Boolean = False Implements IUserData.FileExists
|
||||||
Friend Overridable Property DataMerging As Boolean
|
Friend Overridable Property DataMerging As Boolean
|
||||||
Get
|
Get
|
||||||
@@ -828,48 +855,19 @@ BlockNullPicture:
|
|||||||
Return ListImagesLoader.ApplyLVIColor(Me, New ListViewItem(ToString(), GetLVIGroup(Destination)) With {.Name = LVIKey, .Tag = LVIKey}, True)
|
Return ListImagesLoader.ApplyLVIColor(Me, New ListViewItem(ToString(), GetLVIGroup(Destination)) With {.Name = LVIKey, .Tag = LVIKey}, True)
|
||||||
End If
|
End If
|
||||||
End Function
|
End Function
|
||||||
Friend Overridable ReadOnly Property FitToAddParams As Boolean Implements IUserData.FitToAddParams
|
|
||||||
Get
|
|
||||||
With Settings
|
|
||||||
If IsSubscription And Not .MainFrameUsersShowSubscriptions Then Return False
|
|
||||||
If Not IsSubscription And Not .MainFrameUsersShowDefaults Then Return False
|
|
||||||
If LastUpdated.HasValue And Not .ViewDateMode.Value = ShowingDates.Off Then
|
|
||||||
Dim f As Date = If(.ViewDateFrom.HasValue, .ViewDateFrom.Value.Date, Date.MinValue.Date)
|
|
||||||
Dim t As Date = If(.ViewDateTo.HasValue, .ViewDateTo.Value.Date, Date.MaxValue.Date)
|
|
||||||
Select Case DirectCast(.ViewDateMode.Value, ShowingDates)
|
|
||||||
Case ShowingDates.In : If Not LastUpdated.Value.ValueBetween(f, t) Then Return False
|
|
||||||
Case ShowingDates.Not : If LastUpdated.Value.ValueBetween(f, t) Then Return False
|
|
||||||
End Select
|
|
||||||
End If
|
|
||||||
If Not .Labels.ExcludedIgnore AndAlso .Labels.Excluded.ValuesList.ListContains(Labels) Then Return False
|
|
||||||
If .SelectedSites.Count = 0 OrElse .SelectedSites.Contains(Site) Then
|
|
||||||
Select Case .ShowingMode.Value
|
|
||||||
Case ShowingModes.Regular : Return Not Temporary And Not Favorite
|
|
||||||
Case ShowingModes.Temporary : Return Temporary
|
|
||||||
Case ShowingModes.Favorite : Return Favorite
|
|
||||||
Case ShowingModes.Deleted : Return Not UserExists
|
|
||||||
Case ShowingModes.Suspended : Return UserSuspended
|
|
||||||
Case ShowingModes.Labels : Return Settings.Labels.Current.ValuesList.ListContains(Labels)
|
|
||||||
Case ShowingModes.NoLabels : Return Labels.Count = 0
|
|
||||||
Case Else : Return True
|
|
||||||
End Select
|
|
||||||
Else
|
|
||||||
Return False
|
|
||||||
End If
|
|
||||||
End With
|
|
||||||
End Get
|
|
||||||
End Property
|
|
||||||
Friend Function GetLVIGroup(ByVal Destination As ListView) As ListViewGroup Implements IUserData.GetLVIGroup
|
Friend Function GetLVIGroup(ByVal Destination As ListView) As ListViewGroup Implements IUserData.GetLVIGroup
|
||||||
Try
|
Try
|
||||||
If Settings.ShowingMode.Value = ShowingModes.Labels And Not Settings.ShowGroupsInsteadLabels Then
|
With Settings
|
||||||
If Labels.Count > 0 And Settings.Labels.Current.Count > 0 Then
|
If Not .ShowAllUsers.Value AndAlso (.AdvancedFilter.Labels.Count > 0 Or .AdvancedFilter.LabelsNo) AndAlso Not .ShowGroupsInsteadLabels Then
|
||||||
For i% = 0 To Labels.Count - 1
|
If Labels.Count > 0 And .AdvancedFilter.Labels.Count > 0 Then
|
||||||
If Settings.Labels.Current.Contains(Labels(i)) Then Return Destination.Groups.Item(Labels(i))
|
For i% = 0 To Labels.Count - 1
|
||||||
Next
|
If .AdvancedFilter.Labels.Contains(Labels(i)) Then Return Destination.Groups.Item(Labels(i))
|
||||||
|
Next
|
||||||
|
End If
|
||||||
|
ElseIf Settings.GroupUsers Then
|
||||||
|
Return Destination.Groups.Item(GetLviGroupName(HOST, Temporary, Favorite, IsCollection))
|
||||||
End If
|
End If
|
||||||
ElseIf Settings.ShowGroups Then
|
End With
|
||||||
Return Destination.Groups.Item(GetLviGroupName(HOST, Temporary, Favorite, IsCollection))
|
|
||||||
End If
|
|
||||||
Return Destination.Groups.Item(LabelsKeeper.NoLabeledName)
|
Return Destination.Groups.Item(LabelsKeeper.NoLabeledName)
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
Return Destination.Groups.Item(LabelsKeeper.NoLabeledName)
|
Return Destination.Groups.Item(LabelsKeeper.NoLabeledName)
|
||||||
@@ -884,6 +882,7 @@ BlockNullPicture:
|
|||||||
LatestData = New List(Of UserMedia)
|
LatestData = New List(Of UserMedia)
|
||||||
_TempMediaList = New List(Of UserMedia)
|
_TempMediaList = New List(Of UserMedia)
|
||||||
_TempPostsList = New List(Of String)
|
_TempPostsList = New List(Of String)
|
||||||
|
_MD5List = New List(Of String)
|
||||||
Labels = New List(Of String)
|
Labels = New List(Of String)
|
||||||
UserUpdatedEventHandlers = New List(Of IUserData.UserUpdatedEventHandler)
|
UserUpdatedEventHandlers = New List(Of IUserData.UserUpdatedEventHandler)
|
||||||
UserDownloadStateChangedEventHandlers = New List(Of UserDownloadStateChangedEventHandler)
|
UserDownloadStateChangedEventHandlers = New List(Of UserDownloadStateChangedEventHandler)
|
||||||
@@ -933,6 +932,10 @@ BlockNullPicture:
|
|||||||
FileExists = True
|
FileExists = True
|
||||||
Using x As New XmlFile(MyFileSettings) With {.XmlReadOnly = True}
|
Using x As New XmlFile(MyFileSettings) With {.XmlReadOnly = True}
|
||||||
If User.Name.IsEmptyString Then User.Name = x.Value(Name_UserName)
|
If User.Name.IsEmptyString Then User.Name = x.Value(Name_UserName)
|
||||||
|
_NameTrue = x.Value(Name_TrueName)
|
||||||
|
#Disable Warning BC40008
|
||||||
|
If _NameTrue.IsEmptyString AndAlso x.Contains(Name_TrueName2) Then _NameTrue = x.Value(Name_TrueName2)
|
||||||
|
#Enable Warning
|
||||||
UserExists = x.Value(Name_UserExists).FromXML(Of Boolean)(True)
|
UserExists = x.Value(Name_UserExists).FromXML(Of Boolean)(True)
|
||||||
UserSuspended = x.Value(Name_UserSuspended).FromXML(Of Boolean)(False)
|
UserSuspended = x.Value(Name_UserSuspended).FromXML(Of Boolean)(False)
|
||||||
ID = x.Value(Name_UserID)
|
ID = x.Value(Name_UserID)
|
||||||
@@ -978,7 +981,13 @@ BlockNullPicture:
|
|||||||
LogError(ex, "user information loading error")
|
LogError(ex, "user information loading error")
|
||||||
End Try
|
End Try
|
||||||
End Sub
|
End Sub
|
||||||
Friend Overridable Sub UpdateUserInformation() Implements IUserData.UpdateUserInformation
|
Private Sub UpdateUserInformation_Ex()
|
||||||
|
If _ForceSaveUserInfoOnException Then UpdateUserInformation()
|
||||||
|
End Sub
|
||||||
|
Friend Overridable Overloads Sub UpdateUserInformation() Implements IUserData.UpdateUserInformation
|
||||||
|
UpdateUserInformation(False)
|
||||||
|
End Sub
|
||||||
|
Friend Overridable Overloads Sub UpdateUserInformation(ByVal DisableUserInfoUpdate As Boolean)
|
||||||
Try
|
Try
|
||||||
UpdateDataFiles()
|
UpdateDataFiles()
|
||||||
MyFileSettings.Exists(SFO.Path)
|
MyFileSettings.Exists(SFO.Path)
|
||||||
@@ -987,6 +996,7 @@ BlockNullPicture:
|
|||||||
x.Add(Name_Plugin, HOST.Key)
|
x.Add(Name_Plugin, HOST.Key)
|
||||||
x.Add(Name_AccountName, AccountName)
|
x.Add(Name_AccountName, AccountName)
|
||||||
x.Add(Name_UserName, User.Name)
|
x.Add(Name_UserName, User.Name)
|
||||||
|
x.Add(Name_TrueName, _NameTrue)
|
||||||
x.Add(Name_Model_User, CInt(UserModel))
|
x.Add(Name_Model_User, CInt(UserModel))
|
||||||
x.Add(Name_Model_Collection, CInt(CollectionModel))
|
x.Add(Name_Model_Collection, CInt(CollectionModel))
|
||||||
x.Add(Name_SpecialPath, User.SpecialPath)
|
x.Add(Name_SpecialPath, User.SpecialPath)
|
||||||
@@ -1029,7 +1039,7 @@ BlockNullPicture:
|
|||||||
|
|
||||||
x.Save(MyFileSettings)
|
x.Save(MyFileSettings)
|
||||||
End Using
|
End Using
|
||||||
If Not IsSavedPosts Then Settings.UpdateUsersList(User)
|
If Not IsSavedPosts And Not DisableUserInfoUpdate Then Settings.UpdateUsersList(User, True)
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
LogError(ex, "user information saving error")
|
LogError(ex, "user information saving error")
|
||||||
End Try
|
End Try
|
||||||
@@ -1062,6 +1072,8 @@ BlockNullPicture:
|
|||||||
If _ContentList.Count > 0 Then x.AddRange(_ContentList)
|
If _ContentList.Count > 0 Then x.AddRange(_ContentList)
|
||||||
x.Save(MyFileData)
|
x.Save(MyFileData)
|
||||||
End Using
|
End Using
|
||||||
|
If Not MyMD5File.IsEmptyString And _MD5List.Count > 0 Then _
|
||||||
|
TextSaver.SaveTextToFile(_MD5List.ListToString(Environment.NewLine), MyMD5File, True,, EDP.None)
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
LogError(ex, "history saving error")
|
LogError(ex, "history saving error")
|
||||||
End Try
|
End Try
|
||||||
@@ -1143,6 +1155,7 @@ BlockNullPicture:
|
|||||||
Protected UseClientTokens As Boolean = False
|
Protected UseClientTokens As Boolean = False
|
||||||
Protected _ForceSaveUserData As Boolean = False
|
Protected _ForceSaveUserData As Boolean = False
|
||||||
Protected _ForceSaveUserInfo As Boolean = False
|
Protected _ForceSaveUserInfo As Boolean = False
|
||||||
|
Protected _ForceSaveUserInfoOnException As Boolean = False
|
||||||
Private _DownloadInProgress As Boolean = False
|
Private _DownloadInProgress As Boolean = False
|
||||||
Private _EnvirUserExists As Boolean
|
Private _EnvirUserExists As Boolean
|
||||||
Private _EnvirUserSuspended As Boolean
|
Private _EnvirUserSuspended As Boolean
|
||||||
@@ -1150,15 +1163,19 @@ BlockNullPicture:
|
|||||||
Private _EnvirChanged As Boolean = False
|
Private _EnvirChanged As Boolean = False
|
||||||
Private _PictureExists As Boolean
|
Private _PictureExists As Boolean
|
||||||
Private _EnvirInvokeUserUpdated As Boolean = False
|
Private _EnvirInvokeUserUpdated As Boolean = False
|
||||||
|
Protected _ResponserAutoUpdateCookies As Boolean = False
|
||||||
|
Protected _ResponserAddResponseReceivedHandler As Boolean = False
|
||||||
Protected Sub EnvirDownloadSet()
|
Protected Sub EnvirDownloadSet()
|
||||||
TokenPersonal = Nothing
|
TokenPersonal = Nothing
|
||||||
ProgressPre.Reset()
|
ProgressPre.Reset()
|
||||||
UpdateDataFiles()
|
UpdateDataFiles()
|
||||||
|
_MD5Loaded = False
|
||||||
_DownloadInProgress = True
|
_DownloadInProgress = True
|
||||||
_DescriptionChecked = False
|
_DescriptionChecked = False
|
||||||
_DescriptionEveryTime = Settings.UpdateUserDescriptionEveryTime
|
_DescriptionEveryTime = Settings.UpdateUserDescriptionEveryTime
|
||||||
_ForceSaveUserData = False
|
_ForceSaveUserData = False
|
||||||
_ForceSaveUserInfo = False
|
_ForceSaveUserInfo = False
|
||||||
|
_ForceSaveUserInfoOnException = False
|
||||||
_EnvirUserExists = UserExists
|
_EnvirUserExists = UserExists
|
||||||
_EnvirUserSuspended = UserSuspended
|
_EnvirUserSuspended = UserSuspended
|
||||||
_EnvirCreatedByChannel = CreatedByChannel
|
_EnvirCreatedByChannel = CreatedByChannel
|
||||||
@@ -1175,6 +1192,7 @@ BlockNullPicture:
|
|||||||
Select Case Caller
|
Select Case Caller
|
||||||
Case NameOf(UserExists) : If Not _EnvirUserExists = CBool(NewValue) Then _EnvirChanged = True : _EnvirInvokeUserUpdated = True
|
Case NameOf(UserExists) : If Not _EnvirUserExists = CBool(NewValue) Then _EnvirChanged = True : _EnvirInvokeUserUpdated = True
|
||||||
Case NameOf(UserSuspended) : If Not _EnvirUserSuspended = CBool(NewValue) Then _EnvirChanged = True : _EnvirInvokeUserUpdated = True
|
Case NameOf(UserSuspended) : If Not _EnvirUserSuspended = CBool(NewValue) Then _EnvirChanged = True : _EnvirInvokeUserUpdated = True
|
||||||
|
Case NameOf(NameTrue) : _EnvirChanged = True : _EnvirInvokeUserUpdated = True : _ForceSaveUserInfo = True : _ForceSaveUserInfoOnException = True
|
||||||
Case Else : _EnvirChanged = True
|
Case Else : _EnvirChanged = True
|
||||||
End Select
|
End Select
|
||||||
End If
|
End If
|
||||||
@@ -1191,7 +1209,14 @@ BlockNullPicture:
|
|||||||
If Not Responser Is Nothing Then Responser.Dispose()
|
If Not Responser Is Nothing Then Responser.Dispose()
|
||||||
Responser = New Responser
|
Responser = New Responser
|
||||||
If Not HOST.Responser Is Nothing Then Responser.Copy(HOST.Responser)
|
If Not HOST.Responser Is Nothing Then Responser.Copy(HOST.Responser)
|
||||||
|
If Not Responser Is Nothing And (_ResponserAutoUpdateCookies Or _ResponserAddResponseReceivedHandler) Then
|
||||||
|
If _ResponserAutoUpdateCookies Then
|
||||||
|
Responser.CookiesUpdateMode = CookieUpdateModes.ReplaceByNameAll
|
||||||
|
Responser.CookiesExtractMode = Responser.CookiesExtractModes.Any
|
||||||
|
Responser.CookiesExtractedAutoSave = False
|
||||||
|
End If
|
||||||
|
If _ResponserAddResponseReceivedHandler Then AddHandler Responser.ResponseReceived, AddressOf Responser_ResponseReceived
|
||||||
|
End If
|
||||||
Responser.DecodersError = New ErrorsDescriber(EDP.SendToLog + EDP.ReturnValue) With {
|
Responser.DecodersError = New ErrorsDescriber(EDP.SendToLog + EDP.ReturnValue) With {
|
||||||
.DeclaredMessage = New MMessage($"SymbolsConverter error: [{ToStringForLog()}]", ToStringForLog())}
|
.DeclaredMessage = New MMessage($"SymbolsConverter error: [{ToStringForLog()}]", ToStringForLog())}
|
||||||
|
|
||||||
@@ -1228,7 +1253,7 @@ BlockNullPicture:
|
|||||||
ProgressPre.Done()
|
ProgressPre.Done()
|
||||||
ThrowAny(Token)
|
ThrowAny(Token)
|
||||||
|
|
||||||
If UseMD5Comparison And Not IsSubscription Then ValidateMD5(Token) : ProgressPre.Done() : ThrowAny(Token)
|
If RemoveExistingDuplicates And Not IsSubscription Then ValidateMD5(Token) : ProgressPre.Done() : ThrowAny(Token)
|
||||||
|
|
||||||
If _TempPostsList.Count > 0 And Not DownloadMissingOnly And Not __isChannelsSupport Then
|
If _TempPostsList.Count > 0 And Not DownloadMissingOnly And Not __isChannelsSupport Then
|
||||||
If _TempPostsList.Count > 1000 Then _TempPostsList.ListAddList(_TempPostsList.ListTake(-2, 1000, EDP.ReturnValue).ListReverse, LAP.ClearBeforeAdd)
|
If _TempPostsList.Count > 1000 Then _TempPostsList.ListAddList(_TempPostsList.ListTake(-2, 1000, EDP.ReturnValue).ListReverse, LAP.ClearBeforeAdd)
|
||||||
@@ -1259,8 +1284,10 @@ BlockNullPicture:
|
|||||||
Dim mca& = If(ContentMissingExists, _ContentList.LongCount(Function(c) MissingFinder(c)), 0)
|
Dim mca& = If(ContentMissingExists, _ContentList.LongCount(Function(c) MissingFinder(c)), 0)
|
||||||
If DownloadedTotal(False) > 0 Or _EnvirChanged Or Not mcb = mca Or _ForceSaveUserData Then
|
If DownloadedTotal(False) > 0 Or _EnvirChanged Or Not mcb = mca Or _ForceSaveUserData Then
|
||||||
If Not __isChannelsSupport Then
|
If Not __isChannelsSupport Then
|
||||||
LastUpdated = Now
|
If DownloadedTotal(False) > 0 Then
|
||||||
RunScript()
|
LastUpdated = Now
|
||||||
|
RunScript()
|
||||||
|
End If
|
||||||
DownloadedPictures(True) = SFile.GetFiles(MyFile.CutPath, "*.jpg|*.jpeg|*.png|*.gif|*.webm",, EDP.ReturnValue).Count
|
DownloadedPictures(True) = SFile.GetFiles(MyFile.CutPath, "*.jpg|*.jpeg|*.png|*.gif|*.webm",, EDP.ReturnValue).Count
|
||||||
DownloadedVideos(True) = SFile.GetFiles(MyFile.CutPath, "*.mp4|*.mkv|*.mov", SearchOption.AllDirectories, EDP.ReturnValue).Count
|
DownloadedVideos(True) = SFile.GetFiles(MyFile.CutPath, "*.mp4|*.mkv|*.mov", SearchOption.AllDirectories, EDP.ReturnValue).Count
|
||||||
If Labels.Contains(LabelsKeeper.NoParsedUser) Then Labels.Remove(LabelsKeeper.NoParsedUser)
|
If Labels.Contains(LabelsKeeper.NoParsedUser) Then Labels.Remove(LabelsKeeper.NoParsedUser)
|
||||||
@@ -1279,21 +1306,26 @@ BlockNullPicture:
|
|||||||
ThrowIfDisposed()
|
ThrowIfDisposed()
|
||||||
If Not _PictureExists Or _EnvirInvokeUserUpdated Then OnUserUpdated()
|
If Not _PictureExists Or _EnvirInvokeUserUpdated Then OnUserUpdated()
|
||||||
Catch oex As OperationCanceledException When Token.IsCancellationRequested Or TokenPersonal.IsCancellationRequested Or TokenQueue.IsCancellationRequested
|
Catch oex As OperationCanceledException When Token.IsCancellationRequested Or TokenPersonal.IsCancellationRequested Or TokenQueue.IsCancellationRequested
|
||||||
|
UpdateUserInformation_Ex()
|
||||||
MyMainLOG = $"{ToStringForLog()}: downloading canceled"
|
MyMainLOG = $"{ToStringForLog()}: downloading canceled"
|
||||||
Canceled = True
|
Canceled = True
|
||||||
Catch exit_ex As ExitException
|
Catch exit_ex As ExitException
|
||||||
|
UpdateUserInformation_Ex()
|
||||||
If Not exit_ex.Silent Then
|
If Not exit_ex.Silent Then
|
||||||
If exit_ex.SimpleLogLine Then
|
If exit_ex.SimpleLogLine Then
|
||||||
MyMainLOG = $"{ToStringForLog()}: downloading canceled (exit) ({exit_ex.Message})"
|
LogError(Nothing, $"downloading interrupted (exit) ({exit_ex.Message})")
|
||||||
Else
|
Else
|
||||||
ErrorsDescriber.Execute(EDP.SendToLog, exit_ex, $"{ToStringForLog()}: downloading canceled (exit)")
|
LogError(exit_ex, "downloading interrupted (exit)")
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
|
If _EnvirInvokeUserUpdated Then OnUserUpdated()
|
||||||
Canceled = True
|
Canceled = True
|
||||||
Catch dex As ObjectDisposedException When Disposed
|
Catch dex As ObjectDisposedException When Disposed
|
||||||
Canceled = True
|
Canceled = True
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
|
UpdateUserInformation_Ex()
|
||||||
LogError(ex, "downloading data error")
|
LogError(ex, "downloading data error")
|
||||||
|
If _EnvirInvokeUserUpdated Then OnUserUpdated()
|
||||||
HasError = True
|
HasError = True
|
||||||
Finally
|
Finally
|
||||||
If Not UserExists Then AddNonExistingUserToLog($"User '{ToStringForLog()}' not found on the site")
|
If Not UserExists Then AddNonExistingUserToLog($"User '{ToStringForLog()}' not found on the site")
|
||||||
@@ -1311,6 +1343,7 @@ BlockNullPicture:
|
|||||||
ProgressPre.Done()
|
ProgressPre.Done()
|
||||||
__DOWNLOAD_IN_PROGRESS = False
|
__DOWNLOAD_IN_PROGRESS = False
|
||||||
OnUserDownloadStateChanged(False)
|
OnUserDownloadStateChanged(False)
|
||||||
|
If _ResponserAddResponseReceivedHandler Then Responser_ResponseReceived_RemoveHandler()
|
||||||
End Try
|
End Try
|
||||||
End Sub
|
End Sub
|
||||||
Protected Sub UpdateDataFiles()
|
Protected Sub UpdateDataFiles()
|
||||||
@@ -1328,11 +1361,23 @@ BlockNullPicture:
|
|||||||
MyFilePosts = MyFileSettings
|
MyFilePosts = MyFileSettings
|
||||||
MyFilePosts.Name &= "_Posts"
|
MyFilePosts.Name &= "_Posts"
|
||||||
MyFilePosts.Extension = "txt"
|
MyFilePosts.Extension = "txt"
|
||||||
|
If Not IsSavedPosts Then
|
||||||
|
MyMD5File = MyFileSettings
|
||||||
|
MyMD5File.Name &= "_MD5"
|
||||||
|
MyMD5File.Extension = "txt"
|
||||||
|
End If
|
||||||
Else
|
Else
|
||||||
Throw New ArgumentNullException("User.File", "User file not detected")
|
Throw New ArgumentNullException("User.File", "User file not detected")
|
||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
Protected MustOverride Sub DownloadDataF(ByVal Token As CancellationToken)
|
Protected MustOverride Sub DownloadDataF(ByVal Token As CancellationToken)
|
||||||
|
Protected Overridable Sub Responser_ResponseReceived(ByVal Sender As Object, ByVal e As EventArguments.WebDataResponse)
|
||||||
|
End Sub
|
||||||
|
Protected Sub Responser_ResponseReceived_RemoveHandler()
|
||||||
|
If Not Responser Is Nothing And _ResponserAddResponseReceivedHandler And Not Disposed Then
|
||||||
|
Try : RemoveHandler Responser.ResponseReceived, AddressOf Responser_ResponseReceived : Catch : End Try
|
||||||
|
End If
|
||||||
|
End Sub
|
||||||
Protected Function CreateCache() As CacheKeeper
|
Protected Function CreateCache() As CacheKeeper
|
||||||
Dim Cache As New CacheKeeper($"{DownloadContentDefault_GetRootDir()}\_tCache\")
|
Dim Cache As New CacheKeeper($"{DownloadContentDefault_GetRootDir()}\_tCache\")
|
||||||
Cache.CacheDeleteError = CacheDeletionError(Cache)
|
Cache.CacheDeleteError = CacheDeletionError(Cache)
|
||||||
@@ -1348,6 +1393,7 @@ BlockNullPicture:
|
|||||||
ResetHost()
|
ResetHost()
|
||||||
URL = Data.URL
|
URL = Data.URL
|
||||||
AccountName = Data.AccountName
|
AccountName = Data.AccountName
|
||||||
|
TokenQueue = Token
|
||||||
If HOST Is Nothing Then Throw New ExitException($"Host '{AccountName}' not found")
|
If HOST Is Nothing Then Throw New ExitException($"Host '{AccountName}' not found")
|
||||||
Data.DownloadState = UserMediaStates.Tried
|
Data.DownloadState = UserMediaStates.Tried
|
||||||
Progress = Data.Progress
|
Progress = Data.Progress
|
||||||
@@ -1391,21 +1437,26 @@ BlockNullPicture:
|
|||||||
If _ContentNew.Count > 0 Then
|
If _ContentNew.Count > 0 Then
|
||||||
If _ContentNew.Any(Function(mm) mm.State = UStates.Downloaded) Then
|
If _ContentNew.Any(Function(mm) mm.State = UStates.Downloaded) Then
|
||||||
Data.DownloadState = UserMediaStates.Downloaded
|
Data.DownloadState = UserMediaStates.Downloaded
|
||||||
|
Dim thumbAlong As Boolean = False
|
||||||
|
If TypeOf Data Is DownloadableMediaHost Then thumbAlong = DirectCast(Data, DownloadableMediaHost).ThumbAlong
|
||||||
If _ContentNew(0).Type = UTypes.Picture Or _ContentNew(0).Type = UTypes.GIF Then
|
If _ContentNew(0).Type = UTypes.Picture Or _ContentNew(0).Type = UTypes.GIF Then
|
||||||
DirectCast(Data, IDownloadableMedia).ThumbnailFile = _ContentNew(0).File
|
DirectCast(Data, IDownloadableMedia).ThumbnailFile = _ContentNew(0).File
|
||||||
ElseIf Settings.STDownloader_TakeSnapshot And Settings.FfmpegFile.Exists And Not Settings.STDownloader_RemoveDownloadedAutomatically Then
|
ElseIf Settings.STDownloader_TakeSnapshot And Settings.FfmpegFile.Exists And Not Settings.STDownloader_RemoveDownloadedAutomatically Then
|
||||||
Dim f As SFile = _ContentNew(0).File
|
Dim f As SFile = _ContentNew(0).File
|
||||||
Dim ff As SFile
|
Dim ff As SFile
|
||||||
If Settings.STDownloader_SnapshotsKeepWithFiles Then
|
If Settings.STDownloader_SnapshotsKeepWithFiles Or thumbAlong Then
|
||||||
ff = f
|
ff = f
|
||||||
Else
|
Else
|
||||||
ff = Settings.CacheSnapshots(Settings.STDownloader_SnapShotsCachePermamnent).NewFile
|
ff = Settings.CacheSnapshots(Settings.STDownloader_SnapShotsCachePermamnent).NewFile
|
||||||
End If
|
End If
|
||||||
ff.Name &= "_thumb"
|
ff.Name &= "_thumb"
|
||||||
ff.Extension = "jpg"
|
ff.Extension = "jpg"
|
||||||
f = Web.FFMPEG.TakeSnapshot(f, ff, Settings.FfmpegFile, TimeSpan.FromSeconds(1),,, EDP.LogMessageValue)
|
f = Web.FFMPEG.TakeSnapshot(f, ff, Settings.FfmpegFile, TimeSpan.FromSeconds(1),,, EDP.SendToLog + EDP.ReturnValue)
|
||||||
If f.Exists Then DirectCast(Data, IDownloadableMedia).ThumbnailFile = f
|
If f.Exists Then DirectCast(Data, IDownloadableMedia).ThumbnailFile = f
|
||||||
End If
|
End If
|
||||||
|
Dim filesSize# = (From mm As UserMedia In _ContentNew Where mm.State = UStates.Downloaded AndAlso mm.File.Exists Select mm.File.Size).Sum
|
||||||
|
If filesSize > 0 Then filesSize /= 1024
|
||||||
|
Data.Size = filesSize
|
||||||
Else
|
Else
|
||||||
Data.DownloadState = UserMediaStates.Missing
|
Data.DownloadState = UserMediaStates.Missing
|
||||||
End If
|
End If
|
||||||
@@ -1438,81 +1489,94 @@ BlockNullPicture:
|
|||||||
End Sub
|
End Sub
|
||||||
#End Region
|
#End Region
|
||||||
#Region "MD5 support"
|
#Region "MD5 support"
|
||||||
Protected Const VALIDATE_MD5_ERROR As String = "VALIDATE_MD5_ERROR"
|
Private Const VALIDATE_MD5_ERROR As String = "VALIDATE_MD5_ERROR"
|
||||||
Friend Property UseMD5Comparison As Boolean = False
|
Friend Property UseMD5Comparison As Boolean = False
|
||||||
Protected Property StartMD5Checked As Boolean = False
|
Protected Property StartMD5Checked As Boolean = False
|
||||||
Friend Property RemoveExistingDuplicates As Boolean = False
|
Friend Property RemoveExistingDuplicates As Boolean = False
|
||||||
Protected Overridable Sub ValidateMD5(ByVal Token As CancellationToken)
|
Private ReadOnly ErrMD5 As New ErrorsDescriber(EDP.ReturnValue)
|
||||||
|
Private _MD5Loaded As Boolean = False
|
||||||
|
Private Sub LoadMD5()
|
||||||
|
Try
|
||||||
|
If Not _MD5Loaded Then
|
||||||
|
_MD5Loaded = True
|
||||||
|
_MD5List.Clear()
|
||||||
|
If _ContentList.Count > 0 Then _MD5List.ListAddList(_ContentList.Select(Function(c) c.MD5), LAP.NotContainsOnly, EDP.ReturnValue)
|
||||||
|
If MyMD5File.Exists Then _MD5List.ListAddList(MyMD5File.GetLines, LAP.NotContainsOnly, EDP.ThrowException)
|
||||||
|
End If
|
||||||
|
Catch ex As Exception
|
||||||
|
ErrorsDescriber.Execute(EDP.SendToLog, ex, "LoadMD5")
|
||||||
|
End Try
|
||||||
|
End Sub
|
||||||
|
Private Function ValidateMD5_GetMD5(ByVal __data As UserMedia, ByVal IsUrl As Boolean) As String
|
||||||
|
Try
|
||||||
|
Dim ImgFormat As Imaging.ImageFormat = Nothing
|
||||||
|
Dim hash$ = String.Empty
|
||||||
|
Dim __isGif As Boolean = False
|
||||||
|
If __data.Type = UTypes.GIF Then
|
||||||
|
ImgFormat = Imaging.ImageFormat.Gif
|
||||||
|
__isGif = True
|
||||||
|
ElseIf Not __data.File.IsEmptyString Then
|
||||||
|
ImgFormat = GetImageFormat(__data.File)
|
||||||
|
End If
|
||||||
|
If ImgFormat Is Nothing Then ImgFormat = Imaging.ImageFormat.Jpeg
|
||||||
|
If IsUrl And Not __isGif Then
|
||||||
|
hash = ByteArrayToString(GetMD5(SFile.GetBytesFromNet(__data.URL.IfNullOrEmpty(__data.URL_BASE), ErrMD5), ImgFormat, ErrMD5))
|
||||||
|
ElseIf IsUrl And __isGif Then
|
||||||
|
hash = ByteArrayToString(GetMD5FromBytes(SFile.GetBytesFromNet(__data.URL.IfNullOrEmpty(__data.URL_BASE), ErrMD5), ErrMD5))
|
||||||
|
Else
|
||||||
|
hash = ByteArrayToString(GetMD5(SFile.GetBytes(__data.File, ErrMD5), ImgFormat, ErrMD5))
|
||||||
|
End If
|
||||||
|
If hash.IsEmptyString And Not __isGif Then
|
||||||
|
If ImgFormat Is Imaging.ImageFormat.Jpeg Then ImgFormat = Imaging.ImageFormat.Png Else ImgFormat = Imaging.ImageFormat.Jpeg
|
||||||
|
If IsUrl Then
|
||||||
|
hash = ByteArrayToString(GetMD5(SFile.GetBytesFromNet(__data.URL.IfNullOrEmpty(__data.URL_BASE), ErrMD5), ImgFormat, ErrMD5))
|
||||||
|
Else
|
||||||
|
hash = ByteArrayToString(GetMD5(SFile.GetBytes(__data.File, ErrMD5), ImgFormat, ErrMD5))
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
Return hash
|
||||||
|
Catch
|
||||||
|
Return String.Empty
|
||||||
|
End Try
|
||||||
|
End Function
|
||||||
|
Private Sub ValidateMD5(ByVal Token As CancellationToken)
|
||||||
Try
|
Try
|
||||||
Dim missingMD5 As Predicate(Of UserMedia) = Function(d) (d.Type = UTypes.GIF Or d.Type = UTypes.Picture) And d.MD5.IsEmptyString
|
Dim missingMD5 As Predicate(Of UserMedia) = Function(d) (d.Type = UTypes.GIF Or d.Type = UTypes.Picture) And d.MD5.IsEmptyString
|
||||||
If UseMD5Comparison And _TempMediaList.Exists(missingMD5) Then
|
If RemoveExistingDuplicates Then
|
||||||
|
RemoveExistingDuplicates = False
|
||||||
|
_ForceSaveUserInfo = True
|
||||||
|
LoadMD5()
|
||||||
Dim i%
|
Dim i%
|
||||||
Dim itemsCount% = 0
|
Dim itemsCount% = 0
|
||||||
Dim limit% = If(DownloadTopCount, 0)
|
Dim limit% = If(DownloadTopCount, 0)
|
||||||
Dim data As UserMedia = Nothing
|
Dim data As UserMedia = Nothing
|
||||||
Dim hashList As New Dictionary(Of String, SFile)
|
|
||||||
Dim f As SFile
|
Dim f As SFile
|
||||||
Dim ErrMD5 As New ErrorsDescriber(EDP.ReturnValue)
|
|
||||||
Dim __getMD5 As Func(Of UserMedia, Boolean, String) =
|
|
||||||
Function(ByVal __data As UserMedia, ByVal IsUrl As Boolean) As String
|
|
||||||
Try
|
|
||||||
Dim ImgFormat As Imaging.ImageFormat = Nothing
|
|
||||||
Dim hash$ = String.Empty
|
|
||||||
Dim __isGif As Boolean = False
|
|
||||||
If __data.Type = UTypes.GIF Then
|
|
||||||
ImgFormat = Imaging.ImageFormat.Gif
|
|
||||||
__isGif = True
|
|
||||||
ElseIf Not __data.File.IsEmptyString Then
|
|
||||||
ImgFormat = GetImageFormat(__data.File)
|
|
||||||
End If
|
|
||||||
If ImgFormat Is Nothing Then ImgFormat = Imaging.ImageFormat.Jpeg
|
|
||||||
If IsUrl And Not __isGif Then
|
|
||||||
hash = ByteArrayToString(GetMD5(SFile.GetBytesFromNet(__data.URL.IfNullOrEmpty(__data.URL_BASE), ErrMD5), ImgFormat, ErrMD5))
|
|
||||||
ElseIf IsUrl And __isGif Then
|
|
||||||
hash = ByteArrayToString(GetMD5FromBytes(SFile.GetBytesFromNet(__data.URL.IfNullOrEmpty(__data.URL_BASE), ErrMD5), ErrMD5))
|
|
||||||
Else
|
|
||||||
hash = ByteArrayToString(GetMD5(SFile.GetBytes(__data.File, ErrMD5), ImgFormat, ErrMD5))
|
|
||||||
End If
|
|
||||||
If hash.IsEmptyString And Not __isGif Then
|
|
||||||
If ImgFormat Is Imaging.ImageFormat.Jpeg Then ImgFormat = Imaging.ImageFormat.Png Else ImgFormat = Imaging.ImageFormat.Jpeg
|
|
||||||
If IsUrl Then
|
|
||||||
hash = ByteArrayToString(GetMD5(SFile.GetBytesFromNet(__data.URL.IfNullOrEmpty(__data.URL_BASE), ErrMD5), ImgFormat, ErrMD5))
|
|
||||||
Else
|
|
||||||
hash = ByteArrayToString(GetMD5(SFile.GetBytes(__data.File, ErrMD5), ImgFormat, ErrMD5))
|
|
||||||
End If
|
|
||||||
End If
|
|
||||||
Return hash
|
|
||||||
Catch
|
|
||||||
Return String.Empty
|
|
||||||
End Try
|
|
||||||
End Function
|
|
||||||
If Not StartMD5Checked Then
|
If Not StartMD5Checked Then
|
||||||
StartMD5Checked = True
|
StartMD5Checked = True
|
||||||
If _ContentList.Exists(missingMD5) Then
|
Dim existingFiles As List(Of SFile) = SFile.GetFiles(MyFileSettings.CutPath, "*.jpg|*.jpeg|*.png|*.gif",, EDP.ReturnValue).ListIfNothing
|
||||||
Dim existingFiles As List(Of SFile) = SFile.GetFiles(MyFileSettings.CutPath, "*.jpg|*.jpeg|*.png|*.gif",, EDP.ReturnValue).ListIfNothing
|
Dim eIndx%
|
||||||
Dim eIndx%
|
Dim eFinder As Predicate(Of SFile) = Function(ff) ff.File = data.File.File
|
||||||
Dim eFinder As Predicate(Of SFile) = Function(ff) ff.File = data.File.File
|
|
||||||
If RemoveExistingDuplicates Then
|
If existingFiles.Count > 0 Then
|
||||||
RemoveExistingDuplicates = False
|
Dim h$
|
||||||
_ForceSaveUserInfo = True
|
ProgressPre.ChangeMax(existingFiles.Count)
|
||||||
If existingFiles.Count > 0 Then
|
For i = existingFiles.Count - 1 To 0 Step -1
|
||||||
Dim h$
|
ProgressPre.Perform()
|
||||||
ProgressPre.ChangeMax(existingFiles.Count)
|
h = ValidateMD5_GetMD5(New UserMedia With {.File = existingFiles(i)}, False)
|
||||||
For i = existingFiles.Count - 1 To 0 Step -1
|
If Not h.IsEmptyString Then
|
||||||
ProgressPre.Perform()
|
If _MD5List.Contains(h) Then
|
||||||
h = __getMD5(New UserMedia With {.File = existingFiles(i)}, False)
|
MyMainLOG = $"{ToStringForLog()}: Removed image [{existingFiles(i).File}] (duplicate)"
|
||||||
If Not h.IsEmptyString Then
|
existingFiles(i).Delete(SFO.File, SFODelete.DeleteToRecycleBin, ErrMD5)
|
||||||
If hashList.ContainsKey(h) Then
|
existingFiles.RemoveAt(i)
|
||||||
MyMainLOG = $"{ToStringForLog()}: Removed image [{existingFiles(i).File}] (duplicate of [{hashList(h).File}])"
|
Else
|
||||||
existingFiles(i).Delete(SFO.File, SFODelete.DeleteToRecycleBin, ErrMD5)
|
_MD5List.Add(h)
|
||||||
existingFiles.RemoveAt(i)
|
End If
|
||||||
Else
|
|
||||||
hashList.Add(h, existingFiles(i))
|
|
||||||
End If
|
|
||||||
End If
|
|
||||||
Next
|
|
||||||
End If
|
End If
|
||||||
End If
|
Next
|
||||||
|
End If
|
||||||
|
|
||||||
|
If _ContentList.Count > 0 AndAlso _ContentList.Exists(missingMD5) Then
|
||||||
ProgressPre.ChangeMax(_ContentList.Count)
|
ProgressPre.ChangeMax(_ContentList.Count)
|
||||||
For i = 0 To _ContentList.Count - 1
|
For i = 0 To _ContentList.Count - 1
|
||||||
data = _ContentList(i)
|
data = _ContentList(i)
|
||||||
@@ -1522,61 +1586,34 @@ BlockNullPicture:
|
|||||||
ThrowAny(Token)
|
ThrowAny(Token)
|
||||||
eIndx = existingFiles.FindIndex(eFinder)
|
eIndx = existingFiles.FindIndex(eFinder)
|
||||||
If eIndx >= 0 Then
|
If eIndx >= 0 Then
|
||||||
data.MD5 = __getMD5(New UserMedia With {.File = existingFiles(eIndx)}, False)
|
data.MD5 = ValidateMD5_GetMD5(New UserMedia With {.File = existingFiles(eIndx)}, False)
|
||||||
If Not data.MD5.IsEmptyString Then _ContentList(i) = data : _ForceSaveUserData = True
|
If Not data.MD5.IsEmptyString Then _ContentList(i) = data : _ForceSaveUserData = True
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
existingFiles.RemoveAll(eFinder)
|
existingFiles.RemoveAll(eFinder)
|
||||||
End If
|
End If
|
||||||
Next
|
Next
|
||||||
If existingFiles.Count > 0 Then
|
|
||||||
ProgressPre.ChangeMax(existingFiles.Count)
|
|
||||||
For i = 0 To existingFiles.Count - 1
|
|
||||||
f = existingFiles(i)
|
|
||||||
ProgressPre.Perform()
|
|
||||||
data = New UserMedia(f.File) With {
|
|
||||||
.State = UStates.Downloaded,
|
|
||||||
.Type = IIf(f.Extension = "gif", UTypes.GIF, UTypes.Picture),
|
|
||||||
.File = f
|
|
||||||
}
|
|
||||||
ThrowAny(Token)
|
|
||||||
data.MD5 = __getMD5(data, False)
|
|
||||||
If Not data.MD5.IsEmptyString Then _ContentList.Add(data) : _ForceSaveUserData = True
|
|
||||||
Next
|
|
||||||
existingFiles.Clear()
|
|
||||||
End If
|
|
||||||
End If
|
End If
|
||||||
End If
|
|
||||||
|
|
||||||
If _ContentList.Count > 0 Then
|
If existingFiles.Count > 0 Then
|
||||||
With _ContentList.Select(Function(d) d.MD5)
|
ProgressPre.ChangeMax(existingFiles.Count)
|
||||||
If .ListExists Then .ToList.ForEach(Sub(md5value) _
|
For i = 0 To existingFiles.Count - 1
|
||||||
If Not md5value.IsEmptyString AndAlso Not hashList.ContainsKey(md5value) Then hashList.Add(md5value, New SFile))
|
f = existingFiles(i)
|
||||||
End With
|
ProgressPre.Perform()
|
||||||
End If
|
data = New UserMedia(f.File) With {
|
||||||
|
.State = UStates.Downloaded,
|
||||||
ProgressPre.ChangeMax(_TempMediaList.Count)
|
.Type = IIf(f.Extension = "gif", UTypes.GIF, UTypes.Picture),
|
||||||
For i = _TempMediaList.Count - 1 To 0 Step -1
|
.File = f
|
||||||
ProgressPre.Perform()
|
}
|
||||||
If limit > 0 And itemsCount >= limit Then
|
|
||||||
_TempMediaList.RemoveAt(i)
|
|
||||||
Else
|
|
||||||
data = _TempMediaList(i)
|
|
||||||
If missingMD5(data) Then
|
|
||||||
ThrowAny(Token)
|
ThrowAny(Token)
|
||||||
data.MD5 = __getMD5(data, True)
|
data.MD5 = ValidateMD5_GetMD5(data, False)
|
||||||
If Not data.MD5.IsEmptyString Then
|
If Not data.MD5.IsEmptyString Then _ContentList.Add(data) : _ForceSaveUserData = True
|
||||||
If hashList.ContainsKey(data.MD5) Then
|
Next
|
||||||
_TempMediaList.RemoveAt(i)
|
existingFiles.Clear()
|
||||||
Else
|
|
||||||
hashList.Add(data.MD5, New SFile)
|
|
||||||
_TempMediaList(i) = data
|
|
||||||
itemsCount += 1
|
|
||||||
End If
|
|
||||||
End If
|
|
||||||
End If
|
|
||||||
End If
|
End If
|
||||||
Next
|
End If
|
||||||
|
|
||||||
|
If _ContentList.Count > 0 Then _MD5List.ListAddList(_ContentList.Select(Function(d) d.MD5), LAP.NotContainsOnly, EDP.ReturnValue)
|
||||||
End If
|
End If
|
||||||
Catch iex As ArgumentOutOfRangeException When Disposed
|
Catch iex As ArgumentOutOfRangeException When Disposed
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
@@ -1614,6 +1651,7 @@ BlockNullPicture:
|
|||||||
Source.Progress.Done()
|
Source.Progress.Done()
|
||||||
End Sub
|
End Sub
|
||||||
End Class
|
End Class
|
||||||
|
Protected Const VideoFolderName As String = "Video"
|
||||||
Protected Sub DownloadContentDefault(ByVal Token As CancellationToken)
|
Protected Sub DownloadContentDefault(ByVal Token As CancellationToken)
|
||||||
Try
|
Try
|
||||||
Dim i%
|
Dim i%
|
||||||
@@ -1622,6 +1660,7 @@ BlockNullPicture:
|
|||||||
If _ContentNew.Count > 0 Then
|
If _ContentNew.Count > 0 Then
|
||||||
_ContentNew.RemoveAll(Function(c) c.URL.IsEmptyString)
|
_ContentNew.RemoveAll(Function(c) c.URL.IsEmptyString)
|
||||||
If _ContentNew.Count > 0 Then
|
If _ContentNew.Count > 0 Then
|
||||||
|
If UseMD5Comparison Then LoadMD5()
|
||||||
MyFile.Exists(SFO.Path)
|
MyFile.Exists(SFO.Path)
|
||||||
Dim MissingErrorsAdd As Boolean = Settings.AddMissingErrorsToLog
|
Dim MissingErrorsAdd As Boolean = Settings.AddMissingErrorsToLog
|
||||||
Dim MyDir$ = DownloadContentDefault_GetRootDir()
|
Dim MyDir$ = DownloadContentDefault_GetRootDir()
|
||||||
@@ -1630,6 +1669,7 @@ BlockNullPicture:
|
|||||||
Dim __interrupt As Boolean
|
Dim __interrupt As Boolean
|
||||||
Dim f As SFile
|
Dim f As SFile
|
||||||
Dim v As UserMedia
|
Dim v As UserMedia
|
||||||
|
Dim __fileDeleted As Boolean
|
||||||
Dim fileNumProvider As SFileNumbers = SFileNumbers.Default
|
Dim fileNumProvider As SFileNumbers = SFileNumbers.Default
|
||||||
Dim __deleteFile As Action(Of SFile, String) = Sub(ByVal FileToDelete As SFile, ByVal FileUrl As String)
|
Dim __deleteFile As Action(Of SFile, String) = Sub(ByVal FileToDelete As SFile, ByVal FileUrl As String)
|
||||||
Try
|
Try
|
||||||
@@ -1641,9 +1681,21 @@ BlockNullPicture:
|
|||||||
ErrorsDescriber.Execute(EDP.SendToLog, file_del_ex)
|
ErrorsDescriber.Execute(EDP.SendToLog, file_del_ex)
|
||||||
End Try
|
End Try
|
||||||
End Sub
|
End Sub
|
||||||
|
Dim updateDownCount As Action = Sub()
|
||||||
|
Dim __n% = IIf(__fileDeleted, -1, 1)
|
||||||
|
If __isVideo Then
|
||||||
|
v.Type = UTypes.Video
|
||||||
|
DownloadedVideos(False) += __n
|
||||||
|
ElseIf v.Type = UTypes.GIF Then
|
||||||
|
DownloadedPictures(False) += __n
|
||||||
|
Else
|
||||||
|
v.Type = UTypes.Picture
|
||||||
|
DownloadedPictures(False) += __n
|
||||||
|
End If
|
||||||
|
End Sub
|
||||||
|
|
||||||
Using w As New OptionalWebClient(Me)
|
Using w As New OptionalWebClient(Me)
|
||||||
If vsf Then CSFileP($"{MyDir}\Video\").Exists(SFO.Path)
|
If vsf Then CSFileP($"{MyDir}\{VideoFolderName}\").Exists(SFO.Path)
|
||||||
Progress.Maximum += _ContentNew.Count
|
Progress.Maximum += _ContentNew.Count
|
||||||
If IsSingleObjectDownload Then
|
If IsSingleObjectDownload Then
|
||||||
If _ContentNew.Count = 1 And _ContentNew(0).Type = UTypes.Video Then
|
If _ContentNew.Count = 1 And _ContentNew(0).Type = UTypes.Video Then
|
||||||
@@ -1671,6 +1723,8 @@ BlockNullPicture:
|
|||||||
|
|
||||||
If v.URL_BASE.IsEmptyString Then v.URL_BASE = v.URL
|
If v.URL_BASE.IsEmptyString Then v.URL_BASE = v.URL
|
||||||
|
|
||||||
|
__fileDeleted = False
|
||||||
|
|
||||||
If Not f.IsEmptyString And Not v.URL.IsEmptyString Then
|
If Not f.IsEmptyString And Not v.URL.IsEmptyString Then
|
||||||
Try
|
Try
|
||||||
__isVideo = v.Type = UTypes.Video Or f.Extension = "mp4" Or v.Type = UTypes.m3u8
|
__isVideo = v.Type = UTypes.Video Or f.Extension = "mp4" Or v.Type = UTypes.m3u8
|
||||||
@@ -1691,7 +1745,7 @@ BlockNullPicture:
|
|||||||
End If
|
End If
|
||||||
If __isVideo And vsf Then
|
If __isVideo And vsf Then
|
||||||
If v.SpecialFolder.IsEmptyString OrElse Not v.SpecialFolder.EndsWith("*") Then
|
If v.SpecialFolder.IsEmptyString OrElse Not v.SpecialFolder.EndsWith("*") Then
|
||||||
f.Path = $"{f.PathWithSeparator}Video"
|
f.Path = $"{f.PathWithSeparator}{VideoFolderName}"
|
||||||
If Not v.SpecialFolder.IsEmptyString Then f.Exists(SFO.Path)
|
If Not v.SpecialFolder.IsEmptyString Then f.Exists(SFO.Path)
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
@@ -1715,19 +1769,26 @@ BlockNullPicture:
|
|||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
|
|
||||||
If __isVideo Then
|
updateDownCount()
|
||||||
v.Type = UTypes.Video
|
|
||||||
DownloadedVideos(False) += 1
|
|
||||||
ElseIf v.Type = UTypes.GIF Then
|
|
||||||
DownloadedPictures(False) += 1
|
|
||||||
Else
|
|
||||||
v.Type = UTypes.Picture
|
|
||||||
DownloadedPictures(False) += 1
|
|
||||||
End If
|
|
||||||
|
|
||||||
v.File = ChangeFileNameByProvider(f, v)
|
v.File = ChangeFileNameByProvider(f, v)
|
||||||
v.State = UStates.Downloaded
|
v.State = UStates.Downloaded
|
||||||
DownloadContentDefault_PostProcessing(v, f, Token)
|
DownloadContentDefault_PostProcessing(v, f, Token)
|
||||||
|
If UseMD5Comparison And (v.Type = UTypes.GIF Or v.Type = UTypes.Picture) Then
|
||||||
|
If v.File.Exists Then
|
||||||
|
v.MD5 = ValidateMD5_GetMD5(v, False)
|
||||||
|
If Not v.MD5.IsEmptyString Then
|
||||||
|
If _MD5List.Contains(v.MD5) Then
|
||||||
|
__fileDeleted = v.File.Delete(SFO.File, SFODelete.DeletePermanently, EDP.ReturnValue)
|
||||||
|
If __fileDeleted Then dCount -= 1 : updateDownCount()
|
||||||
|
Else
|
||||||
|
_MD5List.Add(v.MD5)
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
Else
|
||||||
|
dCount -= 1
|
||||||
|
End If
|
||||||
|
End If
|
||||||
dCount += 1
|
dCount += 1
|
||||||
Catch woex As OperationCanceledException When Token.IsCancellationRequested
|
Catch woex As OperationCanceledException When Token.IsCancellationRequested
|
||||||
__deleteFile.Invoke(f, v.URL_BASE)
|
__deleteFile.Invoke(f, v.URL_BASE)
|
||||||
@@ -1745,7 +1806,7 @@ BlockNullPicture:
|
|||||||
Else
|
Else
|
||||||
v.State = UStates.Skipped
|
v.State = UStates.Skipped
|
||||||
End If
|
End If
|
||||||
_ContentNew(i) = v
|
If Not __fileDeleted Then _ContentNew(i) = v
|
||||||
If DownloadTopCount.HasValue AndAlso dCount >= DownloadTopCount.Value Then
|
If DownloadTopCount.HasValue AndAlso dCount >= DownloadTopCount.Value Then
|
||||||
Progress.Perform(_ContentNew.Count - dTotal)
|
Progress.Perform(_ContentNew.Count - dTotal)
|
||||||
Exit Sub
|
Exit Sub
|
||||||
@@ -1778,6 +1839,7 @@ BlockNullPicture:
|
|||||||
Protected Overridable Function ValidateDownloadFile(ByVal URL As String, ByVal Media As UserMedia, ByRef Interrupt As Boolean) As Boolean
|
Protected Overridable Function ValidateDownloadFile(ByVal URL As String, ByVal Media As UserMedia, ByRef Interrupt As Boolean) As Boolean
|
||||||
Return True
|
Return True
|
||||||
End Function
|
End Function
|
||||||
|
''' <returns><c>MyFile.CutPath(IIf(IsSingleObjectDownload, 0, 1)).PathNoSeparator</c></returns>
|
||||||
Protected Overridable Function DownloadContentDefault_GetRootDir() As String
|
Protected Overridable Function DownloadContentDefault_GetRootDir() As String
|
||||||
Return MyFile.CutPath(IIf(IsSingleObjectDownload, 0, 1)).PathNoSeparator
|
Return MyFile.CutPath(IIf(IsSingleObjectDownload, 0, 1)).PathNoSeparator
|
||||||
End Function
|
End Function
|
||||||
@@ -1815,6 +1877,31 @@ BlockNullPicture:
|
|||||||
Protected Overridable Function CreateFileFromUrl(ByVal URL As String) As SFile
|
Protected Overridable Function CreateFileFromUrl(ByVal URL As String) As SFile
|
||||||
Return New SFile(URL)
|
Return New SFile(URL)
|
||||||
End Function
|
End Function
|
||||||
|
Protected Overridable Function SimpleDownloadAvatar(ByVal ImageAddress As String, Optional ByVal FileCreateFunc As Func(Of String, SFile) = Nothing,
|
||||||
|
Optional ByVal e As ErrorsDescriber = Nothing) As SFile
|
||||||
|
Try
|
||||||
|
If Not ImageAddress.IsEmptyString Then
|
||||||
|
Dim f As SFile
|
||||||
|
If FileCreateFunc Is Nothing Then
|
||||||
|
f = CreateFileFromUrl(ImageAddress)
|
||||||
|
Else
|
||||||
|
f = FileCreateFunc.Invoke(ImageAddress)
|
||||||
|
End If
|
||||||
|
If Not f.Name.IsEmptyString Then f.Name = f.Name.StringRemoveWinForbiddenSymbols.StringTrim
|
||||||
|
If Not f.Name.IsEmptyString Then
|
||||||
|
f.Path = DownloadContentDefault_GetRootDir()
|
||||||
|
f.Separator = "\"
|
||||||
|
If f.Extension.IsEmptyString Then f.Extension = "jpg"
|
||||||
|
If Not f.Exists Then GetWebFile(ImageAddress, f, EDP.ReturnValue)
|
||||||
|
If f.Exists Then IconBannerDownloaded = True : Return f
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
Return Nothing
|
||||||
|
Catch ex As Exception
|
||||||
|
If Not e.Exists Then e = New ErrorsDescriber(EDP.ReturnValue)
|
||||||
|
Return ErrorsDescriber.Execute(e, ex, $"SimpleDownloadAvatar({ImageAddress})", New SFile)
|
||||||
|
End Try
|
||||||
|
End Function
|
||||||
Protected Overridable Function ChangeFileNameByProvider(ByVal f As SFile, ByVal m As UserMedia) As SFile
|
Protected Overridable Function ChangeFileNameByProvider(ByVal f As SFile, ByVal m As UserMedia) As SFile
|
||||||
Dim ff As SFile = Nothing
|
Dim ff As SFile = Nothing
|
||||||
Try
|
Try
|
||||||
@@ -1896,7 +1983,10 @@ BlockNullPicture:
|
|||||||
If m.Contains(IUserData.EraseMode.History) Then
|
If m.Contains(IUserData.EraseMode.History) Then
|
||||||
If MyFilePosts.Delete(SFO.File, SFODelete.DeleteToRecycleBin, e) Then result = True
|
If MyFilePosts.Delete(SFO.File, SFODelete.DeleteToRecycleBin, e) Then result = True
|
||||||
If MyFileData.Delete(SFO.File, SFODelete.DeleteToRecycleBin, e) Then result = True
|
If MyFileData.Delete(SFO.File, SFODelete.DeleteToRecycleBin, e) Then result = True
|
||||||
|
If MyMD5File.Delete(SFO.File, SFODelete.DeleteToRecycleBin, e) Then result = True
|
||||||
|
LastUpdated = Nothing
|
||||||
EraseData_AdditionalDataFiles()
|
EraseData_AdditionalDataFiles()
|
||||||
|
UpdateUserInformation()
|
||||||
End If
|
End If
|
||||||
If m.Contains(IUserData.EraseMode.Data) Then
|
If m.Contains(IUserData.EraseMode.Data) Then
|
||||||
Dim files As List(Of SFile) = SFile.GetFiles(DownloadContentDefault_GetRootDir.CSFileP,, SearchOption.AllDirectories, e)
|
Dim files As List(Of SFile) = SFile.GetFiles(DownloadContentDefault_GetRootDir.CSFileP,, SearchOption.AllDirectories, e)
|
||||||
@@ -1910,6 +2000,8 @@ BlockNullPicture:
|
|||||||
_TempMediaList.Clear()
|
_TempMediaList.Clear()
|
||||||
_ContentNew.Clear()
|
_ContentNew.Clear()
|
||||||
_ContentList.Clear()
|
_ContentList.Clear()
|
||||||
|
_MD5List.Clear()
|
||||||
|
_MD5Loaded = False
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
@@ -1918,7 +2010,7 @@ BlockNullPicture:
|
|||||||
Return ErrorsDescriber.Execute(EDP.SendToLog + EDP.ReturnValue, ex, $"EraseData({CInt(Mode)}): {ToStringForLog()}", False)
|
Return ErrorsDescriber.Execute(EDP.SendToLog + EDP.ReturnValue, ex, $"EraseData({CInt(Mode)}): {ToStringForLog()}", False)
|
||||||
End Try
|
End Try
|
||||||
End Function
|
End Function
|
||||||
Protected Overridable Sub EraseData_AdditionalDataFiles()
|
Protected Overridable Sub EraseData_AdditionalDataFiles() Implements IPluginContentProvider.ResetHistoryData
|
||||||
End Sub
|
End Sub
|
||||||
Friend Overridable Function Delete(Optional ByVal Multiple As Boolean = False, Optional ByVal CollectionValue As Integer = -1) As Integer Implements IUserData.Delete
|
Friend Overridable Function Delete(Optional ByVal Multiple As Boolean = False, Optional ByVal CollectionValue As Integer = -1) As Integer Implements IUserData.Delete
|
||||||
Dim f As SFile = SFile.GetPath(MyFile.CutPath.Path)
|
Dim f As SFile = SFile.GetPath(MyFile.CutPath.Path)
|
||||||
@@ -1934,7 +2026,18 @@ BlockNullPicture:
|
|||||||
Return 0
|
Return 0
|
||||||
End If
|
End If
|
||||||
End Function
|
End Function
|
||||||
Friend Overridable Function MoveFiles(ByVal __CollectionName As String, ByVal __SpecialCollectionPath As SFile) As Boolean Implements IUserData.MoveFiles
|
Friend Function SplitCollectionGetNewUserInfo() As SplitCollectionUserInfo
|
||||||
|
Dim u As New SplitCollectionUserInfo With {.UserOrig = User, .UserNew = User}
|
||||||
|
With u.UserNew
|
||||||
|
.CollectionName = String.Empty
|
||||||
|
.SpecialCollectionPath = Nothing
|
||||||
|
.UserModel = UsageModel.Default
|
||||||
|
.CollectionModel = UsageModel.Default
|
||||||
|
.UpdateUserFile()
|
||||||
|
End With
|
||||||
|
Return u
|
||||||
|
End Function
|
||||||
|
Friend Overridable Function MoveFiles(ByVal __CollectionName As String, ByVal __SpecialCollectionPath As SFile, Optional ByVal NewUser As SplitCollectionUserInfo? = Nothing) As Boolean Implements IUserData.MoveFiles
|
||||||
Dim UserBefore As UserInfo = User
|
Dim UserBefore As UserInfo = User
|
||||||
Dim Removed As Boolean = True
|
Dim Removed As Boolean = True
|
||||||
Dim _TurnBack As Boolean = False
|
Dim _TurnBack As Boolean = False
|
||||||
@@ -1950,6 +2053,7 @@ BlockNullPicture:
|
|||||||
User.SpecialCollectionPath = String.Empty
|
User.SpecialCollectionPath = String.Empty
|
||||||
User.UserModel = UsageModel.Default
|
User.UserModel = UsageModel.Default
|
||||||
User.CollectionModel = UsageModel.Default
|
User.CollectionModel = UsageModel.Default
|
||||||
|
If NewUser.HasValue Then User.SpecialPath = NewUser.Value.UserNew.SpecialPath
|
||||||
Else
|
Else
|
||||||
Settings.Users.Remove(Me)
|
Settings.Users.Remove(Me)
|
||||||
Removed = True
|
Removed = True
|
||||||
@@ -2057,7 +2161,7 @@ BlockNullPicture:
|
|||||||
End Function
|
End Function
|
||||||
Private Class FilesCopyingException : Inherits ErrorsDescriberException
|
Private Class FilesCopyingException : Inherits ErrorsDescriberException
|
||||||
Friend Sub New(ByVal User As IUserData, ByVal Msg As String, ByVal Path As SFile)
|
Friend Sub New(ByVal User As IUserData, ByVal Msg As String, ByVal Path As SFile)
|
||||||
SendInLogOnlyMessage = True
|
SendToLogOnlyMessage = True
|
||||||
If User.IncludedInCollection Then _MainMessage = $"[{User.CollectionName}] - "
|
If User.IncludedInCollection Then _MainMessage = $"[{User.CollectionName}] - "
|
||||||
_MainMessage &= $"[{User.Site}] - [{User.Name}]. {Msg}: {Path.Path}."
|
_MainMessage &= $"[{User.Site}] - [{User.Name}]. {Msg}: {Path.Path}."
|
||||||
End Sub
|
End Sub
|
||||||
@@ -2150,6 +2254,12 @@ BlockNullPicture:
|
|||||||
Private Sub BTT_CONTEXT_DOWN_KeyClick(sender As Object, e As MyKeyEventArgs) Handles BTT_CONTEXT_DOWN.KeyClick
|
Private Sub BTT_CONTEXT_DOWN_KeyClick(sender As Object, e As MyKeyEventArgs) Handles BTT_CONTEXT_DOWN.KeyClick
|
||||||
Downloader.Add(Me, e.IncludeInTheFeed)
|
Downloader.Add(Me, e.IncludeInTheFeed)
|
||||||
End Sub
|
End Sub
|
||||||
|
Private Sub BTT_CONTEXT_DOWN_LIMIT_KeyClick(sender As Object, e As MyKeyEventArgs) Handles BTT_CONTEXT_DOWN_LIMIT.KeyClick
|
||||||
|
ControlInvokeFast(MainFrameObj.MF, Sub() MainFrameObj.MF.DownloadSelectedUser(MainFrame.DownUserLimits.Number, e.IncludeInTheFeed, Me), EDP.SendToLog)
|
||||||
|
End Sub
|
||||||
|
Private Sub BTT_CONTEXT_DOWN_DATE_KeyClick(sender As Object, e As MyKeyEventArgs) Handles BTT_CONTEXT_DOWN_DATE.KeyClick
|
||||||
|
ControlInvokeFast(MainFrameObj.MF, Sub() MainFrameObj.MF.DownloadSelectedUser(MainFrame.DownUserLimits.Date, e.IncludeInTheFeed, Me), EDP.SendToLog)
|
||||||
|
End Sub
|
||||||
Private Sub BTT_CONTEXT_EDIT_Click(sender As Object, e As EventArgs) Handles BTT_CONTEXT_EDIT.Click
|
Private Sub BTT_CONTEXT_EDIT_Click(sender As Object, e As EventArgs) Handles BTT_CONTEXT_EDIT.Click
|
||||||
Using f As New Editors.UserCreatorForm(Me)
|
Using f As New Editors.UserCreatorForm(Me)
|
||||||
f.ShowDialog()
|
f.ShowDialog()
|
||||||
@@ -2181,18 +2291,20 @@ BlockNullPicture:
|
|||||||
End Sub
|
End Sub
|
||||||
#End Region
|
#End Region
|
||||||
#Region "IComparable Support"
|
#Region "IComparable Support"
|
||||||
Friend Overridable Function CompareTo(ByVal Other As UserDataBase) As Integer Implements IComparable(Of UserDataBase).CompareTo
|
Friend Overridable Overloads Function CompareTo(ByVal Other As UserDataBase) As Integer Implements IComparable(Of UserDataBase).CompareTo
|
||||||
If IsCollection Then
|
If TypeOf Other Is UserDataBind Then
|
||||||
|
Return 1
|
||||||
|
ElseIf IsCollection Then
|
||||||
Return Name.CompareTo(Other.Name)
|
Return Name.CompareTo(Other.Name)
|
||||||
Else
|
Else
|
||||||
Return FriendlyName.IfNullOrEmpty(Name).StringTrim.CompareTo(Other.FriendlyName.IfNullOrEmpty(Other.Name).StringTrim)
|
Return FriendlyName.IfNullOrEmpty(Name).StringTrim.CompareTo(Other.FriendlyName.IfNullOrEmpty(Other.Name).StringTrim)
|
||||||
End If
|
End If
|
||||||
End Function
|
End Function
|
||||||
Friend Overridable Function CompareTo(ByVal Obj As Object) As Integer Implements IComparable.CompareTo
|
Friend Overridable Overloads Function CompareTo(ByVal Obj As Object) As Integer Implements IComparable.CompareTo
|
||||||
If Not Obj Is Nothing AndAlso TypeOf Obj Is UserDataBase Then
|
If Not Obj Is Nothing AndAlso TypeOf Obj Is UserDataBase Then
|
||||||
Return CompareTo(DirectCast(Obj, UserDataBase))
|
Return CompareTo(DirectCast(Obj, UserDataBase))
|
||||||
Else
|
Else
|
||||||
Return False
|
Return 0
|
||||||
End If
|
End If
|
||||||
End Function
|
End Function
|
||||||
#End Region
|
#End Region
|
||||||
@@ -2200,7 +2312,7 @@ BlockNullPicture:
|
|||||||
Friend Overridable Overloads Function Equals(ByVal Other As UserDataBase) As Boolean Implements IEquatable(Of UserDataBase).Equals
|
Friend Overridable Overloads Function Equals(ByVal Other As UserDataBase) As Boolean Implements IEquatable(Of UserDataBase).Equals
|
||||||
Return LVIKey = Other.LVIKey And IsSavedPosts = Other.IsSavedPosts
|
Return LVIKey = Other.LVIKey And IsSavedPosts = Other.IsSavedPosts
|
||||||
End Function
|
End Function
|
||||||
Public Overrides Function Equals(ByVal Obj As Object) As Boolean
|
Public Overloads Overrides Function Equals(ByVal Obj As Object) As Boolean
|
||||||
If Not Obj Is Nothing AndAlso TypeOf Obj Is UserDataBase Then
|
If Not Obj Is Nothing AndAlso TypeOf Obj Is UserDataBase Then
|
||||||
Return Equals(DirectCast(Obj, UserDataBase))
|
Return Equals(DirectCast(Obj, UserDataBase))
|
||||||
Else
|
Else
|
||||||
@@ -2223,10 +2335,13 @@ BlockNullPicture:
|
|||||||
LatestData.Clear()
|
LatestData.Clear()
|
||||||
_TempMediaList.Clear()
|
_TempMediaList.Clear()
|
||||||
_TempPostsList.Clear()
|
_TempPostsList.Clear()
|
||||||
|
_MD5List.Clear()
|
||||||
TokenPersonal = Nothing
|
TokenPersonal = Nothing
|
||||||
If Not ProgressPre Is Nothing Then ProgressPre.Reset() : ProgressPre.Dispose()
|
If Not ProgressPre Is Nothing Then ProgressPre.Reset() : ProgressPre.Dispose()
|
||||||
If Not Responser Is Nothing Then Responser.Dispose()
|
If Not Responser Is Nothing Then Responser.Dispose()
|
||||||
If Not BTT_CONTEXT_DOWN Is Nothing Then BTT_CONTEXT_DOWN.Dispose()
|
If Not BTT_CONTEXT_DOWN Is Nothing Then BTT_CONTEXT_DOWN.Dispose()
|
||||||
|
If Not BTT_CONTEXT_DOWN_LIMIT Is Nothing Then BTT_CONTEXT_DOWN_LIMIT.Dispose()
|
||||||
|
If Not BTT_CONTEXT_DOWN_DATE Is Nothing Then BTT_CONTEXT_DOWN_DATE.Dispose()
|
||||||
If Not BTT_CONTEXT_EDIT Is Nothing Then BTT_CONTEXT_EDIT.Dispose()
|
If Not BTT_CONTEXT_EDIT Is Nothing Then BTT_CONTEXT_EDIT.Dispose()
|
||||||
If Not BTT_CONTEXT_DELETE Is Nothing Then BTT_CONTEXT_DELETE.Dispose()
|
If Not BTT_CONTEXT_DELETE Is Nothing Then BTT_CONTEXT_DELETE.Dispose()
|
||||||
If Not BTT_CONTEXT_ERASE Is Nothing Then BTT_CONTEXT_ERASE.Dispose()
|
If Not BTT_CONTEXT_ERASE Is Nothing Then BTT_CONTEXT_ERASE.Dispose()
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ Namespace API.Base.YTDLP
|
|||||||
Friend Sub New(ByVal _Token As Threading.CancellationToken)
|
Friend Sub New(ByVal _Token As Threading.CancellationToken)
|
||||||
MyBase.New(_Token)
|
MyBase.New(_Token)
|
||||||
Commands.Clear()
|
Commands.Clear()
|
||||||
MainProcessName = "yt-dlp"
|
MainProcessName = Settings.YtdlpFile.File.Name '"yt-dlp"
|
||||||
ChangeDirectory(Settings.YtdlpFile.File)
|
ChangeDirectory(Settings.YtdlpFile.File)
|
||||||
End Sub
|
End Sub
|
||||||
End Class
|
End Class
|
||||||
|
|||||||
@@ -134,6 +134,7 @@ Namespace API.Base
|
|||||||
m.GetMemberCustomAttributes(Of Provider).ListExists
|
m.GetMemberCustomAttributes(Of Provider).ListExists
|
||||||
Dim m1 As MemberInfo, m2 As MemberInfo
|
Dim m1 As MemberInfo, m2 As MemberInfo
|
||||||
Dim tmpObj As Object
|
Dim tmpObj As Object
|
||||||
|
Dim maxOffset%
|
||||||
|
|
||||||
members = GetObjectMembers(MyObject, Function(m) (m.MemberType = MemberTypes.Field Or m.MemberType = MemberTypes.Property) AndAlso
|
members = GetObjectMembers(MyObject, Function(m) (m.MemberType = MemberTypes.Field Or m.MemberType = MemberTypes.Property) AndAlso
|
||||||
Not m.GetCustomAttribute(Of PSettingAttribute) Is Nothing,, True,
|
Not m.GetCustomAttribute(Of PSettingAttribute) Is Nothing,, True,
|
||||||
@@ -175,6 +176,9 @@ Namespace API.Base
|
|||||||
|
|
||||||
If MyMembers.Count > 0 Then
|
If MyMembers.Count > 0 Then
|
||||||
|
|
||||||
|
maxOffset = MyMembers.Max(Function(mm) mm.LeftOffset)
|
||||||
|
If maxOffset > 0 Then MyMembers.ForEach(Sub(mm) mm.LeftOffset = maxOffset)
|
||||||
|
|
||||||
Dim prov As IEnumerable(Of Provider)
|
Dim prov As IEnumerable(Of Provider)
|
||||||
Dim _prov As Provider
|
Dim _prov As Provider
|
||||||
Dim si% = -1
|
Dim si% = -1
|
||||||
|
|||||||
28
SCrawler/API/BaseObjects/SplitCollectionUserInfo.vb
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
' 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.Base
|
||||||
|
Friend Structure SplitCollectionUserInfo
|
||||||
|
Friend UserOrig As UserInfo
|
||||||
|
Friend UserNew As UserInfo
|
||||||
|
Friend Changed As Boolean
|
||||||
|
Friend ReadOnly Property SameDrive As Boolean
|
||||||
|
Get
|
||||||
|
Return GetUserDrive(UserOrig) = GetUserDrive(UserNew)
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
|
Private Shared Function GetUserDrive(ByVal User As UserInfo) As String
|
||||||
|
Dim u As UserInfo = User
|
||||||
|
If u.File.IsEmptyString Then u.UpdateUserFile()
|
||||||
|
Return u.File.Segments.FirstOrDefault.StringToLower
|
||||||
|
End Function
|
||||||
|
Public Overrides Function ToString() As String
|
||||||
|
Return $"[{UserOrig.File.CutPath.PathWithSeparator}] -> [{UserNew.File.CutPath.PathWithSeparator}]"
|
||||||
|
End Function
|
||||||
|
End Structure
|
||||||
|
End Namespace
|
||||||
111
SCrawler/API/BaseObjects/SplitCollectionUserInfoChangePathsForm.Designer.vb
generated
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
' 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.Base
|
||||||
|
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
|
||||||
|
Partial Friend Class SplitCollectionUserInfoChangePathsForm : 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 LBL_INFO As System.Windows.Forms.Label
|
||||||
|
Me.LIST_USERS = New System.Windows.Forms.ListBox()
|
||||||
|
CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer()
|
||||||
|
TP_MAIN = New System.Windows.Forms.TableLayoutPanel()
|
||||||
|
LBL_INFO = New System.Windows.Forms.Label()
|
||||||
|
CONTAINER_MAIN.ContentPanel.SuspendLayout()
|
||||||
|
CONTAINER_MAIN.SuspendLayout()
|
||||||
|
TP_MAIN.SuspendLayout()
|
||||||
|
Me.SuspendLayout()
|
||||||
|
'
|
||||||
|
'CONTAINER_MAIN
|
||||||
|
'
|
||||||
|
'
|
||||||
|
'CONTAINER_MAIN.ContentPanel
|
||||||
|
'
|
||||||
|
CONTAINER_MAIN.ContentPanel.Controls.Add(TP_MAIN)
|
||||||
|
CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(384, 261)
|
||||||
|
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, 261)
|
||||||
|
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(LBL_INFO, 0, 0)
|
||||||
|
TP_MAIN.Controls.Add(Me.LIST_USERS, 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, 50.0!))
|
||||||
|
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
|
TP_MAIN.Size = New System.Drawing.Size(384, 261)
|
||||||
|
TP_MAIN.TabIndex = 0
|
||||||
|
'
|
||||||
|
'LBL_INFO
|
||||||
|
'
|
||||||
|
LBL_INFO.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
LBL_INFO.Location = New System.Drawing.Point(3, 0)
|
||||||
|
LBL_INFO.Name = "LBL_INFO"
|
||||||
|
LBL_INFO.Size = New System.Drawing.Size(378, 50)
|
||||||
|
LBL_INFO.TabIndex = 0
|
||||||
|
LBL_INFO.Text = "Check the user destination paths and change them if necessary." & Global.Microsoft.VisualBasic.ChrW(13) & Global.Microsoft.VisualBasic.ChrW(10) & "Double-click to c" &
|
||||||
|
"hange."
|
||||||
|
LBL_INFO.TextAlign = System.Drawing.ContentAlignment.MiddleCenter
|
||||||
|
'
|
||||||
|
'LIST_USERS
|
||||||
|
'
|
||||||
|
Me.LIST_USERS.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.LIST_USERS.FormattingEnabled = True
|
||||||
|
Me.LIST_USERS.Location = New System.Drawing.Point(3, 53)
|
||||||
|
Me.LIST_USERS.Name = "LIST_USERS"
|
||||||
|
Me.LIST_USERS.Size = New System.Drawing.Size(378, 205)
|
||||||
|
Me.LIST_USERS.TabIndex = 1
|
||||||
|
'
|
||||||
|
'SplitCollectionUserInfoChangePathsForm
|
||||||
|
'
|
||||||
|
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
|
||||||
|
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
|
||||||
|
Me.ClientSize = New System.Drawing.Size(384, 261)
|
||||||
|
Me.Controls.Add(CONTAINER_MAIN)
|
||||||
|
Me.Icon = Global.SCrawler.My.Resources.Resources.UsersIcon_32
|
||||||
|
Me.KeyPreview = True
|
||||||
|
Me.MinimumSize = New System.Drawing.Size(400, 300)
|
||||||
|
Me.Name = "SplitCollectionUserInfoChangePathsForm"
|
||||||
|
Me.ShowInTaskbar = False
|
||||||
|
Me.Text = "Collection users"
|
||||||
|
CONTAINER_MAIN.ContentPanel.ResumeLayout(False)
|
||||||
|
CONTAINER_MAIN.ResumeLayout(False)
|
||||||
|
CONTAINER_MAIN.PerformLayout()
|
||||||
|
TP_MAIN.ResumeLayout(False)
|
||||||
|
Me.ResumeLayout(False)
|
||||||
|
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Private WithEvents LIST_USERS As ListBox
|
||||||
|
End Class
|
||||||
|
End Namespace
|
||||||
@@ -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="LBL_INFO.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</metadata>
|
||||||
|
</root>
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
' 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.Functions.Messaging
|
||||||
|
Namespace API.Base
|
||||||
|
Friend Class SplitCollectionUserInfoChangePathsForm
|
||||||
|
Private WithEvents MyDefs As DefaultFormOptions
|
||||||
|
Friend ReadOnly Property Users As List(Of SplitCollectionUserInfo)
|
||||||
|
''' <summary>
|
||||||
|
''' Cancel = use initial<br/>
|
||||||
|
''' Abort = abort operation<br/>
|
||||||
|
''' OK = use changes
|
||||||
|
''' </summary>
|
||||||
|
Friend Sub New(ByVal _Users As IEnumerable(Of SplitCollectionUserInfo))
|
||||||
|
InitializeComponent()
|
||||||
|
MyDefs = New DefaultFormOptions(Me, Settings.Design)
|
||||||
|
Users = New List(Of SplitCollectionUserInfo)(_Users)
|
||||||
|
End Sub
|
||||||
|
Private Sub SplitCollectionUserInfoChangePathsForm_Load(sender As Object, e As EventArgs) Handles Me.Load
|
||||||
|
With MyDefs
|
||||||
|
.MyViewInitialize()
|
||||||
|
.AddOkCancelToolbar()
|
||||||
|
LIST_USERS.Items.AddRange(Users.Cast(Of Object).ToArray)
|
||||||
|
.EndLoaderOperations()
|
||||||
|
.MyOkCancel.EnableOK = True
|
||||||
|
End With
|
||||||
|
End Sub
|
||||||
|
Private Sub MyDefs_ButtonOkClick(ByVal Sender As Object, ByVal e As KeyHandleEventArgs) Handles MyDefs.ButtonOkClick
|
||||||
|
MyDefs.CloseForm()
|
||||||
|
End Sub
|
||||||
|
Private Sub MyDefs_ButtonCancelClick(ByVal Sender As Object, ByVal e As KeyHandleEventArgs) Handles MyDefs.ButtonCancelClick
|
||||||
|
Dim m As New MMessage("You have canceled the change. Do you want to process user(s) as is or cancel the operation?", "Change user paths",
|
||||||
|
{New MsgBoxButton("Initial", "Process users as is (IGNORE changes to this form)") With {.CallBackObject = DialogResult.Cancel},
|
||||||
|
New MsgBoxButton("Process", "Process users as is (INCLUDE changes here)") With {.CallBackObject = DialogResult.OK},
|
||||||
|
New MsgBoxButton("Abort", "Abort operation") With {.CallBackObject = DialogResult.Abort},
|
||||||
|
New MsgBoxButton("Cancel", "Continue editing here") With {.CallBackObject = DialogResult.Retry}},
|
||||||
|
vbExclamation) With {.ButtonsPerRow = 4}
|
||||||
|
Dim result As DialogResult = CInt(MsgBoxE(m).Button.CallBackObject)
|
||||||
|
If result = DialogResult.Retry Then
|
||||||
|
e.Handled = True
|
||||||
|
Exit Sub
|
||||||
|
Else
|
||||||
|
MyDefs.CloseForm(result)
|
||||||
|
End If
|
||||||
|
End Sub
|
||||||
|
Private Sub SplitCollectionUserInfoChangePathsForm_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed
|
||||||
|
Users.Clear()
|
||||||
|
End Sub
|
||||||
|
Private Sub LIST_USERS_MouseDoubleClick(sender As Object, e As MouseEventArgs) Handles LIST_USERS.MouseDoubleClick
|
||||||
|
Try
|
||||||
|
With LIST_USERS
|
||||||
|
If .SelectedIndex >= 0 Then
|
||||||
|
Dim obj As SplitCollectionUserInfo = .Items(.SelectedIndex)
|
||||||
|
Using f As New SplitCollectionUserInfoPathForm(obj)
|
||||||
|
f.ShowDialog()
|
||||||
|
If f.DialogResult = DialogResult.OK Then
|
||||||
|
obj = f.User
|
||||||
|
If obj.Changed Then
|
||||||
|
Users(.SelectedIndex) = obj
|
||||||
|
.Items(.SelectedIndex) = obj
|
||||||
|
.Refresh()
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
End Using
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
Catch ex As Exception
|
||||||
|
ErrorsDescriber.Execute(EDP.LogMessageValue, ex, "Change user paths")
|
||||||
|
End Try
|
||||||
|
End Sub
|
||||||
|
End Class
|
||||||
|
End Namespace
|
||||||
134
SCrawler/API/BaseObjects/SplitCollectionUserInfoPathForm.Designer.vb
generated
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
' 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.Base
|
||||||
|
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
|
||||||
|
Partial Friend Class SplitCollectionUserInfoPathForm : 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(SplitCollectionUserInfoPathForm))
|
||||||
|
Dim ActionButton2 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||||
|
Me.TXT_PATH_CURR = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
||||||
|
Me.TXT_PATH_NEW = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
||||||
|
CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer()
|
||||||
|
TP_MAIN = New System.Windows.Forms.TableLayoutPanel()
|
||||||
|
CONTAINER_MAIN.ContentPanel.SuspendLayout()
|
||||||
|
CONTAINER_MAIN.SuspendLayout()
|
||||||
|
TP_MAIN.SuspendLayout()
|
||||||
|
CType(Me.TXT_PATH_CURR, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||||
|
CType(Me.TXT_PATH_NEW, 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(484, 84)
|
||||||
|
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(484, 84)
|
||||||
|
CONTAINER_MAIN.TabIndex = 0
|
||||||
|
CONTAINER_MAIN.TopToolStripPanelVisible = False
|
||||||
|
'
|
||||||
|
'TP_MAIN
|
||||||
|
'
|
||||||
|
TP_MAIN.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single]
|
||||||
|
TP_MAIN.ColumnCount = 1
|
||||||
|
TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
|
TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20.0!))
|
||||||
|
TP_MAIN.Controls.Add(Me.TXT_PATH_CURR, 0, 0)
|
||||||
|
TP_MAIN.Controls.Add(Me.TXT_PATH_NEW, 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 = 3
|
||||||
|
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
|
||||||
|
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
|
||||||
|
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
|
TP_MAIN.Size = New System.Drawing.Size(484, 84)
|
||||||
|
TP_MAIN.TabIndex = 0
|
||||||
|
'
|
||||||
|
'TXT_PATH_CURR
|
||||||
|
'
|
||||||
|
Me.TXT_PATH_CURR.CaptionText = "Current"
|
||||||
|
Me.TXT_PATH_CURR.CaptionWidth = 50.0R
|
||||||
|
Me.TXT_PATH_CURR.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.TXT_PATH_CURR.Location = New System.Drawing.Point(4, 4)
|
||||||
|
Me.TXT_PATH_CURR.Name = "TXT_PATH_CURR"
|
||||||
|
Me.TXT_PATH_CURR.Size = New System.Drawing.Size(476, 22)
|
||||||
|
Me.TXT_PATH_CURR.TabIndex = 0
|
||||||
|
Me.TXT_PATH_CURR.TextBoxReadOnly = True
|
||||||
|
'
|
||||||
|
'TXT_PATH_NEW
|
||||||
|
'
|
||||||
|
ActionButton1.BackgroundImage = CType(resources.GetObject("ActionButton1.BackgroundImage"), System.Drawing.Image)
|
||||||
|
ActionButton1.Name = "Refresh"
|
||||||
|
ActionButton1.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Refresh
|
||||||
|
ActionButton2.BackgroundImage = CType(resources.GetObject("ActionButton2.BackgroundImage"), System.Drawing.Image)
|
||||||
|
ActionButton2.Name = "Open"
|
||||||
|
ActionButton2.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Open
|
||||||
|
Me.TXT_PATH_NEW.Buttons.Add(ActionButton1)
|
||||||
|
Me.TXT_PATH_NEW.Buttons.Add(ActionButton2)
|
||||||
|
Me.TXT_PATH_NEW.CaptionText = "New"
|
||||||
|
Me.TXT_PATH_NEW.CaptionWidth = 50.0R
|
||||||
|
Me.TXT_PATH_NEW.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.TXT_PATH_NEW.Location = New System.Drawing.Point(4, 33)
|
||||||
|
Me.TXT_PATH_NEW.Name = "TXT_PATH_NEW"
|
||||||
|
Me.TXT_PATH_NEW.Size = New System.Drawing.Size(476, 22)
|
||||||
|
Me.TXT_PATH_NEW.TabIndex = 1
|
||||||
|
'
|
||||||
|
'SplitCollectionUserInfoPathForm
|
||||||
|
'
|
||||||
|
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
|
||||||
|
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
|
||||||
|
Me.ClientSize = New System.Drawing.Size(484, 84)
|
||||||
|
Me.Controls.Add(CONTAINER_MAIN)
|
||||||
|
Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle
|
||||||
|
Me.Icon = Global.SCrawler.My.Resources.Resources.UsersIcon_32
|
||||||
|
Me.KeyPreview = True
|
||||||
|
Me.MaximizeBox = False
|
||||||
|
Me.MaximumSize = New System.Drawing.Size(500, 123)
|
||||||
|
Me.MinimizeBox = False
|
||||||
|
Me.MinimumSize = New System.Drawing.Size(500, 123)
|
||||||
|
Me.Name = "SplitCollectionUserInfoPathForm"
|
||||||
|
Me.ShowInTaskbar = False
|
||||||
|
Me.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide
|
||||||
|
Me.Text = "User paths"
|
||||||
|
CONTAINER_MAIN.ContentPanel.ResumeLayout(False)
|
||||||
|
CONTAINER_MAIN.ResumeLayout(False)
|
||||||
|
CONTAINER_MAIN.PerformLayout()
|
||||||
|
TP_MAIN.ResumeLayout(False)
|
||||||
|
CType(Me.TXT_PATH_CURR, System.ComponentModel.ISupportInitialize).EndInit()
|
||||||
|
CType(Me.TXT_PATH_NEW, System.ComponentModel.ISupportInitialize).EndInit()
|
||||||
|
Me.ResumeLayout(False)
|
||||||
|
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Private WithEvents TXT_PATH_CURR As PersonalUtilities.Forms.Controls.TextBoxExtended
|
||||||
|
Private WithEvents TXT_PATH_NEW As PersonalUtilities.Forms.Controls.TextBoxExtended
|
||||||
|
End Class
|
||||||
|
End Namespace
|
||||||
154
SCrawler/API/BaseObjects/SplitCollectionUserInfoPathForm.resx
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
<?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/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==
|
||||||
|
</value>
|
||||||
|
</data>
|
||||||
|
<data name="ActionButton2.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>
|
||||||
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
|
wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP
|
||||||
|
WQwhyWIyJIUW5NqyPb7oCVtIlhVTwYf8nv7/t2zJagel9KmqKsIACYL9RjI8UHz5zshougZr/AEvbxEP
|
||||||
|
aZCDBY3VslixaJvX3wzkkDiOwbZtDRGA5vdNAg+TL27qgmt5XkBG/gTdAG7Gt+3PP9oOaEGFCVEC6rp+
|
||||||
|
5g9MfM/c5e4OsEZMZkQEtGL5H2DdZ5JRArDwPA+iKII0TfkC9vroC9j5vq8JTWw3WzWgLMtZGIaa0MR8
|
||||||
|
vlAD8PYlSaIJTTiOowY0p0Bc19XEJo6HE59FAPuMzyAINKGJ1XLFZxHALtMrnkBXOIQIIIQ8YvF/KrgB
|
||||||
|
cMaRN0UdBBkAAAAASUVORK5CYII=
|
||||||
|
</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
68
SCrawler/API/BaseObjects/SplitCollectionUserInfoPathForm.vb
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
' 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.Controls.Base
|
||||||
|
Imports SCrawler.DownloadObjects.STDownloader
|
||||||
|
Namespace API.Base
|
||||||
|
Friend Class SplitCollectionUserInfoPathForm
|
||||||
|
Private WithEvents MyDefs As DefaultFormOptions
|
||||||
|
Friend User As SplitCollectionUserInfo
|
||||||
|
Private ReadOnly UserNewPathDef As String
|
||||||
|
Friend Sub New(ByVal _User As SplitCollectionUserInfo)
|
||||||
|
InitializeComponent()
|
||||||
|
MyDefs = New DefaultFormOptions(Me, Settings.Design)
|
||||||
|
User = _User
|
||||||
|
UserNewPathDef = User.UserNew.File.CutPath.PathWithSeparator
|
||||||
|
End Sub
|
||||||
|
Private Sub SplitCollectionUserInfoPathForm_Load(sender As Object, e As EventArgs) Handles Me.Load
|
||||||
|
With MyDefs
|
||||||
|
.MyViewInitialize()
|
||||||
|
.AddOkCancelToolbar()
|
||||||
|
|
||||||
|
TXT_PATH_CURR.Text = User.UserOrig.File.CutPath.PathWithSeparator
|
||||||
|
TXT_PATH_NEW.Text = UserNewPathDef
|
||||||
|
|
||||||
|
.MyFieldsCheckerE = New FieldsChecker
|
||||||
|
.MyFieldsCheckerE.AddControl(Of String)(TXT_PATH_NEW, "New path")
|
||||||
|
.MyFieldsCheckerE.EndLoaderOperations()
|
||||||
|
|
||||||
|
.EndLoaderOperations()
|
||||||
|
End With
|
||||||
|
End Sub
|
||||||
|
Private Sub MyDefs_ButtonOkClick(ByVal Sender As Object, ByVal e As KeyHandleEventArgs) Handles MyDefs.ButtonOkClick
|
||||||
|
If MyDefs.MyFieldsChecker.AllParamsOK Then MyDefs.CloseForm()
|
||||||
|
End Sub
|
||||||
|
Private Sub TXT_PATH_NEW_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As ActionButtonEventArgs) Handles TXT_PATH_NEW.ActionOnButtonClick
|
||||||
|
Select Case e.DefaultButton
|
||||||
|
Case ActionButton.DefaultButtons.Refresh : TXT_PATH_NEW.Text = UserNewPathDef
|
||||||
|
Case ActionButton.DefaultButtons.Open
|
||||||
|
Using ff As New Editors.GlobalLocationsChooserForm With {.MyInitialLocation = TXT_PATH_NEW.Text}
|
||||||
|
ff.ShowDialog()
|
||||||
|
If ff.DialogResult = DialogResult.OK Then
|
||||||
|
Dim dest As DownloadLocation = ff.MyDestination
|
||||||
|
If Not dest.Path.IsEmptyString Then
|
||||||
|
Dim ph As PathMoverHandler = Editors.GlobalLocationsChooserForm.ModelHandler(dest.Model)
|
||||||
|
If Not ph Is Nothing Then TXT_PATH_NEW.Text = ph.Invoke(User.UserNew, dest.Path.CSFileP).ToString
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
End Using
|
||||||
|
End Select
|
||||||
|
End Sub
|
||||||
|
Private Sub TXT_PATH_NEW_ActionOnTextChanged(sender As Object, e As EventArgs) Handles TXT_PATH_NEW.ActionOnTextChanged
|
||||||
|
If Not MyDefs.Initializing Then
|
||||||
|
Dim f As SFile = TXT_PATH_NEW.Text.CSFileP
|
||||||
|
If Not f.IsEmptyString Then
|
||||||
|
User.UserNew.SpecialPath = f
|
||||||
|
User.UserNew.UpdateUserFile()
|
||||||
|
User.Changed = Not User.UserNew.File.CutPath.PathWithSeparator = UserNewPathDef
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
End Sub
|
||||||
|
End Class
|
||||||
|
End Namespace
|
||||||
18
SCrawler/API/Bluesky/Declarations.vb
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
' Copyright (C) Andy https://github.com/AAndyProgram
|
||||||
|
' This program is free software: you can redistribute it and/or modify
|
||||||
|
' it under the terms of the GNU General Public License as published by
|
||||||
|
' the Free Software Foundation, either version 3 of the License, or
|
||||||
|
' (at your option) any later version.
|
||||||
|
'
|
||||||
|
' This program is distributed in the hope that it will be useful,
|
||||||
|
' but WITHOUT ANY WARRANTY
|
||||||
|
Imports PersonalUtilities.Functions.RegularExpressions
|
||||||
|
Namespace API.Bluesky
|
||||||
|
Friend Module Declarations
|
||||||
|
Friend Const BlueskySiteKey As String = "AndyProgram_Bluesky"
|
||||||
|
Friend ReadOnly DateProvider As New ADateTime("yyyy-MM-ddTHH:mm:ss.FFF%K")
|
||||||
|
Friend ReadOnly RegEx_PlayLists As RParams = RParams.DM("RESOLUTION=\d+x(\d+)\s*(\S+)", 0, RegexReturn.List, EDP.ReturnValue)
|
||||||
|
Friend ReadOnly RegEx_FilePattern As RParams = RParams.DM("(.+?)(\.|@)(gif|m3u8|[^/\?\&]+)", 0, RegexReturn.ListByMatch, EDP.ReturnValue)
|
||||||
|
Friend ReadOnly RegEx_SinglePostPattern As RParams = RParams.DM("profile/([^/]+)/post/([^/\?\&]+)", 0, RegexReturn.ListByMatch, EDP.ReturnValue)
|
||||||
|
End Module
|
||||||
|
End Namespace
|
||||||
51
SCrawler/API/Bluesky/M3U8.vb
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
' Copyright (C) Andy https://github.com/AAndyProgram
|
||||||
|
' This program is free software: you can redistribute it and/or modify
|
||||||
|
' it under the terms of the GNU General Public License as published by
|
||||||
|
' the Free Software Foundation, either version 3 of the License, or
|
||||||
|
' (at your option) any later version.
|
||||||
|
'
|
||||||
|
' This program is distributed in the hope that it will be useful,
|
||||||
|
' but WITHOUT ANY WARRANTY
|
||||||
|
Imports System.Threading
|
||||||
|
Imports SCrawler.API.Base
|
||||||
|
Imports PersonalUtilities.Forms.Toolbars
|
||||||
|
Imports PersonalUtilities.Tools.Web.Clients
|
||||||
|
Imports PersonalUtilities.Functions.RegularExpressions
|
||||||
|
Namespace API.Bluesky
|
||||||
|
Friend NotInheritable Class M3U8
|
||||||
|
Private Sub New()
|
||||||
|
End Sub
|
||||||
|
Private Shared Function GetUrlsList(ByVal URL As String) As List(Of String)
|
||||||
|
Using resp As New Responser With {.AllowAutoRedirect = False}
|
||||||
|
Dim r$ = resp.GetResponse(URL)
|
||||||
|
If Not r.IsEmptyString Then
|
||||||
|
Dim file$ = String.Empty, appender$
|
||||||
|
Dim files As List(Of Sizes) = RegexFields(Of Sizes)(r, {RegEx_PlayLists}, {1, 2})
|
||||||
|
If files.ListExists Then files.RemoveAll(Function(ff) ff.Value = 0 Or ff.Data.IsEmptyString)
|
||||||
|
If files.ListExists Then
|
||||||
|
files.Sort()
|
||||||
|
file = files(0).Data
|
||||||
|
appender = URL.Replace(URL.Split("/").Last, String.Empty)
|
||||||
|
file = M3U8Base.CreateUrl(appender, file)
|
||||||
|
If Not file.IsEmptyString Then
|
||||||
|
r = resp.GetResponse(file)
|
||||||
|
If Not r.IsEmptyString Then
|
||||||
|
Dim l As List(Of String) = RegexReplace(r, M3U8Declarations.TsFilesRegEx)
|
||||||
|
If l.ListExists Then
|
||||||
|
appender = file.Replace(file.Split("/").Last, String.Empty)
|
||||||
|
For i% = 0 To l.Count - 1 : l(i) = M3U8Base.CreateUrl(appender, l(i)) : Next
|
||||||
|
Return l
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
End Using
|
||||||
|
Return Nothing
|
||||||
|
End Function
|
||||||
|
Friend Shared Function Download(ByVal URL As String, ByVal Destination As SFile, ByVal Token As CancellationToken,
|
||||||
|
ByVal Progress As MyProgress, ByVal UsePreProgress As Boolean) As SFile
|
||||||
|
Return M3U8Base.Download(GetUrlsList(URL), Destination,, Token, Progress, UsePreProgress)
|
||||||
|
End Function
|
||||||
|
End Class
|
||||||
|
End Namespace
|
||||||
100
SCrawler/API/Bluesky/SiteSettings.vb
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
' Copyright (C) Andy https://github.com/AAndyProgram
|
||||||
|
' This program is free software: you can redistribute it and/or modify
|
||||||
|
' it under the terms of the GNU General Public License as published by
|
||||||
|
' the Free Software Foundation, either version 3 of the License, or
|
||||||
|
' (at your option) any later version.
|
||||||
|
'
|
||||||
|
' This program is distributed in the hope that it will be useful,
|
||||||
|
' but WITHOUT ANY WARRANTY
|
||||||
|
Imports SCrawler.API.Base
|
||||||
|
Imports SCrawler.Plugin
|
||||||
|
Imports SCrawler.Plugin.Attributes
|
||||||
|
Imports PersonalUtilities.Functions.XML
|
||||||
|
Imports PersonalUtilities.Functions.RegularExpressions
|
||||||
|
Imports PersonalUtilities.Tools.Web.Clients
|
||||||
|
Imports PersonalUtilities.Tools.Web.Documents.JSON
|
||||||
|
Namespace API.Bluesky
|
||||||
|
<Manifest(BlueskySiteKey), SpecialForm(False)>
|
||||||
|
Friend Class SiteSettings : Inherits SiteSettingsBase
|
||||||
|
<PropertyOption(ControlText:="Cookies enabled", ControlToolTip:="If checked, cookies will be used in requests", IsAuth:=True), PXML, PClonable, HiddenControl>
|
||||||
|
Friend ReadOnly Property CookiesEnabled As PropertyValue
|
||||||
|
<PropertyOption(ControlText:="User name", IsAuth:=True, AllowNull:=False), PXML>
|
||||||
|
Friend ReadOnly Property UserHandle As PropertyValue
|
||||||
|
<PropertyOption(ControlText:="Password", IsAuth:=True, AllowNull:=False), PXML>
|
||||||
|
Friend ReadOnly Property UserPassword As PropertyValue
|
||||||
|
<PXML> Friend ReadOnly Property Token As PropertyValue
|
||||||
|
<PXML> Friend ReadOnly Property TokenUpdateTime As PropertyValue
|
||||||
|
<PropertyOption(ControlText:="Token update", ControlToolTip:="Token refresh interval (in minutes)." & vbCr & "Default: 120.", IsAuth:=True), PXML, PClonable, HiddenControl>
|
||||||
|
Friend ReadOnly Property TokenRefreshInterval As PropertyValue
|
||||||
|
Friend Sub New(ByVal AccName As String, ByVal Temp As Boolean)
|
||||||
|
MyBase.New("Bluesky", "bsky.app", AccName, Temp, My.Resources.SiteResources.BlueskyIcon_32, My.Resources.SiteResources.BlueskyPic_32)
|
||||||
|
|
||||||
|
Responser.ContentType = "application/json"
|
||||||
|
|
||||||
|
CookiesEnabled = New PropertyValue(False)
|
||||||
|
UserHandle = New PropertyValue(String.Empty, GetType(String))
|
||||||
|
UserPassword = New PropertyValue(String.Empty, GetType(String))
|
||||||
|
Token = New PropertyValue(String.Empty, GetType(String))
|
||||||
|
TokenUpdateTime = New PropertyValue(Now.AddYears(-1))
|
||||||
|
TokenRefreshInterval = New PropertyValue(120)
|
||||||
|
|
||||||
|
_AllowUserAgentUpdate = False
|
||||||
|
UrlPatternUser = "https://bsky.app/profile/{0}"
|
||||||
|
ImageVideoContains = "bsky.app"
|
||||||
|
UserRegex = RParams.DMS("bsky.app/profile/([^/\?]+)", 1, EDP.ReturnValue)
|
||||||
|
UserOptionsType = GetType(EditorExchangeOptionsBase)
|
||||||
|
End Sub
|
||||||
|
Protected Overrides Function UserOptionsValid(ByVal Options As Object) As Boolean
|
||||||
|
Return DirectCast(Options, EditorExchangeOptionsBase).SiteKey = BlueskySiteKey
|
||||||
|
End Function
|
||||||
|
Protected Overrides Sub UserOptionsSetParameters(ByRef Options As Object)
|
||||||
|
DirectCast(Options, EditorExchangeOptionsBase).SiteKey = BlueskySiteKey
|
||||||
|
End Sub
|
||||||
|
Friend Overrides Function GetInstance(ByVal What As ISiteSettings.Download) As IPluginContentProvider
|
||||||
|
Return New UserData
|
||||||
|
End Function
|
||||||
|
Friend Overrides Function BaseAuthExists() As Boolean
|
||||||
|
Return Not CStr(UserHandle.Value).IsEmptyString And Not CStr(UserPassword.Value).IsEmptyString
|
||||||
|
End Function
|
||||||
|
Friend Overrides Function Available(ByVal What As ISiteSettings.Download, ByVal Silent As Boolean) As Boolean
|
||||||
|
Return MyBase.Available(What, Silent) AndAlso UpdateToken()
|
||||||
|
End Function
|
||||||
|
Private _TokenUpdating As Boolean = False
|
||||||
|
Friend Function UpdateToken(Optional ByVal Force As Boolean = False) As Boolean
|
||||||
|
Try
|
||||||
|
While _TokenUpdating : Threading.Thread.Sleep(100) : End While
|
||||||
|
_TokenUpdating = True
|
||||||
|
If BaseAuthExists() Then
|
||||||
|
If CDate(TokenUpdateTime.Value).AddMinutes(TokenRefreshInterval.Value) < Now Or Force Then
|
||||||
|
Using resp As Responser = Responser.Copy
|
||||||
|
With resp
|
||||||
|
.Mode = Responser.Modes.Curl
|
||||||
|
.Method = "POST"
|
||||||
|
.CurlSslNoRevoke = True
|
||||||
|
.CurlInsecure = True
|
||||||
|
.CurlArgumentsLeft = "-d ""{\" & $"""identifier\"": \""{UserHandle.Value}\"", \""password\"": \""{UserPassword.Value}\""" & "}"""
|
||||||
|
|
||||||
|
Dim r$ = .GetResponse("https://bsky.social/xrpc/com.atproto.server.createSession")
|
||||||
|
If Not r.IsEmptyString Then
|
||||||
|
Using j As EContainer = JsonDocument.Parse(r, EDP.ReturnValue)
|
||||||
|
If j.ListExists Then
|
||||||
|
Dim t$ = j.Value("accessJwt")
|
||||||
|
If Not t.IsEmptyString Then Token.Value = $"Bearer {t}" : TokenUpdateTime.Value = Now : Return True
|
||||||
|
End If
|
||||||
|
End Using
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
End Using
|
||||||
|
Else
|
||||||
|
Return True
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
Return False
|
||||||
|
Catch ex As Exception
|
||||||
|
Return ErrorsDescriber.Execute(EDP.SendToLog + EDP.ReturnValue, ex, "Bluesky.SiteSettings.UpdateToken", False)
|
||||||
|
Finally
|
||||||
|
_TokenUpdating = False
|
||||||
|
End Try
|
||||||
|
End Function
|
||||||
|
End Class
|
||||||
|
End Namespace
|
||||||
330
SCrawler/API/Bluesky/UserData.vb
Normal file
@@ -0,0 +1,330 @@
|
|||||||
|
' Copyright (C) Andy https://github.com/AAndyProgram
|
||||||
|
' This program is free software: you can redistribute it and/or modify
|
||||||
|
' it under the terms of the GNU General Public License as published by
|
||||||
|
' the Free Software Foundation, either version 3 of the License, or
|
||||||
|
' (at your option) any later version.
|
||||||
|
'
|
||||||
|
' This program is distributed in the hope that it will be useful,
|
||||||
|
' but WITHOUT ANY WARRANTY
|
||||||
|
Imports System.Threading
|
||||||
|
Imports SCrawler.API.Base
|
||||||
|
Imports SCrawler.API.YouTube.Objects
|
||||||
|
Imports PersonalUtilities.Functions.XML
|
||||||
|
Imports PersonalUtilities.Functions.RegularExpressions
|
||||||
|
Imports PersonalUtilities.Tools.Web.Documents.JSON
|
||||||
|
Imports UTypes = SCrawler.API.Base.UserMedia.Types
|
||||||
|
Imports UStates = SCrawler.API.Base.UserMedia.States
|
||||||
|
Namespace API.Bluesky
|
||||||
|
Friend Class UserData : Inherits UserDataBase
|
||||||
|
#Region "Declarations"
|
||||||
|
Private ReadOnly Property MySettings As SiteSettings
|
||||||
|
Get
|
||||||
|
Return HOST.Source
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
|
Private ReadOnly Property ID_Encoded As String
|
||||||
|
Get
|
||||||
|
Return If(ID.IsEmptyString, String.Empty, SymbolsConverter.ASCII.EncodeSymbolsOnly(ID))
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
|
#End Region
|
||||||
|
#Region "Loader"
|
||||||
|
Protected Overrides Sub LoadUserInformation_OptionalFields(ByRef Container As XmlFile, ByVal Loading As Boolean)
|
||||||
|
End Sub
|
||||||
|
Friend Overrides Function ExchangeOptionsGet() As Object
|
||||||
|
Return New EditorExchangeOptionsBase(Me) With {.SiteKey = BlueskySiteKey}
|
||||||
|
End Function
|
||||||
|
Friend Overrides Sub ExchangeOptionsSet(ByVal Obj As Object)
|
||||||
|
If Not Obj Is Nothing AndAlso TypeOf Obj Is EditorExchangeOptionsBase AndAlso
|
||||||
|
DirectCast(Obj, EditorExchangeOptionsBase).SiteKey = BlueskySiteKey Then NameTrue = DirectCast(Obj, EditorExchangeOptionsBase).UserName
|
||||||
|
End Sub
|
||||||
|
#End Region
|
||||||
|
#Region "Initializer"
|
||||||
|
Friend Sub New()
|
||||||
|
UseInternalM3U8Function = True
|
||||||
|
End Sub
|
||||||
|
#End Region
|
||||||
|
#Region "Token"
|
||||||
|
Private Function UpdateToken(Optional ByVal Force As Boolean = False, Optional ByVal OnlyAddHeader As Boolean = False) As Boolean
|
||||||
|
Dim process As Boolean = True
|
||||||
|
If CDate(MySettings.TokenUpdateTime.Value).AddHours(2) <= Now Or Force Then
|
||||||
|
process = MySettings.UpdateToken(Force)
|
||||||
|
If process Then _TokenUpdateCount += 1
|
||||||
|
End If
|
||||||
|
If process Or OnlyAddHeader Then Responser.Headers.Add("authorization", MySettings.Token.Value)
|
||||||
|
Return Not Responser.Headers.Value("authorization").IsEmptyString
|
||||||
|
End Function
|
||||||
|
Private _TokenUpdateCount As Integer = 0
|
||||||
|
Private Sub TokenUpdateCountReset()
|
||||||
|
_TokenUpdateCount = 0
|
||||||
|
End Sub
|
||||||
|
#End Region
|
||||||
|
#Region "Download"
|
||||||
|
Private _PostCount As Integer = 0
|
||||||
|
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
|
||||||
|
If Not CBool(MySettings.CookiesEnabled.Value) Then Responser.Cookies.Clear()
|
||||||
|
UpdateToken(, True)
|
||||||
|
_TokenUpdateCount = 0
|
||||||
|
_PostCount = 0
|
||||||
|
DownloadData(String.Empty, Token)
|
||||||
|
End Sub
|
||||||
|
Private Overloads Sub DownloadData(ByVal Cursor As String, ByVal Token As CancellationToken)
|
||||||
|
Dim URL$ = String.Empty
|
||||||
|
Try
|
||||||
|
If ID.IsEmptyString Then GetProfileInfo(Token)
|
||||||
|
If ID.IsEmptyString Then Throw New ArgumentNullException("ID", "ID is null")
|
||||||
|
If UpdateToken() Then
|
||||||
|
Dim nextCursor$ = String.Empty
|
||||||
|
Dim c%
|
||||||
|
URL = $"https://bsky.social/xrpc/app.bsky.feed.getAuthorFeed?actor={ID_Encoded}&filter=posts_and_author_threads&includePins=false&limit=99"
|
||||||
|
If Not Cursor.IsEmptyString Then URL &= $"&cursor={SymbolsConverter.ASCII.EncodeSymbolsOnly(Cursor)}"
|
||||||
|
Dim r$ = Responser.GetResponse(URL)
|
||||||
|
TokenUpdateCountReset()
|
||||||
|
If Not r.IsEmptyString Then
|
||||||
|
Using j As EContainer = JsonDocument.Parse(r)
|
||||||
|
If j.ListExists Then
|
||||||
|
With j("feed")
|
||||||
|
If .ListExists Then
|
||||||
|
For Each post As EContainer In .Self
|
||||||
|
With post({"post"})
|
||||||
|
c = DefaultParser(.Self,, nextCursor)
|
||||||
|
Select Case c
|
||||||
|
Case CInt(DateResult.Skip) * -1 : Continue For
|
||||||
|
Case CInt(DateResult.Exit) * -1 : Exit Sub
|
||||||
|
Case Is > 0 : _PostCount += c
|
||||||
|
End Select
|
||||||
|
If DownloadTopCount.HasValue AndAlso DownloadTopCount.Value <= _PostCount Then Exit Sub
|
||||||
|
End With
|
||||||
|
Next
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
End If
|
||||||
|
End Using
|
||||||
|
|
||||||
|
If Not nextCursor.IsEmptyString Then DownloadData(nextCursor, Token)
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
Catch ex As Exception
|
||||||
|
ProcessException(ex, Token, $"DownloadData({URL})")
|
||||||
|
End Try
|
||||||
|
End Sub
|
||||||
|
#End Region
|
||||||
|
#Region "DefaultParser"
|
||||||
|
Private Const Down_ImageAddress As String = "https://cdn.bsky.app/img/feed_fullsize/plain/{0}/{1}"
|
||||||
|
Private Function GetPostID(ByVal PostUri As String) As String
|
||||||
|
Return If(PostUri.IsEmptyString, String.Empty, PostUri.Split("/").LastOrDefault)
|
||||||
|
End Function
|
||||||
|
Private Function DefaultParser(ByVal e As EContainer, Optional ByVal CheckDateLimits As Boolean = True, Optional ByRef NextCursor As String = Nothing,
|
||||||
|
Optional ByVal CheckTempPosts As Boolean = True, Optional ByVal State As UStates = UStates.Unknown) As Integer
|
||||||
|
Const exitReturn% = CInt(DateResult.Exit) * -1
|
||||||
|
Dim postID$, postDate$, __url$, __urlBase$
|
||||||
|
Dim updateUrl As Boolean
|
||||||
|
Dim c% = 0
|
||||||
|
Dim m As UserMedia
|
||||||
|
Dim d As EContainer
|
||||||
|
With e
|
||||||
|
If .ListExists Then
|
||||||
|
postID = GetPostID(.Value("uri"))
|
||||||
|
postDate = String.Empty
|
||||||
|
__urlBase = String.Empty
|
||||||
|
With .Item({"record"})
|
||||||
|
If .ListExists Then
|
||||||
|
'2025-01-28T02:42:12.415Z
|
||||||
|
postDate = .Value("createdAt")
|
||||||
|
NextCursor = postDate
|
||||||
|
If CheckDateLimits Then
|
||||||
|
Select Case CheckDatesLimit(postDate, DateProvider)
|
||||||
|
Case DateResult.Skip : Return CInt(DateResult.Skip) * -1 'Continue For
|
||||||
|
Case DateResult.Exit : Return exitReturn 'Exit Sub
|
||||||
|
End Select
|
||||||
|
End If
|
||||||
|
|
||||||
|
If CheckTempPosts Then
|
||||||
|
If _TempPostsList.Contains(postID) Then Return exitReturn Else _TempPostsList.Add(postID)
|
||||||
|
End If
|
||||||
|
__urlBase = $"https://bsky.app/profile/{NameTrue}/post/{postID}"
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
|
||||||
|
Dim createMedia As Func(Of String, UTypes, UserMedia) =
|
||||||
|
Function(ByVal url As String, ByVal type As UTypes) As UserMedia
|
||||||
|
m = New UserMedia(url, type) With {
|
||||||
|
.URL_BASE = __urlBase,
|
||||||
|
.File = CreateFileFromUrl(url, type),
|
||||||
|
.Post = New UserPost(postID, If(AConvert(Of Date)(postDate, DateProvider, Nothing, EDP.ReturnValue), Nothing)),
|
||||||
|
.State = State
|
||||||
|
}
|
||||||
|
_TempMediaList.ListAddValue(m, LNC)
|
||||||
|
c += 1
|
||||||
|
Return m
|
||||||
|
End Function
|
||||||
|
|
||||||
|
For Each SecondExtraction As Boolean In {False, True}
|
||||||
|
With If(SecondExtraction, .Item({"record", "embed"}), .Item("embed"))
|
||||||
|
If .ListExists Then
|
||||||
|
|
||||||
|
If If(.Item("images")?.Count, 0) > 0 Then
|
||||||
|
With .Item("images")
|
||||||
|
For Each d In .Self
|
||||||
|
updateUrl = False
|
||||||
|
__url = d.Value("fullsize")
|
||||||
|
If __url.IsEmptyString Then __url = d.Value({"image", "ref"}, "$link") : updateUrl = True
|
||||||
|
If __url.IsEmptyString And SecondExtraction Then updateUrl = False : __url = e.Value({"embed"}, "thumb")
|
||||||
|
If Not __url.IsEmptyString Then createMedia(__url, UTypes.Picture)
|
||||||
|
Next
|
||||||
|
End With
|
||||||
|
End If
|
||||||
|
|
||||||
|
If Not .Value("playlist").IsEmptyString Then createMedia(.Value("playlist"), UTypes.m3u8)
|
||||||
|
|
||||||
|
If If(.Item("external")?.Count, 0) > 0 Then createMedia(.Value({"external"}, "uri"), UTypes.GIF)
|
||||||
|
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
|
||||||
|
If c > 0 Then Exit For
|
||||||
|
Next
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
Return c
|
||||||
|
End Function
|
||||||
|
#End Region
|
||||||
|
#Region "GetProfileInfo"
|
||||||
|
Private Sub GetProfileInfo(ByVal Token As CancellationToken)
|
||||||
|
Try
|
||||||
|
If UpdateToken() Then
|
||||||
|
Dim r$ = Responser.GetResponse($"https://bsky.social/xrpc/app.bsky.actor.getProfile?actor={ID.IfNullOrEmpty(NameTrue)}")
|
||||||
|
TokenUpdateCountReset()
|
||||||
|
If Not r.IsEmptyString Then
|
||||||
|
Using j As EContainer = JsonDocument.Parse(r)
|
||||||
|
If j.ListExists Then
|
||||||
|
ID = j.Value("did")
|
||||||
|
UserSiteNameUpdate(j.Value("displayName"))
|
||||||
|
UserDescriptionUpdate(j.Value("description"))
|
||||||
|
NameTrue = j.Value("handle")
|
||||||
|
SimpleDownloadAvatar(j.Value("avatar"))
|
||||||
|
SimpleDownloadAvatar(j.Value("banner"))
|
||||||
|
End If
|
||||||
|
End Using
|
||||||
|
End If
|
||||||
|
Else
|
||||||
|
Throw New ArgumentException("Token is null", "Token")
|
||||||
|
End If
|
||||||
|
Catch ex As Exception
|
||||||
|
ProcessException(ex, Token, "GetProfileInfo")
|
||||||
|
End Try
|
||||||
|
End Sub
|
||||||
|
#End Region
|
||||||
|
#Region "ReparseMissing"
|
||||||
|
Protected Overrides Sub ReparseMissing(ByVal Token As CancellationToken)
|
||||||
|
Const uriPattern$ = "at://{0}/app.bsky.feed.post/{1}"
|
||||||
|
Dim rList As New List(Of Integer)
|
||||||
|
Try
|
||||||
|
If ContentMissingExists AndAlso UpdateToken() Then
|
||||||
|
Dim r$, url$, uri$
|
||||||
|
Dim tu As Byte
|
||||||
|
Dim m As UserMedia
|
||||||
|
Dim j As EContainer
|
||||||
|
For i% = 0 To _ContentList.Count - 1
|
||||||
|
m = _ContentList(i)
|
||||||
|
If m.State = UStates.Missing Then
|
||||||
|
uri = SymbolsConverter.ASCII.EncodeSymbolsOnly(String.Format(uriPattern, NameTrue, m.Post.ID))
|
||||||
|
url = $"https://bsky.social/xrpc/app.bsky.feed.getPostThread?uri={uri}&depth=10"
|
||||||
|
For tu = 0 To 1
|
||||||
|
Try
|
||||||
|
Responser.ResetStatus()
|
||||||
|
r = Responser.GetResponse(url)
|
||||||
|
TokenUpdateCountReset()
|
||||||
|
If Not r.IsEmptyString Then
|
||||||
|
j = JsonDocument.Parse(r)
|
||||||
|
If j.ListExists Then
|
||||||
|
If DefaultParser(j({"thread", "post"}), False,, False, UStates.Missing) > 0 Then rList.Add(i)
|
||||||
|
j.Dispose()
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
Exit For
|
||||||
|
Catch eex As Exception
|
||||||
|
If ProcessException(eex, Token, $"ReparseMissing({url})",,, False) <> 1 Then Throw eex
|
||||||
|
End Try
|
||||||
|
Next
|
||||||
|
End If
|
||||||
|
Next
|
||||||
|
Else
|
||||||
|
Throw New ArgumentException("Token is null", "Token")
|
||||||
|
End If
|
||||||
|
Catch ex As Exception
|
||||||
|
ProcessException(ex, Token, "ReparseMissing error")
|
||||||
|
Finally
|
||||||
|
If rList.Count > 0 Then
|
||||||
|
For i% = rList.Count - 1 To 0 Step -1 : _ContentList.RemoveAt(rList(i)) : Next
|
||||||
|
rList.Clear()
|
||||||
|
End If
|
||||||
|
End Try
|
||||||
|
End Sub
|
||||||
|
#End Region
|
||||||
|
#Region "CreateFileFromUrl"
|
||||||
|
Protected Overloads Overrides Function CreateFileFromUrl(ByVal URL As String) As SFile
|
||||||
|
Return CreateFileFromUrl(URL, UTypes.Undefined)
|
||||||
|
End Function
|
||||||
|
Protected Overloads Function CreateFileFromUrl(ByVal URL As String, ByVal Type As UTypes) As SFile
|
||||||
|
Dim f As SFile = MyBase.CreateFileFromUrl(URL)
|
||||||
|
Dim force As Boolean = False
|
||||||
|
f.Separator = "\"
|
||||||
|
With URL.Split("/")
|
||||||
|
If .ListExists Then
|
||||||
|
With DirectCast(RegexReplace(.Last, RegEx_FilePattern), List(Of String))
|
||||||
|
If .ListExists(4) Then
|
||||||
|
f.Name = .Item(1).IfNullOrEmpty(f.Name)
|
||||||
|
f.Extension = .Item(3)
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
If Not f.Extension.IsEmptyString AndAlso f.Extension.ToLower = "m3u8" Then force = True : Type = UTypes.m3u8
|
||||||
|
If f.Extension.IsEmptyString Or force Then
|
||||||
|
Select Case Type
|
||||||
|
Case UTypes.Picture : f.Extension = "jpg"
|
||||||
|
Case UTypes.GIF : f.Extension = "gif"
|
||||||
|
Case UTypes.m3u8 : f.Name = "Video" : f.Extension = "mp4"
|
||||||
|
End Select
|
||||||
|
End If
|
||||||
|
Return f
|
||||||
|
End Function
|
||||||
|
#End Region
|
||||||
|
#Region "DownloadContent"
|
||||||
|
Protected Overrides Sub DownloadContent(ByVal Token As CancellationToken)
|
||||||
|
DownloadContentDefault(Token)
|
||||||
|
End Sub
|
||||||
|
Protected Overrides Function DownloadM3U8(ByVal URL As String, ByVal Media As UserMedia, ByVal DestinationFile As SFile, ByVal Token As CancellationToken) As SFile
|
||||||
|
Return M3U8.Download(URL, DestinationFile, Token, Progress, Not IsSingleObjectDownload)
|
||||||
|
End Function
|
||||||
|
#End Region
|
||||||
|
#Region "DownloadSingleObject"
|
||||||
|
Protected Overrides Sub DownloadSingleObject_GetPosts(ByVal Data As IYouTubeMediaContainer, ByVal Token As CancellationToken)
|
||||||
|
_TokenUpdateCount = 0
|
||||||
|
UpdateToken()
|
||||||
|
Dim l As List(Of String) = RegexReplace(Data.URL, RegEx_SinglePostPattern)
|
||||||
|
If l.ListExists(3) Then
|
||||||
|
NameTrue = l(1)
|
||||||
|
_ContentList.Add(New UserMedia(Data.URL) With {.State = UStates.Missing, .Post = l(2)})
|
||||||
|
ReparseMissing(Token)
|
||||||
|
End If
|
||||||
|
MyBase.DownloadSingleObject_GetPosts(Data, Token)
|
||||||
|
End Sub
|
||||||
|
#End Region
|
||||||
|
#Region "Exception"
|
||||||
|
Protected Overrides Function DownloadingException(ByVal ex As Exception, ByVal Message As String, Optional ByVal FromPE As Boolean = False,
|
||||||
|
Optional ByVal EObj As Object = Nothing) As Integer
|
||||||
|
If Responser.StatusCode = Net.HttpStatusCode.BadRequest Then '400
|
||||||
|
If _TokenUpdateCount = 0 AndAlso UpdateToken(True) Then
|
||||||
|
Return 1
|
||||||
|
Else
|
||||||
|
Return 0
|
||||||
|
End If
|
||||||
|
Else
|
||||||
|
Return 0
|
||||||
|
End If
|
||||||
|
End Function
|
||||||
|
#End Region
|
||||||
|
End Class
|
||||||
|
End Namespace
|
||||||
@@ -11,14 +11,15 @@ Imports PersonalUtilities.Functions.XML.Base
|
|||||||
Imports PersonalUtilities.Functions.RegularExpressions
|
Imports PersonalUtilities.Functions.RegularExpressions
|
||||||
Namespace API.Facebook
|
Namespace API.Facebook
|
||||||
Friend Module Declarations
|
Friend Module Declarations
|
||||||
Friend ReadOnly Regex_UserToken_dtsg As RParams = RParams.DMS("DTSGInitialData.:.?{\s*.token.:\s*""([^""]+)", 1, EDP.ReturnValue)
|
|
||||||
Friend ReadOnly Regex_UserToken_lsd As RParams = RParams.DMS("LSD.:.?{\s*.token.:\s*""([^""]+)", 1, EDP.ReturnValue)
|
|
||||||
Friend ReadOnly Regex_UserID As RParams = RParams.DMS("userid.:.(\d+)", 1, RegexOptions.IgnoreCase, EDP.ReturnValue)
|
Friend ReadOnly Regex_UserID As RParams = RParams.DMS("userid.:.(\d+)", 1, RegexOptions.IgnoreCase, EDP.ReturnValue)
|
||||||
|
Friend ReadOnly Regex_AppID As RParams = RParams.DMS("APP_ID.:.(\d+)", 1, RegexOptions.IgnoreCase, EDP.ReturnValue)
|
||||||
|
|
||||||
Friend ReadOnly Regex_Photos_by As RParams = RParams.DMS("photos_by"",""id"":""([^""]+)", 1, EDP.ReturnValue)
|
Friend ReadOnly Regex_Photos_by As RParams = RParams.DMS("photos_by"",""id"":""([^""]+)", 1, EDP.ReturnValue)
|
||||||
Friend ReadOnly Regex_FileName As RParams = RParams.DM("([^/\?]+\..{3,4})(?=(\?|\Z))", 0, EDP.ReturnValue)
|
Friend ReadOnly Regex_FileName As RParams = RParams.DM("([^/\?]+\..{3,4})(?=(\?|\Z))", 0, EDP.ReturnValue)
|
||||||
Friend ReadOnly Regex_ProfileUrlID As RParams = RParams.DMS("profile.php\?id=(\d+)", 1, EDP.ReturnValue)
|
Friend ReadOnly Regex_ProfileUrlID As RParams = RParams.DMS("profile.php\?id=(\d+)", 1, EDP.ReturnValue)
|
||||||
Friend ReadOnly Regex_VideoPageID As RParams = RParams.DMS("pageid.:.(\d+)", 1, RegexOptions.IgnoreCase, EDP.ReturnValue)
|
Friend ReadOnly Regex_VideoPageID As RParams = RParams.DMS("pageid.:.(\d+)", 1, RegexOptions.IgnoreCase, EDP.ReturnValue)
|
||||||
|
Friend ReadOnly Regex_ReelsPageID As RParams = RParams.DMS("\{[^\}]*""tab_key"":""owner_reels"",?[^\}]*""id"":""([^\}""]+)""", 1, RegexOptions.IgnoreCase, EDP.ReturnValue)
|
||||||
|
Friend ReadOnly Regex_ReelsFilePattern As RParams = RParams.DM("[^/]+\.mp4", 0, EDP.ReturnValue)
|
||||||
Friend ReadOnly Regex_StoryBucket As RParams = RParams.DMS("story_bucket[^\>]*?(\d+)", 1, EDP.ReturnValue)
|
Friend ReadOnly Regex_StoryBucket As RParams = RParams.DMS("story_bucket[^\>]*?(\d+)", 1, EDP.ReturnValue)
|
||||||
|
|
||||||
Friend ReadOnly Regex_VideoIDFromURL As RParams = RParams.DMS("facebook.com/([^/]+/videos/|watch/\D*[\?&]{1}v=)(\d+)", 2, EDP.ReturnValue)
|
Friend ReadOnly Regex_VideoIDFromURL As RParams = RParams.DMS("facebook.com/([^/]+/videos/|watch/\D*[\?&]{1}v=)(\d+)", 2, EDP.ReturnValue)
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ Imports SCrawler.Plugin
|
|||||||
Imports SCrawler.Plugin.Attributes
|
Imports SCrawler.Plugin.Attributes
|
||||||
Imports PersonalUtilities.Tools.Web.Clients
|
Imports PersonalUtilities.Tools.Web.Clients
|
||||||
Imports PersonalUtilities.Functions.RegularExpressions
|
Imports PersonalUtilities.Functions.RegularExpressions
|
||||||
|
Imports DN = SCrawler.API.Base.DeclaredNames
|
||||||
Namespace API.Facebook
|
Namespace API.Facebook
|
||||||
<Manifest("AndyProgram_Facebook"), SavedPosts, SeparatedTasks(1), SpecialForm(False)>
|
<Manifest("AndyProgram_Facebook"), SavedPosts, SeparatedTasks(1), SpecialForm(False)>
|
||||||
Friend Class SiteSettings : Inherits ThreadsNet.SiteSettings
|
Friend Class SiteSettings : Inherits ThreadsNet.SiteSettings
|
||||||
@@ -18,7 +19,7 @@ Namespace API.Facebook
|
|||||||
#Region "Auth"
|
#Region "Auth"
|
||||||
<PropertyOption(AllowNull:=False, ControlText:="Accept", ControlToolTip:="Header 'Accept'", IsAuth:=True), ControlNumber(21), PXML, PClonable>
|
<PropertyOption(AllowNull:=False, ControlText:="Accept", ControlToolTip:="Header 'Accept'", IsAuth:=True), ControlNumber(21), PXML, PClonable>
|
||||||
Friend ReadOnly Property Header_Accept As PropertyValue
|
Friend ReadOnly Property Header_Accept As PropertyValue
|
||||||
<PropertyOption(ControlText:="x-ig-app-id", AllowNull:=True, IsAuth:=True)>
|
<PropertyOption(ControlText:="x-ig-app-id", AllowNull:=True, IsAuth:=True), HiddenControl>
|
||||||
Friend Overrides ReadOnly Property HH_IG_APP_ID As PropertyValue
|
Friend Overrides ReadOnly Property HH_IG_APP_ID As PropertyValue
|
||||||
Get
|
Get
|
||||||
Return __HH_IG_APP_ID
|
Return __HH_IG_APP_ID
|
||||||
@@ -29,15 +30,15 @@ Namespace API.Facebook
|
|||||||
Return __HH_CSRF_TOKEN
|
Return __HH_CSRF_TOKEN
|
||||||
End Get
|
End Get
|
||||||
End Property
|
End Property
|
||||||
<PropertyOption(ControlText:="sec-ch-ua-platform-ver", ControlToolTip:="sec-ch-ua-platform-version", IsAuth:=True, LeftOffset:=120), ControlNumber(51), PXML, PClonable>
|
|
||||||
Friend ReadOnly Property HH_PLATFORM_VER As PropertyValue
|
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Defaults"
|
#Region "Defaults"
|
||||||
<PropertyOption(ControlText:="Download photos", IsAuth:=False), PXML, PClonable>
|
<PropertyOption(ControlText:="Download photos", IsAuth:=False, Category:=DN.CAT_UserDefs), PXML, PClonable>
|
||||||
Friend ReadOnly Property ParsePhotoBlock As PropertyValue
|
Friend ReadOnly Property ParsePhotoBlock As PropertyValue
|
||||||
<PropertyOption(ControlText:="Download videos", IsAuth:=False), PXML, PClonable>
|
<PropertyOption(ControlText:="Download videos", IsAuth:=False, Category:=DN.CAT_UserDefs), PXML, PClonable>
|
||||||
Friend ReadOnly Property ParseVideoBlock As PropertyValue
|
Friend ReadOnly Property ParseVideoBlock As PropertyValue
|
||||||
<PropertyOption(ControlText:="Download stories", IsAuth:=False), PXML, PClonable>
|
<PropertyOption(ControlText:="Download reels", IsAuth:=False, Category:=DN.CAT_UserDefs), PXML, PClonable>
|
||||||
|
Friend ReadOnly Property ParseReelsBlock As PropertyValue
|
||||||
|
<PropertyOption(ControlText:="Download stories", IsAuth:=False, Category:=DN.CAT_UserDefs), PXML, PClonable>
|
||||||
Friend ReadOnly Property ParseStoriesBlock As PropertyValue
|
Friend ReadOnly Property ParseStoriesBlock As PropertyValue
|
||||||
#End Region
|
#End Region
|
||||||
#End Region
|
#End Region
|
||||||
@@ -48,12 +49,12 @@ Namespace API.Facebook
|
|||||||
With Responser.Headers
|
With Responser.Headers
|
||||||
.Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.Authority, "www.facebook.com"))
|
.Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.Authority, "www.facebook.com"))
|
||||||
.Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.Origin, "https://www.facebook.com"))
|
.Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.Origin, "https://www.facebook.com"))
|
||||||
.Remove(DeclaredNames.Header_FB_FRIENDLY_NAME)
|
.Remove(Instagram.UserData.GQL_HEADER_FB_FRINDLY_NAME)
|
||||||
End With
|
End With
|
||||||
Header_Accept = New PropertyValue(String.Empty, GetType(String))
|
Header_Accept = New PropertyValue(String.Empty, GetType(String))
|
||||||
HH_PLATFORM_VER = New PropertyValue(String.Empty, GetType(String))
|
|
||||||
ParsePhotoBlock = New PropertyValue(True)
|
ParsePhotoBlock = New PropertyValue(True)
|
||||||
ParseVideoBlock = New PropertyValue(True)
|
ParseVideoBlock = New PropertyValue(True)
|
||||||
|
ParseReelsBlock = New PropertyValue(False)
|
||||||
ParseStoriesBlock = New PropertyValue(True)
|
ParseStoriesBlock = New PropertyValue(True)
|
||||||
|
|
||||||
UrlPatternUser = "https://www.facebook.com/{0}"
|
UrlPatternUser = "https://www.facebook.com/{0}"
|
||||||
@@ -77,7 +78,7 @@ Namespace API.Facebook
|
|||||||
#End Region
|
#End Region
|
||||||
#Region "BaseAuthExists, GetUserUrl, GetUserPostUrl, IsMyUser, IsMyImageVideo"
|
#Region "BaseAuthExists, GetUserUrl, GetUserPostUrl, IsMyUser, IsMyImageVideo"
|
||||||
Friend Overrides Function BaseAuthExists() As Boolean
|
Friend Overrides Function BaseAuthExists() As Boolean
|
||||||
Return Responser.CookiesExists And ACheck(HH_IG_APP_ID.Value)
|
Return Responser.CookiesExists And CBool(DownloadData_Impl.Value) 'And ACheck(HH_IG_APP_ID.Value)
|
||||||
End Function
|
End Function
|
||||||
Friend Overrides Function GetUserUrl(ByVal User As IPluginContentProvider) As String
|
Friend Overrides Function GetUserUrl(ByVal User As IPluginContentProvider) As String
|
||||||
Return DirectCast(User, UserData).GetProfileUrl
|
Return DirectCast(User, UserData).GetProfileUrl
|
||||||
|
|||||||
@@ -23,9 +23,11 @@ Namespace API.Facebook
|
|||||||
Private Const Name_IsNoNameProfile As String = "IsNoNameProfile"
|
Private Const Name_IsNoNameProfile As String = "IsNoNameProfile"
|
||||||
Private Const Name_OptionsParsed As String = "OptionsParsed"
|
Private Const Name_OptionsParsed As String = "OptionsParsed"
|
||||||
Private Const Name_VideoPageID As String = "VideoPageID"
|
Private Const Name_VideoPageID As String = "VideoPageID"
|
||||||
|
Private Const Name_ReelsPageID As String = "ReelsPageID"
|
||||||
Private Const Name_StoryBucket As String = "StoryBucket"
|
Private Const Name_StoryBucket As String = "StoryBucket"
|
||||||
Private Const Name_ParsePhotoBlock As String = "ParsePhotoBlock"
|
Private Const Name_ParsePhotoBlock As String = "ParsePhotoBlock"
|
||||||
Private Const Name_ParseVideoBlock As String = "ParseVideoBlock"
|
Private Const Name_ParseVideoBlock As String = "ParseVideoBlock"
|
||||||
|
Private Const Name_ParseReelsBlock As String = "ParseReelsBlock"
|
||||||
Private Const Name_ParseStoriesBlock As String = "ParseStoriesBlock"
|
Private Const Name_ParseStoriesBlock As String = "ParseStoriesBlock"
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Declarations"
|
#Region "Declarations"
|
||||||
@@ -37,15 +39,18 @@ Namespace API.Facebook
|
|||||||
Private IsNoNameProfile As Boolean = False
|
Private IsNoNameProfile As Boolean = False
|
||||||
Private OptionsParsed As Boolean = False
|
Private OptionsParsed As Boolean = False
|
||||||
Private Property VideoPageID As String = String.Empty
|
Private Property VideoPageID As String = String.Empty
|
||||||
|
Private Property ReelsPageID As String = String.Empty
|
||||||
Private Property StoryBucket As String = String.Empty
|
Private Property StoryBucket As String = String.Empty
|
||||||
Friend Property ParsePhotoBlock As Boolean = True
|
Friend Property ParsePhotoBlock As Boolean = True
|
||||||
Friend Property ParseVideoBlock As Boolean = True
|
Friend Property ParseVideoBlock As Boolean = True
|
||||||
|
Friend Property ParseReelsBlock As Boolean = False
|
||||||
Friend Property ParseStoriesBlock As Boolean = True
|
Friend Property ParseStoriesBlock As Boolean = True
|
||||||
Private Enum PageBlock As Integer
|
Private Enum PageBlock As Integer
|
||||||
Timeline = Sections.Timeline
|
Timeline = Sections.Timeline
|
||||||
Stories = Sections.Stories
|
Stories = Sections.Stories
|
||||||
Photos = 100
|
Photos = 100
|
||||||
Videos = 101
|
Videos = 101
|
||||||
|
Reels = Sections.Reels
|
||||||
Undefined = -1
|
Undefined = -1
|
||||||
End Enum
|
End Enum
|
||||||
#End Region
|
#End Region
|
||||||
@@ -67,6 +72,7 @@ Namespace API.Facebook
|
|||||||
With DirectCast(Obj, UserExchangeOptions)
|
With DirectCast(Obj, UserExchangeOptions)
|
||||||
ParsePhotoBlock = .ParsePhotoBlock
|
ParsePhotoBlock = .ParsePhotoBlock
|
||||||
ParseVideoBlock = .ParseVideoBlock
|
ParseVideoBlock = .ParseVideoBlock
|
||||||
|
ParseReelsBlock = .ParseReelsBlock
|
||||||
ParseStoriesBlock = .ParseStoriesBlock
|
ParseStoriesBlock = .ParseStoriesBlock
|
||||||
End With
|
End With
|
||||||
End If
|
End If
|
||||||
@@ -90,53 +96,85 @@ Namespace API.Facebook
|
|||||||
End If
|
End If
|
||||||
OptionsParsed = .Value(Name_OptionsParsed).FromXML(Of Boolean)(False)
|
OptionsParsed = .Value(Name_OptionsParsed).FromXML(Of Boolean)(False)
|
||||||
VideoPageID = .Value(Name_VideoPageID)
|
VideoPageID = .Value(Name_VideoPageID)
|
||||||
|
ReelsPageID = .Value(Name_ReelsPageID)
|
||||||
StoryBucket = .Value(Name_StoryBucket)
|
StoryBucket = .Value(Name_StoryBucket)
|
||||||
ParsePhotoBlock = .Value(Name_ParsePhotoBlock).FromXML(Of Boolean)(True)
|
ParsePhotoBlock = .Value(Name_ParsePhotoBlock).FromXML(Of Boolean)(True)
|
||||||
ParseVideoBlock = .Value(Name_ParseVideoBlock).FromXML(Of Boolean)(True)
|
ParseVideoBlock = .Value(Name_ParseVideoBlock).FromXML(Of Boolean)(True)
|
||||||
|
ParseReelsBlock = .Value(Name_ParseReelsBlock).FromXML(Of Boolean)(False)
|
||||||
ParseStoriesBlock = .Value(Name_ParseStoriesBlock).FromXML(Of Boolean)(True)
|
ParseStoriesBlock = .Value(Name_ParseStoriesBlock).FromXML(Of Boolean)(True)
|
||||||
Else
|
Else
|
||||||
updateNames.Invoke
|
updateNames.Invoke
|
||||||
.Add(Name_IsNoNameProfile, IsNoNameProfile.BoolToInteger)
|
.Add(Name_IsNoNameProfile, IsNoNameProfile.BoolToInteger)
|
||||||
.Add(Name_OptionsParsed, OptionsParsed.BoolToInteger)
|
.Add(Name_OptionsParsed, OptionsParsed.BoolToInteger)
|
||||||
.Add(Name_VideoPageID, VideoPageID)
|
.Add(Name_VideoPageID, VideoPageID)
|
||||||
|
.Add(Name_ReelsPageID, ReelsPageID)
|
||||||
.Add(Name_StoryBucket, StoryBucket)
|
.Add(Name_StoryBucket, StoryBucket)
|
||||||
.Add(Name_ParsePhotoBlock, ParsePhotoBlock.BoolToInteger)
|
.Add(Name_ParsePhotoBlock, ParsePhotoBlock.BoolToInteger)
|
||||||
.Add(Name_ParseVideoBlock, ParseVideoBlock.BoolToInteger)
|
.Add(Name_ParseVideoBlock, ParseVideoBlock.BoolToInteger)
|
||||||
|
.Add(Name_ParseReelsBlock, ParseReelsBlock.BoolToInteger)
|
||||||
.Add(Name_ParseStoriesBlock, ParseStoriesBlock.BoolToInteger)
|
.Add(Name_ParseStoriesBlock, ParseStoriesBlock.BoolToInteger)
|
||||||
End If
|
End If
|
||||||
End With
|
End With
|
||||||
End Sub
|
End Sub
|
||||||
#End Region
|
#End Region
|
||||||
|
#Region "Initializer"
|
||||||
|
Friend Sub New()
|
||||||
|
_ResponserAutoUpdateCookies = True
|
||||||
|
End Sub
|
||||||
|
#End Region
|
||||||
#Region "Download functions"
|
#Region "Download functions"
|
||||||
Private Token_dtsg As String = String.Empty
|
Private Class TokensException : Inherits Plugin.ExitException
|
||||||
Private Token_lsd As String = String.Empty
|
Friend ReadOnly Property BasicTokens As Boolean
|
||||||
|
Public Sub New(ByVal Message As String, ByVal _BasicTokens As Boolean)
|
||||||
|
MyBase.New(Message)
|
||||||
|
BasicTokens = _BasicTokens
|
||||||
|
End Sub
|
||||||
|
Friend Shared Sub SendToLog(ByVal Source As UserData, ByVal ex As TokensException, ByVal f As String)
|
||||||
|
ErrorsDescriber.Execute(EDP.SendToLog, New ErrorsDescriberException($"{Source.ToStringForLog()} ({f}): {ex.Message}",,, ex) With {
|
||||||
|
.SendToLogOnlyMessage = True, .ReplaceMainMessage = True})
|
||||||
|
End Sub
|
||||||
|
End Class
|
||||||
Private Token_Photosby As String = String.Empty
|
Private Token_Photosby As String = String.Empty
|
||||||
Private Limit As Integer = -1
|
Private Limit As Integer = -1
|
||||||
|
Private Sub WaitTimer()
|
||||||
|
If CInt(MySettings.RequestsWaitTimer_Any.Value) > 0 Then Thread.Sleep(CInt(MySettings.RequestsWaitTimer_Any.Value))
|
||||||
|
End Sub
|
||||||
|
Private Sub DisableDownload()
|
||||||
|
MySettings.DownloadData_Impl.Value = False
|
||||||
|
MyMainLOG = $"{Site} downloading is disabled until you update your credentials"
|
||||||
|
End Sub
|
||||||
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
|
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
|
||||||
Try
|
If CBool(MySettings.DownloadData_Impl.Value) Then
|
||||||
GetUserTokens(Token)
|
Try
|
||||||
LoadSavePostsKV(True)
|
If Responser.Headers.Value(IG.Header_IG_APP_ID).IsEmptyString Then Responser.Headers.Remove(IG.Header_IG_APP_ID)
|
||||||
Limit = If(DownloadTopCount, -1)
|
ResetBaseTokens()
|
||||||
If IsSavedPosts Then
|
GetUserTokens(Token)
|
||||||
DownloadData_SavedPosts(String.Empty, Token)
|
LoadSavePostsKV(True)
|
||||||
Else
|
Limit = If(DownloadTopCount, -1)
|
||||||
If DownloadImages And ParsePhotoBlock Then DownloadData_Photo(String.Empty, Token)
|
If IsSavedPosts Then
|
||||||
If DownloadVideos And ParseVideoBlock Then DownloadData_Video(String.Empty, Token)
|
DownloadData_SavedPosts(String.Empty, Token)
|
||||||
If (DownloadImages Or DownloadVideos) And ParseStoriesBlock Then DownloadData_Stories(Token)
|
Else
|
||||||
End If
|
If DownloadImages And ParsePhotoBlock Then DownloadData_Photo(String.Empty, Token)
|
||||||
LoadSavePostsKV(False)
|
If DownloadVideos And ParseVideoBlock Then DownloadData_Video(String.Empty, Token)
|
||||||
Finally
|
If DownloadVideos And ParseReelsBlock Then DownloadData_Reels(String.Empty, Token)
|
||||||
MySettings.UpdateResponserData(Responser)
|
If (DownloadImages Or DownloadVideos) And ParseStoriesBlock Then DownloadData_Stories(Token)
|
||||||
End Try
|
End If
|
||||||
|
LoadSavePostsKV(False)
|
||||||
|
Finally
|
||||||
|
MySettings.UpdateResponserData(Responser)
|
||||||
|
End Try
|
||||||
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
Private Const Header_fb_fr_name_Photo As String = "ProfileCometAppCollectionPhotosRendererPaginationQuery"
|
Private Const Header_fb_fr_name_Photo As String = "ProfileCometAppCollectionPhotosRendererPaginationQuery"
|
||||||
Private Const Header_fb_fr_name_Video As String = "PagesCometChannelTabAllVideosCardImplPaginationQuery"
|
Private Const Header_fb_fr_name_Video As String = "PagesCometChannelTabAllVideosCardImplPaginationQuery"
|
||||||
Private Const Header_fb_fr_name_Stories As String = "StoriesSuspenseContentPaneRootWithEntryPointQuery"
|
Private Const Header_fb_fr_name_Stories As String = "StoriesSuspenseContentPaneRootWithEntryPointQuery"
|
||||||
Private Const Header_fb_fr_name_SavedPosts As String = "CometSaveDashboardAllItemsPaginationQuery"
|
Private Const Header_fb_fr_name_SavedPosts As String = "CometSaveDashboardAllItemsPaginationQuery"
|
||||||
|
Private Const Header_fb_fr_name_Reels As String = "ProfileCometAppCollectionReelsRendererPaginationQuery"
|
||||||
Private Const DocID_Photo As String = "6684543058255697"
|
Private Const DocID_Photo As String = "6684543058255697"
|
||||||
Private Const DocID_Video As String = "24545934291687581"
|
Private Const DocID_Video As String = "24545934291687581"
|
||||||
Private Const DocID_Stories As String = "6771064226315961"
|
Private Const DocID_Stories As String = "6771064226315961"
|
||||||
Private Const DocID_SavedPosts As String = "7112228098805003"
|
Private Const DocID_SavedPosts As String = "7112228098805003"
|
||||||
|
Private Const DocID_Reels As String = "28517740954539304"
|
||||||
Private Const Graphql_UrlPattern As String = "https://www.facebook.com/api/graphql?lsd={0}&doc_id={1}&server_timestamps=true&fb_dtsg={3}&fb_api_req_friendly_name={2}&variables={4}"
|
Private Const Graphql_UrlPattern As String = "https://www.facebook.com/api/graphql?lsd={0}&doc_id={1}&server_timestamps=true&fb_dtsg={3}&fb_api_req_friendly_name={2}&variables={4}"
|
||||||
Private Const VideoHtmlUrlPattern As String = "https://www.facebook.com/watch/?v={0}"
|
Private Const VideoHtmlUrlPattern As String = "https://www.facebook.com/watch/?v={0}"
|
||||||
Private Sub DownloadData_Photo(ByVal Cursor As String, ByVal Token As CancellationToken)
|
Private Sub DownloadData_Photo(ByVal Cursor As String, ByVal Token As CancellationToken)
|
||||||
@@ -149,15 +187,15 @@ Namespace API.Facebook
|
|||||||
Dim pid As PostKV
|
Dim pid As PostKV
|
||||||
|
|
||||||
ValidateBaseTokens()
|
ValidateBaseTokens()
|
||||||
If Token_Photosby.IsEmptyString Then Throw New ArgumentNullException("Token_Photosby", "Unable to obtain token")
|
If Token_Photosby.IsEmptyString Then Throw New TokensException("Unable to obtain token 'Token_Photosby'", False)
|
||||||
|
|
||||||
URL = String.Format(Graphql_UrlPattern, Token_lsd, DocID_Photo, Header_fb_fr_name_Photo,
|
URL = String.Format(Graphql_UrlPattern, Token_lsd, DocID_Photo, Header_fb_fr_name_Photo, Token_dtsg_Var,
|
||||||
SymbolsConverter.ASCII.EncodeSymbolsOnly(Token_dtsg),
|
|
||||||
SymbolsConverter.ASCII.EncodeSymbolsOnly("{" & String.Format(VarPattern, Cursor, Token_Photosby) & "}"))
|
SymbolsConverter.ASCII.EncodeSymbolsOnly("{" & String.Format(VarPattern, Cursor, Token_Photosby) & "}"))
|
||||||
|
|
||||||
ResponserApplyDefs(Header_fb_fr_name_Photo)
|
ResponserApplyDefs(Header_fb_fr_name_Photo)
|
||||||
ThrowAny(Token)
|
ThrowAny(Token)
|
||||||
|
|
||||||
|
WaitTimer()
|
||||||
Dim r$ = Responser.GetResponse(URL)
|
Dim r$ = Responser.GetResponse(URL)
|
||||||
If Not r.IsEmptyString Then
|
If Not r.IsEmptyString Then
|
||||||
Using j As EContainer = JsonDocument.Parse(r)
|
Using j As EContainer = JsonDocument.Parse(r)
|
||||||
@@ -199,6 +237,8 @@ Namespace API.Facebook
|
|||||||
End If
|
End If
|
||||||
|
|
||||||
If newPostsDetected And Not nextCursor.IsEmptyString Then DownloadData_Photo(nextCursor, Token)
|
If newPostsDetected And Not nextCursor.IsEmptyString Then DownloadData_Photo(nextCursor, Token)
|
||||||
|
Catch tex As TokensException When Not tex.BasicTokens
|
||||||
|
TokensException.SendToLog(Me, tex, "data (photo)")
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
ProcessException(ex, Token, $"data (photo) downloading error [{URL}]",, Responser)
|
ProcessException(ex, Token, $"data (photo) downloading error [{URL}]",, Responser)
|
||||||
End Try
|
End Try
|
||||||
@@ -211,17 +251,17 @@ Namespace API.Facebook
|
|||||||
Dim newPostsDetected As Boolean = False
|
Dim newPostsDetected As Boolean = False
|
||||||
Dim pid As PostKV
|
Dim pid As PostKV
|
||||||
|
|
||||||
If VideoPageID.IsEmptyString Then GetVideoPageID(Token)
|
If VideoPageID.IsEmptyString Then GetVideoPageID(False, Token)
|
||||||
If VideoPageID.IsEmptyString Then Throw New ArgumentNullException("VideoPageID", "Unable to obtain VideoPageID")
|
If VideoPageID.IsEmptyString Then Throw New TokensException("Unable to obtain 'VideoPageID'", False)
|
||||||
ValidateBaseTokens()
|
ValidateBaseTokens()
|
||||||
|
|
||||||
URL = String.Format(Graphql_UrlPattern, Token_lsd, DocID_Video, Header_fb_fr_name_Video,
|
URL = String.Format(Graphql_UrlPattern, Token_lsd, DocID_Video, Header_fb_fr_name_Video, Token_dtsg_Var,
|
||||||
SymbolsConverter.ASCII.EncodeSymbolsOnly(Token_dtsg),
|
|
||||||
SymbolsConverter.ASCII.EncodeSymbolsOnly("{" & String.Format(VarPattern, If(Cursor.IsEmptyString, "null", $"""{Cursor}"""), VideoPageID) & "}"))
|
SymbolsConverter.ASCII.EncodeSymbolsOnly("{" & String.Format(VarPattern, If(Cursor.IsEmptyString, "null", $"""{Cursor}"""), VideoPageID) & "}"))
|
||||||
|
|
||||||
ResponserApplyDefs(Header_fb_fr_name_Video)
|
ResponserApplyDefs(Header_fb_fr_name_Video)
|
||||||
ThrowAny(Token)
|
ThrowAny(Token)
|
||||||
|
|
||||||
|
WaitTimer()
|
||||||
Dim r$ = Responser.GetResponse(URL)
|
Dim r$ = Responser.GetResponse(URL)
|
||||||
If Not r.IsEmptyString Then
|
If Not r.IsEmptyString Then
|
||||||
Using j As EContainer = JsonDocument.Parse(r)
|
Using j As EContainer = JsonDocument.Parse(r)
|
||||||
@@ -252,6 +292,8 @@ Namespace API.Facebook
|
|||||||
End If
|
End If
|
||||||
|
|
||||||
If newPostsDetected And Not nextCursor.IsEmptyString Then DownloadData_Video(nextCursor, Token)
|
If newPostsDetected And Not nextCursor.IsEmptyString Then DownloadData_Video(nextCursor, Token)
|
||||||
|
Catch tex As TokensException When Not tex.BasicTokens
|
||||||
|
TokensException.SendToLog(Me, tex, "data (video)")
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
ProcessException(ex, Token, $"data (video) downloading error [{URL}]",, Responser)
|
ProcessException(ex, Token, $"data (video) downloading error [{URL}]",, Responser)
|
||||||
End Try
|
End Try
|
||||||
@@ -266,15 +308,15 @@ Namespace API.Facebook
|
|||||||
Dim postDate As Date?
|
Dim postDate As Date?
|
||||||
|
|
||||||
ValidateBaseTokens()
|
ValidateBaseTokens()
|
||||||
If StoryBucket.IsEmptyString Then Throw New ArgumentNullException("StoryBucket", "Unable to obtain StoryBucket")
|
If StoryBucket.IsEmptyString Then Throw New TokensException("Unable to obtain 'StoryBucket'", False)
|
||||||
|
|
||||||
URL = String.Format(Graphql_UrlPattern, Token_lsd, DocID_Stories, Header_fb_fr_name_Stories,
|
URL = String.Format(Graphql_UrlPattern, Token_lsd, DocID_Stories, Header_fb_fr_name_Stories, Token_dtsg_Var,
|
||||||
SymbolsConverter.ASCII.EncodeSymbolsOnly(Token_dtsg),
|
|
||||||
SymbolsConverter.ASCII.EncodeSymbolsOnly("{" & String.Format(VarPattern, StoryBucket) & "}"))
|
SymbolsConverter.ASCII.EncodeSymbolsOnly("{" & String.Format(VarPattern, StoryBucket) & "}"))
|
||||||
|
|
||||||
ResponserApplyDefs(Header_fb_fr_name_Stories)
|
ResponserApplyDefs(Header_fb_fr_name_Stories)
|
||||||
ThrowAny(Token)
|
ThrowAny(Token)
|
||||||
|
|
||||||
|
WaitTimer()
|
||||||
Dim r$ = Responser.GetResponse(URL)
|
Dim r$ = Responser.GetResponse(URL)
|
||||||
If Not r.IsEmptyString Then r = RegexReplace(r, RParams.DM("[^\r\n]+", 0, EDP.ReturnValue))
|
If Not r.IsEmptyString Then r = RegexReplace(r, RParams.DM("[^\r\n]+", 0, EDP.ReturnValue))
|
||||||
If Not r.IsEmptyString Then
|
If Not r.IsEmptyString Then
|
||||||
@@ -320,10 +362,129 @@ Namespace API.Facebook
|
|||||||
End If
|
End If
|
||||||
End Using
|
End Using
|
||||||
End If
|
End If
|
||||||
|
Catch tex As TokensException When Not tex.BasicTokens
|
||||||
|
TokensException.SendToLog(Me, tex, "data (stories)")
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
ProcessException(ex, Token, $"data (stories) downloading error [{URL}]",, Responser)
|
ProcessException(ex, Token, $"data (stories) downloading error [{URL}]",, Responser)
|
||||||
End Try
|
End Try
|
||||||
End Sub
|
End Sub
|
||||||
|
Private Sub DownloadData_Reels(ByVal Cursor As String, ByVal Token As CancellationToken)
|
||||||
|
Dim URL$ = String.Empty
|
||||||
|
Const VarPattern$ = """count"":10,""cursor"":{0},""feedLocation"":""COMET_MEDIA_VIEWER"",""feedbackSource"":65,""focusCommentID"":null,""renderLocation"":null,""scale"":1,""useDefaultActor"":true,""id"":""{1}"",""__relay_internal__pv__FBReelsMediaFooter_comet_enable_reels_ads_gkrelayprovider"":true,""__relay_internal__pv__IsWorkUserrelayprovider"":false"
|
||||||
|
Try
|
||||||
|
Dim nextCursor$ = String.Empty
|
||||||
|
Dim newPostsDetected As Boolean = False
|
||||||
|
Dim nodeFound As Boolean = False
|
||||||
|
Dim pid As PostKV = Nothing
|
||||||
|
Dim __urlBase$ = String.Empty
|
||||||
|
Dim lines As List(Of String)
|
||||||
|
Dim j As EContainer, rr As EContainer
|
||||||
|
Dim jDataRoot As EContainer = Nothing
|
||||||
|
Dim indx% = -1
|
||||||
|
Dim s As New List(Of Sizes)
|
||||||
|
Dim videoIdNode$() = {"profile_reel_node", "node", "video", "id"}
|
||||||
|
|
||||||
|
Dim obtainBasePostData As Action = Sub()
|
||||||
|
If indx.ValueBetween(0, jDataRoot.Count - 1) Then
|
||||||
|
With jDataRoot(indx)
|
||||||
|
pid = New PostKV(String.Empty, .Item(videoIdNode).XmlIfNothingValue.
|
||||||
|
IfNullOrEmpty(.Value({"node"}, "id")), PageBlock.Reels)
|
||||||
|
pid.Code = $"Reels:{pid.ID}"
|
||||||
|
nextCursor = .Value("cursor")
|
||||||
|
If Not .Item(videoIdNode).XmlIfNothing.IsEmptyString Then
|
||||||
|
__urlBase = $"https://www.facebook.com/reel/{pid.ID}"
|
||||||
|
Else
|
||||||
|
__urlBase = String.Empty
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
Else
|
||||||
|
pid = Nothing
|
||||||
|
nextCursor = String.Empty
|
||||||
|
__urlBase = String.Empty
|
||||||
|
End If
|
||||||
|
End Sub
|
||||||
|
Dim createFile As Func(Of String, SFile, SFile) = Function(ByVal __url As String, ByVal cFile As SFile) As SFile
|
||||||
|
Dim f As New SFile(RegexReplace(__url, Regex_ReelsFilePattern))
|
||||||
|
If Not f.IsEmptyString Then Return f Else Return cFile
|
||||||
|
End Function
|
||||||
|
|
||||||
|
If ReelsPageID.IsEmptyString Then GetVideoPageID(True, Token)
|
||||||
|
If ReelsPageID.IsEmptyString Then Throw New TokensException("Unable to obtain 'ReelsPageID'", False)
|
||||||
|
ValidateBaseTokens()
|
||||||
|
|
||||||
|
URL = String.Format(Graphql_UrlPattern, Token_lsd, DocID_Reels, Header_fb_fr_name_Reels, Token_dtsg_Var,
|
||||||
|
SymbolsConverter.ASCII.EncodeSymbolsOnly("{" & String.Format(VarPattern, If(Cursor.IsEmptyString, "null", $"""{Cursor}"""), ReelsPageID) & "}"))
|
||||||
|
|
||||||
|
ResponserApplyDefs(Header_fb_fr_name_Reels)
|
||||||
|
ThrowAny(Token)
|
||||||
|
|
||||||
|
WaitTimer()
|
||||||
|
Dim r$ = Responser.GetResponse(URL)
|
||||||
|
If Not r.IsEmptyString Then
|
||||||
|
lines = r.StringToList(Of String)(vbCrLf).ListIfNothing
|
||||||
|
If lines.ListExists Then
|
||||||
|
For Each line$ In lines
|
||||||
|
j = JsonDocument.Parse(line, EDP.ReturnValue)
|
||||||
|
If j.ListExists Then
|
||||||
|
jDataRoot = j({"data", "node", "aggregated_fb_shorts", "edges"})
|
||||||
|
If jDataRoot.ListExists Then
|
||||||
|
|
||||||
|
With j({"extensions", "all_video_dash_prefetch_representations"})
|
||||||
|
If .ListExists Then
|
||||||
|
ProgressPre.ChangeMax(.Count)
|
||||||
|
For indx = 0 To .Count - 1
|
||||||
|
ProgressPre.Perform()
|
||||||
|
|
||||||
|
obtainBasePostData()
|
||||||
|
If Not pid.ID.IsEmptyString AndAlso Not PostKvExists(pid) Then
|
||||||
|
newPostsDetected = True
|
||||||
|
PostsKVIDs.ListAddValue(pid, LNC)
|
||||||
|
_TempPostsList.Add(pid.Code)
|
||||||
|
|
||||||
|
With .ItemF({indx, "representations"})
|
||||||
|
If .ListExists Then
|
||||||
|
s.Clear()
|
||||||
|
For Each rr In .Self : s.Add(New Sizes(rr.Value("width"), rr.Value("base_url"))) : Next
|
||||||
|
If s.Count > 0 Then s.RemoveAll(Function(ss) ss.Value = 0 Or ss.Data.IsEmptyString)
|
||||||
|
If s.Count > 0 Then
|
||||||
|
s.Sort()
|
||||||
|
_TempMediaList.ListAddValue(New UserMedia(s(0).Data, UTypes.Video) With {
|
||||||
|
.URL_BASE = __urlBase.IfNullOrEmpty(.URL_BASE),
|
||||||
|
.Post = pid.ID,
|
||||||
|
.File = createFile(s(0).Data, .File),
|
||||||
|
.SpecialFolder = "Reels*"
|
||||||
|
}, LNC)
|
||||||
|
s.Clear()
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
|
||||||
|
|
||||||
|
If Limit > 0 And _TempMediaList.Count >= Limit Then j.Dispose() : Exit Sub
|
||||||
|
Else
|
||||||
|
j.Dispose()
|
||||||
|
Exit Sub
|
||||||
|
End If
|
||||||
|
|
||||||
|
Next
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
|
||||||
|
End If
|
||||||
|
|
||||||
|
j.Dispose()
|
||||||
|
End If
|
||||||
|
Next
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
|
||||||
|
If newPostsDetected And Not nextCursor.IsEmptyString Then DownloadData_Reels(nextCursor, Token)
|
||||||
|
Catch tex As TokensException When Not tex.BasicTokens
|
||||||
|
TokensException.SendToLog(Me, tex, "data (reels)")
|
||||||
|
Catch ex As Exception
|
||||||
|
ProcessException(ex, Token, $"data (reels) downloading error [{URL}]",, Responser)
|
||||||
|
End Try
|
||||||
|
End Sub
|
||||||
Private Sub DownloadData_SavedPosts(ByVal Cursor As String, ByVal Token As CancellationToken)
|
Private Sub DownloadData_SavedPosts(ByVal Cursor As String, ByVal Token As CancellationToken)
|
||||||
Dim URL$ = String.Empty
|
Dim URL$ = String.Empty
|
||||||
Const VarPattern$ = """content_filter"":[],""count"":10,""cursor"":{0},""scale"":1,""use_case"":""SAVE_DEFAULT"""
|
Const VarPattern$ = """content_filter"":[],""count"":10,""cursor"":{0},""scale"":1,""use_case"":""SAVE_DEFAULT"""
|
||||||
@@ -335,13 +496,13 @@ Namespace API.Facebook
|
|||||||
Dim pid As PostKV
|
Dim pid As PostKV
|
||||||
|
|
||||||
ValidateBaseTokens()
|
ValidateBaseTokens()
|
||||||
URL = String.Format(Graphql_UrlPattern, Token_lsd, DocID_SavedPosts, Header_fb_fr_name_SavedPosts,
|
URL = String.Format(Graphql_UrlPattern, Token_lsd, DocID_SavedPosts, Header_fb_fr_name_SavedPosts, Token_dtsg_Var,
|
||||||
SymbolsConverter.ASCII.EncodeSymbolsOnly(Token_dtsg),
|
|
||||||
SymbolsConverter.ASCII.EncodeSymbolsOnly("{" & String.Format(VarPattern, If(Cursor.IsEmptyString, "null", $"""{Cursor}""")) & "}"))
|
SymbolsConverter.ASCII.EncodeSymbolsOnly("{" & String.Format(VarPattern, If(Cursor.IsEmptyString, "null", $"""{Cursor}""")) & "}"))
|
||||||
|
|
||||||
ResponserApplyDefs(Header_fb_fr_name_SavedPosts)
|
ResponserApplyDefs(Header_fb_fr_name_SavedPosts)
|
||||||
ThrowAny(Token)
|
ThrowAny(Token)
|
||||||
|
|
||||||
|
WaitTimer()
|
||||||
Dim r$ = Responser.GetResponse(URL)
|
Dim r$ = Responser.GetResponse(URL)
|
||||||
If Not r.IsEmptyString Then
|
If Not r.IsEmptyString Then
|
||||||
Using j As EContainer = JsonDocument.Parse(r)
|
Using j As EContainer = JsonDocument.Parse(r)
|
||||||
@@ -399,6 +560,7 @@ Namespace API.Facebook
|
|||||||
If Round > 0 Then ThrowAny(Token)
|
If Round > 0 Then ThrowAny(Token)
|
||||||
Dim script$, newUrl$
|
Dim script$, newUrl$
|
||||||
Dim jNode As EContainer, jNode2 As EContainer
|
Dim jNode As EContainer, jNode2 As EContainer
|
||||||
|
WaitTimer()
|
||||||
Dim r$ = resp.GetResponse(PostUrl)
|
Dim r$ = resp.GetResponse(PostUrl)
|
||||||
|
|
||||||
If Not r.IsEmptyString Then
|
If Not r.IsEmptyString Then
|
||||||
@@ -466,16 +628,28 @@ Namespace API.Facebook
|
|||||||
#End Region
|
#End Region
|
||||||
#Region "ValidateBaseTokens, GetVideoPageID, GetUserTokens"
|
#Region "ValidateBaseTokens, GetVideoPageID, GetUserTokens"
|
||||||
''' <exception cref="ArgumentNullException"></exception>
|
''' <exception cref="ArgumentNullException"></exception>
|
||||||
Private Sub ValidateBaseTokens()
|
Protected Overrides Function ValidateBaseTokens() As Boolean
|
||||||
If Token_dtsg.IsEmptyString Then Throw New ArgumentNullException("Token_dtsg", "Unable to obtain token")
|
Dim tokens$ = String.Empty
|
||||||
If Token_lsd.IsEmptyString Then Throw New ArgumentNullException("Token_lsd", "Unable to obtain token")
|
If Not ValidateBaseTokens(tokens) Then
|
||||||
End Sub
|
DisableDownload()
|
||||||
Private Sub GetVideoPageID(ByVal Token As CancellationToken)
|
Throw New TokensException($"Unable to obtain token(s) ({tokens}). Your credentials may have expired.", True)
|
||||||
Dim URL$ = $"{GetProfileUrl()}\videos"
|
Else
|
||||||
|
Return True
|
||||||
|
End If
|
||||||
|
End Function
|
||||||
|
Private Sub GetVideoPageID(ByVal GetReels As Boolean, ByVal Token As CancellationToken)
|
||||||
|
Dim URL$ = $"{GetProfileUrl()}\{IIf(GetReels, "reels", "videos")}"
|
||||||
Dim resp As Responser = HtmlResponserCreate()
|
Dim resp As Responser = HtmlResponserCreate()
|
||||||
Try
|
Try
|
||||||
|
WaitTimer()
|
||||||
Dim r$ = resp.GetResponse(URL)
|
Dim r$ = resp.GetResponse(URL)
|
||||||
If Not r.IsEmptyString Then VideoPageID = RegexReplace(r, Regex_VideoPageID)
|
If Not r.IsEmptyString Then
|
||||||
|
If GetReels Then
|
||||||
|
ReelsPageID = RegexReplace(r, Regex_ReelsPageID)
|
||||||
|
Else
|
||||||
|
VideoPageID = RegexReplace(r, Regex_VideoPageID)
|
||||||
|
End If
|
||||||
|
End If
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
ProcessException(ex, Token, "get video page ID",, resp)
|
ProcessException(ex, Token, "get video page ID",, resp)
|
||||||
Finally
|
Finally
|
||||||
@@ -486,14 +660,20 @@ Namespace API.Facebook
|
|||||||
Dim URL$ = If(IsSavedPosts, "https://www.facebook.com/saved", GetProfileUrl())
|
Dim URL$ = If(IsSavedPosts, "https://www.facebook.com/saved", GetProfileUrl())
|
||||||
Dim resp As Responser = HtmlResponserCreate()
|
Dim resp As Responser = HtmlResponserCreate()
|
||||||
Try
|
Try
|
||||||
Token_dtsg = String.Empty
|
ResetBaseTokens()
|
||||||
Token_lsd = String.Empty
|
|
||||||
Token_Photosby = String.Empty
|
Token_Photosby = String.Empty
|
||||||
|
WaitTimer()
|
||||||
Dim r$ = resp.GetResponse(URL)
|
Dim r$ = resp.GetResponse(URL)
|
||||||
If Not r.IsEmptyString Then
|
If Not r.IsEmptyString Then
|
||||||
If Responser.CookiesExists Then Responser.Cookies.Update(resp.Cookies)
|
If Responser.CookiesExists Then Responser.Cookies.Update(resp.Cookies)
|
||||||
Token_dtsg = RegexReplace(r, Regex_UserToken_dtsg)
|
ParseTokens(r, 0)
|
||||||
Token_lsd = RegexReplace(r, Regex_UserToken_lsd)
|
Dim app_id$ = RegexReplace(r, Regex_AppID)
|
||||||
|
If Not app_id.IsEmptyString Then
|
||||||
|
If Not AEquals(Of String)(MySettings.HH_IG_APP_ID.Value, app_id) Then
|
||||||
|
MySettings.HH_IG_APP_ID.Value = app_id
|
||||||
|
Responser.Headers.Add(IG.Header_IG_APP_ID, app_id)
|
||||||
|
End If
|
||||||
|
End If
|
||||||
Token_Photosby = RegexReplace(r, Regex_Photos_by)
|
Token_Photosby = RegexReplace(r, Regex_Photos_by)
|
||||||
If StoryBucket.IsEmptyString Then StoryBucket = RegexReplace(r, Regex_StoryBucket)
|
If StoryBucket.IsEmptyString Then StoryBucket = RegexReplace(r, Regex_StoryBucket)
|
||||||
If ID.IsEmptyString Then
|
If ID.IsEmptyString Then
|
||||||
@@ -511,8 +691,7 @@ Namespace API.Facebook
|
|||||||
#Region "Responser options"
|
#Region "Responser options"
|
||||||
Private Sub ResponserApplyDefs(ByVal __fb_friendly_name As String)
|
Private Sub ResponserApplyDefs(ByVal __fb_friendly_name As String)
|
||||||
With Responser
|
With Responser
|
||||||
.Headers.Add(ThreadsNet.UserData.Header_FB_LSD, Token_lsd)
|
UpdateHeadersGQL(__fb_friendly_name)
|
||||||
.Headers.Add(DeclaredNames.Header_FB_FRIENDLY_NAME, __fb_friendly_name)
|
|
||||||
.Method = "POST"
|
.Method = "POST"
|
||||||
.Accept = "*/*"
|
.Accept = "*/*"
|
||||||
.Referer = GetProfileUrl()
|
.Referer = GetProfileUrl()
|
||||||
@@ -532,14 +711,14 @@ Namespace API.Facebook
|
|||||||
.Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.SecFetchSite, "none"))
|
.Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.SecFetchSite, "none"))
|
||||||
.Add("Sec-Fetch-User", "?1")
|
.Add("Sec-Fetch-User", "?1")
|
||||||
.Add("Upgrade-Insecure-Requests", 1)
|
.Add("Upgrade-Insecure-Requests", 1)
|
||||||
Dim h$ = Responser.Headers.Value(IG.Header_Browser)
|
Dim cloneHeader As Action(Of String) = Sub(ByVal hName As String)
|
||||||
If Not h.IsEmptyString Then .Add(IG.Header_Browser, h)
|
Dim hValue$ = Responser.Headers.Value(hName)
|
||||||
h = Responser.Headers.Value(IG.Header_BrowserExt)
|
If Not hValue.IsEmptyString Then .Add(hName, hValue)
|
||||||
If Not h.IsEmptyString Then .Add(IG.Header_BrowserExt, h)
|
End Sub
|
||||||
h = .Value(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.SecChUaPlatform))
|
cloneHeader.Invoke(IG.Header_Browser)
|
||||||
If Not h.IsEmptyString Then .Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.SecChUaPlatform, h))
|
cloneHeader.Invoke(IG.Header_BrowserExt)
|
||||||
If ACheck(MySettings.HH_PLATFORM_VER.Value) Then _
|
cloneHeader.Invoke(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.SecChUaPlatform).Name)
|
||||||
.Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.SecChUaPlatformVersion, MySettings.HH_PLATFORM_VER.Value))
|
cloneHeader.Invoke(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.SecChUaPlatformVersion).Name)
|
||||||
.Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.SecChUaMobile, "?0"))
|
.Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.SecChUaMobile, "?0"))
|
||||||
.Add("Sec-Ch-Ua-Model", "")
|
.Add("Sec-Ch-Ua-Model", "")
|
||||||
End With
|
End With
|
||||||
@@ -615,48 +794,88 @@ Namespace API.Facebook
|
|||||||
HtmlResponserDispose(resp)
|
HtmlResponserDispose(resp)
|
||||||
End Try
|
End Try
|
||||||
End Sub
|
End Sub
|
||||||
|
Private Structure VideoResolution : Implements IComparable(Of VideoResolution)
|
||||||
|
Friend W As Integer
|
||||||
|
Friend H As Integer
|
||||||
|
Friend B As Integer
|
||||||
|
Friend U As String
|
||||||
|
Friend ReadOnly Property Wrong As Boolean
|
||||||
|
Get
|
||||||
|
Return W = 0 Or H = 0 Or B = 0 Or U.IsEmptyString
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
|
Private Function CompareTo(ByVal Other As VideoResolution) As Integer Implements IComparable(Of VideoResolution).CompareTo
|
||||||
|
Return CLng(Math.Max(W, H) * B).CompareTo(CLng(Math.Max(Other.W, Other.H) * Other.B)) * -1
|
||||||
|
End Function
|
||||||
|
End Structure
|
||||||
Protected Function ReparseSingleVideo(ByVal m As UserMedia, ByVal resp As Responser, ByRef result As Boolean) As UserMedia
|
Protected Function ReparseSingleVideo(ByVal m As UserMedia, ByVal resp As Responser, ByRef result As Boolean) As UserMedia
|
||||||
Const nameSD$ = "browser_native_sd_url"
|
Const nameSD$ = "browser_native_sd_url"
|
||||||
Const nameHD$ = "browser_native_hd_url"
|
Const nameHD$ = "browser_native_hd_url"
|
||||||
|
Const nameDPR$ = "all_video_dash_prefetch_representations"
|
||||||
Const pattern$ = "<script type=""application/json""[^\>]*data-sjs>([^<]+?{0}[^<]+)<"
|
Const pattern$ = "<script type=""application/json""[^\>]*data-sjs>([^<]+?{0}[^<]+)<"
|
||||||
Dim URL$ = String.Empty
|
Dim URL$ = String.Empty
|
||||||
Dim j As EContainer = Nothing
|
Dim j As EContainer = Nothing
|
||||||
Try
|
Try
|
||||||
Dim r$, script$, __url$
|
Dim r$ = String.Empty, script$ = String.Empty, __url$ = String.Empty
|
||||||
|
Dim isNewNodes As Boolean = False
|
||||||
|
Dim __date As Date? = Nothing
|
||||||
Dim jNode As EContainer
|
Dim jNode As EContainer
|
||||||
Dim jf As Predicate(Of EContainer) = Function(ee) Not ee.Name.IsEmptyString AndAlso (ee.Name.ToLower = nameSD Or ee.Name.ToLower = nameHD)
|
Dim jf As Predicate(Of EContainer) = Function(ee) Not ee.Name.IsEmptyString AndAlso (ee.Name.ToLower = nameSD Or ee.Name.ToLower = nameHD)
|
||||||
Dim re As RParams = RParams.DMS("", 1, RegexOptions.IgnoreCase, EDP.ReturnValue)
|
Dim re As RParams = RParams.DMS("", 1, RegexOptions.IgnoreCase, EDP.ReturnValue)
|
||||||
|
Dim nf As New XML.Base.NodeParams(nameDPR, True, True, True, True, 20)
|
||||||
|
Dim __extractScript As Action(Of String) = Sub(ByVal inputName As String)
|
||||||
|
re.Pattern = String.Format(pattern, inputName)
|
||||||
|
script = RegexReplace(r, re)
|
||||||
|
End Sub
|
||||||
If m.Post.ID.IsEmptyString Then
|
If m.Post.ID.IsEmptyString Then
|
||||||
URL = m.URL_BASE
|
URL = m.URL_BASE
|
||||||
Else
|
Else
|
||||||
URL = String.Format(VideoHtmlUrlPattern, m.Post.ID)
|
URL = String.Format(VideoHtmlUrlPattern, m.Post.ID)
|
||||||
End If
|
End If
|
||||||
|
WaitTimer()
|
||||||
r = resp.GetResponse(URL)
|
r = resp.GetResponse(URL)
|
||||||
If Not r.IsEmptyString Then
|
If Not r.IsEmptyString Then
|
||||||
re.Pattern = String.Format(pattern, nameHD)
|
__extractScript(nameHD)
|
||||||
script = RegexReplace(r, re)
|
If script.IsEmptyString Then __extractScript(nameSD)
|
||||||
If script.IsEmptyString Then
|
If script.IsEmptyString Then __extractScript(nameDPR) : isNewNodes = True
|
||||||
re.Pattern = String.Format(pattern, nameSD)
|
|
||||||
script = RegexReplace(r, re)
|
|
||||||
End If
|
|
||||||
If Not script.IsEmptyString Then
|
If Not script.IsEmptyString Then
|
||||||
j = JsonDocument.Parse(script)
|
j = JsonDocument.Parse(script)
|
||||||
If j.ListExists Then
|
If j.ListExists Then
|
||||||
j.SetSourceReferences()
|
j.SetSourceReferences()
|
||||||
jNode = j.Find(jf, True)
|
If isNewNodes Then
|
||||||
If Not jNode Is Nothing Then
|
jNode = j.GetNode({nf})
|
||||||
With DirectCast(jNode.Source, EContainer)
|
If Not jNode Is Nothing Then
|
||||||
__url = .Value(nameHD).IfNullOrEmpty(.Value(nameSD))
|
With jNode.ItemF({0, "representations"})
|
||||||
If Not __url.IsEmptyString Then
|
If .ListExists Then
|
||||||
m.URL = __url
|
Dim intE As New ErrorsDescriber(False, False, False, 0)
|
||||||
m.URL_BASE = URL
|
Dim intC As Func(Of String, Integer) = Function(__input) AConvert(Of Integer)(__input, intE)
|
||||||
m.Type = UTypes.Video
|
Dim dataV As List(Of VideoResolution) = .Select(Function(jj) New VideoResolution With {
|
||||||
m.File = CreateFileFromUrl(__url)
|
.W = intC(jj.Value("width")),
|
||||||
m.Post.Date = AConvert(Of Date)(.Value("publish_time"), UnixDate32Provider, Nothing)
|
.H = intC(jj.Value("height")),
|
||||||
result = True
|
.B = intC(jj.Value("bandwidth")),
|
||||||
Return m
|
.U = jj.Value("base_url")}).ListIfNothing
|
||||||
End If
|
If dataV.ListExists Then dataV.RemoveAll(Function(dd) dd.Wrong)
|
||||||
End With
|
If dataV.ListExists Then dataV.Sort() : __url = dataV(0).U : dataV.Clear() : __date = m.Post.Date
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
End If
|
||||||
|
Else
|
||||||
|
jNode = j.Find(jf, True)
|
||||||
|
If Not jNode Is Nothing Then
|
||||||
|
With DirectCast(jNode.Source, EContainer)
|
||||||
|
__url = .Value(nameHD).IfNullOrEmpty(.Value(nameSD))
|
||||||
|
If Not __url.IsEmptyString Then __date = AConvert(Of Date)(.Value("publish_time"), UnixDate32Provider, Nothing)
|
||||||
|
End With
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
If Not __url.IsEmptyString Then
|
||||||
|
m.URL = __url
|
||||||
|
m.URL_BASE = URL
|
||||||
|
m.Type = UTypes.Video
|
||||||
|
m.File = CreateFileFromUrl(__url)
|
||||||
|
m.Post.Date = __date
|
||||||
|
result = True
|
||||||
|
Return m
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
@@ -694,7 +913,10 @@ Namespace API.Facebook
|
|||||||
#End Region
|
#End Region
|
||||||
#Region "DownloadSingleObject"
|
#Region "DownloadSingleObject"
|
||||||
Protected Overrides Sub DownloadSingleObject_GetPosts(ByVal Data As IYouTubeMediaContainer, ByVal Token As CancellationToken)
|
Protected Overrides Sub DownloadSingleObject_GetPosts(ByVal Data As IYouTubeMediaContainer, ByVal Token As CancellationToken)
|
||||||
_ContentList.Add(New UserMedia(Data.URL, UTypes.VideoPre) With {.Post = CStr(AConvert(Of String)(Data.URL, Regex_VideoIDFromURL, String.Empty))})
|
_ContentList.Add(New UserMedia(Data.URL, UTypes.VideoPre) With {
|
||||||
|
.Post = CStr(AConvert(Of String)(Data.URL, Regex_VideoIDFromURL, String.Empty)),
|
||||||
|
.State = UStates.Missing
|
||||||
|
})
|
||||||
ReparseMissing(Token)
|
ReparseMissing(Token)
|
||||||
End Sub
|
End Sub
|
||||||
#End Region
|
#End Region
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ Namespace API.Facebook
|
|||||||
Friend Property ParsePhotoBlock As Boolean = True
|
Friend Property ParsePhotoBlock As Boolean = True
|
||||||
<PSetting(NameOf(SiteSettings.ParseVideoBlock), NameOf(MySettings))>
|
<PSetting(NameOf(SiteSettings.ParseVideoBlock), NameOf(MySettings))>
|
||||||
Friend Property ParseVideoBlock As Boolean = True
|
Friend Property ParseVideoBlock As Boolean = True
|
||||||
|
<PSetting(NameOf(SiteSettings.ParseReelsBlock), NameOf(MySettings))>
|
||||||
|
Friend Property ParseReelsBlock As Boolean = False
|
||||||
<PSetting(NameOf(SiteSettings.ParseStoriesBlock), NameOf(MySettings))>
|
<PSetting(NameOf(SiteSettings.ParseStoriesBlock), NameOf(MySettings))>
|
||||||
Friend Property ParseStoriesBlock As Boolean = True
|
Friend Property ParseStoriesBlock As Boolean = True
|
||||||
Private ReadOnly Property MySettings As SiteSettings
|
Private ReadOnly Property MySettings As SiteSettings
|
||||||
@@ -20,12 +22,14 @@ Namespace API.Facebook
|
|||||||
MySettings = u.HostCollection.Default.Source
|
MySettings = u.HostCollection.Default.Source
|
||||||
ParsePhotoBlock = u.ParsePhotoBlock
|
ParsePhotoBlock = u.ParsePhotoBlock
|
||||||
ParseVideoBlock = u.ParseVideoBlock
|
ParseVideoBlock = u.ParseVideoBlock
|
||||||
|
ParseReelsBlock = u.ParseReelsBlock
|
||||||
ParseStoriesBlock = u.ParseStoriesBlock
|
ParseStoriesBlock = u.ParseStoriesBlock
|
||||||
End Sub
|
End Sub
|
||||||
Friend Sub New(ByVal s As SiteSettings)
|
Friend Sub New(ByVal s As SiteSettings)
|
||||||
MySettings = s
|
MySettings = s
|
||||||
ParsePhotoBlock = s.ParsePhotoBlock.Value
|
ParsePhotoBlock = s.ParsePhotoBlock.Value
|
||||||
ParseVideoBlock = s.ParseVideoBlock.Value
|
ParseVideoBlock = s.ParseVideoBlock.Value
|
||||||
|
ParseReelsBlock = s.ParseReelsBlock.Value
|
||||||
ParseStoriesBlock = s.ParseStoriesBlock.Value
|
ParseStoriesBlock = s.ParseStoriesBlock.Value
|
||||||
End Sub
|
End Sub
|
||||||
End Class
|
End Class
|
||||||
|
|||||||
@@ -15,7 +15,12 @@ Namespace API.Instagram
|
|||||||
Friend Const InstagramSite As String = "Instagram"
|
Friend Const InstagramSite As String = "Instagram"
|
||||||
Friend Const InstagramSiteKey As String = "AndyProgram_Instagram"
|
Friend Const InstagramSiteKey As String = "AndyProgram_Instagram"
|
||||||
Friend ReadOnly FilesPattern As RParams = RParams.DMS(".+?([^/\?]+?\.[\w\d]{3,4})(?=(\?|\Z))", 1, EDP.ReturnValue)
|
Friend ReadOnly FilesPattern As RParams = RParams.DMS(".+?([^/\?]+?\.[\w\d]{3,4})(?=(\?|\Z))", 1, EDP.ReturnValue)
|
||||||
Friend Sub UpdateResponser(ByVal Source As IResponse, ByRef Destination As Responser)
|
Friend ReadOnly ObtainMedia_SizeFuncPic_RegexP As RParams = RParams.DMS("_p(\d+)x(\d+)", 1, EDP.ReturnValue)
|
||||||
|
Friend ReadOnly ObtainMedia_SizeFuncPic_RegexS As RParams = RParams.DMS("_s(\d+)x(\d+)", 1, EDP.ReturnValue)
|
||||||
|
Friend Const PageTokenRegexPatternDefault As String = "\[\],{""token"":""(.*?)""},\d+\]"
|
||||||
|
Friend ReadOnly Regex_UserToken_dtsg As RParams = RParams.DMS("DTSGInitialData["":,.\[\]]*?{\s*.token.:\s*""([^""]+)", 1, EDP.ReturnValue)
|
||||||
|
Friend ReadOnly Regex_UserToken_lsd As RParams = RParams.DMS("LSD["":,.\[\]]*?{\s*.token.:\s*""([^""]+)", 1, EDP.ReturnValue)
|
||||||
|
Friend Sub UpdateResponser(ByVal Source As IResponse, ByRef Destination As Responser, ByVal UpdateWwwClaim As Boolean)
|
||||||
Const r_wwwClaimName$ = "x-ig-set-www-claim"
|
Const r_wwwClaimName$ = "x-ig-set-www-claim"
|
||||||
Const r_tokenName$ = SiteSettings.Header_CSRF_TOKEN_COOKIE
|
Const r_tokenName$ = SiteSettings.Header_CSRF_TOKEN_COOKIE
|
||||||
If Not Source Is Nothing Then
|
If Not Source Is Nothing Then
|
||||||
@@ -32,17 +37,17 @@ Namespace API.Instagram
|
|||||||
Dim token$ = String.Empty
|
Dim token$ = String.Empty
|
||||||
With Source
|
With Source
|
||||||
If isInternal Then
|
If isInternal Then
|
||||||
If .HeadersExists Then wwwClaim = .Headers.Value(wwwClaimName)
|
If UpdateWwwClaim And .HeadersExists Then wwwClaim = .Headers.Value(wwwClaimName)
|
||||||
If .CookiesExists Then token = If(.Cookies.FirstOrDefault(Function(c) c.Name = tokenName)?.Value, String.Empty)
|
If .CookiesExists Then token = If(.Cookies.FirstOrDefault(Function(c) c.Name = tokenName)?.Value, String.Empty)
|
||||||
Else
|
Else
|
||||||
If .HeadersExists Then
|
If .HeadersExists Then
|
||||||
wwwClaim = .Headers.Value(wwwClaimName)
|
If UpdateWwwClaim Then wwwClaim = .Headers.Value(wwwClaimName)
|
||||||
token = .Headers.Value(tokenName)
|
token = .Headers.Value(tokenName)
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
End With
|
End With
|
||||||
|
|
||||||
If Not wwwClaim.IsEmptyString Then Destination.Headers.Add(SiteSettings.Header_IG_WWW_CLAIM, wwwClaim)
|
If UpdateWwwClaim And Not wwwClaim.IsEmptyString Then Destination.Headers.Add(SiteSettings.Header_IG_WWW_CLAIM, wwwClaim)
|
||||||
If Not token.IsEmptyString Then Destination.Headers.Add(SiteSettings.Header_CSRF_TOKEN, token)
|
If Not token.IsEmptyString Then Destination.Headers.Add(SiteSettings.Header_CSRF_TOKEN, token)
|
||||||
If Not isInternal Then
|
If Not isInternal Then
|
||||||
Destination.Cookies.Update(Source.Cookies, CookieKeeper.UpdateModes.ReplaceByNameAll, False, EDP.SendToLog)
|
Destination.Cookies.Update(Source.Cookies, CookieKeeper.UpdateModes.ReplaceByNameAll, False, EDP.SendToLog)
|
||||||
|
|||||||