Compare commits

...

457 Commits

Author SHA1 Message Date
Yaronzz f4854f4b74 Fix formatting issues in README.md
Build exe / build (macos-latest) (push) Has been cancelled
Build exe / build (ubuntu-latest) (push) Has been cancelled
Build exe / build (windows-latest) (push) Has been cancelled
2025-10-17 11:41:40 +08:00
Yaronzz 8352f0f6e2 UPDATE 2023-11-01 13:41:16 +08:00
Yaronzz a8da5c0ff3 Merge pull request #1106 from exislow/gui-playlists
[GUI] Show user's playlists and allow to download them.
2023-10-31 13:34:49 +08:00
Robert Honz df7c444487 Added playlist -> right click to download the whole playlist in "playlist style". 2023-10-31 06:08:40 +01:00
Robert Honz d88dca4da6 Style fix. 2023-10-23 21:55:57 +02:00
Robert Honz 88b5b61328 KeyPressEvent select all items. 2023-10-23 21:55:26 +02:00
Robert Honz 56c9cf5695 Refactoring: Mainly removed unused imports. 2023-10-23 15:00:06 +02:00
Robert Honz 379eca8458 Multiple title can be downloaded sequentially. 2023-10-23 14:34:14 +02:00
Robert Honz 7d6f9fc6e1 * Playlist content will be displayed in table.
* Can select multiple items to download.
2023-10-23 13:41:17 +02:00
Robert Honz 87eabab36f * Added tidalapi as dependency.
* Added TreeView to display user's playlists.
2023-10-22 21:16:20 +02:00
Robert Honz 288c75bcc7 Removed tidal. import. 2023-10-22 10:51:47 +02:00
Yaronzz 62d83b5975 update readme 2023-09-06 10:25:38 +08:00
Yaronzz 251af9e745 Merge branch 'master' of https://github.com/yaronzz/Tidal-Media-Downloader into master 2023-09-06 09:34:13 +08:00
Yaronzz 0751c37b35 update 2023-09-06 09:34:01 +08:00
Yaronzz 4f32b14441 1. Add quality 'MAX'
2. Try to parse 'dash+xml'
2023-09-06 09:31:50 +08:00
Yaronzz 97928ef207 Merge pull request #1075 from yaronzz/dependabot/pip/TIDALDL-PY/requests-2.31.0
Bump requests from 2.27.1 to 2.31.0 in /TIDALDL-PY
2023-07-13 08:41:48 +08:00
Yaronzz 9edd5967f0 Merge pull request #1078 from adibue/doc-link-fix
Fix links to documentation
2023-07-13 08:41:23 +08:00
Adrian Bühler 8449b85d81 Fix links to documentation 2023-06-14 15:57:28 +02:00
dependabot[bot] 2f4ad82421 Bump requests from 2.27.1 to 2.31.0 in /TIDALDL-PY
Bumps [requests](https://github.com/psf/requests) from 2.27.1 to 2.31.0.
- [Release notes](https://github.com/psf/requests/releases)
- [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md)
- [Commits](https://github.com/psf/requests/compare/v2.27.1...v2.31.0)

---
updated-dependencies:
- dependency-name: requests
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-23 03:22:30 +00:00
Yaronzz 513be57c3d fix getTrackPath bug 2022-12-21 09:16:22 +08:00
Yaronzz 3eb11252c2 Merge pull request #1006 from roberts91/made-video-download-optional
Made video download optional
2022-12-21 08:54:51 +08:00
Yaronzz b972f7cda8 Merge branch 'master' into made-video-download-optional 2022-12-21 08:51:23 +08:00
Yaronzz b1b643109c Merge pull request #1019 from DJSweder/patch-1
Update czech.py
2022-11-14 09:28:34 +08:00
Yaronzz c15ad63542 Merge pull request #1017 from Click1701/master
Update german.py
2022-11-14 09:27:29 +08:00
DJSweder 09321db35e Update czech.py
Some minor changes
2022-11-13 16:52:45 +01:00
Click1701 132e516250 Update german.py
Translated yet untranslated parts and other slight changes
2022-11-08 17:20:17 +01:00
Yaronzz a771c598ae upload new version 2022-10-31 14:08:07 +08:00
Yaronzz db76e84123 Merge pull request #1003 from Zibbp/master
fix(cover): return if no cover found
2022-10-31 13:37:45 +08:00
Yaronzz 7eb4419177 Merge pull request #1002 from bladeoner/stale
Update stale.yml
2022-10-31 13:36:28 +08:00
Yaronzz df3c405667 Merge pull request #1001 from grzekru/delay_setting
Add delay setting
2022-10-31 13:36:10 +08:00
Yaronzz 951fd102ad Merge pull request #999 from bladeoner/workflow
Update Github Workflow
2022-10-31 13:33:55 +08:00
Robert Sæther 252076f6dd Added missing translations 2022-10-31 04:27:30 +01:00
Robert Sæther 11828a0e8e Made video download optional when downloading playlists, albums or mixes 2022-10-31 02:30:57 +01:00
Isaac 93f363f405 fix(cover): return if no cover found 2022-10-28 10:02:27 -05:00
bladeoner 12a96d8a46 Update stale.yml 2022-10-26 08:21:25 +02:00
Grzegorz Krukar 238b2da4b3 Add delay setting 2022-10-25 23:51:16 +02:00
bladeoner 76313d68c9 Update Github Workflow 2022-10-21 13:36:42 +02:00
Yaronzz 4e8751ceb1 upload new version 2022-10-12 10:28:26 +08:00
Yaronzz 2dfcbad8f0 Merge pull request #995 from roberts91/added-playlist-format-option
Added option to control playlist folder format, added norwegian translations, translation file cleanup (all files now have same structure)
2022-10-12 10:17:57 +08:00
Robert Sæther 07d18ce2d6 Language file clean-up (all files has same structure), added norwegian translations 2022-10-10 15:36:29 +02:00
Robert Sæther 7fdd307176 Minor translation cleanup 2022-10-10 14:53:07 +02:00
Robert Sæther 11805382cc Removed duplicate translation 2022-10-10 14:18:07 +02:00
Robert Sæther 044a847e78 Added option to control playlist folder format 2022-10-10 01:22:47 +02:00
Yaronzz 6e49253e99 Merge pull request #992 from dansleboby/fix-issue-970-986
Fix issue #970 and #986
2022-09-27 10:44:18 +08:00
Gilbert Paquin 0c83717469 Only take streamReady track
This is when a track is still in the playlist and no longer on tidal, you can't play the song anymore through tidal

Fix Issue #970
2022-09-23 16:37:04 -04:00
Gilbert Paquin 7f1afb27f1 Random delay and long wait if for any reason the random delay too short
Fix issue #986
2022-09-23 16:35:55 -04:00
Yaronzz 18efb49213 Merge pull request #983 from omensight/master
Fix error when cover is not present
2022-09-13 09:42:46 +08:00
Mijael Viricochea Parra a275275cb6 Revert "Build file added for Windows"
This reverts commit 7e5b6d22c4.
2022-09-12 21:32:48 -04:00
Mijael Viricochea Parra 7e5b6d22c4 Build file added for Windows 2022-09-09 21:31:01 -04:00
Mijael Viricochea 96742046ba Fix error when cover is not present 2022-09-08 16:30:41 -04:00
Yaronzz 3199dcedc6 upload new version 2022-08-29 10:30:03 +08:00
Yaronzz 2cf59b3195 Fix #931 2022-08-29 10:25:50 +08:00
Yaronzz be84a3631a Merge pull request #974 from yohann69/patch-1
Update french.py
2022-08-23 09:16:24 +08:00
Yaronzz 9ce35af72f Merge pull request #967 from bladeoner/language
Update Hungarian language
2022-08-23 09:16:00 +08:00
Yohann 9d904a0fea Update french.py 2022-08-11 18:40:28 +02:00
bladeoner 5e05afd775 Update Hungarian language 2022-08-01 23:29:18 +02:00
Yaronzz dece506d58 Merge pull request #962 from DJSweder/patch-2
Update czech.py
2022-07-28 23:24:38 +08:00
DJSweder c2cc170988 Update czech.py
Correction of author's information.
2022-07-26 14:11:33 +02:00
DJSweder 3cab9ea295 Update czech.py
Corrections and completion translation into Czech language.
2022-07-26 10:18:10 +02:00
Yaronzz 5cf094d227 Merge pull request #946 from acherifi/add_artists_search_and_favorites
Add capability to perform an artist search and download all albums
2022-07-26 10:05:10 +08:00
Yaronzz 2e1e15ed3f Merge pull request #959 from KitDaCatsun/patch-2
Made errors in __post__ throw after 3 attempts
2022-07-26 10:02:57 +08:00
KitDaCatsun 7434470216 Made errors in __post__ throw after 3 attempts
`range(3)` gives `0, 1, 2` so `index >= 3` would never be reached. Assuming intended behavior was to throw if an error occurs on the third try and ignore errors on the first and second
2022-07-25 10:17:04 +01:00
Yaronzz 2ce2a310ae Merge pull request #958 from KitDaCatsun/patch-1
Removed unused assignment
2022-07-25 17:14:31 +08:00
KitDaCatsun dfc7af7796 Removed unused assignment
header set to {} then immediately given new value
2022-07-25 09:06:17 +01:00
Ali CHERIFI 63bf063dd3 Fix except block 2022-07-14 22:51:38 +02:00
Ali CHERIFI 3e8a3436b4 Add capability to perform an artist search and download all albums 2022-07-14 22:43:12 +02:00
Yaronzz e08e5efc88 upload new version 2022-07-14 09:54:54 +08:00
Yaronzz 7f3758e18c Fix bug of #945 2022-07-14 09:52:45 +08:00
Yaronzz 3e2d74a37f update readme 2022-07-08 11:15:13 +08:00
Yaronzz 69ccd65025 update readme 2022-07-08 11:11:49 +08:00
Yaronzz 81b82e6c29 update gui 2022-07-08 10:54:05 +08:00
Yaronzz 346befda6d update gui 2022-07-08 09:59:48 +08:00
Yaronzz 450102bfea Merge pull request #940 from Frikilinux/lang-es
Translate new options and fix typos
2022-07-08 08:34:11 +08:00
Frikilinux a966b3d93d Translate new options and fix typos 2022-07-07 19:01:27 -03:00
Yaronzz 55df515256 upload new version #936 2022-07-06 14:57:30 +08:00
Yaronzz 242747719a Mulithread download 2022-07-06 14:43:59 +08:00
Yaronzz e3c5886a02 upload v2022.6.30.1 2022-06-30 09:06:27 +08:00
Yaronzz 33c49b83db fix #934 2022-06-30 08:57:04 +08:00
Yaronzz ed13b9b92d check qt_material #933 2022-06-30 08:45:13 +08:00
Yaronzz e45f649e46 update readme 2022-06-27 17:38:10 +08:00
Yaronzz 0172301769 check api key 2022-06-27 11:16:00 +08:00
Yaronzz a7aa38e563 fix bug of #930 2022-06-24 18:30:53 +08:00
Yaronzz fd97a2b966 upload new version 2022-06-24 10:19:41 +08:00
Yaronzz e1ee47b93c update 2022-06-23 14:07:26 +08:00
Yaronzz 61b9dd3af8 update 2022-06-23 13:43:47 +08:00
Yaronzz 628a42b058 add require module 2022-06-23 13:38:40 +08:00
Yaronzz 2c392f0e22 upload new version 2022-06-23 11:55:19 +08:00
Yaronzz dc57d4d01d Merge pull request #927 from yaronzz/refactor
Refactor
2022-06-23 11:42:21 +08:00
Yaronzz 8ed83b1672 Merge remote-tracking branch 'remotes/origin/master' into refactor
# Conflicts:
#	README.md
#	TIDALDL-PY/tidal_dl/tidal.py
2022-06-23 11:38:42 +08:00
Yaronzz 3099820956 1. update setup.py 2022-06-23 11:26:33 +08:00
Yaronzz d643de43e9 1. add simple-gui 2022-06-23 10:03:17 +08:00
Yaronzz 39db4730c5 update README.md 2022-06-22 11:44:08 +08:00
Yaronzz 937aa7ca8f Merge pull request #924 from RandomNinjaAtk/patch-1
Bugfix for unable [ERR] {TITLE} parse ts urls failed
2022-06-21 15:22:42 +08:00
RandomNinjaAtk 84b9f6f6bc Bugfix for unable [ERR] {TITLE} parse ts urls failed
See issue: #872 

Tested and verified this change works locally.
2022-06-20 18:05:28 -04:00
Yaronzz b1ebd6f0b2 remove settings: onlyM4a 2022-06-20 17:34:41 +08:00
Yaronzz e1562ba30e 1. rebuild tidal-dl 2022-06-20 15:15:52 +08:00
Yaronzz 8876be13b6 fix bug of #916 2022-06-17 17:06:36 +08:00
Yaronzz 30a6c8c55a Merge pull request #896 from artiescie/master
for playlist dl, perform deletes as well as adds in the target dir
2022-06-09 11:47:09 +08:00
Yaronzz eb01de7f3a Merge pull request #912 from Blackjack200/master
improve chinese translation
2022-06-09 11:43:08 +08:00
Yaronzz e652556de2 skip 2022-06-07 08:41:21 +08:00
AZ1IDJC 00ef2f906f improve chinese translation 2022-06-05 23:28:09 +08:00
Yaronzz aba9493201 Merge pull request #903 from bladeoner/stale
Update stale job increase number of operations
2022-05-18 20:35:59 +08:00
bladeoner c78a56fff0 Update stale job increase number of operations 2022-04-26 10:59:06 +02:00
Richard Curzon 56bf0f9510 if there are .lrc lyric files, and corresponding music is deleted, then delete also the .lrc 2022-04-17 05:53:49 -04:00
Richard Curzon 2ebf80869c For playlist, remove TIDAL songs and redownload PL, the songs will be removed in the mirror image dl folder 2022-04-16 09:09:12 -04:00
Yaronzz bb5be5e5fb Merge pull request #895 from bladeoner/stale 2022-04-16 18:18:31 +08:00
bladeoner 5c2a13d4d1 Update stale messages 2022-04-16 12:02:36 +02:00
Yaronzz c61be4bbf3 update readme 2022-04-02 10:44:26 +08:00
Yaronzz a969583d79 update readme 2022-04-01 17:23:27 +08:00
Yaronzz 9f9a4f9aef update readme 2022-04-01 16:43:59 +08:00
Yaronzz 3b3af6a174 update workflow 2022-04-01 16:27:22 +08:00
Yaronzz 166961297e update workflow 2022-04-01 16:20:37 +08:00
Yaronzz 1f5343569f update workflow 2022-04-01 15:56:17 +08:00
Yaronzz 9e9d47f470 update workflow 2022-04-01 15:40:55 +08:00
Yaronzz 6870a8c37f update workflow 2022-04-01 15:11:27 +08:00
Yaronzz 4d368dd04d update workflow 2022-04-01 15:04:26 +08:00
Yaronzz 64b98ee117 update workflow 2022-04-01 12:34:05 +08:00
Yaronzz 5ec77efb19 update workflow 2022-04-01 12:27:41 +08:00
Yaronzz 65da2f7272 Create stale.yml 2022-04-01 11:52:32 +08:00
Yaronzz a5fb92db92 update workflow 2022-04-01 11:50:36 +08:00
Yaronzz 81e244f230 update workflow 2022-04-01 11:42:03 +08:00
Yaronzz 6a1b931340 update workflow 2022-04-01 11:38:02 +08:00
Yaronzz 8a21b01c1d update workflow 2022-04-01 11:25:21 +08:00
Yaronzz 96f46c2b59 update workflow 2022-04-01 10:32:42 +08:00
Yaronzz ffe335c17e update workflow 2022-04-01 10:18:21 +08:00
Yaronzz 79b537c186 update workflow 2022-04-01 09:56:59 +08:00
Yaronzz a806785609 update workflow 2022-04-01 09:50:11 +08:00
Yaronzz 06ff60ca74 update workflow 2022-04-01 09:47:00 +08:00
Yaronzz b34013129e update workflow 2022-04-01 09:30:38 +08:00
Yaronzz f1a5b1d764 update workflow 2022-04-01 09:27:40 +08:00
Yaronzz d52980506c Merge branch 'master' of https://github.com/yaronzz/Tidal-Media-Downloader into master 2022-04-01 09:27:06 +08:00
Yaronzz 34bab40d3d update 2022-04-01 09:26:55 +08:00
Yaronzz 747d06c7b4 Update util.py 2022-03-31 18:00:42 +08:00
Yaronzz 41573b7b39 Merge pull request #878 from bladeoner/language
Update Dutch language
2022-03-24 08:44:16 +08:00
bladeoner112@gmail.com d7e078db2e Update Dutch Language 2022-03-18 17:35:54 +01:00
392309221 363a854428 add m3u8dl.py 2022-03-14 15:55:22 +08:00
392309221 ad00099c9d Add video-path-format 2022-03-08 09:23:25 +08:00
392309221 6676a380e1 Add track-path-format 'TrackID' 2022-03-08 08:53:24 +08:00
Yaronzz bab13ff718 Merge pull request #877 from Kyo-70/patch-1
Update the Portuguese Translation
2022-03-07 15:14:40 +08:00
Yaronzz 9707c5c276 Merge branch 'master' into patch-1 2022-03-07 15:14:23 +08:00
Yaronzz 48206d675a Merge pull request #875 from PatrykMis/lng-polish
Add Polish translation, global typo fixes
2022-03-07 15:12:14 +08:00
Kyo-70 f877c184bb Update the Portuguese Translation
here is my contribution
2022-03-05 18:40:01 -04:00
Patryk Mis 59b360b285 Fix global typos 2022-03-04 19:59:44 +01:00
Patryk Mis 1a09571788 Add Polish translation 2022-03-04 19:49:47 +01:00
Yaronzz 2484a8d4d8 fix #874 2022-03-04 18:03:38 +08:00
Yaronzz 5e73ad35fa upload new version 2022-03-04 17:12:09 +08:00
Yaronzz 8503a622b0 1. fix #844 2022-03-04 17:02:30 +08:00
Yaronzz ab479300ea Merge pull request #871 from bladeoner/language
Add Dutch language
2022-03-02 10:12:49 +08:00
Yaronzz 96fb847479 Merge pull request #870 from bladeoner/workflow
Update Github Workflow
2022-03-02 10:12:40 +08:00
bladeoner 5484669333 Add Dutch language 2022-03-01 16:20:38 +01:00
bladeoner e366edbbea Update Github Workflow 2022-03-01 10:40:54 +01:00
Yaronzz e8ef25183d Merge pull request #864 from bladeoner/workflow
Add nightly build for tidal-dl and update README.md
2022-02-28 14:52:42 +08:00
Yaronzz c94c5283a7 Merge pull request #868 from bladeoner/requirements
Update requirements, add pydub and fix aigp warning
2022-02-28 09:12:53 +08:00
Yaronzz 77803c0b41 Merge pull request #869 from bladeoner/url
Update link to HTTPS
2022-02-28 09:12:18 +08:00
bladeoner b5bd4af56d Add nightly build for tidal-dl and update README.md 2022-02-27 17:36:09 +01:00
bladeoner 0a28baad64 Update link to HTTPS 2022-02-27 15:29:25 +01:00
bladeoner 6a1cd1d1d1 Update requirements, add pydub and fix aigp warning 2022-02-27 15:24:26 +01:00
392309221 25e72aa45e fix bug of setting path 2022-02-25 09:34:30 +08:00
Yaronzz 90f869fcdb Merge pull request #860 from bladeoner/reports
Replace bug, feature request and question reports
2022-02-23 10:00:47 +08:00
Yaronzz 72a2cb804a Merge pull request #858 from 9uyone/master
Update Ukrainian
2022-02-23 10:00:13 +08:00
bladeoner 752fb9e719 Replace bug, feature request and question reports 2022-02-22 11:14:15 +01:00
9uyone ac745e1434 correction of date in ukrainian.py 2022-02-20 23:02:08 +02:00
9uyone cbb4480d1e Update Ukrainian 2022-02-20 22:36:55 +02:00
Yaronzz a410370f45 update Hungarian #847 2022-02-11 08:40:00 +08:00
Yaronzz b8c4333d4e Merge pull request #846 from CDzungx/master
Update vietnamese.py
2022-02-11 08:37:09 +08:00
CDzungx 7e165f6c17 Update vietnamese.py
Update translations
2022-02-09 11:51:54 +07:00
Yaronzz c9ae7bfebd upload new version 2022-02-07 11:31:25 +08:00
Yaronzz 1d5b8cd8f6 Merge pull request #840 from 1nikolas/patch-1
New Api key
2022-02-07 08:42:16 +08:00
Yaronzz d41c8ddcae Merge pull request #836 from 9uyone/master
Update Ukrainian language
2022-02-07 08:40:08 +08:00
Nikolas Spiridakis 3d4b143c74 fix api key 2022-02-05 23:20:15 +02:00
Nikolas Spiridakis 5892525593 New Api key 2022-02-05 22:35:36 +02:00
9uyone ff0e794b8c Update ukrainian.py 2022-02-03 20:52:42 +02:00
Yaronzz 5f42afa31a Merge pull request #812 from Towe1ie/fix/set-access-token
Fix set access token typo and countryCode
2022-01-21 23:53:30 +08:00
Nemanja Lučić 2a56bee611 Format 2022-01-21 15:53:41 +01:00
Nemanja Lučić 685b7cb1f8 Format 2022-01-21 15:52:22 +01:00
Nemanja Lucic b0df00c0a3 Fix set access token typo and countryCode 2022-01-21 12:57:49 +01:00
Yaronzz 30917d1b0f Fix bug of "ReleaseDate" 2022-01-21 10:56:08 +08:00
Yaronzz 3848c4cf89 update 2022-01-21 09:40:51 +08:00
Yaronzz 753b6f6f76 Merge branch 'master' of https://github.com/yaronzz/Tidal-Media-Downloader into master 2022-01-21 09:17:05 +08:00
Yaronzz d6739dc63e upload new version 2022-01-21 09:16:45 +08:00
Yaronzz 4e14fb0501 Merge pull request #805 from Frikilinux/lang-es
Update Spanish language
2022-01-20 11:33:36 +08:00
Frikilinux 397ad9f823 Update Spanish language 2022-01-19 18:19:49 -03:00
Yaronzz d2218c58c1 Update FUNDING.yml 2022-01-18 17:34:02 +08:00
Yaronzz 7627c2a0f7 upload new version 2022-01-18 16:54:19 +08:00
Yaronzz 69a7ff6813 update gui 2022-01-18 11:59:37 +08:00
Yaronzz 133def9722 optimize code 2022-01-17 16:53:50 +08:00
Yaronzz 1b3afaabd0 upload new version 2022-01-11 17:40:38 +08:00
Yaronzz 9cb690378b upload new version 2022-01-11 17:37:51 +08:00
Yaronzz dd4b7254d9 Reset directory 2021-12-30 11:47:36 +08:00
yaronzz 394506e40d Optimize login 2021-12-28 17:42:14 +08:00
Yaronzz 6399cab7c4 Album folder format support: {None} 2021-12-27 17:37:28 +08:00
Yaronzz ba1a559a4b Settings: add type-folder(eg Album/Video/Playlist) 2021-12-27 17:00:45 +08:00
Yaronzz 41d7e30df5 upload new version 2021-11-30 11:08:32 +08:00
Yaronzz 94139c9f79 Merge pull request #750 from jee019/master
create Japanese translation file
2021-11-30 11:04:10 +08:00
jee019 5d4f8fb314 create Japanese translation 2021-11-30 11:43:31 +09:00
Yaronzz beae239007 Merge pull request #739 from jee019/master
update english.py & korean.py
2021-11-30 09:38:38 +08:00
jee019 f20c84eb6e Update english.py 2021-11-24 16:04:09 +09:00
jee019 588482707a Update korean.py 2021-11-24 16:03:25 +09:00
jee019 2ebb283119 Update english.py 2021-11-24 15:28:59 +09:00
jee019 3bfa300fad Update english.py 2021-11-24 15:24:31 +09:00
jee019 8ca30f65f3 Update korean.py 2021-11-24 15:23:17 +09:00
Yaronzz fa6a9fbbf8 upload new version 2021-11-21 01:46:13 +08:00
Yaronzz 8af25e0600 upload new version 2021-11-17 21:58:04 +08:00
Yaronzz 944b98c4b4 update 2021-11-15 23:20:15 +08:00
Yaronzz 8254a61389 Merge pull request #719 from hozzaq/patch-1
Update util.py
2021-11-15 23:08:49 +08:00
Haadiy Rozzaq d016c433ff Update util.py 2021-11-15 19:20:14 +07:00
Yaronzz 5e0b4303fd UPDATE README.md 2021-11-15 14:50:14 +08:00
Yaronzz dc1ba689c4 upload new version 2021-11-15 14:46:52 +08:00
Yaronzz fc96331c1c upload util.py 2021-11-15 14:19:51 +08:00
Yaronzz 6cc1805c48 Merge pull request #717 from CDzungx/patch-2
Update vietnamese.py
2021-11-15 14:16:56 +08:00
Yaronzz fa05a63adf Merge pull request #716 from jee019/master
Add Korean translation and improved English translation
2021-11-15 14:16:44 +08:00
CDzungx de26068faf Update vietnamese.py
Fix & translate new strings
2021-11-13 15:17:39 +07:00
jee019 273fef3526 Add files via upload 2021-11-12 11:19:23 +09:00
jee019 66b24c90e8 Fix grammatical errors 2021-11-11 20:28:43 +09:00
jee019 07e20b0f3d Update korean.py 2021-11-11 20:27:01 +09:00
jee019 133dd93dda new translation
translate into Korean
2021-11-11 20:24:17 +09:00
jee019 4bbd54a3b0 Add files via upload
translate into Korean
2021-11-11 20:18:58 +09:00
Yaronzz 49714129b1 Merge pull request #704 from grzekru/additional-tags
Additional tags for album path and track name + information in readme
2021-10-28 08:40:40 +08:00
Grzegorz Krukar 6fd2ec4a48 Additional tags for album path and track name + information in readme 2021-10-22 23:41:49 +02:00
Yaronzz f9f510fca1 Merge pull request #703 from backwards-rat-race/feature/album-artist-path
Add support for folder paths using only the main album artist name
2021-10-18 08:36:08 +08:00
backwards-rat-race d65d474462 Add support for creating a folder structure using only the main artists name for album via a AlbumArtistName path option 2021-10-17 15:16:48 +01:00
Yaronzz d8db1a4136 upload new version:v2021.9.23.1 2021-09-23 16:36:44 +08:00
Yaronzz 953edfc174 Support mixes 2021-09-23 16:29:24 +08:00
Yaronzz 580c707369 update README.md 2021-09-23 16:28:09 +08:00
Yaronzz b56973e7b3 Merge pull request #688 from Frikilinux/fix-lang
Fix grammatical errors and add new translations
2021-09-22 16:44:04 +08:00
Frikilinux 17ad5aed6e Fix grammatical errors and add new translations 2021-09-15 19:38:36 -03:00
Yaronzz e84185febb Get lyrics from tidal 2021-09-15 16:55:50 +08:00
Yaronzz ec9a4f2d90 update 2021-09-15 15:41:08 +08:00
Yaronzz c0088b04ce update gui 2021-09-15 15:40:23 +08:00
Yaronzz ae3347fc70 Merge pull request #687 from rgnet1/timed-lyrics
Timed lyrics - .lrc files
2021-09-15 14:28:33 +08:00
Ramzey ffa342d69e Changed wording of timed lyrics prompt 2021-09-14 21:33:11 -07:00
Ramzey 7676a7000d added lyrc file strings to language files 2021-09-14 20:56:06 -07:00
Ramzey 38ea6c307f added timed lyrics option 2021-09-14 20:21:40 -07:00
Yaronzz 2fc3140d26 update gui 2021-09-10 16:50:49 +08:00
Yaronzz 97efe6ba99 Merge branch 'master' of https://github.com/yaronzz/Tidal-Media-Downloader into master 2021-09-10 15:37:06 +08:00
yaronzz 27cca38398 Fix bug of "Illegal characters in path" 2021-09-09 18:44:44 +08:00
yaronzz ece21c126f update language 2021-09-09 15:58:46 +08:00
Yaronzz d035a7e01c Merge pull request #654 from neaumusic/fix-artist-and-remix-version-names
fix(artists): include all artist names
2021-09-09 09:54:55 +08:00
yaronzz 859503f518 upload GUI-CROSS Project 2021-09-02 17:54:59 +08:00
neaumusic 3cce1077b8 use album.artists not track.albumartists 2021-08-22 20:20:50 -07:00
Yaronzz da9a50829e Merge pull request #672 from Toastie/covers_with_playlists
Save covers when downloading songs from playlists into album folders.
2021-08-12 09:06:47 +08:00
Simon Kopischke 67f8337a7d Save covers when downloading songs from playlists.
If the option for saving covers is set to true and the playlist folder is not used, songs are saved according to their album. In this case album covers would now be saved too.
2021-08-05 14:16:38 +02:00
Yaronzz 79df599882 Update README.md 2021-07-14 09:24:53 +08:00
yaronzz 5ca25ac55d upload new version 2021-07-06 10:36:00 +08:00
Yaronzz a2eb174b68 Merge pull request #659 from Frikilinux/hungarian-lang
New language Hungarian
2021-07-02 13:58:53 +08:00
Yaronzz aedfa6cfda Merge pull request #660 from Frikilinux/fix-lang
Deleted extra lines
2021-07-02 13:57:57 +08:00
neaumusic 5b403f7342 fix(naming): fix artist and remix version names 2021-06-21 12:56:48 -07:00
Frikilinux 2f9b972157 Deleted extra lines 2021-06-20 15:53:54 -03:00
Frikilinux a7e49ed0c3 New language Hungarian 2021-06-20 15:33:49 -03:00
Yaronzz eafae6a2f7 Merge pull request #658 from djdembeck/patch-1
add lyricsgenius to requirements.txt
2021-06-18 08:27:48 +08:00
David Dembeck 93af46ca6d add lyricsgenius to requirements.txt 2021-06-17 15:03:14 -05:00
Yaronzz a71586b100 Merge pull request #653 from Gadgeteer234/Gadgeteer234-patch-1
Include version in track metadata
2021-06-16 17:20:58 +08:00
Yaronzz 0f2a829405 Merge pull request #656 from almirus/patch-1
Update russian.py
2021-06-16 17:19:10 +08:00
Yaronzz f4a40ea1bd Merge pull request #657 from Frikilinux/fix-typo
Fix typo in "quality" word
2021-06-16 17:18:49 +08:00
Frikilinux a90cc7f0d3 Fix typo in "quality" word 2021-06-15 20:31:05 -03:00
almirus 2b166bddd3 Update russian.py 2021-06-14 22:36:18 +03:00
Gadgeteer234 81312d979e Update download.py 2021-06-12 19:26:59 +02:00
Yaronzz 37c10f6887 Merge pull request #644 from CDzungx/patch-1
Update Vietnamese translations
2021-06-05 22:03:52 +08:00
Yaronzz 8bce18d142 Merge branch 'master' into patch-1 2021-06-05 22:03:43 +08:00
Yaronzz d0d854c88c Merge pull request #643 from Frikilinux/master
Fix language for Settings path
2021-06-05 22:02:48 +08:00
Yaronzz 6487568646 Merge branch 'master' into master 2021-06-05 22:02:40 +08:00
Yaronzz 23f8f1a75c Merge pull request #641 from Frikilinux/spanish
Translated Lyrics lines to Spanish
2021-06-05 22:00:31 +08:00
ZOTTA eacd1d09b6 Merge branch 'yaronzz:master' into master 2021-06-04 22:56:49 -03:00
CDzungx 9d903f6f15 Update Vietnamese translations 2021-05-31 23:33:26 +07:00
Yaronzz 44eeeb89f1 Update README.md 2021-05-31 14:52:06 +08:00
yaronzz f4d8a89336 upload new version 2021-05-31 09:54:03 +08:00
Frikilinux af6f9706fb Fix settigs path language 2021-05-30 22:48:36 -03:00
Frikilinux ac2671cdf0 Fix typo 2021-05-27 18:16:28 -03:00
Frikilinux 67aec8be03 Translated new lyrics lines 2021-05-27 18:11:49 -03:00
ZOTTA b23b292749 Merge pull request #1 from yaronzz/master
Sync Forked Repo
2021-05-27 17:54:41 -03:00
yaronzz e38a3c4b50 add lyrics 2021-05-27 19:33:02 +08:00
yaronzz 99e2039e1e upload new version 2021-05-25 10:57:53 +08:00
Yaronzz 96a2c10548 Merge pull request #639 from Wikidepia/fix-file
Replace __file__ to file
2021-05-21 09:34:30 +08:00
Yaronzz 7392b24c0b Merge pull request #635 from Frikilinux/spanish
Translated new spanish lines
2021-05-21 09:34:16 +08:00
Akmal b9a919ca55 Replace __file__ to file
__file__ supposed to be variable from Python
2021-05-21 07:54:12 +07:00
Frikilinux 158ea422e9 Translated new lines 2021-05-12 19:59:56 -03:00
yaronzz 72dffe5822 upload vv2021-04-30-1 2021-04-30 17:57:21 +08:00
yaronzz 13d2e70a43 Add 'AlbumInfo.txt' 2021-04-30 17:50:20 +08:00
yaronzz 33673d612e upload v2021-04-30 2021-04-30 17:01:17 +08:00
yaronzz 6aeac3ddb5 Fix bug of download video 2021-04-30 10:27:01 +08:00
yaronzz 75ca800dce upload version 2021.4.23.0 2021-04-23 09:16:21 +08:00
yaronzz cae74e8ebd Show get-quality 2021-03-29 10:42:50 +08:00
yaronzz ca3f544fc6 update language Danish 2021-03-29 10:01:46 +08:00
Yaronzz 2ace7ce319 Merge pull request #614 from KB885/master
Add Danish translation
2021-03-29 09:33:35 +08:00
Jacob 659f0a1fa6 Update language.py 2021-03-25 18:41:07 +00:00
Jacob 8e26911fd4 Create danish.py 2021-03-25 18:39:14 +00:00
yaronzz 7a2267eb7b upload new version 2021-03-24 19:22:22 +08:00
yaronzz 3127d281fa fix bug of download video.#612 #610 2021-03-24 19:15:40 +08:00
yaronzz fdac054187 upload new version 2021-03-24 09:03:01 +08:00
yaronzz fc2e899cdc Fix bug of #599 2021-03-18 11:08:20 +08:00
yaronzz 2b1f9198a5 fix bug of #606 2021-03-18 10:52:47 +08:00
yaronzz eb8b0ee57d Merge branch 'master' of https://github.com/yaronzz/Tidal-Media-Downloader into master 2021-02-20 09:51:37 +08:00
yaronzz 23638ecc80 upload new version 2021-02-20 09:45:21 +08:00
yaronzz 1e2423f7a1 1、add log 2021-02-20 09:09:09 +08:00
Yaronzz c245903066 Merge pull request #569 from therealgorgeous/patch-3
Update.
2021-01-08 17:21:05 +08:00
Yaronzz 927554a56c Merge pull request #576 from MineClashTV/patch-1
Update german.py
2021-01-08 17:20:48 +08:00
Pascal Puffke 0f43ca96b1 Update german.py
Completed translation and fixed a few minor mistakes
2021-01-04 17:59:33 +01:00
therealgorgeous 42db8237e7 Update.
CHOICE_LOGOUT = "Çıkış"
AUTH_START_LOGIN = "Giriş işlemleri başlatıldı..."
AUTH_LOGIN_CODE = "Girmen gereken kod: {}"
AUTH_NEXT_STEP = "Bu siteden {} hesabınıza giriş yapınız ve üstteki kodu giriniz. ({} dakikanız var.)"
AUTH_WAITING = "İşlemleri tamamlamanız bekleniyor..."
AUTH_TIMEOUT = "Lütfen size verilen süre içerisinde işlemleriniz tamamlayınız."
2020-12-22 14:59:40 +03:00
yaronzz f165976c8b Fix bug of download failed "stat: path should be string, bytes, os.PathLike or integer, not list" 2020-12-17 10:59:26 +08:00
yaronzz 75f840c6f8 Merge branch 'master' of https://github.com/yaronzz/Tidal-Media-Downloader into master 2020-12-16 10:14:01 +08:00
yaronzz 537eeebc04 Fix bug of "Connection aborted"(Linux platform) 2020-12-16 10:12:25 +08:00
Yaronzz 5dc30f430e Merge pull request #557 from geeksunny:reset-track-format-fix
Fix for track file format reset
2020-12-16 10:10:24 +08:00
Yaronzz f5de0125a4 Merge pull request #554 from moisespr123:atmos-tag
Trim album path
2020-12-16 10:08:29 +08:00
Justin Swanson 026ddac8a5 Fix for track file format reset 2020-12-11 18:11:23 -06:00
moisesmcardona 05b900ec4c Merge remote-tracking branch 'upstream/master' into atmos-tag 2020-12-10 13:08:48 -04:00
moisesmcardona 7453dab3e2 Trim album path 2020-12-10 13:08:27 -04:00
yaronzz 2c7f5b479f Merge branch 'master' of https://github.com/yaronzz/Tidal-Media-Downloader into master 2020-12-10 11:58:19 +08:00
yaronzz a7d47ca728 Add feature: set the accessToken manually 2020-12-10 11:57:45 +08:00
Yaronzz dc4d3565b9 Merge pull request #545 from moisespr123/atmos-tag
Add label [A] before albumtitle for Dolby Atmos content
2020-12-05 12:50:38 +08:00
moisesmcardona 6f8d2b0949 Add label [A] before albumtitle for Dolby Atmos content 2020-12-02 17:57:25 -04:00
yaronzz 3774497c09 upload new verison 2020-12-02 13:51:54 +08:00
yaronzz cfc7809327 update russian 2020-12-01 10:26:59 +08:00
Yaronzz fcfdb11b1e Merge pull request #541 from moisespr123:fix-settings-1
Settings: Restore default album and track file format by typing "default", and don't do anything if nothing is entered
2020-12-01 10:17:12 +08:00
moisesmcardona eccedb9a45 restore default album and track file format, and ignore if nothing if entered. 2020-11-26 15:54:37 -04:00
yaronzz 71d1c32114 Merge branch 'pr/moisespr123/528' of https://github.com/yaronzz/Tidal-Media-Downloader into master 2020-11-23 09:41:42 +08:00
yaronzz 73e3d20f0b Ability to download multiple urls at a time. 2020-11-23 09:40:41 +08:00
moisesmcardona 4e9532d51e Ability to download multiple urls at a time. 2020-11-17 20:26:08 -05:00
yaronzz 4754ac264b fix :releaseDate is none 2020-11-16 13:32:38 +08:00
yaronzz 4028f69875 fix bug of settings path 2020-11-13 18:42:16 +08:00
yaronzz 521881fc44 upload new version 2020-11-13 10:04:01 +08:00
yaronzz fa8958af57 Merge branch 'master' of https://github.com/yaronzz/Tidal-Media-Downloader into master 2020-11-13 09:45:43 +08:00
Yaronzz e7d9f8223e Merge pull request #525 from Frikilinux:spanish
Translated new features and fixed spelling
2020-11-13 09:45:07 +08:00
Yaronzz 7efbf57fd2 Merge pull request #524 from streetsamurai00mi:vi-VN
vi-VN updated translation for version 2020.11.9.0
2020-11-13 09:36:55 +08:00
Frikilinux 68fe880d77 Translated new features and fixed spelling 2020-11-12 19:12:58 -03:00
Minh Ngo 42ba56f9fc vi-VN updated translation 2020-11-13 00:35:12 +07:00
yaronzz 5602fab50f 1. add choice:logout; 2. update aigpy; 3. color login print 2020-11-12 09:40:34 +08:00
yaronzz 2a87764019 Merge branch 'master' of https://github.com/yaronzz/Tidal-Media-Downloader into master 2020-11-10 18:40:33 +08:00
Yaronzz 50f0b234d0 Merge pull request #517 from MarcusJohnson91/Independent-Config
Tidal-DL Now looks in the home folder for the config files instead of the current directory
2020-11-10 18:40:18 +08:00
yaronzz 3a11633ad9 Merge branch 'master' of https://github.com/yaronzz/Tidal-Media-Downloader into master
# Conflicts:
#	TIDALDL-PY/tidal_dl/download.py
2020-11-10 18:27:49 +08:00
yaronzz b1bb8191f0 upload updatelog.md 2020-11-10 18:20:37 +08:00
Yaronzz c89e39c4e6 Merge pull request #520 from moisespr123:strip-artist-album
Strip Artist and Album Title
2020-11-10 18:18:54 +08:00
moisesmcardona 63e9ace797 Strip Artist and Album title 2020-11-09 15:22:22 -05:00
moisesmcardona 5f9a985fca Merge branch 'master' of https://github.com/yaronzz/Tidal-Media-Downloader 2020-11-09 13:06:56 -05:00
Marcus Johnson e6cf8dbba1 Bumped the Time and Version numbers
Settings.py is 2.0 because of the incompatible filename change
2020-11-08 18:45:47 -08:00
Marcus Johnson 8f14c87f5f Made the config files be stored in the home folder so it will stop asking you to reenter your settings any time you happen to be CD'd to a diff folder
Also, renamed the token files so they make more sense.

UserSettings.json is now .tidal-dl.token.json

Settings.json is now .tidal-dl.json
2020-11-08 18:24:38 -08:00
Yaronzz f262ebf0a3 Merge pull request #516 from sporek:album-explicit-flag
Album flag respects the addExplicitTag setting
2020-11-09 09:45:51 +08:00
sporek 1ab94e4659 Album flag respects addExplicitTag
Removes the 'E' from the album folder name if addExplicitFlag is False.
2020-11-08 19:15:29 +00:00
Yaronzz 00fc75342e Merge pull request #515 from yaronzz/pr/sporek/511-2
Pr/sporek/511 2
2020-11-09 01:07:16 +08:00
Yaronzz 6d69c29aa3 Merge branch 'master' of https://github.com/yaronzz/Tidal-Media-Downloader into pr/sporek/511-2 2020-11-09 01:04:04 +08:00
Yaronzz a76bd2f564 Merge pull request #511 from sporek/OAuth2-login
Improved login flow using OAuth2
2020-11-09 01:03:49 +08:00
Yaronzz f2b088a4b3 update chinese language 2020-11-09 01:03:29 +08:00
Yaronzz 08670be579 Merge branch 'master' into OAuth2-login 2020-11-09 00:48:52 +08:00
Yaronzz 91f61b04a7 update LangTurkish 2020-11-09 00:40:08 +08:00
Yaronzz bc16c5df9c Merge pull request #504 from joyel24:master
Improved French Translation
2020-11-08 23:51:47 +08:00
sporek 5bfd9c4ce3 OAuth2
Updated translation templates to reflect the new login method. Any modified strings will be in English until translations can be contributed.
2020-11-07 20:29:40 -08:00
sporek a902152600 OAuth2
Added support for OAuth2 changes
2020-11-07 18:58:05 -08:00
sporek 72ae968746 OAuth2
Full OAuth2 login flow
2020-11-07 18:56:38 -08:00
joyel24 a73a7a0923 Improve French Translation 2020-10-25 12:33:13 +00:00
joyel24 d08601e2fd Improve French Translation 2020-10-25 12:21:27 +00:00
joyel24 7bba146e0b Merge pull request #2 from yaronzz/master
update from yaronzz repo
2020-10-25 12:56:02 +01:00
moisesmcardona 581650d68f Merge branch 'master' of https://github.com/yaronzz/Tidal-Media-Downloader into master 2020-10-24 15:36:17 -04:00
Yaronzz 43e93d9e0c upload new version 2020-10-22 00:57:35 +08:00
Yaronzz 784aa84ff0 Merge branch 'master' of https://github.com/yaronzz/Tidal-Media-Downloader 2020-10-22 00:54:31 +08:00
Yaronzz 3b17785566 Tag: composer 2020-10-22 00:54:05 +08:00
Yaronzz ed48ab74d6 Merge pull request #503 from Frikilinux/spanish
Added translate for new settings and fixed spelling
2020-10-21 08:33:37 +08:00
Frikilinux 7e9f1b044a Add translate for new settings and fixed spelling 2020-10-20 20:44:27 -03:00
Yaronzz bd449293a1 Settings: show progress 2020-10-21 00:13:26 +08:00
Yaronzz cfa31bcc4d Merge branch 'master' of https://github.com/yaronzz/Tidal-Media-Downloader
# Conflicts:
#	TIDALDL-PY/tidal_dl/lang/spanish.py
2020-10-20 23:47:16 +08:00
Yaronzz 8519ca0b58 Support language: german 2020-10-20 23:40:59 +08:00
Yaronzz 29ce61abc8 Support language: german 2020-10-20 23:40:49 +08:00
Yaronzz 3ec758076c Merge pull request #502 from Frikilinux/spanish
Correct spelling and change some words
2020-10-20 23:34:24 +08:00
Frikilinux ff34c0966b Correct spelling and change some words 2020-10-19 23:14:12 -03:00
moisesmcardona da82076632 Merge branch 'master' of https://github.com/yaronzz/Tidal-Media-Downloader into master 2020-10-19 12:28:42 -04:00
yaronzz 4f74d65554 Settings: album folder format、track file format 2020-10-19 10:54:13 +08:00
Yaronzz ea458c95c0 Merge pull request #494 from scottwedge/master
Fxes #493
2020-10-19 10:47:33 +08:00
Yaronzz 4e865733f8 Merge pull request #481 from Sematre/master
Add German translation
2020-10-19 10:46:24 +08:00
swedge 002b4a7c27 Fxes #493 2020-10-12 22:51:36 -04:00
moisesmcardona 9d4745fd14 Merge branch 'master' of https://github.com/yaronzz/Tidal-Media-Downloader into master 2020-10-02 10:02:14 -04:00
Sematre 598bce5567 Add German translation 2020-10-01 21:32:47 +02:00
Yaronzz 51fbf37693 Merge pull request #478 from streetsamurai00mi/vie
vi-VN updated translation
2020-09-27 23:54:24 +08:00
Minh Ngo f127f6dde7 vi-VN updated translation 2020-09-27 22:16:54 +07:00
Yaronzz 03a844b4ce update 2020-09-26 16:38:07 +08:00
Yaronzz 888fa440f5 Support language vietnamese 2020-09-26 04:01:34 +08:00
Yaronzz 8456625dfe update README.md 2020-09-26 03:58:46 +08:00
Yaronzz 77e8e1b480 Merge pull request #461 from streetsamurai00mi/vie
add vietnamese.py
2020-09-26 03:46:25 +08:00
Yaronzz 12f32d9adb - Fix: download video failed. Resolution parse error.
- Windows: auto get accessToken from tidaldesktop cache
2020-09-26 03:24:11 +08:00
Yaronzz 434270bdbb - Fix: download video failed. Resolution parse error.
- Windows: auto get accessToken from tidaldesktop cache
2020-09-26 03:23:57 +08:00
Yaronzz aee587d5be just change Turkish language 2020-09-25 01:09:45 +08:00
Yaronzz 7658cd27f3 update turkish language 2020-09-25 01:02:56 +08:00
yaronzz 9028af6636 add contributors 2020-09-21 19:14:08 +08:00
Minh Ngo 2d8f3f0b62 add vietnamese.py 2020-09-16 21:22:13 +07:00
Yaronzz 65c92caf14 Create FUNDING.yml 2020-09-15 00:25:17 +08:00
Yaronzz f274b31c74 Add language-Ukrainian 2020-09-10 01:21:23 +08:00
Yaronzz a6e27f1b3c usage by command: tidal-dl --help 2020-09-06 23:58:49 +08:00
moisesmcardona e8ffdd08b7 Merge branch 'master' of https://github.com/yaronzz/Tidal-Media-Downloader into master 2020-09-05 17:47:12 -04:00
Yaronzz ae3611b69a #### v2020-08-30
- support language portuguese
- multithreading download a track
2020-08-30 11:11:52 +08:00
Yaronzz 6ca02a5e31 add language: portuguese 2020-08-25 16:29:19 +08:00
Yaronzz 3d4a0fb749 fix: macos - downlod failed 2020-08-24 00:08:02 +08:00
Yaronzz c6b8487bb9 add errmsg when downloading failed 2020-08-23 00:50:24 +08:00
Yaronzz e2be8da456 support language spanish\croatian 2020-08-22 23:36:45 +08:00
moisesmcardona fabb23c313 Merge branch 'master' of https://github.com/yaronzz/Tidal-Media-Downloader into master 2020-08-20 07:42:42 -04:00
Yaronzz 0df6b9c5a9 add czech language 2020-08-20 19:04:01 +08:00
Yaronzz 74045121f7 update language 2020-08-20 18:53:47 +08:00
Yaronzz 97dcdcd5ff Merge pull request #430 from manolab/patch-1
Create italian.py
2020-08-20 18:48:19 +08:00
Yaronzz 54513b8dd5 Add Turkish Language 2020-08-20 18:43:35 +08:00
Normando Marcolongo 31e1fb7470 Create italian.py 2020-08-20 12:35:42 +02:00
Yaronzz 72f15692cd multi-language 2020-08-19 17:36:54 +08:00
Yaronzz f88da7dfbc update README.md 2020-08-19 11:48:03 +08:00
Yaronzz c522744752 update 2020-08-19 11:20:43 +08:00
Yaronzz af31d06612 Merge pull request #421 from yaronzz/dependabot/pip/TIDALDL-PY/requests-2.20.0
Bump requests from 2.18.4 to 2.20.0 in /TIDALDL-PY
2020-08-19 11:14:46 +08:00
Yaronzz 1b09ff98ce ignore 2020-08-19 10:42:52 +08:00
dependabot[bot] efebe46537 Bump requests from 2.18.4 to 2.20.0 in /TIDALDL-PY
Bumps [requests](https://github.com/psf/requests) from 2.18.4 to 2.20.0.
- [Release notes](https://github.com/psf/requests/releases)
- [Changelog](https://github.com/psf/requests/blob/master/HISTORY.md)
- [Commits](https://github.com/psf/requests/compare/v2.18.4...v2.20.0)

Signed-off-by: dependabot[bot] <support@github.com>
2020-08-19 02:41:28 +00:00
Yaronzz f564c3147f code rebuild 2020-08-19 10:40:38 +08:00
moisesmcardona 7bbd0d0fcf Merge branch 'master' of https://github.com/yaronzz/Tidal-Media-Downloader into master 2020-08-12 09:18:52 -04:00
Yaronzz c282481c86 update README.md 2020-08-07 12:59:36 +08:00
Yaronzz bb0de655ed update README.md 2020-08-06 23:14:05 +08:00
moisesmcardona 5a007d4ef3 Merge branch 'master' of https://github.com/yaronzz/Tidal-Media-Downloader 2020-07-17 08:01:28 -04:00
Yaronzz f63549e063 Upload new version 2020-07-16 03:33:35 +08:00
moisesmcardona 9951c0a200 Merge branch 'master' of https://github.com/yaronzz/Tidal-Media-Downloader 2020-07-05 19:47:12 -04:00
Yaronzz 7b56f5065f upload new version(gui) 2020-07-03 13:19:13 +08:00
Yaronzz 6ada0fb36f upload new version(cli) 2020-07-03 13:07:47 +08:00
moisesmcardona 0ab3b1d6f4 Merge branch 'master' of https://github.com/yaronzz/Tidal-Media-Downloader 2020-07-01 11:12:15 -04:00
Yaronzz e1375ae827 update README.md 2020-06-29 15:42:11 +08:00
Yaronzz ca0352ef61 ignoreCertificate 2020-06-29 15:39:04 +08:00
Yaronzz 86465503b5 upload new version 2020-06-28 17:58:53 +08:00
Yaronzz b2f1d005cd Merge branch 'master' of https://github.com/yaronzz/Tidal-Media-Downloader 2020-06-28 16:29:04 +08:00
Yaronzz f87802ebdf - Fix bug of login err
- Show track-codec when downloading
- Show audioModes on info-page
2020-06-28 16:28:48 +08:00
moisesmcardona b551f35337 Merge branch 'master' of https://github.com/yaronzz/Tidal-Media-Downloader 2020-06-26 11:40:01 -04:00
Yaronzz 08cb252f12 Update README.md 2020-06-26 21:35:44 +08:00
moisesmcardona f6e44d4a34 Merge branch 'master' of https://github.com/yaronzz/Tidal-Media-Downloader 2020-06-25 07:45:36 -04:00
Yaronzz b069b8854d Add AlbumID after album-folder-name (settings IDBeforeFolder) 2020-06-25 01:59:42 +08:00
moisesmcardona 2ba8765e77 Merge branch 'master' of https://github.com/yaronzz/Tidal-Media-Downloader 2020-06-22 21:49:58 -04:00
Yaronzz 7fb7e52ab3 Fix bug of login(GUI) 2020-06-23 01:29:23 +08:00
moisesmcardona 973d06b02a Merge branch 'master' of https://github.com/yaronzz/Tidal-Media-Downloader 2020-06-17 19:27:41 -04:00
Yaronzz 44e670f87d Fix bug of long-file-path 2020-06-17 01:08:41 +08:00
Yaronzz 3a7b81c6d0 Merge branch 'master' of https://github.com/yaronzz/Tidal-Media-Downloader 2020-06-16 00:55:36 +08:00
Yaronzz 1578625fb6 fix getstream err 2020-06-16 00:55:09 +08:00
Yaronzz d834b00353 Another login method for gui 2020-06-16 00:53:31 +08:00
Yaronzz c8bbe83265 Merge pull request #325 from onefourthreeNX/master
fix albums with space in name
2020-06-14 16:18:25 +08:00
Yaronzz 449f4fde39 update README.md 2020-06-14 13:44:43 +08:00
Yaronzz 75c275dd31 upload updatelog.md 2020-06-14 13:33:41 +08:00
Yaronzz dc56206c87 Upload new version 2020-06-14 13:28:09 +08:00
onefourthreeNX f1df4fe92d fix albums with space in name
some albums have spaces in the name. this fixes that issue.
2020-06-08 20:59:52 -06:00
Yaronzz 49b6d429ad Upload new version 2020-06-09 02:34:04 +08:00
Yaronzz 2315daac2c - Reduce the number of logins
- If one token is invalid, it is allowed to use only the other
2020-06-09 02:31:09 +08:00
Yaronzz 21b3e1340d Merge branch 'master' of https://github.com/yaronzz/Tidal-Media-Downloader 2020-06-09 01:23:27 +08:00
Yaronzz 99df194302 - Fix bug of getTrack
- Add errmessage(convert mp4 to m4a failed) #288
- Check All/Uncheck All #248
2020-06-09 01:23:08 +08:00
Yaronzz b643649848 temporary-use 2020-06-08 22:47:27 +08:00
Yaronzz 5066ef7932 Update tokens.json 2020-06-08 18:07:17 +08:00
Yaronzz ca7428c06d Update tokens.json 2020-06-08 18:02:46 +08:00
Yaronzz 8cb8395076 update token 2020-06-06 23:44:58 +08:00
moisesmcardona e59a5d1b8e Merge branch 'master' of https://github.com/yaronzz/Tidal-Media-Downloader 2020-06-03 08:19:53 -04:00
Yaronzz 926a147e25 (GUI)upload new version 2020-05-31 22:54:31 +08:00
Yaronzz aaf4310d63 (CLI) upload new version 2020-05-31 22:50:03 +08:00
moisesmcardona 6915c658ff merge 2020-05-29 14:33:34 -04:00
Yaronzz afcb915d09 Fix bug of getstream 2020-05-30 01:45:35 +08:00
moisesmcardona 5418403887 Merge branch 'master' of https://github.com/yaronzz/Tidal-Media-Downloader 2020-05-28 18:46:20 -04:00
Yaronzz 4a309daf48 Merge branch 'master' of https://github.com/yaronzz/Tidal-Media-Downloader 2020-05-28 13:07:24 +08:00
Yaronzz 7b06951119 Use CDN request 2020-05-28 13:06:48 +08:00
Yaronzz b619e2d178 Use another token(lossless download m4a) 2020-05-28 11:51:23 +08:00
moisesmcardona 05646cfdf3 Merge 2020-05-26 10:27:24 -04:00
moisesmcardona 1ea18455f9 Merge branch 'master' of https://github.com/yaronzz/Tidal-Media-Downloader 2020-04-07 14:22:46 -04:00
moisesmcardona 39dab5b134 Solution changes 2020-04-07 14:21:58 -04:00
joel 2608174dfa Merge branch 'master' of https://github.com/yaronzz/Tidal-Media-Downloader 2020-03-30 12:25:02 +02:00
moisesmcardona 93368cc4ac Merge branch 'master' of https://github.com/yaronzz/Tidal-Media-Downloader 2020-03-24 09:45:13 -04:00
moisesmcardona 273fc96e10 Merge 2020-03-22 09:16:35 -04:00
joyel24 0381dbb4fa Merge 2020-02-28 13:54:06 +01:00
221 changed files with 6843 additions and 39880 deletions
+3 -3
View File
@@ -1,3 +1,3 @@
*.xaml linguist-language=csharp
*.cs linguist-language=csharp
*.py linguist-language=python
*.py linguist-language=python
*.xaml linguist-language=csharp
*.cs linguist-language=csharp
+14
View File
@@ -0,0 +1,14 @@
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: yaronzz
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
custom: ['https://www.buymeacoffee.com/yaronzz']
+64
View File
@@ -0,0 +1,64 @@
name: Bug Report
description: Create a bug report to help us improve.
title: "[BUG]: "
labels: bug
body:
- type: markdown
attributes:
value: |
Please search for this issue in issues-page first. Avoid duplication.
Please read Wiki first.
https://github.com/yaronzz/Tidal-Media-Downloader/wiki
- type: textarea
id: which-tool
attributes:
label: Which tool
description: Describe which tool has been used.
placeholder: |
tidal-gui or tidal-dl
validations:
required: true
- type: textarea
id: version
attributes:
label: Version
description: Describe the version of the tool.
placeholder: |
eg 2019.12.1.0
validations:
required: true
- type: textarea
id: platform
attributes:
label: Platform
description: Describe the platform on which the tool has been used.
placeholder: |
Windows\Linux\Macos\Android
validations:
required: true
- type: textarea
id: describe-bug
attributes:
label: Describe the bug
description: Describe the bug as accurately as possible.
placeholder: |
How to reappear this bug?
Which albumID\trackID\artistID?
Please describe in detail.
validations:
required: true
- type: textarea
id: logs
attributes:
label: Relevant log output
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
render: shell
validations:
required: false
- type: textarea
id: screenshots
attributes:
label: Add screenshots
description: Please add screenshots if available.
validations:
required: false
-25
View File
@@ -1,25 +0,0 @@
---
name: Bug report
about: Create a bug report to help us improve
title: "[BUG] xxxxxxxxxxxxx"
labels: bug
---
<!-- Please search for this issue in issues-page first. Avoid duplication. -->
<!-- Please read Wiki first. -->
<!-- https://github.com/yaronzz/Tidal-Media-Downloader/wiki -->
**Which tool**
<!-- tidal-gui or tidal-dl -->
**Version**
<!-- eg 2019.12.1.0 -->
**Platform**
<!-- Windows\Linux\Macos\Android -->
**Bug description**
<!-- How to reappear this bug?
Which albumID\trackID\artistID?
Please describe in detail. -->
**Screenshot**
+1
View File
@@ -0,0 +1 @@
blank_issues_enabled: false
+34
View File
@@ -0,0 +1,34 @@
name: Feature Request
description: Open a feature request to Tidal-Media-Downloader.
title: "[FEATURE]: "
labels: feature request
body:
- type: markdown
attributes:
value: |
Please search for this issue in issues-page first. Avoid duplication.
Please read Wiki first.
https://github.com/yaronzz/Tidal-Media-Downloader/wiki
- type: textarea
id: which-tool
attributes:
label: Which tool
description: Describe for which tool you want a feature to be added.
placeholder: |
tidal-gui or tidal-dl
validations:
required: true
- type: textarea
id: feature
attributes:
label: Describe the feature
description: Describe the feature as accurately as possible.
validations:
required: true
- type: textarea
id: screenshots
attributes:
label: Add screenshots
description: Please add screenshots if available.
validations:
required: false
-18
View File
@@ -1,18 +0,0 @@
---
name: Feature request
about: Open a feature request to Tidal-Media-Downloader
title: "[FEATURE] xxxxxxxxxxxxx"
labels: feature request
---
<!-- Please search for this issue in issues-page first. Avoid duplication. -->
<!-- Please read Wiki first. -->
<!-- https://github.com/yaronzz/Tidal-Media-Downloader/wiki -->
**Which tool**
<!-- tidal-gui or tidal-dl -->
**Which feature**
<!-- eg. Support IOS -->
**Description**
<!-- Please describe in detail. Screenshot-->
@@ -0,0 +1,34 @@
name: Questions
description: Question for the tool.
title: "[QUESTION]: "
labels: question
body:
- type: markdown
attributes:
value: |
Please search for this issue in issues-page first. Avoid duplication.
Please read Wiki first.
https://github.com/yaronzz/Tidal-Media-Downloader/wiki
- type: textarea
id: which-tool
attributes:
label: Which tool
description: Describe which tool the question is about.
placeholder: |
tidal-gui or tidal-dl
validations:
required: true
- type: textarea
id: question
attributes:
label: Describe your question
description: Describe your question as accurately as possible.
validations:
required: true
- type: textarea
id: screenshots
attributes:
label: Add screenshots
description: Please add screenshots if available.
validations:
required: false
-17
View File
@@ -1,17 +0,0 @@
---
name: Question
about: Question for the tool
title: "[QUESTION] xxxxxxxxxxxxx"
labels: question
---
<!-- Please search for this issue in issues-page first. Avoid duplication. -->
<!-- Please read Wiki first. -->
<!--
https://github.com/yaronzz/Tidal-Media-Downloader/wiki
https://yaronzz.top/post/tidal_dl_installation/
-->
**Which tool**
<!-- tidal-gui or tidal-dl -->
**Question**
+28
View File
@@ -0,0 +1,28 @@
# # This workflow warns and then closes issues and PRs that have had no activity for a specified amount of time.
# #
# # You can adjust the behavior by modifying this file.
# # For more information, see:
# # https://github.com/actions/stale
# name: Mark stale issues and pull requests
# on:
# schedule:
# - cron: '45 15 * * *'
# jobs:
# stale:
# runs-on: ubuntu-latest
# permissions:
# issues: write
# pull-requests: write
# steps:
# - uses: actions/stale@v6
# with:
# repo-token: ${{ secrets.GITHUB_TOKEN }}
# stale-issue-message: 'This issue has been automatically marked as stale because it has not had recent activity.'
# stale-pr-message: 'This pull request has been automatically marked as stale because it has not had recent activity.'
# stale-issue-label: 'no-issue-activity'
# stale-pr-label: 'no-pr-activity'
# operations-per-run: 60
+77
View File
@@ -0,0 +1,77 @@
name: Build exe
on: [push, pull_request]
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-latest, ubuntu-latest, windows-latest]
steps:
- name: Checkout repo
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Install dependencies
shell: bash
run: |
pip3 install wheel
pip3 install pyinstaller
pip3 install PyQt5
pip3 install -r requirements.txt --upgrade
working-directory: TIDALDL-PY
- name: Clean directory
shell: bash
run: |
rm -rf dist
rm -rf build
rm -rf tidal_dl.egg-info
rm -rf tidal_gui.egg-info
rm -rf MANIFEST.in
working-directory: TIDALDL-PY
- name: Build tidal-dl
run: |
pyinstaller -F tidal_dl/__init__.py -n tidal-dl
working-directory: TIDALDL-PY
# - name: Build tidal-gui-macOs
# shell: bash
# if: ${{ matrix.os == 'macos-latest' }}
# run: |
# cp -rf guiStatic.in MANIFEST.in
# pyinstaller -F tidal_gui/__init__.py -w -n tidal-gui
# cp -rf tidal_gui/resource dist/
# working-directory: TIDALDL-PY
# - name: Build tidal-gui
# shell: bash
# if: ${{ matrix.os != 'macos-latest' }}
# run: |
# cp -rf guiStatic.in MANIFEST.in
# pyinstaller -D tidal_gui/__init__.py -w -n tidal-gui
# working-directory: TIDALDL-PY
# - name: Gzip tidal-gui
# shell: bash
# if: ${{ matrix.os != 'macos-latest' }}
# run: |
# cp -rf ../tidal_gui/resource ./tidal-gui/
# tar -zcvf tidal-gui.tar.gz tidal-gui
# rm -rf tidal-gui
# working-directory: TIDALDL-PY/dist
- name: Upload artifact
uses: actions/upload-artifact@v3
with:
name: tidal-dl-${{ runner.os }}
path: |
TIDALDL-PY/dist/*
+180 -66
View File
@@ -1,66 +1,180 @@
/Dll/AIGS.vshost.exe
/Dll/AIGS.vshost.exe.manifest
/Dll/AIGS.pdb
/TIDALDL-PY/tidal-dl.ini
/TIDALDL-PY/tidal_dl.egg-info
/TIDALDL-PY/build
/TIDALDL-PY/dist
/TIDALDL-PY/__main__.spec
/TIDALDL-PY/tidal_dl/__pycache__
/TIDALDL-PY/exe/Track
/TIDALDL-PY/exe/Video
/TIDALDL-PY/exe/tidal-dl.ini
/TIDALDL-PY/exe/Album
/TIDALDL-PY/exe/Playlist
/TIDALDL-UI/obj
/TIDALDL-UI/bin/Release
/TIDALDL-UI/bin/Debug/Tidal-Media-Downloader.pdb
/TIDALDL-UI/bin/Debug/AIGS.pdb
/TIDALDL-UI/bin/Debug/MaterialDesignThemes.Wpf.pdb
/TIDALDL-UI/bin/Debug/MaterialDesignThemes.Wpf.xml
/TIDALDL-UI/bin/Debug/Tidal-dl.ini
/TIDALDL-UI/bin/Debug/Tidal-Media-Downloader.exe.config
/TIDALDL-CMD-1
/TIDALDL-UI-1
/trunk
/TIDALDL-UI/TIDALDL-UI/bin/Debug/MaterialDesignThemes.Wpf.xml
/TIDALDL-UI/TIDALDL-UI/bin/Debug/policy.2.0.taglib-sharp.config
/TIDALDL-UI/TIDALDL-UI/bin/Debug/Stylet.xml
/TIDALDL-UI/TIDALDL-UI/bin/Debug/tidal-dl.ini
/TIDALDL-UI/TIDALDL-UI/bin/Debug/tidal-downloader.exe.config
/TIDALDL-UI/TIDALDL-UI/bin/Debug/tidal-downloader.pdb
/TIDALDL-UI/TIDALDL-UI/obj
/TIDALDL-UI/TIDALDL-UI.v12.suo
/TIDALDL-UI/.vs
/TIDALDL-UI/TIDALDL-UI/bin/Debug/tidal-ui-dl.exe.config
/TIDALDL-UI/TIDALDL-UI/bin/Debug/tidal-ui-dl.pdb
/TIDALDL-UI/TIDALDL-UI/bin/Debug/tidal-gui.application
/TIDALDL-UI/TIDALDL-UI/bin/Debug/tidal-gui.exe.config
/TIDALDL-UI/TIDALDL-UI/bin/Debug/tidal-gui.exe.manifest
/TIDALDL-UI/TIDALDL-UI/bin/Debug/tidal-gui.pdb
/TIDALDL-UI/TIDALDL-UI/bin/Debug/tidal-gui.vshost.application
/TIDALDL-UI/TIDALDL-UI/bin/Debug/tidal-gui.vshost.exe
/TIDALDL-UI/TIDALDL-UI/bin/Debug/tidal-gui.vshost.exe.config
/TIDALDL-UI/TIDALDL-UI/bin/Debug/tidal-gui.vshost.exe.manifest
/TIDALDL-UI/TIDALDL-UI/bin/Release/tidal-dl.ini
/TIDALDL-UI/TIDALDL-UI/bin/Release/tidal-gui.application
/TIDALDL-UI/TIDALDL-UI/bin/Release/tidal-gui.exe.config
/TIDALDL-UI/TIDALDL-UI/bin/Release/tidal-gui.exe.manifest
/TIDALDL-UI/TIDALDL-UI/bin/Release/tidal-gui.pdb
/TIDALDL-UI/TIDALDL-UI/bin/Release/app.publish
/TIDALDL-UI/TIDALDL-UI/bin/Release/MaterialDesignThemes.Wpf.xml
/TIDALDL-UI/TIDALDL-UI/bin/Release/policy.2.0.taglib-sharp.config
/TIDALDL-UI/TIDALDL-UI/bin/Release/Stylet.xml
/TIDALDL-PY/.vscode
/TIDALDL-UI/packages/Costura.Fody.3.3.0
/TIDALDL-UI/packages/Fody.3.3.5
/TIDALDL-UI/packages/MaterialDesignColors.1.1.3
/TIDALDL-UI/packages/MaterialDesignThemes.2.5.1
/TIDALDL-UI/packages/PropertyChanged.Fody.2.6.0
/TIDALDL-UI/packages/Stylet.1.1.22
/TIDALDL-UI/packages/Stylet.Start.1.1.22
/TIDALDL-UI/packages/taglib.2.1.0.0
/TIDALDL-UI/TIDALDL-UI/bin
TIDALDL-PY/__pycache__/setup.cpython-37.pyc
.gitignore
.gitignore
/Dll/AIGS.vshost.exe
/Dll/AIGS.vshost.exe.manifest
/Dll/AIGS.pdb
/TIDALDL-PY/tidal-dl.ini
/TIDALDL-PY/tidal_dl.egg-info
/TIDALDL-PY/build
/TIDALDL-PY/dist
/TIDALDL-PY/__main__.spec
/TIDALDL-PY/tidal_dl/__pycache__
/TIDALDL-PY/exe/Track
/TIDALDL-PY/exe/Video
/TIDALDL-PY/exe/tidal-dl.ini
/TIDALDL-PY/exe/Album
/TIDALDL-PY/exe/Playlist
/TIDALDL-UI/obj
/TIDALDL-UI/bin/Release
/TIDALDL-UI/bin/Debug/Tidal-Media-Downloader.pdb
/TIDALDL-UI/bin/Debug/AIGS.pdb
/TIDALDL-UI/bin/Debug/MaterialDesignThemes.Wpf.pdb
/TIDALDL-UI/bin/Debug/MaterialDesignThemes.Wpf.xml
/TIDALDL-UI/bin/Debug/Tidal-dl.ini
/TIDALDL-UI/bin/Debug/Tidal-Media-Downloader.exe.config
/TIDALDL-CMD-1
/TIDALDL-UI-1
/trunk
/TIDALDL-UI/TIDALDL-UI/bin/Debug/MaterialDesignThemes.Wpf.xml
/TIDALDL-UI/TIDALDL-UI/bin/Debug/policy.2.0.taglib-sharp.config
/TIDALDL-UI/TIDALDL-UI/bin/Debug/Stylet.xml
/TIDALDL-UI/TIDALDL-UI/bin/Debug/tidal-dl.ini
/TIDALDL-UI/TIDALDL-UI/bin/Debug/tidal-downloader.exe.config
/TIDALDL-UI/TIDALDL-UI/bin/Debug/tidal-downloader.pdb
/TIDALDL-UI/TIDALDL-UI/obj
/TIDALDL-UI/TIDALDL-UI.v12.suo
/TIDALDL-UI/.vs
/TIDALDL-UI/TIDALDL-UI/bin/Debug/tidal-ui-dl.exe.config
/TIDALDL-UI/TIDALDL-UI/bin/Debug/tidal-ui-dl.pdb
/TIDALDL-UI/TIDALDL-UI/bin/Debug/tidal-gui.application
/TIDALDL-UI/TIDALDL-UI/bin/Debug/tidal-gui.exe.config
/TIDALDL-UI/TIDALDL-UI/bin/Debug/tidal-gui.exe.manifest
/TIDALDL-UI/TIDALDL-UI/bin/Debug/tidal-gui.pdb
/TIDALDL-UI/TIDALDL-UI/bin/Debug/tidal-gui.vshost.application
/TIDALDL-UI/TIDALDL-UI/bin/Debug/tidal-gui.vshost.exe
/TIDALDL-UI/TIDALDL-UI/bin/Debug/tidal-gui.vshost.exe.config
/TIDALDL-UI/TIDALDL-UI/bin/Debug/tidal-gui.vshost.exe.manifest
/TIDALDL-UI/TIDALDL-UI/bin/Release/tidal-dl.ini
/TIDALDL-UI/TIDALDL-UI/bin/Release/tidal-gui.application
/TIDALDL-UI/TIDALDL-UI/bin/Release/tidal-gui.exe.config
/TIDALDL-UI/TIDALDL-UI/bin/Release/tidal-gui.exe.manifest
/TIDALDL-UI/TIDALDL-UI/bin/Release/tidal-gui.pdb
/TIDALDL-UI/TIDALDL-UI/bin/Release/app.publish
/TIDALDL-UI/TIDALDL-UI/bin/Release/MaterialDesignThemes.Wpf.xml
/TIDALDL-UI/TIDALDL-UI/bin/Release/policy.2.0.taglib-sharp.config
/TIDALDL-UI/TIDALDL-UI/bin/Release/Stylet.xml
/TIDALDL-PY/.vscode
/TIDALDL-UI/packages/Costura.Fody.3.3.0
/TIDALDL-UI/packages/Fody.3.3.5
/TIDALDL-UI/packages/MaterialDesignColors.1.1.3
/TIDALDL-UI/packages/MaterialDesignThemes.2.5.1
/TIDALDL-UI/packages/PropertyChanged.Fody.2.6.0
/TIDALDL-UI/packages/Stylet.1.1.22
/TIDALDL-UI/packages/Stylet.Start.1.1.22
/TIDALDL-UI/packages/taglib.2.1.0.0
/TIDALDL-UI/TIDALDL-UI/bin
TIDALDL-PY/__pycache__/setup.cpython-37.pyc
.gitignore
.gitignore
/TIDALDL-PY/settings.json
/TIDALDL-PY/usersettings.json
/TIDALDL-PY/__init__.spec
TIDALDL-PY/tidal_dl/lang/__pycache__/__init__.cpython-37.pyc
TIDALDL-PY/tidal_dl/lang/__pycache__/arabic.cpython-37.pyc
TIDALDL-PY/tidal_dl/lang/__pycache__/chinese.cpython-37.pyc
TIDALDL-PY/tidal_dl/lang/__pycache__/czech.cpython-37.pyc
TIDALDL-PY/tidal_dl/lang/__pycache__/english.cpython-37.pyc
TIDALDL-PY/tidal_dl/lang/__pycache__/filipino.cpython-37.pyc
TIDALDL-PY/tidal_dl/lang/__pycache__/italian.cpython-37.pyc
TIDALDL-PY/tidal_dl/lang/__pycache__/language.cpython-37.pyc
TIDALDL-PY/tidal_dl/lang/__pycache__/russian.cpython-37.pyc
TIDALDL-PY/tidal_dl/lang/__pycache__/turkish.cpython-37.pyc
TIDALDL-PY-原/build/__main__/aigpy-2020.7.3.0-py3.7.egg/aigpy/__pycache__/__init__.cpython-37.pyc
TIDALDL-PY-原/build/__main__/aigpy-2020.7.3.0-py3.7.egg/aigpy/__pycache__/__main__.cpython-37.pyc
TIDALDL-PY-原/build/__main__/aigpy-2020.7.3.0-py3.7.egg/aigpy/__pycache__/cmdHelper.cpython-37.pyc
TIDALDL-PY-原/build/__main__/aigpy-2020.7.3.0-py3.7.egg/aigpy/__pycache__/configHelper.cpython-37.pyc
TIDALDL-PY-原/build/__main__/aigpy-2020.7.3.0-py3.7.egg/aigpy/__pycache__/convertHelper.cpython-37.pyc
TIDALDL-PY-原/build/__main__/aigpy-2020.7.3.0-py3.7.egg/aigpy/__pycache__/ffmpegHelper.cpython-37.pyc
TIDALDL-PY-原/build/__main__/aigpy-2020.7.3.0-py3.7.egg/aigpy/__pycache__/fileHelper.cpython-37.pyc
TIDALDL-PY-原/build/__main__/aigpy-2020.7.3.0-py3.7.egg/aigpy/__pycache__/httpHelper.cpython-37.pyc
TIDALDL-PY-原/build/__main__/aigpy-2020.7.3.0-py3.7.egg/aigpy/__pycache__/logHelper.cpython-37.pyc
TIDALDL-PY-原/build/__main__/aigpy-2020.7.3.0-py3.7.egg/aigpy/__pycache__/m3u8Helper.cpython-37.pyc
TIDALDL-PY-原/build/__main__/aigpy-2020.7.3.0-py3.7.egg/aigpy/__pycache__/mathHelper.cpython-37.pyc
TIDALDL-PY-原/build/__main__/aigpy-2020.7.3.0-py3.7.egg/aigpy/__pycache__/netHelper.cpython-37.pyc
TIDALDL-PY-原/build/__main__/aigpy-2020.7.3.0-py3.7.egg/aigpy/__pycache__/pathHelper.cpython-37.pyc
TIDALDL-PY-原/build/__main__/aigpy-2020.7.3.0-py3.7.egg/aigpy/__pycache__/pipHelper.cpython-37.pyc
TIDALDL-PY-原/build/__main__/aigpy-2020.7.3.0-py3.7.egg/aigpy/__pycache__/progressHelper.cpython-37.pyc
TIDALDL-PY-原/build/__main__/aigpy-2020.7.3.0-py3.7.egg/aigpy/__pycache__/serverHelper.cpython-37.pyc
TIDALDL-PY-原/build/__main__/aigpy-2020.7.3.0-py3.7.egg/aigpy/__pycache__/stringHelper.cpython-37.pyc
TIDALDL-PY-原/build/__main__/aigpy-2020.7.3.0-py3.7.egg/aigpy/__pycache__/systemHelper.cpython-37.pyc
TIDALDL-PY-原/build/__main__/aigpy-2020.7.3.0-py3.7.egg/aigpy/__pycache__/tagHelper.cpython-37.pyc
TIDALDL-PY-原/build/__main__/aigpy-2020.7.3.0-py3.7.egg/aigpy/__pycache__/threadHelper.cpython-37.pyc
TIDALDL-PY-原/build/__main__/aigpy-2020.7.3.0-py3.7.egg/aigpy/__pycache__/updateHelper.cpython-37.pyc
TIDALDL-PY-原/build/__main__/aigpy-2020.7.3.0-py3.7.egg/aigpy/__pycache__/versionHelper.cpython-37.pyc
TIDALDL-PY-原/build/__main__/aigpy-2020.7.3.0-py3.7.egg/aigpy/__pycache__/zipHelper.cpython-37.pyc
/TIDALDL-PY-原
/TIDALDL-UI-原
/TIDALDL-PY/download
TIDALDL-PY/tidal_dl/lang/__pycache__/croatian.cpython-37.pyc
TIDALDL-PY/tidal_dl/lang/__pycache__/spanish.cpython-37.pyc
TIDALDL-PY/tidal_dl_test.egg-info/dependency_links.txt
TIDALDL-PY/tidal_dl_test.egg-info/entry_points.txt
TIDALDL-PY/tidal_dl_test.egg-info/PKG-INFO
TIDALDL-PY/tidal_dl_test.egg-info/requires.txt
TIDALDL-PY/tidal_dl_test.egg-info/SOURCES.txt
TIDALDL-PY/tidal_dl_test.egg-info/top_level.txt
TIDALDL-PY/downloadd/Album/Capital Cities/[E] Solarize/01 - Space.flac.part
TIDALDL-PY/downloadd/Album/Capital Cities/[E] Solarize/cover.jpg
TIDALDL-PY/downloadd/Album/Capital Cities/[E] Solarize/01 - Space.flac.part
TIDALDL-PY/downloadd/Album/Capital Cities/[E] Solarize/cover.jpg
TIDALDL-PY/tidal_dl/lang/__pycache__/ukrainian.cpython-37.pyc
/TIDALDL-PY/tidal_dl/lang/__pycache__
/旧版备份
/usersettings.json
/settings.json
/download
download/Album/Ed Sheeran/÷ (Deluxe)/05 - Perfect.flac
download/Album/Ed Sheeran/÷ (Deluxe)/cover.jpg
download/Album/Ed Sheeran/÷ (Deluxe)/Tmp0/1.part
download/Album/Ed Sheeran/÷ (Deluxe)/Tmp0/5.part
download/Album/Ed Sheeran/÷ (Deluxe)/Tmp0/9.part
download/Playlist/Boy Bands- K-Pop Kings/Tmp0/0.part
download/Playlist/Boy Bands- K-Pop Kings/Tmp0/1.part
download/Playlist/Boy Bands- K-Pop Kings/Tmp0/3.part
download/Playlist/Boy Bands- K-Pop Kings/Tmp0/4.part
download/Playlist/Boy Bands- K-Pop Kings/Tmp0/5.part
download/Playlist/Boy Bands- K-Pop Kings/Tmp0/6.part
download/Playlist/Boy Bands- K-Pop Kings/Tmp0/7.part
download/Playlist/Boy Bands- K-Pop Kings/Tmp0/9.part
download/Playlist/Boy Bands- K-Pop Kings/Tmp0/10.part
download/Playlist/Boy Bands- K-Pop Kings/Tmp0/11.part
download/Playlist/Boy Bands- K-Pop Kings/Tmp0/12.part
download/Playlist/Boy Bands- K-Pop Kings/Tmp0/13.part
download/Playlist/Boy Bands- K-Pop Kings/Tmp0/14.part
download/Playlist/Boy Bands- K-Pop Kings/Tmp0/15.part
download/Playlist/Boy Bands- K-Pop Kings/Tmp0/16.part
download/Playlist/Boy Bands- K-Pop Kings/Tmp0/17.part
download/Playlist/Boy Bands- K-Pop Kings/Tmp0/18.part
download/Playlist/Boy Bands- K-Pop Kings/Tmp0/19.part
download/Playlist/Boy Bands- K-Pop Kings/Tmp0/20.part
download/Playlist/Boy Bands- K-Pop Kings/Tmp0/21.part
download/Playlist/Boy Bands- K-Pop Kings/Tmp0/22.part
/TIDALDL-GUI
/.vscode/.env
/.vscode/settings.json
/TIDALDL-PY/test/track.json
/TIDALDL-PY/test/video.json
/__init__.spec
/test.py
/TIDALDL-GUI-CROSS/MANIFEST.in
/TIDALDL-GUI-CROSS/__init__.spec
/TIDALDL-GUI-CROSS/workspace.code-workspace
/TIDALDL-GUI-CROSS/.idea
/TIDALDL-GUI-CROSS/tidal_gui/__pycache__
/TIDALDL-GUI-CROSS/tidal_gui/.tidal-dl.log
.idea
tidal_dl-BAK
/TIDALDL-PY2/tidal_dl
/TIDALDL-GUI-CROSS/tidal_gui/view/__pycache__
/TIDALDL-GUI-CROSS/tidal_gui/viewModel/__pycache__
/TIDALDL-GUI-CROSS/tidal_gui/control/__pycache__
__pycache__
clean.sh
TIDALDL-PY/MANIFEST.in
TIDALDL-PY/exe/resource
TIDALDL-PY/exe/tidal_dl_win.tar.gz
.github/workflows/continuous-integration-workflow copy.yml
TIDALDL-PY/tidal-gui.spec
.history/
.gitignore
/TIDALDL-PY/tidal_dl_old
/TIDALDL-PY/tidal_gui_old
/TIDALDL-PY/tidal_gui
+68
View File
@@ -0,0 +1,68 @@
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python: current",
"type": "python",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal",
// "python": "python3",
"env": {
"PYTHONPATH": "${workspaceRoot}/TIDALDL-PY/tidal_dl/"
},
"justMyCode": false
},
{
"name": "Python: common line",
"type": "python",
"request": "launch",
"program": "${workspaceRoot}/TIDALDL-PY/tidal_dl/__init__.py",
"console": "integratedTerminal",
// "python": "python3",
"env": {
"PYTHONPATH": "${workspaceRoot}/TIDALDL-PY/tidal_dl/"
},
"args": [
"--link",
"https://tidal.com/browse/track/70973230",
"-o",
"e:\\test",
"-q",
"0",
"-g"
]
},
{
"name": "Python: main",
"type": "python",
"request": "launch",
"program": "${workspaceRoot}/TIDALDL-PY/tidal_dl/__init__.py",
"console": "integratedTerminal",
// "python": "python3",
"env": {
"PYTHONPATH": "${workspaceRoot}/TIDALDL-PY/tidal_dl/"
},
"justMyCode": false
},
{
"name": "Python: gui",
"type": "python",
"request": "launch",
"program": "${workspaceRoot}/TIDALDL-PY/tidal_gui/__init__.py",
"console": "integratedTerminal",
// "python": "python3",
"env": {
"PYTHONPATH": "${workspaceRoot}/TIDALDL-PY/tidal_dl/"
},
"justMyCode": false
}
]
}
-6
View File
@@ -1,6 +0,0 @@
{
"token":"MbjR4DLXz1ghC4rV",
"token_phone": "pl4Vc0hemlAXD0mN",
"//token_phone" : "hZ9wuySZCmpLLiui"
}
+201 -201
View File
@@ -1,201 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+156 -80
View File
@@ -1,80 +1,156 @@
<div align="center">
<h1>Tidal-Media-Downloader</h1>
<a href="https://github.com/yaronzz/Tidal-Media-Downloader/blob/master/LICENSE">
<img src="https://img.shields.io/github/license/yaronzz/Tidal-Media-Downloader.svg?style=flat-square" alt="">
</a>
<a href="https://github.com/yaronzz/Tidal-Media-Downloader/releases">
<img src="https://img.shields.io/github/v/release/yaronzz/Tidal-Media-Downloader.svg?style=flat-square" alt="">
</a>
<a href="https://www.python.org/">
<img src="https://img.shields.io/github/issues/yaronzz/Tidal-Media-Downloader.svg?style=flat-square" alt="">
</a>
<a href="https://github.com/yaronzz/Tidal-Media-Downloader">
<img src="https://img.shields.io/github/downloads/yaronzz/Tidal-Media-Downloader/total?label=tidal-gui%20download" alt="">
</a>
<a href="https://pypi.org/project/tidal-dl/">
<img src="https://img.shields.io/pypi/dm/tidal-dl?label=tidal-dl%20download" alt="">
</a>
</div>
<p align="center">
«Tidal-Media-Downloader» is an application that lets you download videos and tracks from Tidal. It supports two version: tidal-dl and tidal-gui.
<br>
<a href="https://github.com/yaronzz/Tidal-Media-Downloader/releases">Download</a> |
<a href="https://yaronzz.top/post/tidal_dl_installation/">Documentation</a> |
<a href="https://yaronzz.top/post/tidal_dl_installation_chn/">中文文档</a> |
<a href="https://t.me/Tidal_Media_Downloader">Channel</a>
<br>
</p>
----
<a href="https://www.buymeacoffee.com/yaronzz" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/default-orange.png" alt="Buy Me A Coffee" style="height: 51px !important;width: 217px !important;" ></a>
### **Installation**
- Windows: [tidal-gui.exe](https://github.com/yaronzz/Tidal-Media-Downloader/releases)
- Windows\Linux\MacOs:
``` python
root:~# pip3 install tidal-dl --upgrade
root:~# tidal-dl
```
- Android: [Install](https://yaronzz.top/post/tidal_dl_installation/#Install)
- Detailed description: [Documentation](https://yaronzz.top/post/tidal_dl_installation/)
### **Requirement**
- [FFmpeg](http://ffmpeg.org/) : Convert video
### **Telegram**
- [Group](https://t.me/tidal_group) : Feed back
- [Channel](https://t.me/Tidal_Media_Downloader) : Notify the new version
### **Features**
1. Download single video\track\album\playlist
2. Download favorite tracks\artist-albums
3. Add metadate
4. Multiple downloads
5. Selectable video resolution and track quality
### **Screenshots**
![](https://cdn.jsdelivr.net/gh/yaronzz/CDN@latest/blog/tidal/tidal_dl_log.jpg)
![](https://cdn.jsdelivr.net/gh/yaronzz/CDN@latest/blog/tidal/tidal_gui_example.jpg)
### **Libraries and reference**
- [AIGS](https://github.com/yaronzz/AIGS)
- [AIGPY](https://github.com/yaronzz/AIGPY)
- [Stylet](https://github.com/canton7/Stylet)
- [PropertyChanged.Fody](https://github.com/Fody/PropertyChanged)
- [MaterialDesignInXamlToolkit](https://github.com/ButchersBoy/MaterialDesignInXamlToolkit)
- [Taglib-sharp](https://github.com/mono/taglib-sharp)
- [python-tidal](https://github.com/tamland/python-tidal)
- [RedSea](https://github.com/redsudo/RedSea)
### **Support**
If you really like my projects and want to support me, you can star this project.
### **Disclaimer**
- Private use only.
- Need a Tidal-HIFI subscription.
- You should not use this method to distribute or pirate music.
- It may be illegal to use this in your country, so be informed.
<br>
<a href="https://github.com/yaronzz/Tidal-Media-Downloader-PRO">[GUI-REPOSITORY]</a>
<br>
![Tidal-Media-Downloader](https://socialify.git.ci/yaronzz/Tidal-Media-Downloader/image?description=1&font=Rokkitt&forks=1&issues=1&language=1&name=1&owner=1&pattern=Circuit%20Board&stargazers=1&theme=Dark)
<div align="center">
<h1>Tidal-Media-Downloader</h1>
<a href="https://github.com/yaronzz/Tidal-Media-Downloader/blob/master/LICENSE">
<img src="https://img.shields.io/github/license/yaronzz/Tidal-Media-Downloader.svg?style=flat-square" alt="">
</a>
<a href="https://github.com/yaronzz/Tidal-Media-Downloader/releases">
<img src="https://img.shields.io/github/v/release/yaronzz/Tidal-Media-Downloader.svg?style=flat-square" alt="">
</a>
<a href="https://www.python.org/">
<img src="https://img.shields.io/github/issues/yaronzz/Tidal-Media-Downloader.svg?style=flat-square" alt="">
</a>
<a href="https://github.com/yaronzz/Tidal-Media-Downloader">
<img src="https://img.shields.io/github/downloads/yaronzz/Tidal-Media-Downloader/total?label=tidal-gui%20download" alt="">
</a>
<a href="https://pypi.org/project/tidal-dl/">
<img src="https://img.shields.io/pypi/dm/tidal-dl?label=tidal-dl%20download" alt="">
</a>
<a href="https://github.com/yaronzz/Tidal-Media-Downloader/actions/workflows/build.yml">
<img src="https://github.com/yaronzz/Tidal-Media-Downloader/actions/workflows/build.yml/badge.svg" alt="">
</a>
</div>
<p align="center">
«Tidal-Media-Downloader» is an application that lets you download videos and tracks from Tidal. It supports two version: tidal-dl and tidal-gui. (This repository only contains tidal-dl, and the release isn't the newest gui version.)
<br>
<a href="https://github.com/yaronzz/Tidal-Media-Downloader-PRO/releases">Download</a> |
<a href="https://doc.yaronzz.com/post/tidal_dl_installation/">Documentation</a> |
<a href="https://doc.yaronzz.com/post/tidal_dl_installation_chn/">中文文档</a> |
<br>
</p>
## 📺 Installation
```shell
pip3 install tidal-dl --upgrade
```
| USE | FUNCTION |
| ----------------------------------------------------- | -------------------------- |
| tidal-dl | Show interactive interface |
| tidal-dl -h | Show help-message |
| tidal-dl -l "https://tidal.com/browse/track/70973230" | Download link |
| tidal-dl -g | Show simple-gui |
If you are using windows system, you can use [tidal-pro](https://github.com/yaronzz/Tidal-Media-Downloader-PRO)
### Nightly Builds
|Download nightly builds from continuous integration: | [![Build Status][Build]][Actions]
|-------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------|
[Actions]: https://github.com/yaronzz/Tidal-Media-Downloader/actions
[Build]: https://github.com/yaronzz/Tidal-Media-Downloader/workflows/Tidal%20Media%20Downloader/badge.svg
## 🤖 Features
- Download album \ track \ video \ playlist \ artist-albums
- Add metadata to songs
- Selectable video resolution and track quality
## 💽 User Interface
<img src="https://i.loli.net/2020/08/19/gqW6zHI1SrKlomC.png" alt="image" style="zoom: 50%;" />
![image-20220708105823257](https://s2.loli.net/2022/07/08/vV6HsxugwoDyGr8.png)
![image-20200806013705425](https://i.loli.net/2020/08/06/sPLowIlCGyOdpVN.png)
## Settings - Possible Tags
### Album
| Tag | Example value |
| ----------------- | ------------------------------------ |
| {ArtistName} | The Beatles |
| {AlbumArtistName} | The Beatles |
| {Flag} | M/A/E (Master/Dolby Atmos/Explicit) |
| {AlbumID} | 55163243 |
| {AlbumYear} | 1963 |
| {AlbumTitle} | Please Please Me (Remastered) |
| {AudioQuality} | LOSSLESS |
| {DurationSeconds} | 1919 |
| {Duration} | 31:59 |
| {NumberOfTracks} | 14 |
| {NumberOfVideos} | 0 |
| {NumberOfVolumes} | 1 |
| {ReleaseDate} | 1963-03-22 |
| {RecordType} | ALBUM |
| {None} | |
### Track
| Tag | Example Value |
| ----------------- | ------------------------------------------ |
| {TrackNumber} | 01 |
| {ArtistName} | The Beatles |
| {ArtistsName} | The Beatles |
| {TrackTitle} | I Saw Her Standing There (Remastered 2009) |
| {ExplicitFlag} | (*Explicit*) |
| {AlbumYear} | 1963 |
| {AlbumTitle} | Please Please Me (Remastered) |
| {AudioQuality} | LOSSLESS |
| {DurationSeconds} | 173 |
| {Duration} | 02:53 |
| {TrackID} | 55163244 |
### Video
| Tag | Example Value |
| ----------------- | ------------------------------------------ |
| {VideoNumber} | 00 |
| {ArtistName} | DMX |
| {ArtistsName} | DMX, Westside Gunn |
| {VideoTitle} | Hood Blues |
| {ExplicitFlag} | (*Explicit*) |
| {VideoYear} | 2021 |
| {TrackID} | 188932980 |
## ☕ Support
If you really like my projects and want to support me, you can buy me a coffee and star this project.
<a href="https://www.buymeacoffee.com/yaronzz" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/arial-orange.png" alt="Buy Me A Coffee" style="height: 51px !important;width: 217px !important;" ></a>
## 🎂 Contributors
This project exists thanks to all the people who contribute.
<a href="https://github.com/yaronzz/Tidal-Media-Downloader/graphs/contributors"><img src="https://contributors-img.web.app/image?repo=yaronzz/Tidal-Media-Downloader" /></a>
## 🎨 Libraries and reference
- [aigpy](https://github.com/yaronzz/AIGPY)
- [python-tidal](https://github.com/tamland/python-tidal)
- [redsea](https://github.com/redsudo/RedSea)
- [tidal-wiki](https://github.com/Fokka-Engineering/TIDAL/wiki)
## 📜 Disclaimer
- Private use only.
- Need a Tidal-HIFI subscription.
- You should not use this method to distribute or pirate music.
- It may be illegal to use this in your country, so be informed.
## Developing
```shell
pip3 uninstall tidal-dl
pip3 install -r requirements.txt --user
python3 setup.py install
```
-15
View File
@@ -1,15 +0,0 @@
[album]
90521280
[artist]
10954264
[track]
66214149
90521281
[video]
92418079
[url]
https://tidal.com/album/71121869
Binary file not shown.
+3
View File
@@ -0,0 +1,3 @@
include tidal_gui/resource/themeDefault.qss
include tidal_gui/resource/svg/*.svg
include tidal_gui/resource/svg/*/*.svg
-6
View File
@@ -1,6 +0,0 @@
brew install python3
curl -O http://python-distribute.org/distribute_setup.py
python3 distribute_setup.py
curl -O https://raw.github.com/pypa/pip/master/contrib/get-pip.py
python3 get-pip.py
pip3 install --upgrade tidal-dl
+12 -6
View File
@@ -1,6 +1,12 @@
aigpy==2020.5.4.0
requests==2.21.0
ffmpeg==1.4
futures
pycryptodome==3.7.0
pydub==0.23.1
requests==2.31.0
colorama==0.4.4
prettytable==3.1.1
mutagen==1.45.1
psutil==5.9.0
pycryptodome==3.14.1
aigpy==2022.7.8.1
lyricsgenius==3.0.1
pydub==0.25.1
PyQt5==5.15.7
qt-material==2.12
+16
View File
@@ -0,0 +1,16 @@
from setuptools import setup, find_packages
setup(
name = 'tidal-gui',
version = '2022.01.18.3',
license = "Apache2",
description = "Tidal Music Downloader-GUI.",
author = 'YaronH',
author_email = "yaronhuang@foxmail.com",
packages=find_packages(exclude=['tidal_dl*']),
include_package_data = True,
platforms = "any",
install_requires=["tidal-dl"],
entry_points={'console_scripts': [ 'tidal-gui = tidal_gui:main', ]}
)
+23 -16
View File
@@ -1,16 +1,23 @@
from setuptools import setup, find_packages
setup(
name = 'tidal-dl',
version="2020.5.19.0",
license="Apache2",
description = "Tidal Music Downloader.",
author = 'YaronH',
author_email = "yaronhuang@qq.com",
packages = find_packages(),
include_package_data = True,
platforms = "any",
install_requires=["aigpy>=2020.5.4.0", "requests", "ffmpeg", "pycryptodome", "pydub", ],
entry_points={'console_scripts': [ 'tidal-dl = tidal_dl:main', ]}
)
from setuptools import setup, find_packages
from tidal_dl.printf import VERSION
setup(
name='tidal-dl',
version=VERSION,
license="Apache2",
description="Tidal Music Downloader.",
author='YaronH',
author_email="yaronhuang@foxmail.com",
packages=find_packages(exclude=['tidal_gui*']),
include_package_data=False,
platforms="any",
install_requires=["aigpy>=2022.7.8.1",
"requests>=2.22.0",
"pycryptodome",
"pydub",
"prettytable",
"lxml"],
entry_points={'console_scripts': ['tidal-dl = tidal_dl:main', ]}
)
+147 -279
View File
@@ -1,294 +1,162 @@
# -*- coding: utf-8 -*-
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File : __init__.py
@Time : 2020/11/08
@Author : Yaronzz
@Version : 3.0
@Contact : yaronhuang@foxmail.com
@Desc :
'''
import sys
import os
import time
import getopt
import aigpy
from aigpy import pipHelper
from aigpy import pathHelper
from aigpy.cmdHelper import myinput, myinputInt
from events import *
from settings import *
from gui import startGui
from printf import Printf
from tidal_dl.tidal import TidalConfig
from tidal_dl.tidal import TidalAccount, TidalToken
from tidal_dl.download import Download
from tidal_dl.printhelper import printMenu, printChoice2, printErr, printWarning, LOG
TIDAL_DL_VERSION = "2020.5.19.0"
TIDAL_TOKEN = TidalToken()
def logInByTime():
cf = TidalConfig()
def mainCommand():
try:
Lasttime = float(cf.lastlogintime)
Lastlocaltime = time.localtime(Lasttime)
except:
Lastlocaltime = None
Curtime = time.time()
Curlocaltime = time.localtime(Curtime)
if Lastlocaltime is not None:
if Curlocaltime.tm_mon == Lastlocaltime.tm_mon and Curlocaltime.tm_mday == Lastlocaltime.tm_mday and Curlocaltime.tm_hour < Lastlocaltime.tm_hour + 3:
return
if logIn(cf.username, cf.password) == False:
while logIn("", "") == False:
pass
def logIn(username="", password=""):
if username == "" or password == "":
print("----------------LogIn------------------")
username = myinput("username:")
password = myinput("password:")
account = TidalAccount(username, password, TIDAL_TOKEN)
account2 = TidalAccount(username, password, TIDAL_TOKEN, True)
# if account.errmsg != "":
# printErr(0, account.errmsg)
# return False
# if account2.errmsg != "":
# printErr(0, account2.errmsg)
# return False
if account.errmsg != "" and account2.errmsg != "":
printErr(0, account.errmsg)
return False
elif account.errmsg != "":
account = account2
elif account2.errmsg != "":
account2 = account
cf = TidalConfig()
cf.set_account(username, password, account.session_id, account.country_code, account.user_id, account2.session_id)
Curtime = time.time()
cf.set_lastlogintime(str(Curtime))
return True
def showConfig():
cf = TidalConfig()
print("----------------Config------------------")
print("Username : " + cf.username)
print("Output directory : " + cf.outputdir)
print("SessionID : " + cf.sessionid)
print("Country Code : " + cf.countrycode)
print("Sound Quality : " + cf.quality)
print("Video Resolution : " + cf.resolution)
print("Download Threads : " + cf.threadnum)
print("Only M4a : " + cf.onlym4a)
print("Show download progress : " + cf.showprogress + "(enable when threadnum=1)")
print("Use hyphens : " + cf.addhyphen + "(between number and title)")
print("Add year : " + cf.addyear + "(in album title)")
print("Add explicit tag : " + cf.addexplicit)
print("Playlist songs in artist folders : " + cf.plfile2arfolder + "(organized with artist folder)")
print("Include singles : " + cf.includesingle + "(download artist album)")
print("Save covers : " + cf.savephoto)
print("Version : " + TIDAL_DL_VERSION)
myinput("Enter to return.")
def setting():
cf = TidalConfig()
print("----------------Settings----------------")
print("Output directory :\t" + cf.outputdir)
print("Sound Quality :\t" + cf.quality)
print("Video Resolution :\t" + cf.resolution)
print("Download Threads :\t" + cf.threadnum)
print("Only M4a :\t" + cf.onlym4a)
print("Show download progress :\t" + cf.showprogress + "(enable when threadnum=1)")
print("Use hyphens :\t" + cf.addhyphen + "(between number and title)")
print("Add year :\t" + cf.addyear + "(in album title)")
print("Add explicit tag :\t" + cf.addexplicit)
print("Playlist songs in artist folders :\t" + cf.plfile2arfolder + "(organized with artist folder)")
print("Include singles :\t" + cf.includesingle + "(download artist album)")
print("Save covers : " + cf.savephoto)
while True:
outputdir = myinput("Output directory(Enter '0' Unchanged):".ljust(12))
if outputdir == '0':
outputdir = cf.outputdir
break
if os.path.isdir(outputdir) == False:
printErr(0, "Path is Err!")
continue
break
while True:
index = myinputInt("Download Quality(0-LOW,1-HIGH,2-LOSSLESS,3-HI_RES):".ljust(12), 999)
if index > 3 or index < 0:
printErr(0, "Quality Err!")
continue
if index == 0:
quality = 'LOW'
if index == 1:
quality = 'HIGH'
if index == 2:
quality = 'LOSSLESS'
if index == 3:
quality = 'HI_RES'
break
while True:
index = myinputInt("Video resolution(0-1080,1-720,2-480,3-360,4-240):".ljust(12), 99)
if index > 4 or index < 0:
printErr(0, "Resolution Err")
continue
if index == 0:
resolution = '1080'
if index == 1:
resolution = '720'
if index == 2:
resolution = '480'
if index == 3:
resolution = '360'
if index == 4:
resolution = '240'
break
while True:
threadnum = myinput("Number of download threads:".ljust(12))
if cf.valid_threadnum(threadnum) == False:
printErr(0, "ThreadNum Err")
continue
break
status = myinputInt("Convert Mp4 to M4a(0-No, 1-Yes):".ljust(12), 0)
status2 = myinputInt("Show download progress (only available on single thread)(0-No, 1-Yes):".ljust(12), 0)
status3 = myinputInt("Use hyphens instead of spaces in file names(0-No, 1-Yes):".ljust(12), 0)
while True:
index = myinputInt("Add year to album folder names(0-No, 1-Before, 2-After):".ljust(12), 99)
if index > 2 or index < 0:
printErr(0, "Addyear input Err")
continue
if index == 0:
addyear = 'No'
if index == 1:
addyear = 'Before'
if index == 2:
addyear = 'After'
break
status5 = myinputInt("Download playlist songs in artist folder structure? (0-No,1-Yes):".ljust(12), 0)
status6 = myinputInt("Add explicit tag to file names(0-No, 1-Yes):".ljust(12), 0)
status7 = myinputInt("Include singles and EPs when downloading an artist's albums (0-No, 1-Yes):".ljust(12), 0)
status8 = myinputInt("Save covers(0-No, 1-Yes):".ljust(12), 0)
cf.set_outputdir(outputdir)
cf.set_quality(quality)
cf.set_resolution(resolution)
cf.set_threadnum(threadnum)
cf.set_onlym4a(status)
cf.set_showprogress(status2)
cf.set_addhyphen(status3)
cf.set_addyear(addyear)
cf.set_plfile2arfolder(status5)
cf.set_addexplicit(status6)
cf.set_includesingle(status7)
cf.set_savephoto(status8)
pathHelper.mkdirs(outputdir + "/Album/")
pathHelper.mkdirs(outputdir + "/Playlist/")
pathHelper.mkdirs(outputdir + "/Video/")
pathHelper.mkdirs(outputdir + "/Favorite/")
return
def main(argv=None):
if byCommand() is True:
opts, args = getopt.getopt(sys.argv[1:],
"hvgl:o:q:r:",
["help", "version", "gui", "link=", "output=", "quality", "resolution"])
except getopt.GetoptError as errmsg:
Printf.err(vars(errmsg)['msg'] + ". Use 'tidal-dl -h' for usage.")
return
print(LOG)
cf = TidalConfig()
if logIn(cf.username, cf.password) == False:
while logIn("", "") == False:
pass
link = None
showGui = False
cf = TidalConfig()
onlineVer = pipHelper.getLastVersion('tidal-dl')
print("====================Tidal-dl========================")
print("Output directory : " + cf.outputdir)
print("Sound Quality : " + cf.quality)
print("Video Resolution : " + cf.resolution)
print("Download Threads : " + cf.threadnum)
print("Only M4a : " + cf.onlym4a)
print("Show download progress : " + cf.showprogress + "(enable when threadnum=1)")
print("Use hyphens : " + cf.addhyphen + "(between number and title)")
print("Add year : " + cf.addyear + "(in album title)")
print("Add explicit tag : " + cf.addexplicit)
print("Playlist songs in artist folders : " + cf.plfile2arfolder + "(organized with artist folder)")
print("Include singles : " + cf.includesingle + "(download artist album)")
print("Save covers : " + cf.savephoto)
print("Current Version : " + TIDAL_DL_VERSION)
if onlineVer != None:
print("Latest Version : " + onlineVer)
print("====================================================")
dl = Download(cf.threadnum)
if not dl.ffmpeg.enable:
printWarning(0, "Couldn't find ffmpeg!\n")
while True:
printMenu()
strchoice, choice = printChoice2("Enter Choice:", 99)
if choice == 0:
for opt, val in opts:
if opt in ('-h', '--help'):
Printf.usage()
return
elif choice == 1:
logIn()
cf = TidalConfig()
dl = Download(cf.threadnum)
elif choice == 2:
setting()
cf = TidalConfig()
dl = Download(cf.threadnum)
elif choice == 3:
dl.downloadAlbum()
elif choice == 4:
dl.downloadTrack()
elif choice == 5:
dl.downloadPlaylist()
elif choice == 6:
dl.downloadVideo()
elif choice == 7:
dl.downloadFavorite()
elif choice == 8:
dl.downloadArtistAlbum(cf.includesingle == "True")
elif choice == 9:
showConfig()
#Hidden Code For Developer [200-299]
elif choice == 200:
dl.downloadArtistAlbum(False)
if opt in ('-v', '--version'):
Printf.logo()
return
if opt in ('-g', '--gui'):
showGui = True
continue
if opt in ('-l', '--link'):
link = val
continue
if opt in ('-o', '--output'):
SETTINGS.downloadPath = val
SETTINGS.save()
continue
if opt in ('-q', '--quality'):
SETTINGS.audioQuality = SETTINGS.getAudioQuality(val)
SETTINGS.save()
continue
if opt in ('-r', '--resolution'):
SETTINGS.videoQuality = SETTINGS.getVideoQuality(val)
SETTINGS.save()
continue
if not aigpy.path.mkdirs(SETTINGS.downloadPath):
Printf.err(LANG.select.MSG_PATH_ERR + SETTINGS.downloadPath)
return
if showGui:
startGui()
return
if link is not None:
if not loginByConfig():
loginByWeb()
Printf.info(LANG.select.SETTING_DOWNLOAD_PATH + ':' + SETTINGS.downloadPath)
start(link)
def main():
SETTINGS.read(getProfilePath())
TOKEN.read(getTokenPath())
TIDAL_API.apiKey = apiKey.getItem(SETTINGS.apiKeyIndex)
if len(sys.argv) > 1:
mainCommand()
return
Printf.logo()
Printf.settings()
if not apiKey.isItemValid(SETTINGS.apiKeyIndex):
changeApiKey()
loginByWeb()
elif not loginByConfig():
loginByWeb()
Printf.checkVersion()
while True:
Printf.choices()
choice = Printf.enter(LANG.select.PRINT_ENTER_CHOICE)
if choice == "0":
return
elif choice == "1":
if not loginByConfig():
loginByWeb()
elif choice == "2":
loginByWeb()
elif choice == "3":
loginByAccessToken()
elif choice == "4":
changePathSettings()
elif choice == "5":
changeQualitySettings()
elif choice == "6":
changeSettings()
elif choice == "7":
if changeApiKey():
loginByWeb()
else:
dl.downloadUrl(strchoice)
dl.downloadByFile(strchoice)
start(choice)
def byCommand():
try:
if len(sys.argv) != 2:
return False
logInByTime()
cf = TidalConfig()
dl = Download(cf.threadnum)
dl.downloadUrl(sys.argv[1])
return True
except Exception as e:
return False
return False
def debug():
# cf = TidalConfig()
# while logIn(cf.username, cf.password) == False:
# pass
# add tag Credits,Info song and full tag (discnumber,irsc,composer,arrenger,publisher,replayGain,releasedate)
# https://api.tidal.com/v1/albums/71121869/tracks?token=wdgaB1CilGA-S_s2&countryCode=TH
print('\nThis is the debug version!!\n')
# os.system("pip install aigpy --upgrade")
# trackid = 70973230
dl = Download(1)
dl.downloadTrack("90521281")
# dl.downloadAlbum("120929182", True)
# dl.tool.getPlaylist("36ea71a8-445e-41a4-82ab-6628c581535d")
# ss = dl.tool.getPlaylistArtworkUrl("36ea71a8-445e-41a4-82ab-6628c581535d")
# ss = dl.tool.getPlaylistArtworkUrl("36ea71a8-445e-41a4-82ab-6628c581535d",480)
# dl.downloadVideo(57261945) #1hours
# tidal.com/browse/track/125155002 dubi
# dl.downloadVideo(84094460)
def test():
SETTINGS.read(getProfilePath())
TOKEN.read(getTokenPath())
if not loginByConfig():
loginByWeb()
SETTINGS.audioQuality = AudioQuality.Master
SETTINGS.videoFileFormat = VideoQuality.P240
SETTINGS.checkExist = False
SETTINGS.includeEP = True
SETTINGS.saveCovers = True
SETTINGS.lyricFile = True
SETTINGS.showProgress = True
SETTINGS.showTrackInfo = True
SETTINGS.saveAlbumInfo = True
SETTINGS.downloadVideos = True
SETTINGS.downloadPath = "./download/"
SETTINGS.usePlaylistFolder = True
SETTINGS.albumFolderFormat = R"{ArtistName}/{Flag} {AlbumTitle} [{AlbumID}] [{AlbumYear}]"
SETTINGS.playlistFolderFormat = R"Playlist/{PlaylistName} [{PlaylistUUID}]"
SETTINGS.trackFileFormat = R"{TrackNumber} - {ArtistName} - {TrackTitle}{ExplicitFlag}"
SETTINGS.videoFileFormat = R"{VideoNumber} - {ArtistName} - {VideoTitle}{ExplicitFlag}"
SETTINGS.multiThread = False
SETTINGS.apiKeyIndex = 4
SETTINGS.checkExist = False
Printf.settings()
TIDAL_API.getPlaylistSelf()
# test example
# https://tidal.com/browse/track/70973230
# if __name__ == '__main__':
# main(sys.argv)
# track 70973230 77798028 212657
start('242700165')
# album 58138532 77803199 21993753 79151897 56288918
# start('58138532')
# playlist 98235845-13e8-43b4-94e2-d9f8e603cee7
# start('98235845-13e8-43b4-94e2-d9f8e603cee7')
# video 155608351 188932980 https://tidal.com/browse/track/55130637
# start("155608351")https://tidal.com/browse/track/199683732
__all__ = ['debug', 'main', 'tidal', 'download']
if __name__ == '__main__':
# test()
main()
-7
View File
@@ -1,7 +0,0 @@
# -*- coding: utf-8 -*-
import sys
sys.path.append('./')
import tidal_dl
if __name__ == '__main__':
# tidal_dl.debug()
tidal_dl.main(sys.argv)
+108
View File
@@ -0,0 +1,108 @@
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
"""
@File : apiKey.py
@Date : 2021/11/30
@Author : Yaronzz
@Version : 3.0
@Contact : yaronhuang@foxmail.com
@Desc :
"""
import json
import requests
__KEYS_JSON__ = '''
{
"version": "1.0.1",
"keys": [
{
"platform": "Fire TV",
"formats": "Normal/High/HiFi(No Master)",
"clientId": "OmDtrzFgyVVL6uW56OnFA2COiabqm",
"clientSecret": "zxen1r3pO0hgtOC7j6twMo9UAqngGrmRiWpV7QC1zJ8=",
"valid": "False",
"from": "Fokka-Engineering (https://github.com/Fokka-Engineering/libopenTIDAL/blob/655528e26e4f3ee2c426c06ea5b8440cf27abc4a/README.md#example)"
},
{
"platform": "Fire TV",
"formats": "Master-Only(Else Error)",
"clientId": "7m7Ap0JC9j1cOM3n",
"clientSecret": "vRAdA108tlvkJpTsGZS8rGZ7xTlbJ0qaZ2K9saEzsgY=",
"valid": "True",
"from": "Dniel97 (https://github.com/Dniel97/RedSea/blob/4ba02b88cee33aeb735725cb854be6c66ff372d4/config/settings.example.py#L68)"
},
{
"platform": "Android TV",
"formats": "Normal/High/HiFi(No Master)",
"clientId": "Pzd0ExNVHkyZLiYN",
"clientSecret": "W7X6UvBaho+XOi1MUeCX6ewv2zTdSOV3Y7qC3p3675I=",
"valid": "False",
"from": ""
},
{
"platform": "TV",
"formats": "Normal/High/HiFi/Master",
"clientId": "8SEZWa4J1NVC5U5Y",
"clientSecret": "owUYDkxddz+9FpvGX24DlxECNtFEMBxipU0lBfrbq60=",
"valid": "False",
"from": "morguldir (https://github.com/morguldir/python-tidal/commit/50f1afcd2079efb2b4cf694ef5a7d67fdf619d09)"
},
{
"platform": "Android Auto",
"formats": "Normal/High/HiFi/Master",
"clientId": "zU4XHVVkc2tDPo4t",
"clientSecret": "VJKhDFqJPqvsPVNBV6ukXTJmwlvbttP7wlMlrc72se4=",
"valid": "True",
"from": "1nikolas (https://github.com/yaronzz/Tidal-Media-Downloader/pull/840)"
}
]
}
'''
__API_KEYS__ = json.loads(__KEYS_JSON__)
__ERROR_KEY__ = {
'platform': 'None',
'formats': '',
'clientId': '',
'clientSecret': '',
'valid': 'False',
},
def getNum():
return len(__API_KEYS__['keys'])
def getItem(index: int):
if index < 0 or index >= len(__API_KEYS__['keys']):
return __ERROR_KEY__
return __API_KEYS__['keys'][index]
def isItemValid(index: int):
item = getItem(index)
return item['valid'] == 'True'
def getItems():
return __API_KEYS__['keys']
def getLimitIndexs():
array = []
for i in range(len(__API_KEYS__['keys'])):
array.append(str(i))
return array
def getVersion():
return __API_KEYS__['version']
# Load from gist
try:
respond = requests.get('https://api.github.com/gists/48d01f5a24b4b7b37f19443977c22cd6')
if respond.status_code == 200:
content = respond.json()['files']['tidal-api-key.json']['content']
__API_KEYS__ = json.loads(content)
except:
pass
-31
View File
@@ -1,31 +0,0 @@
# -*- coding: utf-8 -*-
import os
import re
from aigpy import fileHelper
class CheckTool(object):
def __init__(self):
self.paths = []
def isInErr(self, index, errIndex):
for i in errIndex:
if i == index:
return True
return False
def clear(self):
self.paths = []
def addPath(self, path):
self.paths.append(path)
def checkPaths(self):
index = 0
flag = False
errIndex = []
for path in self.paths:
if fileHelper.getFileSize(path) <= 0:
errIndex.append(index)
flag = True
index = index + 1
return flag, errIndex
+63 -63
View File
@@ -1,63 +1,63 @@
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File : decryption.py
@Time : 2019/02/27
@Author : Yaron Huang
@Version : 1.0
@Contact : yaronhuang@qq.com
@Desc : HIGH Quality Track Dectyption;File From Project 'RedSea'
'''
import base64
from Crypto.Cipher import AES
from Crypto.Util import Counter
def decrypt_security_token(security_token):
'''
Decrypts security token into key and nonce pair
security_token should match the securityToken value from the web response
'''
# Do not change this
master_key = 'UIlTTEMmmLfGowo/UC60x2H45W6MdGgTRfo/umg4754='
# Decode the base64 strings to ascii strings
master_key = base64.b64decode(master_key)
security_token = base64.b64decode(security_token)
# Get the IV from the first 16 bytes of the securityToken
iv = security_token[:16]
encrypted_st = security_token[16:]
# Initialize decryptor
decryptor = AES.new(master_key, AES.MODE_CBC, iv)
# Decrypt the security token
decrypted_st = decryptor.decrypt(encrypted_st)
# Get the audio stream decryption key and nonce from the decrypted security token
key = decrypted_st[:16]
nonce = decrypted_st[16:24]
return key, nonce
def decrypt_file(efile, dfile, key, nonce):
'''
Decrypts an encrypted MQA file given the file, key and nonce
'''
# Initialize counter and file decryptor
counter = Counter.new(64, prefix=nonce, initial_value=0)
decryptor = AES.new(key, AES.MODE_CTR, counter=counter)
# Open and decrypt
with open(efile, 'rb') as eflac:
flac = decryptor.decrypt(eflac.read())
# Replace with decrypted file
with open(dfile, 'wb') as dflac:
dflac.write(flac)
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File : decryption.py
@Time : 2019/02/27
@Author : Yaron Huang
@Version : 1.0
@Contact : yaronhuang@qq.com
@Desc : HIGH Quality Track Decryption;File From Project 'RedSea'
'''
import base64
from Crypto.Cipher import AES
from Crypto.Util import Counter
def decrypt_security_token(security_token):
'''
Decrypts security token into key and nonce pair
security_token should match the securityToken value from the web response
'''
# Do not change this
master_key = 'UIlTTEMmmLfGowo/UC60x2H45W6MdGgTRfo/umg4754='
# Decode the base64 strings to ascii strings
master_key = base64.b64decode(master_key)
security_token = base64.b64decode(security_token)
# Get the IV from the first 16 bytes of the securityToken
iv = security_token[:16]
encrypted_st = security_token[16:]
# Initialize decryptor
decryptor = AES.new(master_key, AES.MODE_CBC, iv)
# Decrypt the security token
decrypted_st = decryptor.decrypt(encrypted_st)
# Get the audio stream decryption key and nonce from the decrypted security token
key = decrypted_st[:16]
nonce = decrypted_st[16:24]
return key, nonce
def decrypt_file(efile, dfile, key, nonce):
'''
Decrypts an encrypted MQA file given the file, key and nonce
'''
# Initialize counter and file decryptor
counter = Counter.new(64, prefix=nonce, initial_value=0)
decryptor = AES.new(key, AES.MODE_CTR, counter=counter)
# Open and decrypt
with open(efile, 'rb') as eflac:
flac = decryptor.decrypt(eflac.read())
# Replace with decrypted file
with open(dfile, 'wb') as dflac:
dflac.write(flac)
+222 -735
View File
@@ -1,735 +1,222 @@
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File : download.py
@Time : 2019/02/27
@Author : Yaron Huang
@Version : 1.0
@Contact : yaronhuang@qq.com
@Desc : Download Function
'''
import sys
import os
import codecs
from datetime import datetime
from aigpy import pathHelper
# from tidal_dl import netHelper
from aigpy import netHelper
from aigpy import fileHelper
from aigpy import cmdHelper
from aigpy import systemHelper
# from tidal_dl.ffmpegHelper import FFmpegTool
from aigpy.ffmpegHelper import FFmpegTool
from aigpy.cmdHelper import myinput, myinputInt
from aigpy.threadHelper import ThreadTool
from aigpy.progressHelper import ProgressTool
from tidal_dl.check import CheckTool
from tidal_dl.tidal import TidalTool
from tidal_dl.tidal import TidalConfig
from tidal_dl.tidal import TidalAccount
from tidal_dl.decryption import decrypt_security_token
from tidal_dl.decryption import decrypt_file
from tidal_dl.printhelper import printChoice, printErr, printSUCCESS
class Download(object):
def __init__(self, threadNum=3):
self.config = TidalConfig()
self.tool = TidalTool()
self.thread = ThreadTool(int(threadNum))
self.ffmpeg = FFmpegTool(mergerTimeout=45)
self.progress = ProgressTool(100)
self.check = CheckTool()
self.showpro = False
if self.config.showprogress == 'True':
self.showpro = True
pathHelper.mkdirs(self.config.outputdir + "/Album/")
pathHelper.mkdirs(self.config.outputdir + "/Playlist/")
pathHelper.mkdirs(self.config.outputdir + "/Video/")
pathHelper.mkdirs(self.config.outputdir + "/Favorite/")
def __isNeedDownload(self, path, url):
curSize = fileHelper.getFileSize(path)
if curSize <= 0:
return True
netSize = netHelper.getFileSize(url)
if curSize >= netSize:
return False
return True
# dowmload track thread
def __thradfunc_dl(self, paraList):
count = 1
printRet = True
pstr = paraList['title'] + "(Download Err!)"
redownload = True
needDl = True
bIsSuccess = False
albumInfo = None
index = None
coverpath = None
if 'redownload' in paraList:
redownload = paraList['redownload']
if 'retry' in paraList:
count = count + paraList['retry']
if 'show' in paraList:
printRet = paraList['show']
if 'album' in paraList:
albumInfo = paraList['album']
if 'index' in paraList:
index = paraList['index']
if 'coverpath' in paraList:
coverpath = paraList['coverpath']
if redownload is False:
needDl = self.__isNeedDownload(paraList['path'], paraList['url'])
# DEBUG
# self.tool.setTrackMetadata(paraList['trackinfo'], paraList['path'], albumInfo, index, coverpath)
showprogress = False
if int(self.config.threadnum) <= 1 and self.showpro:
showprogress = True
Contributors = self.tool.getTrackContributors(paraList['trackinfo']['id'])
if needDl:
try:
while count > 0:
count = count - 1
check = netHelper.downloadFile(paraList['url'], paraList['path']+'.part', showprogress=showprogress, stimeout=20)
if check is True:
if paraList['key'] == '':
# unencrypted -> just move into place
os.replace(paraList['path']+'.part', paraList['path'])
break
else:
# encrypted -> decrypt and remove encrypted file
key, nonce = decrypt_security_token(paraList['key'])
decrypt_file(paraList['path']+'.part', paraList['path'], key, nonce)
os.remove(paraList['path']+'.part')
break
if check:
bIsSuccess = True
paraList['path'] = self.tool.covertMp4toM4a(paraList['path'])
self.tool.setTrackMetadata(paraList['trackinfo'], paraList['path'],
albumInfo, index, coverpath, Contributors)
pstr = paraList['title']
except Exception as e:
printErr(14, str(e) + " while downloading " + paraList['url'])
else:
pstr = paraList['title']
bIsSuccess = True
if printRet:
if(bIsSuccess):
printSUCCESS(14, pstr)
else:
printErr(14, pstr)
return
# creat album output dir
def __creatAlbumDir(self, albumInfo, quality='LOW'):
# creat outputdir
title = pathHelper.replaceLimitChar(albumInfo['title'], '-')
author = pathHelper.replaceLimitChar(albumInfo['artist']['name'], '-')
# add year
if self.config.addyear != 'No':
if self.config.addyear == 'Before':
title = '[' + str(datetime.strptime(albumInfo['releaseDate'], '%Y-%m-%d').year) + '] '+title
elif self.config.addyear == 'After':
title = title+' [' + str(datetime.strptime(albumInfo['releaseDate'], '%Y-%m-%d').year) + ']'
else:
title = title
# add quality[M] labels
if 'audioQuality' in albumInfo and albumInfo['audioQuality'] == 'HI_RES' and quality == 'HI_RES':
title = '[M] '+title
targetDir = self.config.outputdir + "/Album/" + author + '/' + title
targetDir = os.path.abspath(targetDir)
pathHelper.mkdirs(targetDir)
# creat volumes dir
count = 1
numOfVolumes = int(albumInfo['numberOfVolumes'])
if numOfVolumes > 1:
while count < numOfVolumes + 1:
volumeDir = targetDir + "/Volume" + str(count)
pathHelper.mkdirs(volumeDir)
count = count + 1
return targetDir
def _getSongExtension(self, downloadUrl):
if downloadUrl.find('.flac?') != -1:
return '.flac'
if downloadUrl.find('.m4a?') != -1:
return '.m4a'
if downloadUrl.find('.mp4?') != -1:
return '.mp4'
return '.m4a'
def _IsExplicitString(self, IsExplicit):
String = None
if IsExplicit:
String = 'Explicit'
return String
def __getAlbumSongSavePath(self, targetDir, albumInfo, item, extension):
if extension is None:
extension = ".m4a"
seq = self.tool.getIndexStr(item['trackNumber'], albumInfo['numberOfTracks'])
name = seq + pathHelper.replaceLimitChar(item['title'], '-')
fileExplicit = self._IsExplicitString(item['explicit'])
if self.config.addhyphen == 'True':
name = seq + '- ' + pathHelper.replaceLimitChar(item['title'], '-')
if self.config.addexplicit == "True" and fileExplicit is not None:
name = name + " - " + fileExplicit
seq = item['volumeNumber']
path = targetDir + "/"
if int(albumInfo['numberOfVolumes']) > 1:
path += 'Volume' + str(seq) + "/"
maxlen = 255
if systemHelper.isLinux():
maxlen = 4090
# truncate filename when it's longer than system's
# filename limit which is 255
len_sum = len(path) + len(name) + len(extension)
if len_sum > maxlen:
diff = maxlen - len_sum
name = name[: len(name) + diff]
filePath = path + name + extension
checklen = len(filePath)
return filePath
def __getExistFiles(self, paths):
ret = []
for item in paths:
if os.path.isfile(item):
ret.append(item)
return ret
def __getVideoResolutionIndex(self, reslist):
array = []
# if reslist != None:
# for item in reslist:
# subs = item.split('x')
# subs = subs[1].split(',')
# array.append(int(subs[0]))
for item in reslist:
subs = item.split('x')
subs = subs[1].split(',')
array.append(int(subs[0]))
cmp = int(self.config.resolution)
ret = 0
for item in array:
if cmp >= item:
return ret
ret += 1
return len(array) - 1
def downloadAlbum(self, album_id=None, redl_flag=None):
while_count = 9999
while while_count > 0:
while_count -= 1
if album_id is not None:
while_count = 0
sID = album_id
else:
print("----------------ALBUM------------------")
sID = printChoice("Enter AlbumID(Enter '0' go back):", True, 0)
if sID == 0:
return
aAlbumInfo = self.tool.getAlbum(sID)
if self.tool.errmsg != "":
printErr(0, "Get AlbumInfo Err! " + self.tool.errmsg)
continue
print("[Title] %s" % (aAlbumInfo['title']))
print("[SongNum] %s\n" % (aAlbumInfo['numberOfTracks']))
# Get Tracks
aAlbumTracks = self.tool.getAlbumTracks(sID)
if self.tool.errmsg != "":
printErr(0, "Get AlbumTracks Err!" + self.tool.errmsg)
continue
aAlbumVideos = self.tool.getAlbumVideos(sID)
# Creat OutputDir
targetDir = self.__creatAlbumDir(aAlbumInfo, self.config.quality)
# write msg
string = self.tool.convertAlbumInfoToString(aAlbumInfo, aAlbumTracks)
with codecs.open(targetDir + "/AlbumInfo.txt", 'w', 'utf-8') as fd:
fd.write(string)
# download cover
coverPath = targetDir + '/' + pathHelper.replaceLimitChar(aAlbumInfo['title'], '-') + '.jpg'
if aAlbumInfo['cover'] is not None:
coverUrl = self.tool.getAlbumArtworkUrl(aAlbumInfo['cover'])
netHelper.downloadFile(coverUrl, coverPath)
# check exist files
redownload = True
if redl_flag is None:
existFiles = pathHelper.getDirFiles(targetDir)
for item in existFiles:
if '.txt' in item:
continue
if '.jpg' in item:
continue
check = printChoice("Some tracks already exist. Redownload?(y/n):")
if not cmdHelper.isInputYes(check):
redownload = False
break
else:
redownload = redl_flag
# download album tracks
for item in aAlbumTracks['items']:
streamInfo = self.tool.getStreamUrl(str(item['id']), self.config.quality)
if self.tool.errmsg != "" or not streamInfo:
printErr(14, item['title'] + "(Get Stream Url Err!" + self.tool.errmsg + ")")
continue
fileType = self._getSongExtension(streamInfo['url'])
filePath = self.__getAlbumSongSavePath(targetDir, aAlbumInfo, item, fileType)
paraList = {'album': aAlbumInfo,
'redownload': redownload,
'title': item['title'],
'trackinfo': item,
'url': streamInfo['url'],
'path': filePath,
'retry': 3,
'key': streamInfo['encryptionKey'],
'coverpath': coverPath}
self.thread.start(self.__thradfunc_dl, paraList)
# wait all download thread
self.thread.waitAll()
self.tool.removeTmpFile(targetDir)
# remove cover
if self.config.savephoto != 'True':
pathHelper.remove(coverPath)
# download video
for item in aAlbumVideos:
item = item['item']
filePath = targetDir + '/' + pathHelper.replaceLimitChar(item['title'], '-') + ".mp4"
filePath = os.path.abspath(filePath)
if os.access(filePath, 0):
os.remove(filePath)
try:
resolutionList, urlList = self.tool.getVideoResolutionList(item['id'])
selectIndex = self.__getVideoResolutionIndex(resolutionList)
if self.ffmpeg.mergerByM3u8_Multithreading2(urlList[int(selectIndex)], filePath, showprogress=self.showpro):
printSUCCESS(14, item['title'])
else:
printErr(14, item['title'])
except:
printErr(14, item['title'])
# return
return
def downloadArtistAlbum(self, includeSingles=True, artistID=None):
while True:
print("-------------ARTIST ALBUM--------------")
if artistID is not None:
sID = artistID
else:
sID = printChoice("Enter Artist ID(Enter '0' go back):", True, 0)
if sID == 0:
return
array = self.tool.getArtistAlbum(sID, includeSingles)
if self.tool.errmsg != "":
printErr(0, "Get AlbumList Err! " + self.tool.errmsg)
continue
redownload = True
if artistID is None:
check = printChoice("Skip downloaded files?(y/n):")
if not cmdHelper.isInputYes(check):
redownload = False
for index, item in enumerate(array):
print("----Album[{0}/{1}]----".format(index+1, len(array)))
self.downloadAlbum(item['id'], redownload)
if artistID is not None:
# Break out of the function if we are only downloading one artist's albums
return
def downloadTrack(self, track_id=None):
while_count = 9999
while while_count > 0:
while_count -= 1
if track_id is not None:
while_count = 0
sID = track_id
else:
print("----------------TRACK------------------")
sID = printChoice("Enter TrackID(Enter '0' go back):", True, 0)
if sID == 0:
return
aTrackInfo = self.tool.getTrack(sID)
if self.tool.errmsg != "":
printErr(0, "Get TrackInfo Err! " + self.tool.errmsg)
return
aAlbumInfo = self.tool.getAlbum(aTrackInfo['album']['id'])
if self.tool.errmsg != "":
printErr(0, "Get TrackInfo Err! " + self.tool.errmsg)
return
# t = self.tool.getTrackContributors(sID)
print("[AlbumTitle ] %s" % (aAlbumInfo['title']))
print("[TrackTitle ] %s" % (aTrackInfo['title']))
print("[Duration ] %s" % (aTrackInfo['duration']))
print("[TrackNumber] %s" % (aTrackInfo['trackNumber']))
print("[Explicit ] %s" % (aAlbumInfo['explicit']))
# print("[Version ] %s\n" % (aTrackInfo['version']))
# Creat OutputDir
targetDir = self.__creatAlbumDir(aAlbumInfo, self.config.quality)
# download cover
coverPath = targetDir + '/' + pathHelper.replaceLimitChar(aAlbumInfo['title'], '-') + '.jpg'
if aAlbumInfo['cover'] is not None:
coverUrl = self.tool.getAlbumArtworkUrl(aAlbumInfo['cover'])
netHelper.downloadFile(coverUrl, coverPath)
# download
streamInfo = self.tool.getStreamUrl(sID, self.config.quality)
if self.tool.errmsg != "" or not streamInfo:
printErr(14, aTrackInfo['title'] + "(Get Stream Url Err!" + self.tool.errmsg + ")")
continue
fileType = self._getSongExtension(streamInfo['url'])
filePath = self.__getAlbumSongSavePath(targetDir, aAlbumInfo, aTrackInfo, fileType)
paraList = {'album': aAlbumInfo,
'title': aTrackInfo['title'],
'trackinfo': aTrackInfo,
'url': streamInfo['url'],
'path': filePath,
'retry': 3,
'key': streamInfo['encryptionKey'],
'coverpath': coverPath}
self.thread.start(self.__thradfunc_dl, paraList)
# wait all download thread
self.thread.waitAll()
self.tool.removeTmpFile(targetDir)
# remove cover
if self.config.savephoto != 'True':
pathHelper.remove(coverPath)
return
def downloadVideo(self, video_id=None):
flag = True
while flag:
targetDir = self.config.outputdir + "/Video/"
if video_id is None:
print("----------------VIDEO------------------")
sID = printChoice("Enter VideoID(Enter '0' go back):", True, 0)
if sID == 0:
return
else:
flag = False
sID = video_id
aVideoInfo = self.tool.getVideo(sID)
if self.tool.errmsg != "":
printErr(0, "Get VideoInfo Err! " + self.tool.errmsg)
continue
print("[Title ] %s" % (aVideoInfo['title']))
print("[Duration ] %s" % (aVideoInfo['duration']))
print("[TrackNumber] %s" % (aVideoInfo['trackNumber']))
print("[Type ] %s\n" % (aVideoInfo['type']))
# get resolution
index = 0
resolutionList, urlList = self.tool.getVideoResolutionList(sID)
if self.tool.errmsg != "":
printErr(14, self.tool.errmsg)
continue
index = self.__getVideoResolutionIndex(resolutionList)
path = targetDir + "/" + pathHelper.replaceLimitChar(aVideoInfo['title'], '-') + ".mp4"
path = os.path.abspath(path)
if os.access(path, 0):
os.remove(path)
if self.ffmpeg.mergerByM3u8_Multithreading2(urlList[int(index)], path, True):
printSUCCESS(14, aVideoInfo['title'])
else:
printErr(14, aVideoInfo['title'])
return
def downloadPlaylist(self, playlist_id=None):
while True:
targetDir = self.config.outputdir + "/Playlist/"
if playlist_id is None:
print("--------------PLAYLIST-----------------")
sID = printChoice("Enter PlayListID(Enter '0' go back):")
if sID == '0':
return
else:
sID = playlist_id
aPlaylistInfo, aItemInfo = self.tool.getPlaylist(sID)
if self.tool.errmsg != "":
printErr(0, "Get PlaylistInfo Err! " + self.tool.errmsg)
return
print("[Title] %s" % (aPlaylistInfo['title']))
print("[Type] %s" % (aPlaylistInfo['type']))
print("[NumberOfTracks] %s" % (aPlaylistInfo['numberOfTracks']))
print("[NumberOfVideos] %s" % (aPlaylistInfo['numberOfVideos']))
print("[Duration] %s\n" % (aPlaylistInfo['duration']))
# Creat OutputDir
targetDir = targetDir + pathHelper.replaceLimitChar(aPlaylistInfo['title'], '-')
targetDir = os.path.abspath(targetDir).strip()
pathHelper.mkdirs(targetDir)
# write msg
string = self.tool.convertPlaylistInfoToString(aPlaylistInfo, aItemInfo)
with codecs.open(targetDir + "/PlaylistInfo.txt", 'w', 'utf-8') as fd:
fd.write(string)
# download cover
coverPath = targetDir + '/' + pathHelper.replaceLimitChar(aPlaylistInfo['title'], '-') + '.jpg'
coverUrl = self.tool.getPlaylistArtworkUrl(aPlaylistInfo['uuid'])
check = netHelper.downloadFile(coverUrl, coverPath)
# download track
bBreakFlag = False
bFirstTime = True
errIndex = []
index = 0
while bBreakFlag is False:
self.check.clear()
index = 0
tmpcoverpath = []
for item in aItemInfo:
type = item['type']
item = item['item']
if type != 'track':
continue
index = index + 1
if bFirstTime is False:
if self.check.isInErr(index - 1, errIndex) == False:
continue
streamInfo = self.tool.getStreamUrl(str(item['id']), self.config.quality)
# streamInfo = self.tool.getStreamUrl(str(item['id']), 'DOLBY_ATMOS')
if self.tool.errmsg != "" or not streamInfo:
printErr(14, item['title'] + "(Get Stream Url Err!!" + self.tool.errmsg + ")")
continue
aAlbumInfo = self.tool.getAlbum(item['album']['id'])
fileType = self._getSongExtension(streamInfo['url'])
# change targetDir
targetDir2 = targetDir
if self.config.plfile2arfolder == "True":
targetDir2 = self.__creatAlbumDir(aAlbumInfo, self.config.quality)
filePath = self.__getAlbumSongSavePath(targetDir2, aAlbumInfo, item, fileType)
paraList = {'album': aAlbumInfo, 'title': item['title'], 'trackinfo': item,
'url': streamInfo['url'], 'path': filePath, 'retry': 3, 'key': streamInfo['encryptionKey']}
else:
seq = self.tool.getIndexStr(index, len(aItemInfo))
filePath = targetDir2 + '/' + seq + " "+ pathHelper.replaceLimitChar(item['title'], '-') + fileType
paraList = {'album': aAlbumInfo, 'index': index, 'title': item['title'], 'trackinfo': item,
'url': streamInfo['url'], 'path': filePath, 'retry': 3, 'key': streamInfo['encryptionKey']}
try:
coverPath = targetDir2 + '/' + pathHelper.replaceLimitChar(aAlbumInfo['title'], '-') + '.jpg'
coverUrl = self.tool.getAlbumArtworkUrl(aAlbumInfo['cover'])
netHelper.downloadFile(coverUrl, coverPath)
paraList['coverpath'] = coverPath
tmpcoverpath.append(coverPath)
except:
cmdHelper.myprint("Could not download artwork for '{}'".format(
item['title']), cmdHelper.TextColor.Red, None)
if self.config.onlym4a == "True":
self.check.addPath(filePath.replace(".mp4", ".m4a"))
else:
self.check.addPath(filePath)
self.thread.start(self.__thradfunc_dl, paraList)
self.thread.waitAll()
self.tool.removeTmpFile(targetDir)
# remove cover
if self.config.savephoto != 'True':
for item in tmpcoverpath:
pathHelper.remove(item)
bBreakFlag = True
bFirstTime = False
# check
isErr, errIndex = self.check.checkPaths()
if isErr:
check = printChoice("[Err]\t\t" + str(len(errIndex)) + " Tracks Download Failed.Try Again?(y/n):")
if check == 'y' or check == 'Y':
bBreakFlag = False
# download video
for item in aItemInfo:
type = item['type']
item = item['item']
if type != 'video':
continue
filePath = targetDir + '/' + pathHelper.replaceLimitChar(item['title'], '-') + ".mp4"
filePath = os.path.abspath(filePath)
if os.access(filePath, 0):
os.remove(filePath)
videoID = item['id']
resolutionList, urlList = self.tool.getVideoResolutionList(videoID)
if urlList is None:
printErr(14, item['title'] + '(' + self.tool.errmsg + ')')
else:
selectIndex = self.__getVideoResolutionIndex(resolutionList)
if self.ffmpeg.mergerByM3u8_Multithreading2(urlList[int(selectIndex)], filePath, showprogress=self.showpro):
printSUCCESS(14, item['title'])
else:
printErr(14, item['title'] + "(Download Or Merger Err!)")
if playlist_id is not None:
return
return
def downloadFavorite(self):
targetDir = self.config.outputdir + "/Favorite/"
pathHelper.mkdirs(targetDir)
trackList, videoList = self.tool.getFavorite(self.config.userid)
if self.tool.errmsg != "":
printErr(0, "Get FavoriteList Err! " + self.tool.errmsg)
return
print("[NumberOfTracks] %s" % (len(trackList)))
print("[NumberOfVideos] %s" % (len(videoList)))
# download track
for item in trackList:
item = item['item']
streamInfo = self.tool.getStreamUrl(str(item['id']), self.config.quality)
if self.tool.errmsg != "" or not streamInfo:
printErr(14, item['title'] + "(Get Stream Url Err!!" + self.tool.errmsg + ")")
continue
fileType = self._getSongExtension(streamInfo['url'])
filePath = targetDir + '/' + pathHelper.replaceLimitChar(item['title'], '-') + fileType
aAlbumInfo = self.tool.getAlbum(item['album']['id'])
paraList = {'album': aAlbumInfo, 'title': item['title'], 'trackinfo': item,
'url': streamInfo['url'], 'path': filePath, 'retry': 3, 'key': streamInfo['encryptionKey']}
self.thread.start(self.__thradfunc_dl, paraList)
self.thread.waitAll()
# download video
for item in videoList:
item = item['item']
filePath = targetDir + '/' + pathHelper.replaceLimitChar(item['title'], '-') + ".mp4"
filePath = os.path.abspath(filePath)
if os.access(filePath, 0):
os.remove(filePath)
resolutionList, urlList = self.tool.getVideoResolutionList(item['id'])
selectIndex = self.__getVideoResolutionIndex(resolutionList)
if self.ffmpeg.mergerByM3u8_Multithreading2(urlList[int(selectIndex)], filePath, showprogress=self.showpro):
printSUCCESS(14, item['title'])
else:
printErr(14, item['title'])
return
def downloadUrl(self, link):
stype, sid = self.tool.parseLink(link)
if stype is None or sid is None:
return
if stype == "album":
print("----------------ALBUM------------------")
self.downloadAlbum(sid)
elif stype == "track":
print("----------------TRACK------------------")
self.downloadTrack(sid)
elif stype == "video":
print("----------------VIDEO------------------")
self.downloadVideo(sid)
elif stype == "playlist":
print("--------------PLAYLIST-----------------")
self.downloadPlaylist(sid)
elif stype == "artist":
print("----------------ARTIST-----------------")
self.downloadArtistAlbum(self.config.includesingle == "True", sid)
def downloadByFile(self, path):
if not os.path.exists(path):
return
arr = self.tool.parseFile(path)
print("----------------FILE------------------")
print("[Number of albums] %s" % (len(arr['album'])))
print("[Number of artists] %s" % (len(arr['artist'])))
print("[Number of tracks] %s" % (len(arr['track'])))
print("[Number of videos] %s" % (len(arr['video'])))
print("[Number of URLs] %s" % (len(arr['url'])))
if len(arr['album']) > 0:
redownload = True
check = printChoice("Skip downloaded files?(y/n):")
if not cmdHelper.isInputYes(check):
redownload = False
for index, item in enumerate(arr['album']):
print("----Album[{0}/{1}]----".format(index+1, len(arr['album'])))
print("[ID] %s" % (item))
self.downloadAlbum(item, redownload)
for index, item in enumerate(arr['artist']):
print(index)
print("----Artist[{0}/{1}]----".format(index+1, len(arr['artist'])))
print("[ID] %s" % (item))
includeSingles = self.config.includesingle == "True"
self.downloadArtistAlbum(includeSingles, item)
for index, item in enumerate(arr['track']):
print("----Track[{0}/{1}]----".format(index+1, len(arr['track'])))
print("[ID] %s" % (item))
self.downloadTrack(item)
for index, item in enumerate(arr['video']):
print("----Video[{0}/{1}]----".format(index+1, len(arr['video'])))
print("[ID] %s" % (item))
self.downloadVideo(item)
for index, item in enumerate(arr['url']):
print("----Url[{0}/{1}]----".format(index+1, len(arr['url'])))
print("[link] %s" % (item))
stype, sid = self.tool.parseLink(item)
if stype is None or sid is None:
printErr(14, 'Link can`t parse!')
continue
print("[ID] %s" % (sid))
if stype == "album":
print("[Type] %s" % ("album"))
self.downloadAlbum(sid)
if stype == "track":
print("[Type] %s" % ("track"))
self.downloadTrack(sid)
if stype == "video":
print("[Type] %s" % ("video"))
self.downloadVideo(sid)
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File : download.py
@Time : 2020/11/08
@Author : Yaronzz
@Version : 1.0
@Contact : yaronhuang@foxmail.com
@Desc :
'''
from concurrent.futures import ThreadPoolExecutor
from decryption import *
from printf import *
from tidal import *
def __isSkip__(finalpath, url):
if not SETTINGS.checkExist:
return False
curSize = aigpy.file.getSize(finalpath)
if curSize <= 0:
return False
netSize = aigpy.net.getSize(url)
return curSize >= netSize
def __encrypted__(stream, srcPath, descPath):
if aigpy.string.isNull(stream.encryptionKey):
os.replace(srcPath, descPath)
else:
key, nonce = decrypt_security_token(stream.encryptionKey)
decrypt_file(srcPath, descPath, key, nonce)
os.remove(srcPath)
def __parseContributors__(roleType, Contributors):
if Contributors is None:
return None
try:
ret = []
for item in Contributors['items']:
if item['role'] == roleType:
ret.append(item['name'])
return ret
except:
return None
def __setMetaData__(track: Track, album: Album, filepath, contributors, lyrics):
obj = aigpy.tag.TagTool(filepath)
obj.album = track.album.title
obj.title = track.title
if not aigpy.string.isNull(track.version):
obj.title += ' (' + track.version + ')'
obj.artist = list(map(lambda artist: artist.name, track.artists))
obj.copyright = track.copyRight
obj.tracknumber = track.trackNumber
obj.discnumber = track.volumeNumber
obj.composer = __parseContributors__('Composer', contributors)
obj.isrc = track.isrc
obj.albumartist = list(map(lambda artist: artist.name, album.artists))
obj.date = album.releaseDate
obj.totaldisc = album.numberOfVolumes
obj.lyrics = lyrics
if obj.totaldisc <= 1:
obj.totaltrack = album.numberOfTracks
coverpath = TIDAL_API.getCoverUrl(album.cover, "1280", "1280")
obj.save(coverpath)
def downloadCover(album):
if album is None:
return
path = getAlbumPath(album) + '/cover.jpg'
url = TIDAL_API.getCoverUrl(album.cover, "1280", "1280")
aigpy.net.downloadFile(url, path)
def downloadAlbumInfo(album, tracks):
if album is None:
return
path = getAlbumPath(album)
aigpy.path.mkdirs(path)
path += '/AlbumInfo.txt'
infos = ""
infos += "[ID] %s\n" % (str(album.id))
infos += "[Title] %s\n" % (str(album.title))
infos += "[Artists] %s\n" % (TIDAL_API.getArtistsName(album.artists))
infos += "[ReleaseDate] %s\n" % (str(album.releaseDate))
infos += "[SongNum] %s\n" % (str(album.numberOfTracks))
infos += "[Duration] %s\n" % (str(album.duration))
infos += '\n'
for index in range(0, album.numberOfVolumes):
volumeNumber = index + 1
infos += f"===========CD {volumeNumber}=============\n"
for item in tracks:
if item.volumeNumber != volumeNumber:
continue
infos += '{:<8}'.format("[%d]" % item.trackNumber)
infos += "%s\n" % item.title
aigpy.file.write(path, infos, "w+")
def downloadVideo(video: Video, album: Album = None, playlist: Playlist = None):
try:
stream = TIDAL_API.getVideoStreamUrl(video.id, SETTINGS.videoQuality)
path = getVideoPath(video, album, playlist)
Printf.video(video, stream)
logging.info("[DL Video] name=" + aigpy.path.getFileName(path) + "\nurl=" + stream.m3u8Url)
m3u8content = requests.get(stream.m3u8Url).content
if m3u8content is None:
Printf.err(f"DL Video[{video.title}] getM3u8 failed.{str(e)}")
return False, f"GetM3u8 failed.{str(e)}"
urls = aigpy.m3u8.parseTsUrls(m3u8content)
if len(urls) <= 0:
Printf.err(f"DL Video[{video.title}] getTsUrls failed.{str(e)}")
return False, "GetTsUrls failed.{str(e)}"
check, msg = aigpy.m3u8.downloadByTsUrls(urls, path)
if check:
Printf.success(video.title)
return True
else:
Printf.err(f"DL Video[{video.title}] failed.{msg}")
return False, msg
except Exception as e:
Printf.err(f"DL Video[{video.title}] failed.{str(e)}")
return False, str(e)
def downloadTrack(track: Track, album=None, playlist=None, userProgress=None, partSize=1048576):
try:
stream = TIDAL_API.getStreamUrl(track.id, SETTINGS.audioQuality)
path = getTrackPath(track, stream, album, playlist)
if SETTINGS.showTrackInfo and not SETTINGS.multiThread:
Printf.track(track, stream)
if userProgress is not None:
userProgress.updateStream(stream)
# check exist
if __isSkip__(path, stream.url):
Printf.success(aigpy.path.getFileName(path) + " (skip:already exists!)")
return True, ''
# download
logging.info("[DL Track] name=" + aigpy.path.getFileName(path) + "\nurl=" + stream.url)
tool = aigpy.download.DownloadTool(path + '.part', stream.urls)
tool.setUserProgress(userProgress)
tool.setPartSize(partSize)
check, err = tool.start(SETTINGS.showProgress and not SETTINGS.multiThread)
if not check:
Printf.err(f"DL Track '{track.title}' failed: {str(err)}")
return False, str(err)
# encrypted -> decrypt and remove encrypted file
__encrypted__(stream, path + '.part', path)
# contributors
try:
contributors = TIDAL_API.getTrackContributors(track.id)
except:
contributors = None
# lyrics
try:
lyrics = TIDAL_API.getLyrics(track.id).subtitles
if SETTINGS.lyricFile:
lrcPath = path.rsplit(".", 1)[0] + '.lrc'
aigpy.file.write(lrcPath, lyrics, 'w')
except:
lyrics = ''
__setMetaData__(track, album, path, contributors, lyrics)
Printf.success(track.title)
return True, ''
except Exception as e:
Printf.err(f"DL Track '{track.title}' failed: {str(e)}")
return False, str(e)
def downloadTracks(tracks, album: Album = None, playlist: Playlist = None):
def __getAlbum__(item: Track):
album = TIDAL_API.getAlbum(item.album.id)
if SETTINGS.saveCovers and not SETTINGS.usePlaylistFolder:
downloadCover(album)
return album
if not SETTINGS.multiThread:
for index, item in enumerate(tracks):
itemAlbum = album
if itemAlbum is None:
itemAlbum = __getAlbum__(item)
item.trackNumberOnPlaylist = index + 1
downloadTrack(item, itemAlbum, playlist)
else:
thread_pool = ThreadPoolExecutor(max_workers=5)
for index, item in enumerate(tracks):
itemAlbum = album
if itemAlbum is None:
itemAlbum = __getAlbum__(item)
item.trackNumberOnPlaylist = index + 1
thread_pool.submit(downloadTrack, item, itemAlbum, playlist)
thread_pool.shutdown(wait=True)
def downloadVideos(videos, album: Album, playlist=None):
for item in videos:
downloadVideo(item, album, playlist)
+37
View File
@@ -0,0 +1,37 @@
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File : enums.py
@Time : 2020/08/08
@Author : Yaronzz
@Version : 3.0
@Contact : yaronhuang@foxmail.com
@Desc :
'''
from enum import Enum
class AudioQuality(Enum):
Normal = 0
High = 1
HiFi = 2
Master = 3
Max = 4
class VideoQuality(Enum):
P240 = 240
P360 = 360
P480 = 480
P720 = 720
P1080 = 1080
class Type(Enum):
Album = 0
Track = 1
Video = 2
Playlist = 3
Artist = 4
Mix = 5
Null = 6
+320
View File
@@ -0,0 +1,320 @@
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
"""
@File : events.py
@Date : 2022/06/10
@Author : Yaronzz
@Version : 1.0
@Contact : yaronhuang@foxmail.com
@Desc :
"""
from download import *
'''
=================================
START DOWNLOAD
=================================
'''
def start_album(obj: Album):
Printf.album(obj)
tracks, videos = TIDAL_API.getItems(obj.id, Type.Album)
if SETTINGS.saveAlbumInfo:
downloadAlbumInfo(obj, tracks)
if SETTINGS.saveCovers and obj.cover is not None:
downloadCover(obj)
downloadTracks(tracks, obj)
if SETTINGS.downloadVideos:
downloadVideos(videos, obj)
def start_track(obj: Track):
album = TIDAL_API.getAlbum(obj.album.id)
if SETTINGS.saveCovers:
downloadCover(album)
downloadTrack(obj, album)
def start_video(obj: Video):
downloadVideo(obj, obj.album)
def start_artist(obj: Artist):
albums = TIDAL_API.getArtistAlbums(obj.id, SETTINGS.includeEP)
Printf.artist(obj, len(albums))
for item in albums:
start_album(item)
def start_playlist(obj: Playlist):
Printf.playlist(obj)
tracks, videos = TIDAL_API.getItems(obj.uuid, Type.Playlist)
downloadTracks(tracks, None, obj)
if SETTINGS.downloadVideos:
downloadVideos(videos, None, obj)
def start_mix(obj: Mix):
Printf.mix(obj)
downloadTracks(obj.tracks, None, None)
downloadVideos(obj.videos, None, None)
def start_file(string):
txt = aigpy.file.getContent(string)
if aigpy.string.isNull(txt):
Printf.err("Nothing can read!")
return
array = txt.split('\n')
for item in array:
if aigpy.string.isNull(item):
continue
if item[0] == '#':
continue
if item[0] == '[':
continue
start(item)
def start_type(etype: Type, obj):
if etype == Type.Album:
start_album(obj)
elif etype == Type.Track:
start_track(obj)
elif etype == Type.Video:
start_video(obj)
elif etype == Type.Artist:
start_artist(obj)
elif etype == Type.Playlist:
start_playlist(obj)
elif etype == Type.Mix:
start_mix(obj)
def start(string):
if aigpy.string.isNull(string):
Printf.err('Please enter something.')
return
strings = string.split(" ")
for item in strings:
if aigpy.string.isNull(item):
continue
if os.path.exists(item):
start_file(item)
return
try:
etype, obj = TIDAL_API.getByString(item)
except Exception as e:
Printf.err(str(e) + " [" + item + "]")
return
try:
start_type(etype, obj)
except Exception as e:
Printf.err(str(e))
'''
=================================
CHANGE SETTINGS
=================================
'''
def changePathSettings():
Printf.settings()
SETTINGS.downloadPath = Printf.enterPath(
LANG.select.CHANGE_DOWNLOAD_PATH,
LANG.select.MSG_PATH_ERR,
'0',
SETTINGS.downloadPath)
SETTINGS.albumFolderFormat = Printf.enterFormat(
LANG.select.CHANGE_ALBUM_FOLDER_FORMAT,
SETTINGS.albumFolderFormat,
SETTINGS.getDefaultPathFormat(Type.Album))
SETTINGS.playlistFolderFormat = Printf.enterFormat(
LANG.select.CHANGE_PLAYLIST_FOLDER_FORMAT,
SETTINGS.playlistFolderFormat,
SETTINGS.getDefaultPathFormat(Type.Playlist))
SETTINGS.trackFileFormat = Printf.enterFormat(
LANG.select.CHANGE_TRACK_FILE_FORMAT,
SETTINGS.trackFileFormat,
SETTINGS.getDefaultPathFormat(Type.Track))
SETTINGS.videoFileFormat = Printf.enterFormat(
LANG.select.CHANGE_VIDEO_FILE_FORMAT,
SETTINGS.videoFileFormat,
SETTINGS.getDefaultPathFormat(Type.Video))
SETTINGS.save()
def changeQualitySettings():
Printf.settings()
SETTINGS.audioQuality = AudioQuality(
int(Printf.enterLimit(LANG.select.CHANGE_AUDIO_QUALITY,
LANG.select.MSG_INPUT_ERR,
['0', '1', '2', '3', '4'])))
SETTINGS.videoQuality = VideoQuality(
int(Printf.enterLimit(LANG.select.CHANGE_VIDEO_QUALITY,
LANG.select.MSG_INPUT_ERR,
['1080', '720', '480', '360'])))
SETTINGS.save()
def changeSettings():
Printf.settings()
SETTINGS.showProgress = Printf.enterBool(LANG.select.CHANGE_SHOW_PROGRESS)
SETTINGS.showTrackInfo = Printf.enterBool(LANG.select.CHANGE_SHOW_TRACKINFO)
SETTINGS.checkExist = Printf.enterBool(LANG.select.CHANGE_CHECK_EXIST)
SETTINGS.includeEP = Printf.enterBool(LANG.select.CHANGE_INCLUDE_EP)
SETTINGS.saveCovers = Printf.enterBool(LANG.select.CHANGE_SAVE_COVERS)
SETTINGS.saveAlbumInfo = Printf.enterBool(LANG.select.CHANGE_SAVE_ALBUM_INFO)
SETTINGS.downloadVideos = Printf.enterBool(LANG.select.CHANGE_DOWNLOAD_VIDEOS)
SETTINGS.lyricFile = Printf.enterBool(LANG.select.CHANGE_ADD_LRC_FILE)
SETTINGS.multiThread = Printf.enterBool(LANG.select.CHANGE_MULITHREAD_DOWNLOAD)
SETTINGS.usePlaylistFolder = Printf.enterBool(LANG.select.SETTING_USE_PLAYLIST_FOLDER + "('0'-No,'1'-Yes):")
SETTINGS.downloadDelay = Printf.enterBool(LANG.select.CHANGE_USE_DOWNLOAD_DELAY)
SETTINGS.language = Printf.enter(LANG.select.CHANGE_LANGUAGE + "(" + LANG.getLangChoicePrint() + "):")
LANG.setLang(SETTINGS.language)
SETTINGS.save()
def changeApiKey():
item = apiKey.getItem(SETTINGS.apiKeyIndex)
ver = apiKey.getVersion()
Printf.info(f'Current APIKeys: {str(SETTINGS.apiKeyIndex)} {item["platform"]}-{item["formats"]}')
Printf.info(f'Current Version: {str(ver)}')
Printf.apikeys(apiKey.getItems())
index = int(Printf.enterLimit("APIKEY index:", LANG.select.MSG_INPUT_ERR, apiKey.getLimitIndexs()))
if index != SETTINGS.apiKeyIndex:
SETTINGS.apiKeyIndex = index
SETTINGS.save()
TIDAL_API.apiKey = apiKey.getItem(index)
return True
return False
'''
=================================
LOGIN
=================================
'''
def __displayTime__(seconds, granularity=2):
if seconds <= 0:
return "unknown"
result = []
intervals = (
('weeks', 604800),
('days', 86400),
('hours', 3600),
('minutes', 60),
('seconds', 1),
)
for name, count in intervals:
value = seconds // count
if value:
seconds -= value * count
if value == 1:
name = name.rstrip('s')
result.append("{} {}".format(value, name))
return ', '.join(result[:granularity])
def loginByWeb():
try:
print(LANG.select.AUTH_START_LOGIN)
# get device code
url = TIDAL_API.getDeviceCode()
print(LANG.select.AUTH_NEXT_STEP.format(
aigpy.cmd.green(url),
aigpy.cmd.yellow(__displayTime__(TIDAL_API.key.authCheckTimeout))))
print(LANG.select.AUTH_WAITING)
start = time.time()
elapsed = 0
while elapsed < TIDAL_API.key.authCheckTimeout:
elapsed = time.time() - start
if not TIDAL_API.checkAuthStatus():
time.sleep(TIDAL_API.key.authCheckInterval + 1)
continue
Printf.success(LANG.select.MSG_VALID_ACCESSTOKEN.format(
__displayTime__(int(TIDAL_API.key.expiresIn))))
TOKEN.userid = TIDAL_API.key.userId
TOKEN.countryCode = TIDAL_API.key.countryCode
TOKEN.accessToken = TIDAL_API.key.accessToken
TOKEN.refreshToken = TIDAL_API.key.refreshToken
TOKEN.expiresAfter = time.time() + int(TIDAL_API.key.expiresIn)
TOKEN.save()
return True
raise Exception(LANG.select.AUTH_TIMEOUT)
except Exception as e:
Printf.err(f"Login failed.{str(e)}")
return False
def loginByConfig():
try:
if aigpy.string.isNull(TOKEN.accessToken):
return False
if TIDAL_API.verifyAccessToken(TOKEN.accessToken):
Printf.info(LANG.select.MSG_VALID_ACCESSTOKEN.format(
__displayTime__(int(TOKEN.expiresAfter - time.time()))))
TIDAL_API.key.countryCode = TOKEN.countryCode
TIDAL_API.key.userId = TOKEN.userid
TIDAL_API.key.accessToken = TOKEN.accessToken
return True
Printf.info(LANG.select.MSG_INVALID_ACCESSTOKEN)
if TIDAL_API.refreshAccessToken(TOKEN.refreshToken):
Printf.success(LANG.select.MSG_VALID_ACCESSTOKEN.format(
__displayTime__(int(TIDAL_API.key.expiresIn))))
TOKEN.userid = TIDAL_API.key.userId
TOKEN.countryCode = TIDAL_API.key.countryCode
TOKEN.accessToken = TIDAL_API.key.accessToken
TOKEN.expiresAfter = time.time() + int(TIDAL_API.key.expiresIn)
TOKEN.save()
return True
else:
TokenSettings().save()
return False
except Exception as e:
return False
def loginByAccessToken():
try:
print("-------------AccessToken---------------")
token = Printf.enter("accessToken('0' go back):")
if token == '0':
return
TIDAL_API.loginByAccessToken(token, TOKEN.userid)
except Exception as e:
Printf.err(str(e))
return
print("-------------RefreshToken---------------")
refreshToken = Printf.enter("refreshToken('0' to skip):")
if refreshToken == '0':
refreshToken = TOKEN.refreshToken
TOKEN.accessToken = token
TOKEN.refreshToken = refreshToken
TOKEN.expiresAfter = 0
TOKEN.countryCode = TIDAL_API.key.countryCode
TOKEN.save()
+300
View File
@@ -0,0 +1,300 @@
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
"""
@File : test.py
@Date : 2022/03/28
@Author : Yaronzz
@Version : 1.0
@Contact : yaronhuang@foxmail.com
@Desc :
"""
import importlib
import sys
import _thread
from events import *
from printf import *
def enableGui():
try:
importlib.import_module('PyQt5')
importlib.import_module('qt_material')
return True
except Exception as e:
return False
if not enableGui():
def startGui():
Printf.err("Not support gui. Please type: `pip3 install PyQt5 qt_material`")
else:
from PyQt5.QtCore import Qt, QObject
from PyQt5.QtGui import QTextCursor, QKeyEvent
from PyQt5.QtCore import pyqtSignal
from PyQt5 import QtWidgets
from qt_material import apply_stylesheet
class EmittingStream(QObject):
textWritten = pyqtSignal(str)
def write(self, text):
self.textWritten.emit(str(text))
class MainView(QtWidgets.QWidget):
s_downloadEnd = pyqtSignal(str, bool, str)
def __init__(self, ) -> None:
super().__init__()
self.initView()
self.setMinimumSize(800, 620)
self.setWindowTitle("TIDAL-DL")
def __info__(self, msg):
QtWidgets.QMessageBox.information(self, 'Info', msg, QtWidgets.QMessageBox.Yes)
def __output__(self, text):
cursor = self.c_printTextEdit.textCursor()
cursor.movePosition(QTextCursor.End)
cursor.insertText(text)
self.c_printTextEdit.setTextCursor(cursor)
self.c_printTextEdit.ensureCursorVisible()
def initView(self):
self.c_lineSearch = QtWidgets.QLineEdit()
self.c_btnSearch = QtWidgets.QPushButton("Search")
self.c_btnDownload = QtWidgets.QPushButton("Download")
self.c_combType = QtWidgets.QComboBox()
self.c_combTQuality = QtWidgets.QComboBox()
self.c_combVQuality = QtWidgets.QComboBox()
# Supported types for search
self.m_supportType = [Type.Album, Type.Playlist, Type.Track, Type.Video, Type.Artist]
for item in self.m_supportType:
self.c_combType.addItem(item.name, item)
for item in AudioQuality:
self.c_combTQuality.addItem(item.name, item)
for item in VideoQuality:
self.c_combVQuality.addItem(item.name, item)
self.c_combTQuality.setCurrentText(SETTINGS.audioQuality.name)
self.c_combVQuality.setCurrentText(SETTINGS.videoQuality.name)
# init table
columnNames = ['#', 'Title', 'Artists', 'Quality']
self.c_tableInfo = QtWidgets.QTableWidget()
self.c_tableInfo.setColumnCount(len(columnNames))
self.c_tableInfo.setRowCount(0)
self.c_tableInfo.setShowGrid(False)
self.c_tableInfo.verticalHeader().setVisible(False)
self.c_tableInfo.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
self.c_tableInfo.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
self.c_tableInfo.horizontalHeader().setStretchLastSection(True)
self.c_tableInfo.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.ResizeMode.ResizeToContents)
self.c_tableInfo.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.c_tableInfo.setFocusPolicy(Qt.NoFocus)
for index, name in enumerate(columnNames):
item = QtWidgets.QTableWidgetItem(name)
self.c_tableInfo.setHorizontalHeaderItem(index, item)
# Create Tree View for playlists.
self.tree_playlists = QtWidgets.QTreeWidget()
self.tree_playlists.setAnimated(False)
self.tree_playlists.setIndentation(20)
self.tree_playlists.setSortingEnabled(True)
self.tree_playlists.setFixedWidth(200)
self.tree_playlists.setColumnCount(1)
self.tree_playlists.setHeaderLabels(("User Playlists",))
# self.tree_playlists.setColumnWidth(0, 100)
self.tree_playlists.setContextMenuPolicy(Qt.CustomContextMenu)
# print
self.c_printTextEdit = QtWidgets.QTextEdit()
self.c_printTextEdit.setReadOnly(True)
self.c_printTextEdit.setFixedHeight(100)
sys.stdout = EmittingStream(textWritten=self.__output__)
sys.stderr = EmittingStream(textWritten=self.__output__)
# layout
self.lineGrid = QtWidgets.QHBoxLayout()
self.lineGrid.addWidget(self.c_combType)
self.lineGrid.addWidget(self.c_lineSearch)
self.lineGrid.addWidget(self.c_btnSearch)
self.line2Grid = QtWidgets.QHBoxLayout()
self.line2Grid.addWidget(QtWidgets.QLabel("QUALITY:"))
self.line2Grid.addWidget(self.c_combTQuality)
self.line2Grid.addWidget(self.c_combVQuality)
self.line2Grid.addStretch(4)
self.line2Grid.addWidget(self.c_btnDownload)
self.funcGrid = QtWidgets.QVBoxLayout()
self.funcGrid.addLayout(self.lineGrid)
self.funcGrid.addWidget(self.c_tableInfo)
self.funcGrid.addLayout(self.line2Grid)
self.funcGrid.addWidget(self.c_printTextEdit)
self.mainGrid = QtWidgets.QHBoxLayout(self)
self.mainGrid.addWidget(self.tree_playlists)
self.mainGrid.addLayout(self.funcGrid)
# connect
self.c_btnSearch.clicked.connect(self.search)
self.c_lineSearch.returnPressed.connect(self.search)
self.c_btnDownload.clicked.connect(self.download)
self.s_downloadEnd.connect(self.downloadEnd)
self.c_combTQuality.currentIndexChanged.connect(self.changeTQuality)
self.c_combVQuality.currentIndexChanged.connect(self.changeVQuality)
self.tree_playlists.itemClicked.connect(self.__displayTracks__)
def keyPressEvent(self, event: QKeyEvent):
if event.modifiers() & Qt.MetaModifier and event.key() == Qt.Key_A:
self.c_tableInfo.selectAll()
def addItem(self, rowIdx: int, colIdx: int, text):
if isinstance(text, str):
item = QtWidgets.QTableWidgetItem(text)
self.c_tableInfo.setItem(rowIdx, colIdx, item)
def search(self):
self.c_tableInfo.setRowCount(0)
self.s_type = self.c_combType.currentData()
self.s_text = self.c_lineSearch.text()
if self.s_text.startswith('http'):
tmpType, tmpId = TIDAL_API.parseUrl(self.s_text)
if tmpType == Type.Null:
self.__info__('Url not support')
return
elif tmpType not in self.m_supportType:
self.__info__(f'Type[{tmpType.name}] not support')
return
tmpData = TIDAL_API.getTypeData(tmpId, tmpType)
if tmpData is None:
self.__info__('Url is wrong!')
return
self.s_type = tmpType
self.s_array = [tmpData]
self.s_result = None
self.c_combType.setCurrentText(tmpType.name)
else:
self.s_result = TIDAL_API.search(self.s_text, self.s_type)
self.s_array = TIDAL_API.getSearchResultItems(self.s_result, self.s_type)
if len(self.s_array) <= 0:
self.__info__('No result')
return
self.setSearchResults(self.s_array, self.s_type)
def setSearchResults(self, s_array, s_type):
self.c_tableInfo.clearSelection()
self.c_tableInfo.setRowCount(len(s_array))
for index, item in enumerate(s_array):
self.addItem(index, 0, str(index + 1))
if s_type in [Type.Album, Type.Track]:
self.addItem(index, 1, item.title)
self.addItem(index, 2, TIDAL_API.getArtistsName(item.artists))
self.addItem(index, 3, item.audioQuality)
elif s_type in [Type.Video]:
self.addItem(index, 1, item.title)
self.addItem(index, 2, TIDAL_API.getArtistsName(item.artists))
self.addItem(index, 3, item.quality)
elif s_type in [Type.Playlist]:
self.addItem(index, 1, item.title)
self.addItem(index, 2, '')
self.addItem(index, 3, '')
elif s_type in [Type.Artist]:
self.addItem(index, 1, item.name)
self.addItem(index, 2, '')
self.addItem(index, 3, '')
self.c_tableInfo.viewport().update()
def download(self):
if self.c_tableInfo.selectionModel().hasSelection() == False:
self.__info__('Please select a row first.')
return
rows = self.c_tableInfo.selectionModel().selectedRows()
items = []
for row in rows:
items.append(self.s_array[row.row()])
self.__downloadFunc__(items)
def __downloadFunc__(self, items):
self.c_btnDownload.setEnabled(False)
def __thread_download__(model: MainView, items):
itemTitle = ''
type = model.s_type
try:
for item in items:
if isinstance(item, Artist):
itemTitle = item.name
else:
itemTitle = item.title
start_type(type, item)
model.s_downloadEnd.emit('Download Success!', True, '')
except Exception as e:
model.s_downloadEnd.emit(itemTitle, False, str(e))
_thread.start_new_thread(__thread_download__, (self, items))
def downloadEnd(self, title, result, msg):
self.c_btnDownload.setEnabled(True)
self.c_btnDownload.setText(f"Download")
if result:
self.__info__(f"Download finished.")
else:
self.__info__(f"Download '{title}' failed:{msg}")
def checkLogin(self):
if not loginByConfig():
self.__info__('Login failed. Please log in using the command line first.')
else:
self.__showSelfPlaylists__()
def changeTQuality(self, index):
SETTINGS.audioQuality = self.c_combTQuality.itemData(index)
SETTINGS.save()
def changeVQuality(self, index):
SETTINGS.videoQuality = self.c_combVQuality.itemData(index)
SETTINGS.save()
def __showSelfPlaylists__(self):
playlists = TIDAL_API.getPlaylistSelf()
for playlist in playlists:
item = QtWidgets.QTreeWidgetItem(self.tree_playlists)
item.setText(0, playlist.title)
item.setText(1, str(playlist.numberOfTracks))
item.setText(2, playlist.uuid)
def __displayTracks__(self, item, column):
tracks, videos = TIDAL_API.getItems(item.text(2), Type.Playlist)
self.s_array = tracks
self.s_type = Type.Track
self.setSearchResults(tracks, Type.Track)
def startGui():
aigpy.cmd.enableColor(False)
app = QtWidgets.QApplication(sys.argv)
apply_stylesheet(app, theme='dark_blue.xml')
window = MainView()
window.show()
window.checkLogin()
app.exec_()
if __name__ == '__main__':
SETTINGS.read(getProfilePath())
TOKEN.read(getTokenPath())
startGui()
+10
View File
@@ -0,0 +1,10 @@
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File : __init__.py
@Time : 2020/08/19
@Author : Yaronzz
@Version : 1.0
@Contact : yaronhuang@foxmail.com
@Desc :
'''
+126
View File
@@ -0,0 +1,126 @@
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File : arabic.py
@Time : 2020/08/19
@Author : shhade for hack
@Version : 1.0
@Contact :
@Desc :
'''
class LangArabic(object):
SETTING = "الاعدادت"
VALUE = "القيمة"
SETTING_DOWNLOAD_PATH = "مجلد التحميل"
SETTING_ONLY_M4A = "تحويل m4a الى mp4"
SETTING_ADD_EXPLICIT_TAG = "اضافة توقيع الفنان"
SETTING_ADD_HYPHEN = "اضافة سطر تحتي"
SETTING_ADD_YEAR = "اضافة سنة الاصدار قبل نجلد التنزيل"
SETTING_USE_TRACK_NUM = "اضف رقم التتبع الخاص بالاغنية"
SETTING_AUDIO_QUALITY = "دقة الصوت"
SETTING_VIDEO_QUALITY = "دقة الفديو"
SETTING_CHECK_EXIST = "التاكد من وجود الملف قبل التنزيل"
SETTING_ARTIST_BEFORE_TITLE = "اسم الفنان قبل اسم الاغنية"
SETTING_ALBUMID_BEFORE_FOLDER = "رقم التتبع قبل مجلد التنزيل"
SETTING_INCLUDE_EP = "اضافة single&ep"
SETTING_SAVE_COVERS = "حفظ صورة الالبوم"
SETTING_LANGUAGE = "اللغة"
SETTING_USE_PLAYLIST_FOLDER = "Use playlist folder"
SETTING_MULITHREAD_DOWNLOAD = "Multi thread download"
SETTING_ALBUM_FOLDER_FORMAT = "Album folder format"
SETTING_PLAYLIST_FOLDER_FORMAT = "Playlist folder format"
SETTING_TRACK_FILE_FORMAT = "Track file format"
SETTING_VIDEO_FILE_FORMAT = "Video file format"
SETTING_SHOW_PROGRESS = "Show progress"
SETTING_SHOW_TRACKINFO = "Show Track Info"
SETTING_SAVE_ALBUMINFO = "Save AlbumInfo.txt"
SETTING_DOWNLOAD_VIDEOS = "Download videos"
SETTING_ADD_LYRICS = "Add lyrics"
SETTING_LYRICS_SERVER_PROXY = "Lyrics server proxy"
SETTING_PATH = "Settings path"
SETTING_ADD_LRC_FILE = "Save timed lyrics (.lrc file)"
SETTING_APIKEY = "APIKey support"
SETTING_ADD_TYPE_FOLDER = "Add Type-Folder"
SETTING_DOWNLOAD_DELAY = "Use Download Delay"
CHOICE = "خيار"
FUNCTION = "وظيفة"
CHOICE_ENTER = "ادخل"
CHOICE_ENTER_URLID = "ادخل 'رابط/رقم تتبع':"
CHOICE_EXIT = "اخرج"
CHOICE_LOGIN = "Check AccessToken"
CHOICE_SETTINGS = "الاعدادات"
CHOICE_SET_ACCESS_TOKEN = "اعداد AccessToken"
CHOICE_DOWNLOAD_BY_URL = "التحميل عبر الرابط او رقم التتبع"
CHOICE_LOGOUT = "Logout"
CHOICE_APIKEY = "Select APIKey"
PRINT_ERR = "[خطأ]"
PRINT_INFO = "[معلومة]"
PRINT_SUCCESS = "[نجاح]"
PRINT_ENTER_CHOICE = "ادخل الخيار:"
PRINT_LATEST_VERSION = "آخر اصدر:"
# PRINT_USERNAME = "اسم المستخدم:"
# PRINT_PASSWORD = "رمز الدخول:"
CHANGE_START_SETTINGS = "بدء الاعدادات('0'-Return,'1'-Yes):"
CHANGE_DOWNLOAD_PATH = "مجلد التنزيل('0' not modify):"
CHANGE_AUDIO_QUALITY = "دقة الصوت('0'-Normal,'1'-High,'2'-HiFi,'3'-Master,'4'-Max):"
CHANGE_VIDEO_QUALITY = "دقة الفديو(1080, 720, 480, 360):"
CHANGE_ONLYM4A = "تحويل M4a الى mp4('0'-No,'1'-Yes):"
CHANGE_ADD_EXPLICIT_TAG = "اضافة توقيع الفنان('0'-No,'1'-Yes):"
CHANGE_ADD_HYPHEN = "استخدم السطور التحتية بدل الفراغات('0'-No,'1'-Yes):"
CHANGE_ADD_YEAR = "اضافة سنة الاصدار الى مجلد الالبوم('0'-No,'1'-Yes):"
CHANGE_USE_TRACK_NUM = "اضافة رقم الاغنية قبل اسمها('0'-No,'1'-Yes):"
CHANGE_CHECK_EXIST = "التحقق من وجود الملف قبل التحميل('0'-No,'1'-Yes):"
CHANGE_ARTIST_BEFORE_TITLE = "اضف اسم الفنان قبل اسم الاغنية('0'-No,'1'-Yes):"
CHANGE_INCLUDE_EP = "اضافة مسطلحات فردي او ثنائي الى الغنية('0'-No,'1'-Yes):"
CHANGE_ALBUMID_BEFORE_FOLDER = "اضف رقم التتبع قبل اسم مجلد الالبوم('0'-No,'1'-Yes):"
CHANGE_SAVE_COVERS = "حفظ صورة الالبوم('0'-No,'1'-Yes):"
CHANGE_LANGUAGE = "اختر لغة"
CHANGE_ALBUM_FOLDER_FORMAT = "Album folder format('0'-not modify,'default'-to set default):"
CHANGE_PLAYLIST_FOLDER_FORMAT = "Playlist folder format('0'-not modify,'default'-to set default):"
CHANGE_TRACK_FILE_FORMAT = "Track file format('0'-not modify,'default'-to set default):"
CHANGE_VIDEO_FILE_FORMAT = "Video file format('0'-not modify,'default'-to set default):"
CHANGE_SHOW_PROGRESS = "Show progress('0'-No,'1'-Yes):"
CHANGE_SHOW_TRACKINFO = "Show track info('0'-No,'1'-Yes):"
CHANGE_SAVE_ALBUM_INFO = "Save AlbumInfo.txt('0'-No,'1'-Yes):"
CHANGE_DOWNLOAD_VIDEOS = "Download videos (when downloading playlists, albums, mixes)('0'-No,'1'-Yes):"
CHANGE_ADD_LYRICS = "Add lyrics('0'-No,'1'-Yes):"
CHANGE_LYRICS_SERVER_PROXY = "Lyrics server proxy('0'-not modify):"
CHANGE_ADD_LRC_FILE = "Save timed lyrics .lrc file ('0'-No,'1'-Yes):"
CHANGE_ADD_TYPE_FOLDER = "Add Type-Folder,eg Album/Video/Playlist('0'-No,'1'-Yes):"
CHANGE_MULITHREAD_DOWNLOAD = "Multi thread download('0'-No,'1'-Yes):"
CHANGE_USE_DOWNLOAD_DELAY = "Use Download Delay('0'-No,'1'-Yes):"
# {} are required in these strings
AUTH_START_LOGIN = "Starting login process..."
AUTH_LOGIN_CODE = "Your login code is {}"
AUTH_NEXT_STEP = "Go to {} within the next {} to complete setup."
AUTH_WAITING = "Waiting for authorization..."
AUTH_TIMEOUT = "Operation timed out."
MSG_VALID_ACCESSTOKEN = "AccessToken good for {}."
MSG_INVALID_ACCESSTOKEN = "Expired AccessToken. Attempting to refresh it."
MSG_PATH_ERR = "!مجلد التنزيل خاطئ"
MSG_INPUT_ERR = "!ادخال خاطئ"
MODEL_ALBUM_PROPERTY = "ملكية الالبوم"
MODEL_TRACK_PROPERTY = "ملكية الاغنية"
MODEL_VIDEO_PROPERTY = "ملكية الفديو"
MODEL_ARTIST_PROPERTY = "ملكية الفنان"
MODEL_PLAYLIST_PROPERTY = "ملكية قائمة الاغاني"
MODEL_TITLE = 'الاسم'
MODEL_TRACK_NUMBER = 'رقم الاغنية'
MODEL_VIDEO_NUMBER = 'رقم الفديو'
MODEL_RELEASE_DATE = 'عام الاصدار'
MODEL_VERSION = 'الاصدار'
MODEL_EXPLICIT = 'توقيع الفنان'
MODEL_ALBUM = 'الالبوم'
MODEL_ID = 'رقم التتبع'
MODEL_NAME = 'الاسم'
MODEL_TYPE = 'النوع'
+126
View File
@@ -0,0 +1,126 @@
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File : chinese.py
@Time : 2020/08/19
@Author : Yaronzz
@Version : 1.0
@Contact : yaronhuang@foxmail.com
@Desc :
'''
class LangChinese(object):
SETTING = "设置"
VALUE = ""
SETTING_DOWNLOAD_PATH = "下载目录"
SETTING_ONLY_M4A = "转换mp4为m4a"
SETTING_ADD_EXPLICIT_TAG = "文件名添加脏标Explicit"
SETTING_ADD_HYPHEN = "文件名用'-'代替空格"
SETTING_ADD_YEAR = "专辑文件夹添加年代标签"
SETTING_USE_TRACK_NUM = "歌曲名称添加序号"
SETTING_AUDIO_QUALITY = "歌曲质量"
SETTING_VIDEO_QUALITY = "视频质量"
SETTING_CHECK_EXIST = "是否跳过已下载的文件"
SETTING_ARTIST_BEFORE_TITLE = "文件名前添加歌手名"
SETTING_ALBUMID_BEFORE_FOLDER = "专辑文件夹添加专辑ID"
SETTING_INCLUDE_EP = "下载歌手专辑时包含其EP单曲"
SETTING_SAVE_COVERS = "保存封面"
SETTING_LANGUAGE = "语言"
SETTING_USE_PLAYLIST_FOLDER = "将歌单下载到歌单目录"
SETTING_MULITHREAD_DOWNLOAD = "多线程下载"
SETTING_ALBUM_FOLDER_FORMAT = "专辑目录格式"
SETTING_PLAYLIST_FOLDER_FORMAT = "Playlist folder format"
SETTING_TRACK_FILE_FORMAT = "歌曲文件名格式"
SETTING_VIDEO_FILE_FORMAT = "视频文件格式"
SETTING_SHOW_PROGRESS = "显示进度条"
SETTING_SHOW_TRACKINFO = "显示歌曲信息"
SETTING_SAVE_ALBUMINFO = "保存AlbumInfo.txt"
SETTING_DOWNLOAD_VIDEOS = "Download videos"
SETTING_ADD_LYRICS = "添加歌词"
SETTING_LYRICS_SERVER_PROXY = "歌词服务器代理"
SETTING_ADD_LRC_FILE = "保存歌词文件 (.lrc file)"
SETTING_PATH = "配置文件目录"
SETTING_APIKEY = "APIKey支持"
SETTING_ADD_TYPE_FOLDER = "添加类型文件夹"
SETTING_DOWNLOAD_DELAY = "Use Download Delay"
CHOICE = "选项"
FUNCTION = "功能"
CHOICE_ENTER = "输入"
CHOICE_ENTER_URLID = "输入 'Url或ID':"
CHOICE_EXIT = "退出"
CHOICE_LOGIN = "检查AccessToken"
CHOICE_SETTINGS = "配置"
CHOICE_SET_ACCESS_TOKEN = "设置AccessToken"
CHOICE_DOWNLOAD_BY_URL = "通过链接或ID下载"
CHOICE_LOGOUT = "注销"
CHOICE_APIKEY = "选择APIKey"
PRINT_ERR = "[错误]"
PRINT_INFO = "[提示]"
PRINT_SUCCESS = "[成功]"
PRINT_ENTER_CHOICE = "输入选项:"
PRINT_LATEST_VERSION = "最新版本:"
# PRINT_USERNAME = "用户:"
# PRINT_PASSWORD = "密码:"
CHANGE_START_SETTINGS = "开始设置('0'-返回,'1'-是):"
CHANGE_DOWNLOAD_PATH = "下载路径('0' 不修改):"
CHANGE_AUDIO_QUALITY = "音频质量('0'-Normal,'1'-High,'2'-HiFi,'3'-Master,'4'-Max):"
CHANGE_VIDEO_QUALITY = "视频质量(1080, 720, 480, 360):"
CHANGE_ONLYM4A = "将Mp4格式的音频转为M4a('0'-不,'1'-是):"
CHANGE_ADD_EXPLICIT_TAG = "歌名后添加脏话标签('0'-不,'1'-是):"
CHANGE_ADD_HYPHEN = "文件名中用'-'代替空格('0'-不,'1'-是):"
CHANGE_ADD_YEAR = "专辑目录前添加年代标签('0'-不,'1'-是):"
CHANGE_USE_TRACK_NUM = "文件名前添加序号('0'-不,'1'-是):"
CHANGE_CHECK_EXIST = "下载前检查是否有已下载的文件('0'-不,'1'-是):"
CHANGE_ARTIST_BEFORE_TITLE = "文件名前添加歌手名称('0'-不,'1'-是):"
CHANGE_INCLUDE_EP = "下载歌手专辑时包含其EP单曲('0'-不,'1'-是):"
CHANGE_ALBUMID_BEFORE_FOLDER = "专辑目录前添加ID('0'-不,'1'-是):"
CHANGE_SAVE_COVERS = "保存封面('0'-不,'1'-是):"
CHANGE_LANGUAGE = "选择语言"
CHANGE_ALBUM_FOLDER_FORMAT = "专辑目录格式('0' 不修改):"
CHANGE_PLAYLIST_FOLDER_FORMAT = "Playlist folder format('0'-not modify,'default'-to set default):"
CHANGE_TRACK_FILE_FORMAT = "歌曲文件名格式('0' 不修改):"
CHANGE_VIDEO_FILE_FORMAT = "视频文件名格式('0'-not modify,'default'-to set default):"
CHANGE_SHOW_PROGRESS = "显示进度条('0'-不,'1'-是):"
CHANGE_SHOW_TRACKINFO = "显示歌曲信息('0'-否,'1'-是):"
CHANGE_SAVE_ALBUM_INFO = "保存AlbumInfo.txt('0'-否,'1'-是):"
CHANGE_DOWNLOAD_VIDEOS = "Download videos (when downloading playlists, albums, mixes)('0'-No,'1'-Yes):"
CHANGE_ADD_LYRICS = "添加歌词('0'-否,'1'-是):"
CHANGE_LYRICS_SERVER_PROXY = "歌词服务器代理('0' 不修改):"
CHANGE_ADD_LRC_FILE = "保存歌词文件 ('0'-否,'1'-是):"
CHANGE_ADD_TYPE_FOLDER = "Add Type-Folder,eg Album/Video/Playlist('0'-No,'1'-Yes):"
CHANGE_MULITHREAD_DOWNLOAD = "多线程下载('0'-否,'1'-是):"
CHANGE_USE_DOWNLOAD_DELAY = "Use Download Delay('0'-No,'1'-Yes):"
# {} are required in these strings
AUTH_START_LOGIN = "开始启动登录..."
AUTH_LOGIN_CODE = "你的登录码为: {}"
AUTH_NEXT_STEP = "请打开 {} 并在 {} 之内完成操作."
AUTH_WAITING = "等待登录验证..."
AUTH_TIMEOUT = "操作超时."
MSG_VALID_ACCESSTOKEN = "AccessToken有效期为 {}."
MSG_INVALID_ACCESSTOKEN = "AccessToken失效. 正在尝试更新它."
MSG_PATH_ERR = "路径错误!"
MSG_INPUT_ERR = "输入错误!"
MODEL_ALBUM_PROPERTY = "专辑信息"
MODEL_TRACK_PROPERTY = "歌曲信息"
MODEL_VIDEO_PROPERTY = "视频信息"
MODEL_ARTIST_PROPERTY = "歌手信息"
MODEL_PLAYLIST_PROPERTY = "歌单信息"
MODEL_TITLE = '标题'
MODEL_TRACK_NUMBER = '歌曲数量'
MODEL_VIDEO_NUMBER = '视频数量'
MODEL_RELEASE_DATE = '发布时间'
MODEL_VERSION = '版本'
MODEL_EXPLICIT = '脏标'
MODEL_ALBUM = '专辑'
MODEL_ID = 'ID'
MODEL_NAME = '名称'
MODEL_TYPE = '类型'
+126
View File
@@ -0,0 +1,126 @@
# !/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File : croatian.py
@Time : 2020/08/19
@Author : Yaronzz
@Version : 1.0
@Contact : yaronhuang@foxmail.com
@Desc :
'''
class LangCroatian(object):
SETTING = "POSTAVKE"
VALUE = "VRIJEDNOST"
SETTING_DOWNLOAD_PATH = "putanja preuzimanja"
SETTING_ONLY_M4A = "Pretvori mp4 u m4a"
SETTING_ADD_EXPLICIT_TAG = "Dodaj eksplicitni znak"
SETTING_ADD_HYPHEN = "Dodaj crticu"
SETTING_ADD_YEAR = "Dodaj godinu prije imena albuma u mapi"
SETTING_USE_TRACK_NUM = "Dodaj korisnicki broj pjesme"
SETTING_AUDIO_QUALITY = "Kvaliteta zvuka"
SETTING_VIDEO_QUALITY = "Kvaliteta videozapisa"
SETTING_CHECK_EXIST = "Provjeri postoji li"
SETTING_ARTIST_BEFORE_TITLE = "Ime izvodjaca prije imena pjesme"
SETTING_ALBUMID_BEFORE_FOLDER = "ID oznaka prije imena albuma u mapi"
SETTING_INCLUDE_EP = "Ukljuci singl i EP"
SETTING_SAVE_COVERS = "Spremi ilustraciju albuma"
SETTING_LANGUAGE = "Jezik"
SETTING_USE_PLAYLIST_FOLDER = "Use playlist folder"
SETTING_MULITHREAD_DOWNLOAD = "Multi thread download"
SETTING_ALBUM_FOLDER_FORMAT = "Album folder format"
SETTING_PLAYLIST_FOLDER_FORMAT = "Playlist folder format"
SETTING_TRACK_FILE_FORMAT = "Track file format"
SETTING_VIDEO_FILE_FORMAT = "Video file format"
SETTING_SHOW_PROGRESS = "Show progress"
SETTING_SHOW_TRACKINFO = "Show Track Info"
SETTING_SAVE_ALBUMINFO = "Save AlbumInfo.txt"
SETTING_DOWNLOAD_VIDEOS = "Download videos"
SETTING_ADD_LYRICS = "Add lyrics"
SETTING_LYRICS_SERVER_PROXY = "Lyrics server proxy"
SETTING_ADD_LRC_FILE = "Save timed lyrics (.lrc file)"
SETTING_PATH = "Settings path"
SETTING_APIKEY = "APIKey support"
SETTING_ADD_TYPE_FOLDER = "Add Type-Folder"
SETTING_DOWNLOAD_DELAY = "Use Download Delay"
CHOICE = "ODABIR"
FUNCTION = "FUNKCIJA"
CHOICE_ENTER = "Ulaz"
CHOICE_ENTER_URLID = "Unesi 'Url/ID':"
CHOICE_EXIT = "Izlaz"
CHOICE_LOGIN = "Check AccessToken"
CHOICE_SETTINGS = "Postavke"
CHOICE_SET_ACCESS_TOKEN = "Postavi AccessToken"
CHOICE_DOWNLOAD_BY_URL = "Preuzmi po url-u ili ID-u"
CHOICE_LOGOUT = "Logout"
CHOICE_APIKEY = "Select APIKey"
PRINT_ERR = "[ERR]"
PRINT_INFO = "[INFO]"
PRINT_SUCCESS = "[USPIJESNO]"
PRINT_ENTER_CHOICE = "Unesi odabir:"
PRINT_LATEST_VERSION = "Posljednja verzija:"
# PRINT_USERNAME = "korisnik:"
# PRINT_PASSWORD = "lozinka:"
CHANGE_START_SETTINGS = "Pokreni postavke (0'-Izlaz,'1'-Da):"
CHANGE_DOWNLOAD_PATH = "Putanja preuzimanja('0' ne mijenjaj):"
CHANGE_AUDIO_QUALITY = "Kvaliteta zvuka('0'-Normalna,'1'-Visoka,'2'-HiFi,'3'-Master,'4'-Max):"
CHANGE_VIDEO_QUALITY = "Kvaliteta videozapisa(1080, 720, 480, 360):"
CHANGE_ONLYM4A = "Pretvori mp4 u m4a('0'-Ne,'1'-Da):"
CHANGE_ADD_EXPLICIT_TAG = "Dodaj eksplicitni znak u imeni datoteke('0'-Ne,'1'-Da):"
CHANGE_ADD_HYPHEN = "Koristi crtice umjesto razmaka u imeni datoteke ('0'-Ne,'1'-Da):"
CHANGE_ADD_YEAR = "Dodaj godinu u imenu albuma u mapi('0'-Ne,'1'-Da):"
CHANGE_USE_TRACK_NUM = "Dodaj broj pjesme prije imena pjesme u datoteci ('0'-Ne,'1'-Da):"
CHANGE_CHECK_EXIST = "Provjeri postoji li ista datoteka prije preuzimanja pjesme('0'-Ne,'1'-Da):"
CHANGE_ARTIST_BEFORE_TITLE = "Dodaj ime izvodjaca prije imena pjesme('0'-Ne,'1'-Da):"
CHANGE_INCLUDE_EP = "Ukljuci singlove i EP-ove prilikom preuzimanja albuma izvodjaca('0'-Ne,'1'-Da):"
CHANGE_ALBUMID_BEFORE_FOLDER = "Dodaj ID oznaku prije imena albuma u datoteci('0'-Ne,'1'-Da):"
CHANGE_SAVE_COVERS = "Spremi ilustracije albuma('0'-Ne,'1'-Da):"
CHANGE_LANGUAGE = "Odaberi jezik"
CHANGE_ALBUM_FOLDER_FORMAT = "Album folder format('0'-not modify,'default'-to set default):"
CHANGE_PLAYLIST_FOLDER_FORMAT = "Playlist folder format('0'-not modify,'default'-to set default):"
CHANGE_TRACK_FILE_FORMAT = "Track file format('0'-not modify,'default'-to set default):"
CHANGE_VIDEO_FILE_FORMAT = "Video file format('0'-not modify,'default'-to set default):"
CHANGE_SHOW_PROGRESS = "Show progress('0'-No,'1'-Yes):"
CHANGE_SHOW_TRACKINFO = "Show track info('0'-No,'1'-Yes):"
CHANGE_SAVE_ALBUM_INFO = "Save AlbumInfo.txt('0'-No,'1'-Yes):"
CHANGE_DOWNLOAD_VIDEOS = "Download videos (when downloading playlists, albums, mixes)('0'-No,'1'-Yes):"
CHANGE_ADD_LYRICS = "Add lyrics('0'-No,'1'-Yes):"
CHANGE_LYRICS_SERVER_PROXY = "Lyrics server proxy('0'-not modify):"
CHANGE_ADD_LRC_FILE = "Save timed lyrics .lrc file ('0'-No,'1'-Yes):"
CHANGE_ADD_TYPE_FOLDER = "Add Type-Folder,eg Album/Video/Playlist('0'-No,'1'-Yes):"
CHANGE_MULITHREAD_DOWNLOAD = "Multi thread download('0'-No,'1'-Yes):"
CHANGE_USE_DOWNLOAD_DELAY = "Use Download Delay('0'-No,'1'-Yes):"
# {} are required in these strings
AUTH_START_LOGIN = "Starting login process..."
AUTH_LOGIN_CODE = "Your login code is {}"
AUTH_NEXT_STEP = "Go to {} within the next {} to complete setup."
AUTH_WAITING = "Waiting for authorization..."
AUTH_TIMEOUT = "Operation timed out."
MSG_VALID_ACCESSTOKEN = "AccessToken good for {}."
MSG_INVALID_ACCESSTOKEN = "Expired AccessToken. Attempting to refresh it."
MSG_PATH_ERR = "Pogreska putanje!"
MSG_INPUT_ERR = "Pogreska unosa!"
MODEL_ALBUM_PROPERTY = "ALBUM-SVOJSTVO"
MODEL_TRACK_PROPERTY = "PJESMA-SVOJSTVO"
MODEL_VIDEO_PROPERTY = "VIDEOZAPIS-SVOJSTVO"
MODEL_ARTIST_PROPERTY = "IZVODJAC-SVOJSTVO"
MODEL_PLAYLIST_PROPERTY = "PLAYLISTA-SVOJSTVO"
MODEL_TITLE = 'Naziv'
MODEL_TRACK_NUMBER = 'Broj pjesme'
MODEL_VIDEO_NUMBER = 'Broj videozapisa'
MODEL_RELEASE_DATE = 'Datum izlaska'
MODEL_VERSION = 'Verzija'
MODEL_EXPLICIT = 'Eksplicitno'
MODEL_ALBUM = 'Album'
MODEL_ID = 'ID'
MODEL_NAME = 'Naziv'
MODEL_TYPE = 'Vrsta'
+126
View File
@@ -0,0 +1,126 @@
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File : czech.py
@Time : 2022/11/13
@Author : Tomikk & Sweder
@Version : 1.2
@Contact : justtomikk@gmail.com & djsweder@gmail.com
@Desc :
'''
class LangCzech(object):
SETTING = "Nastavení"
VALUE = "Hodnota"
SETTING_DOWNLOAD_PATH = "Umístění staženého souboru"
SETTING_ONLY_M4A = "Konvertovat mp4 na m4a"
SETTING_ADD_EXPLICIT_TAG = "Přidat označení explicity"
SETTING_ADD_HYPHEN = "Místo mezer použít pomlčky"
SETTING_ADD_YEAR = "Přidat rok před jméno složky"
SETTING_USE_TRACK_NUM = "Přidat číslo skladby"
SETTING_AUDIO_QUALITY = "Kvalita hudby"
SETTING_VIDEO_QUALITY = "Kvalita videa"
SETTING_CHECK_EXIST = "Zkontrolovat existenci souboru"
SETTING_ARTIST_BEFORE_TITLE = "Jméno interpreta před jménem skladby"
SETTING_ALBUMID_BEFORE_FOLDER = "Id před složkou alba"
SETTING_INCLUDE_EP = "Zahrnout singly & EP"
SETTING_SAVE_COVERS = "Uložit obal alba"
SETTING_LANGUAGE = "Změna jazyka"
SETTING_USE_PLAYLIST_FOLDER = "Používat složku playlistu"
SETTING_MULITHREAD_DOWNLOAD = "Stahování více vlákny"
SETTING_ALBUM_FOLDER_FORMAT = "Formát názvu složky alba"
SETTING_PLAYLIST_FOLDER_FORMAT = "Playlist folder format"
SETTING_TRACK_FILE_FORMAT = "Formát názvu souboru skladby"
SETTING_VIDEO_FILE_FORMAT = "Formát názvu souboru videa"
SETTING_SHOW_PROGRESS = "Zobrazit indikátor stavu stahování"
SETTING_SHOW_TRACKINFO = "Zobrazit informace o skladbě"
SETTING_SAVE_ALBUMINFO = "Uložit soubor AlbumInfo.txt"
SETTING_DOWNLOAD_VIDEOS = "Download videos"
SETTING_ADD_LYRICS = "Přidat texty skladeb"
SETTING_LYRICS_SERVER_PROXY = "Server proxy pro texty skladeb"
SETTING_ADD_LRC_FILE = "Uložit slova skladby s časováním (soubor .lrc)"
SETTING_PATH = "Cesta k souboru s nastavením"
SETTING_APIKEY = "APIKey podporuje"
SETTING_ADD_TYPE_FOLDER = "Složky dle typu obsahu"
SETTING_DOWNLOAD_DELAY = "Stahovat s časovou prodlevou"
CHOICE = "Výběr"
FUNCTION = "Funkce"
CHOICE_ENTER = "Zvolit"
CHOICE_ENTER_URLID = "Vložit 'Url/ID':"
CHOICE_EXIT = "Ukončit"
CHOICE_LOGIN = "Zkontrolovat přístupový token"
CHOICE_SETTINGS = "Nastavení"
CHOICE_SET_ACCESS_TOKEN = "Nastavit přístupový token"
CHOICE_DOWNLOAD_BY_URL = "Stáhnout buď dle URL nebo ID"
CHOICE_LOGOUT = "Odhlásit"
CHOICE_APIKEY = "Vybrat APIKey"
PRINT_ERR = "[Chyba]"
PRINT_INFO = "[Info]"
PRINT_SUCCESS = "[Staženo]"
PRINT_ENTER_CHOICE = "Zvolit volbu:"
PRINT_LATEST_VERSION = "Nejnovější verze:"
# PRINT_USERNAME = "přihlašovací jméno:"
# PRINT_PASSWORD = "heslo"
CHANGE_START_SETTINGS = "Spustit nastavení ('0'-Zpět,'1'-Ano):"
CHANGE_DOWNLOAD_PATH = "Umístění stažených souborů ('0' beze změny):"
CHANGE_AUDIO_QUALITY = "Kvalita hudby ('0'-Normální,'1'-Vysoká,'2'-HiFi,'3'-Master,'4'-Max):"
CHANGE_VIDEO_QUALITY = "Kvalita videa (1080, 720, 480, 360):"
CHANGE_ONLYM4A = "Konvertovat mp4 na m4a ('0'-Ne,'1'-Ano):"
CHANGE_ADD_EXPLICIT_TAG = "Přidat označení explicity k souborům ('0'-Ne,'1'-Ano):"
CHANGE_ADD_HYPHEN = "V názvech souborů používat místo mezer pomlčky ('0'-Ne,'1'-Ano):"
CHANGE_ADD_YEAR = "Přidat rok vydání do názvu složky ('0'-Ne,'1'-Ano):"
CHANGE_USE_TRACK_NUM = "Přidat číslo skladby před název skladby ('0'-Ne,'1'-Ano):"
CHANGE_CHECK_EXIST = "Zkontrolovat existenci souboru před stažením ('0'-Ne,'1'-Ano):"
CHANGE_ARTIST_BEFORE_TITLE = "Přidat jméno interpreta před název skladby ('0'-Ne,'1'-Ano):"
CHANGE_INCLUDE_EP = "Při stahování alb interpreta zahrnout singly a EP ('0'-Ne,'1'-Ano):"
CHANGE_ALBUMID_BEFORE_FOLDER = "Přidat ID před název složky s albem ('0'-Ne,'1'-Ano):"
CHANGE_SAVE_COVERS = "Uložit obaly alb ('0'-Ne,'1'-Ano):"
CHANGE_LANGUAGE = "Zvolit jazyk"
CHANGE_ALBUM_FOLDER_FORMAT = "Formát názvu složky alba ('0' beze změny):"
CHANGE_PLAYLIST_FOLDER_FORMAT = "Playlist folder format('0'-not modify,'default'-to set default):"
CHANGE_TRACK_FILE_FORMAT = "Formát názvu složky skladny ('0' beze změny):"
CHANGE_VIDEO_FILE_FORMAT = "Formát názvu souboru videa ('0'-beze změny,'default'-pro nastavení výchozího názvu):"
CHANGE_SHOW_PROGRESS = "Zobrazit indikátor stavu stahování ('0'-Ne,'1'-Ano):"
CHANGE_SHOW_TRACKINFO = "Zobrazit info o skladbě ('0'-Ne,'1'-Ano):"
CHANGE_SAVE_ALBUM_INFO = "Uložit soubor AlbumInfo.txt ('0'-Ne,'1'-Ano):"
CHANGE_DOWNLOAD_VIDEOS = "Download videos (when downloading playlists, albums, mixes)('0'-No,'1'-Yes):"
CHANGE_ADD_LYRICS = "Přidat texty skladeb ('0'-Ne,'1'-Ano):"
CHANGE_LYRICS_SERVER_PROXY = "Server proxy pro texty skladeb ('0' beze změny):"
CHANGE_ADD_LRC_FILE = "Uložit slova skladby s časováním do souboru .lrc) ('0'-Ne,'1'-Ano):"
CHANGE_ADD_TYPE_FOLDER = "Ukládat do složek dle typu obsahu, např. Album/Video/Playlist ('0'-Ne,'1'-Ano):"
CHANGE_MULITHREAD_DOWNLOAD = "Více vláken pro stahování ('0'-Ne,'1'-Ano):"
CHANGE_USE_DOWNLOAD_DELAY = "Stahovat s časovou prodlevou('0'-Ne,'1'-Ano):"
# {} are required in these strings
AUTH_START_LOGIN = "Spouštění přihlašovacího procesu..."
AUTH_LOGIN_CODE = "Váš přihlašovací kód je {}"
AUTH_NEXT_STEP = "K dokončení nastavení přejděte na stránku {} během následujích {}."
AUTH_WAITING = "Čeká se na autorizaci..."
AUTH_TIMEOUT = "Vypršel časový limit procesu."
MSG_VALID_ACCESSTOKEN = "Přístupový token fukční pro {}."
MSG_INVALID_ACCESSTOKEN = "Platnost přístupového tokenu vypršela. Pokouším se o obnovení."
MSG_PATH_ERR = "Cesta neexistuje!"
MSG_INPUT_ERR = "Chyba zadání!"
MODEL_ALBUM_PROPERTY = "ALBUM-VLASTNOSTI"
MODEL_TRACK_PROPERTY = "SKLADBA-VLASTNOSTI"
MODEL_VIDEO_PROPERTY = "VIDEO-VLASTNOSTI"
MODEL_ARTIST_PROPERTY = "INTERPRET-VLASTNOSTI"
MODEL_PLAYLIST_PROPERTY = "PLAYLIST-VLASTNOSTI"
MODEL_TITLE = 'Název skladby'
MODEL_TRACK_NUMBER = 'Číslo skladby'
MODEL_VIDEO_NUMBER = 'Číslo videa'
MODEL_RELEASE_DATE = 'Datum vydání'
MODEL_VERSION = 'Verze'
MODEL_EXPLICIT = 'Explicitní'
MODEL_ALBUM = 'Album'
MODEL_ID = 'ID'
MODEL_NAME = 'Jméno'
MODEL_TYPE = 'Typ'
+126
View File
@@ -0,0 +1,126 @@
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File : danish.py
@Time : 2021/03/25
@Author : KB885
@Version : 1.0
@Contact :
@Desc :
'''
class LangDanish(object):
SETTING = "INDSTILLINGER"
VALUE = "Værdi"
SETTING_DOWNLOAD_PATH = "Download sti"
SETTING_ONLY_M4A = "Konverter mp4 til m4a"
SETTING_ADD_EXPLICIT_TAG = "Tilføj eksplicit tag"
SETTING_ADD_HYPHEN = "Tilføj bindestreg"
SETTING_ADD_YEAR = "Tilføj år før album mappe"
SETTING_USE_TRACK_NUM = "Tilføj titelnummer"
SETTING_AUDIO_QUALITY = "Lydkvalitet"
SETTING_VIDEO_QUALITY = "Videokvalitet"
SETTING_CHECK_EXIST = "Kontroller eksistens"
SETTING_ARTIST_BEFORE_TITLE = "Kunstnernavn før titelnummer"
SETTING_ALBUMID_BEFORE_FOLDER = "Id før album mappe"
SETTING_INCLUDE_EP = "Inkluder single&ep"
SETTING_SAVE_COVERS = "Gem omslag"
SETTING_LANGUAGE = "Sprog"
SETTING_USE_PLAYLIST_FOLDER = "Brug afspilningsmappen"
SETTING_MULITHREAD_DOWNLOAD = "Flertråede download"
SETTING_ALBUM_FOLDER_FORMAT = "Albummappens format"
SETTING_PLAYLIST_FOLDER_FORMAT = "Spillelistemappens format"
SETTING_TRACK_FILE_FORMAT = "Musiknummerets filformat"
SETTING_VIDEO_FILE_FORMAT = "Video file format"
SETTING_SHOW_PROGRESS = "Vis fremskridt"
SETTING_SHOW_TRACKINFO = "Show Track Info"
SETTING_SAVE_ALBUMINFO = "Save AlbumInfo.txt"
SETTING_DOWNLOAD_VIDEOS = "Download videos"
SETTING_ADD_LYRICS = "Add lyrics"
SETTING_LYRICS_SERVER_PROXY = "Lyrics server proxy"
SETTING_ADD_LRC_FILE = "Save timed lyrics (.lrc file)"
SETTING_PATH = "Settings path"
SETTING_APIKEY = "APIKey support"
SETTING_ADD_TYPE_FOLDER = "Add Type-Folder"
SETTING_DOWNLOAD_DELAY = "Use Download Delay"
CHOICE = "VALG"
FUNCTION = "FUNKTION"
CHOICE_ENTER = "Indtast"
CHOICE_ENTER_URLID = "Indtast 'Url/ID':"
CHOICE_EXIT = "Afslut"
CHOICE_LOGIN = "Kontroller AccessToken"
CHOICE_SETTINGS = "Indstillinger"
CHOICE_SET_ACCESS_TOKEN = "Sæt AccessToken"
CHOICE_DOWNLOAD_BY_URL = "Download via url eller id"
CHOICE_LOGOUT = "Log ud"
CHOICE_APIKEY = "Select APIKey"
PRINT_ERR = "[FEJL]"
PRINT_INFO = "[INFO]"
PRINT_SUCCESS = "[SUCCES]"
PRINT_ENTER_CHOICE = "Indtast Valg:"
PRINT_LATEST_VERSION = "Seneste version:"
# PRINT_USERNAME = "username:"
# PRINT_PASSWORD = "password:"
CHANGE_START_SETTINGS = "Start indstillinger('0'-Tilbage,'1'-Ja):"
CHANGE_DOWNLOAD_PATH = "Download stil('0' ændrer ikke):"
CHANGE_AUDIO_QUALITY = "Lydkvalitet('0'-Normal,'1'-Høj,'2'-HiFi,'3'-Master,'4'-Max):"
CHANGE_VIDEO_QUALITY = "Videokvalitet(1080, 720, 480, 360):"
CHANGE_ONLYM4A = "Konverter mp4 til m4a('0'-Nej,'1'-Ja):"
CHANGE_ADD_EXPLICIT_TAG = "Tilføj eksplicit tag til filnavne('0'-Nej,'1'-Ja):"
CHANGE_ADD_HYPHEN = "Brug bindestreger i stedet for mellemrum i filnavne('0'-Nej,'1'-Ja):"
CHANGE_ADD_YEAR = "Tilføj år til albumnavne('0'-Nej,'1'-Ja):"
CHANGE_USE_TRACK_NUM = "Tilføj titelnummer før filnavne('0'-Nej,'1'-Ja):"
CHANGE_CHECK_EXIST = "Kontrollér filens eksistens før download('0'-Nej,'1'-Ja):"
CHANGE_ARTIST_BEFORE_TITLE = "Tilføj kunsternavn før titlenummer('0'-Nej,'1'-Ja):"
CHANGE_INCLUDE_EP = "Inkluder singler og EP'er når der downloades en kunstners album('0'-Nej,'1'-Ja):"
CHANGE_ALBUMID_BEFORE_FOLDER = "Tilføj id før albummappe('0'-Nej,'1'-Ja):"
CHANGE_SAVE_COVERS = "Gem omslag('0'-Nej,'1'-Ja):"
CHANGE_LANGUAGE = "Vælg sprog"
CHANGE_ALBUM_FOLDER_FORMAT = "Albummappeformat('0' Ændrer ikke, 'default' for at indstille som standard):"
CHANGE_PLAYLIST_FOLDER_FORMAT = "Spillelistemappeformat('0' Ændrer ikke, 'default' for at indstille som standard):"
CHANGE_TRACK_FILE_FORMAT = "Musiknummerets filformat('0' Ændrer ikke, 'default' for at indstille som standard):"
CHANGE_VIDEO_FILE_FORMAT = "Video file format('0'-not modify,'default'-to set default):"
CHANGE_SHOW_PROGRESS = "Vis fremskridt('0'-Nej,'1'-Ja):"
CHANGE_SHOW_TRACKINFO = "Show track info('0'-No,'1'-Yes):"
CHANGE_SAVE_ALBUM_INFO = "Save AlbumInfo.txt('0'-No,'1'-Yes):"
CHANGE_DOWNLOAD_VIDEOS = "Download videos (when downloading playlists, albums, mixes)('0'-No,'1'-Yes):"
CHANGE_ADD_LYRICS = "Add lyrics('0'-No,'1'-Yes):"
CHANGE_LYRICS_SERVER_PROXY = "Lyrics server proxy('0'-not modify):"
CHANGE_ADD_LRC_FILE = "Save timed lyrics .lrc file ('0'-No,'1'-Yes):"
CHANGE_ADD_TYPE_FOLDER = "Add Type-Folder,eg Album/Video/Playlist('0'-No,'1'-Yes):"
CHANGE_MULITHREAD_DOWNLOAD = "Multi thread download('0'-No,'1'-Yes):"
CHANGE_USE_DOWNLOAD_DELAY = "Use Download Delay('0'-No,'1'-Yes):"
# {} are required in these strings
AUTH_START_LOGIN = "Starter login-processen."
AUTH_LOGIN_CODE = "Din login kode er {}"
AUTH_NEXT_STEP = "Gå til {} inden for de næste {} for at afslutte opsætningen."
AUTH_WAITING = "Venter på godkendelse..."
AUTH_TIMEOUT = "Tiden løb ud."
MSG_VALID_ACCESSTOKEN = "AccessToken tilgængelig for {}."
MSG_INVALID_ACCESSTOKEN = "AccessToken udløb. Forsøger at opdatere"
MSG_PATH_ERR = "Sti fejl!"
MSG_INPUT_ERR = "Indtastningsfejl!"
MODEL_ALBUM_PROPERTY = "ALBUM-PROPERTY"
MODEL_TRACK_PROPERTY = "TRACK-PROPERTY"
MODEL_VIDEO_PROPERTY = "VIDEO-PROPERTY"
MODEL_ARTIST_PROPERTY = "ARTIST-PROPERTY"
MODEL_PLAYLIST_PROPERTY = "PLAYLIST-PROPERTY"
MODEL_TITLE = 'Titel'
MODEL_TRACK_NUMBER = 'Titelnummer'
MODEL_VIDEO_NUMBER = 'Videonummer'
MODEL_RELEASE_DATE = 'Udgivelses dato'
MODEL_VERSION = 'Version'
MODEL_EXPLICIT = 'Eksplicit'
MODEL_ALBUM = 'Album'
MODEL_ID = 'ID'
MODEL_NAME = 'Navn'
MODEL_TYPE = 'Type'
+126
View File
@@ -0,0 +1,126 @@
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File : dutch.py
@Time : 2022/03/01
@Author : bladeoner
@Version : 1.0
@Contact :
@Desc :
'''
class LangDutch(object):
SETTING = "INSTELLINGEN"
VALUE = "WAARDE"
SETTING_DOWNLOAD_PATH = "Download pad"
SETTING_ONLY_M4A = "mp4 naar m4a converteren"
SETTING_ADD_EXPLICIT_TAG = "Expliciete tag toevoegen"
SETTING_ADD_HYPHEN = "Koppelteken toevoegen"
SETTING_ADD_YEAR = "Jaar voor albummap toevoegen"
SETTING_USE_TRACK_NUM = "Tracknummer gebruiker toevoegen"
SETTING_AUDIO_QUALITY = "Audiokwaliteit"
SETTING_VIDEO_QUALITY = "Videokwaliteit"
SETTING_CHECK_EXIST = "Controleer of al bestaat"
SETTING_ARTIST_BEFORE_TITLE = "Artiestnaam voor tracktitel"
SETTING_ALBUMID_BEFORE_FOLDER = "ID voor albummap"
SETTING_INCLUDE_EP = "Inclusief singles en EP's"
SETTING_SAVE_COVERS = "Bewaar covers"
SETTING_LANGUAGE = "Taal"
SETTING_USE_PLAYLIST_FOLDER = "Afspeellijst gebruiken"
SETTING_MULITHREAD_DOWNLOAD = "Downloaden met meerdere threads"
SETTING_ALBUM_FOLDER_FORMAT = "Indeling albummap"
SETTING_PLAYLIST_FOLDER_FORMAT = "Playlist folder format"
SETTING_TRACK_FILE_FORMAT = "Bestandsindeling bijhouden"
SETTING_VIDEO_FILE_FORMAT = "Videobestandsindeling"
SETTING_SHOW_PROGRESS = "Toon voortgang"
SETTING_SHOW_TRACKINFO = "Toon trackinfo"
SETTING_SAVE_ALBUMINFO = "AlbumInfo.txt opslaan"
SETTING_DOWNLOAD_VIDEOS = "Download videos"
SETTING_ADD_LYRICS = "Songtekst toevoegen"
SETTING_LYRICS_SERVER_PROXY = "Tekst server proxy"
SETTING_ADD_LRC_FILE = "Getimede songteksten opslaan (.lrc-bestand)"
SETTING_PATH = "Instellingen pad"
SETTING_APIKEY = "APIKey-ondersteuning"
SETTING_ADD_TYPE_FOLDER = "Typemap toevoegen"
SETTING_DOWNLOAD_DELAY = "Use Download Delay"
CHOICE = "KEUZE"
FUNCTION = "FUNCTIE"
CHOICE_ENTER = "Voer in"
CHOICE_ENTER_URLID = "Vul 'Url/ID' in:"
CHOICE_EXIT = "Verlaten"
CHOICE_LOGIN = "Toegangstoken controleren"
CHOICE_SETTINGS = "Instellingen"
CHOICE_SET_ACCESS_TOKEN = "Toegangstoken instellen"
CHOICE_DOWNLOAD_BY_URL = "Downloaden via url of ID"
CHOICE_LOGOUT = "Uitloggen"
CHOICE_APIKEY = "Selecteer APIKey"
PRINT_ERR = "[FOUT]"
PRINT_INFO = "[INFO]"
PRINT_SUCCESS = "[SUCCESS]"
PRINT_ENTER_CHOICE = "Voer keuze in:"
PRINT_LATEST_VERSION = "Laatste versie:"
# PRINT_USERNAME = "gebruikersnaam:"
# PRINT_PASSWORD = "wachtwoord:"
CHANGE_START_SETTINGS = "Start instellingen('0'-Terugkeren,'1'-Ja):"
CHANGE_DOWNLOAD_PATH = "Downloadpad('0'-niet wijzigen):"
CHANGE_AUDIO_QUALITY = "Audiokwaliteit('0'-Normaal,'1'-Hoog,'2'-HiFi,'3'-Master,'4'-Max):"
CHANGE_VIDEO_QUALITY = "Videokwaliteit (1080, 720, 480, 360):"
CHANGE_ONLYM4A = "Converteer mp4 naar m4a('0'-Nee,'1'-Ja):"
CHANGE_ADD_EXPLICIT_TAG = "Expliciete tag toevoegen aan bestandsnamen('0'-Nee,'1'-Ja):"
CHANGE_ADD_HYPHEN = "Gebruik koppeltekens in plaats van spaties in bestandsnamen ('0'-Nee,'1'-Ja):"
CHANGE_ADD_YEAR = "Jaar toevoegen aan albummapnamen ('0'-Nee,'1'-Ja):"
CHANGE_USE_TRACK_NUM = "Voeg tracknummer toe voor bestandsnamen ('0'-Nee,'1'-Ja):"
CHANGE_CHECK_EXIST = "Controleer het bestaande bestand voordat u de track downloadt('0'-Nee,'1'-Ja):"
CHANGE_ARTIST_BEFORE_TITLE = "Voeg artiestnaam toe voor de tracktitel ('0'-Nee,'1'-Ja):"
CHANGE_INCLUDE_EP = "Voeg singles en EP's toe bij het downloaden van de albums van een artiest('0'-Nee,'1'-Ja):"
CHANGE_ALBUMID_BEFORE_FOLDER = "ID toevoegen voor albummap ('0'-Nee,'1'-Ja):"
CHANGE_SAVE_COVERS = "Covers opslaan('0'-Nee,'1'-Ja):"
CHANGE_LANGUAGE = "Selecteer taal"
CHANGE_ALBUM_FOLDER_FORMAT = "Albummapindeling ('0'-niet wijzigen,'default'-om standaard in te stellen):"
CHANGE_PLAYLIST_FOLDER_FORMAT = "Afspeellijstmapindeling format('0'-niet wijzigen,'default'-om standaard in te stellen):"
CHANGE_TRACK_FILE_FORMAT = "Bestandsformaat bijhouden ('0'-niet wijzigen,'default'-om standaard in te stellen):"
CHANGE_VIDEO_FILE_FORMAT = "Videobestandsindeling('0'-niet wijzigen,'default'-om standaard in te stellen):"
CHANGE_SHOW_PROGRESS = "Voortgang weergeven('0'-Nee,'1'-Ja):"
CHANGE_SHOW_TRACKINFO = "Toon trackinfo('0'-Nee,'1'-Ja):"
CHANGE_SAVE_ALBUM_INFO = "Bewaar AlbumInfo.txt('0'-Nee,'1'-Ja):"
CHANGE_DOWNLOAD_VIDEOS = "Download videos (when downloading playlists, albums, mixes)('0'-No,'1'-Yes):"
CHANGE_ADD_LYRICS = "Songtekst toevoegen('0'-Nee,'1'-Ja):"
CHANGE_LYRICS_SERVER_PROXY = "Songtekst proxyserver('0'-niet wijzigen):"
CHANGE_ADD_LRC_FILE = "Sla getimede songtekst .lrc-bestand op ('0'-Nee,'1'-Ja):"
CHANGE_ADD_TYPE_FOLDER = "Type-map toevoegen, bijv. Album/Video/Playlist('0'-Nee,'1'-Ja):"
CHANGE_MULITHREAD_DOWNLOAD = "Multi thread download('0'-No,'1'-Yes):"
CHANGE_USE_DOWNLOAD_DELAY = "Use Download Delay('0'-No,'1'-Yes):"
# {} are required in these strings
AUTH_START_LOGIN = "Inlogproces starten..."
AUTH_LOGIN_CODE = "Uw inlogcode is {}"
AUTH_NEXT_STEP = "Ga naar {} in de volgende {} om de installatie te voltooien."
AUTH_WAITING = "Wachten op toestemming..."
AUTH_TIMEOUT = "Operatie time-out."
MSG_VALID_ACCESSTOKEN = "Toegangstoken goed voor {}."
MSG_INVALID_ACCESSTOKEN = "Verlopen AccessToken. Poging om het te vernieuwen."
MSG_PATH_ERR = "Pad is incorrect!"
MSG_INPUT_ERR = "Invoerfout!"
MODEL_ALBUM_PROPERTY = "ALBUM-EIGENSCHAP"
MODEL_TRACK_PROPERTY = "TRACK-EIGENSCHAP"
MODEL_VIDEO_PROPERTY = "VIDEO-EIGENSCHAP"
MODEL_ARTIST_PROPERTY = "ARTIEST-EIGENSCHAP"
MODEL_PLAYLIST_PROPERTY = "AFSPEELLIJST-EIGENSCHAP"
MODEL_TITLE = 'Titel'
MODEL_TRACK_NUMBER = 'Tracknummer'
MODEL_VIDEO_NUMBER = 'Videonummer'
MODEL_RELEASE_DATE = 'Publicatiedatum'
MODEL_VERSION = 'Versie'
MODEL_EXPLICIT = 'Expliciet'
MODEL_ALBUM = 'Album'
MODEL_ID = 'ID'
MODEL_NAME = 'Naam'
MODEL_TYPE = 'Type'
+126
View File
@@ -0,0 +1,126 @@
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File : english.py
@Time : 2021/11/24
@Author : Yaronzz & jee019
@Version : 1.2
@Contact : yaronhuang@foxmail.com
@Desc :
'''
class LangEnglish(object):
SETTING = "SETTINGS"
VALUE = "VALUE"
SETTING_DOWNLOAD_PATH = "Download path"
SETTING_ONLY_M4A = "Convert mp4 to m4a"
SETTING_ADD_EXPLICIT_TAG = "Add explicit tag"
SETTING_ADD_HYPHEN = "Add hyphen"
SETTING_ADD_YEAR = "Add year before album-folder"
SETTING_USE_TRACK_NUM = "Add user track number"
SETTING_AUDIO_QUALITY = "Audio quality"
SETTING_VIDEO_QUALITY = "Video quality"
SETTING_CHECK_EXIST = "Check exist"
SETTING_ARTIST_BEFORE_TITLE = "ArtistName before track-title"
SETTING_ALBUMID_BEFORE_FOLDER = "Id before album-folder"
SETTING_INCLUDE_EP = "Include singles & EPs"
SETTING_SAVE_COVERS = "Save covers"
SETTING_LANGUAGE = "Language"
SETTING_USE_PLAYLIST_FOLDER = "Use playlist folder"
SETTING_MULITHREAD_DOWNLOAD = "Multi thread download"
SETTING_ALBUM_FOLDER_FORMAT = "Album folder format"
SETTING_PLAYLIST_FOLDER_FORMAT = "Playlist folder format"
SETTING_TRACK_FILE_FORMAT = "Track file format"
SETTING_VIDEO_FILE_FORMAT = "Video file format"
SETTING_SHOW_PROGRESS = "Show progress"
SETTING_SHOW_TRACKINFO = "Show Track Info"
SETTING_SAVE_ALBUMINFO = "Save AlbumInfo.txt"
SETTING_DOWNLOAD_VIDEOS = "Download videos"
SETTING_ADD_LYRICS = "Add lyrics"
SETTING_LYRICS_SERVER_PROXY = "Lyrics server proxy"
SETTING_ADD_LRC_FILE = "Save timed lyrics (.lrc file)"
SETTING_PATH = "Settings path"
SETTING_APIKEY = "APIKey support"
SETTING_ADD_TYPE_FOLDER = "Add Type-Folder"
SETTING_DOWNLOAD_DELAY = "Use Download Delay"
CHOICE = "CHOICE"
FUNCTION = "FUNCTION"
CHOICE_ENTER = "Enter"
CHOICE_ENTER_URLID = "Enter 'Url/ID':"
CHOICE_EXIT = "Exit"
CHOICE_LOGIN = "Check AccessToken"
CHOICE_SETTINGS = "Settings"
CHOICE_SET_ACCESS_TOKEN = "Set AccessToken"
CHOICE_DOWNLOAD_BY_URL = "Download by url or ID"
CHOICE_LOGOUT = "Logout"
CHOICE_APIKEY = "Select APIKey"
PRINT_ERR = "[ERR]"
PRINT_INFO = "[INFO]"
PRINT_SUCCESS = "[SUCCESS]"
PRINT_ENTER_CHOICE = "Enter Choice:"
PRINT_LATEST_VERSION = "Latest version:"
# PRINT_USERNAME = "username:"
# PRINT_PASSWORD = "password:"
CHANGE_START_SETTINGS = "Start settings('0'-Return,'1'-Yes):"
CHANGE_DOWNLOAD_PATH = "Download path('0'-not modify):"
CHANGE_AUDIO_QUALITY = "Audio quality('0'-Normal,'1'-High,'2'-HiFi,'3'-Master,'4'-Max):"
CHANGE_VIDEO_QUALITY = "Video quality(1080, 720, 480, 360):"
CHANGE_ONLYM4A = "Convert mp4 to m4a('0'-No,'1'-Yes):"
CHANGE_ADD_EXPLICIT_TAG = "Add explicit tag to file names('0'-No,'1'-Yes):"
CHANGE_ADD_HYPHEN = "Use hyphens instead of spaces in file names('0'-No,'1'-Yes):"
CHANGE_ADD_YEAR = "Add year to album folder names('0'-No,'1'-Yes):"
CHANGE_USE_TRACK_NUM = "Add track number before file names('0'-No,'1'-Yes):"
CHANGE_CHECK_EXIST = "Check exist file before download track('0'-No,'1'-Yes):"
CHANGE_ARTIST_BEFORE_TITLE = "Add artistName before track title('0'-No,'1'-Yes):"
CHANGE_INCLUDE_EP = "Include singles and EPs when downloading an artist's albums('0'-No,'1'-Yes):"
CHANGE_ALBUMID_BEFORE_FOLDER = "Add id before album folder('0'-No,'1'-Yes):"
CHANGE_SAVE_COVERS = "Save covers('0'-No,'1'-Yes):"
CHANGE_LANGUAGE = "Select language"
CHANGE_ALBUM_FOLDER_FORMAT = "Album folder format('0'-not modify,'default'-to set default):"
CHANGE_PLAYLIST_FOLDER_FORMAT = "Playlist folder format('0'-not modify,'default'-to set default):"
CHANGE_TRACK_FILE_FORMAT = "Track file format('0'-not modify,'default'-to set default):"
CHANGE_VIDEO_FILE_FORMAT = "Video file format('0'-not modify,'default'-to set default):"
CHANGE_SHOW_PROGRESS = "Show progress('0'-No,'1'-Yes):"
CHANGE_SHOW_TRACKINFO = "Show track info('0'-No,'1'-Yes):"
CHANGE_SAVE_ALBUM_INFO = "Save AlbumInfo.txt('0'-No,'1'-Yes):"
CHANGE_DOWNLOAD_VIDEOS = "Download videos (when downloading playlists, albums, mixes)('0'-No,'1'-Yes):"
CHANGE_ADD_LYRICS = "Add lyrics('0'-No,'1'-Yes):"
CHANGE_LYRICS_SERVER_PROXY = "Lyrics server proxy('0'-not modify):"
CHANGE_ADD_LRC_FILE = "Save timed lyrics .lrc file ('0'-No,'1'-Yes):"
CHANGE_ADD_TYPE_FOLDER = "Add Type-Folder,eg Album/Video/Playlist('0'-No,'1'-Yes):"
CHANGE_MULITHREAD_DOWNLOAD = "Multi thread download('0'-No,'1'-Yes):"
CHANGE_USE_DOWNLOAD_DELAY = "Use Download Delay('0'-No,'1'-Yes):"
# {} are required in these strings
AUTH_START_LOGIN = "Starting login process..."
AUTH_LOGIN_CODE = "Your login code is {}"
AUTH_NEXT_STEP = "Go to {} within the next {} to complete setup."
AUTH_WAITING = "Waiting for authorization..."
AUTH_TIMEOUT = "Operation timed out."
MSG_VALID_ACCESSTOKEN = "AccessToken good for {}."
MSG_INVALID_ACCESSTOKEN = "Expired AccessToken. Attempting to refresh it."
MSG_PATH_ERR = "Path is error!"
MSG_INPUT_ERR = "Input error!"
MODEL_ALBUM_PROPERTY = "ALBUM-PROPERTY"
MODEL_TRACK_PROPERTY = "TRACK-PROPERTY"
MODEL_VIDEO_PROPERTY = "VIDEO-PROPERTY"
MODEL_ARTIST_PROPERTY = "ARTIST-PROPERTY"
MODEL_PLAYLIST_PROPERTY = "PLAYLIST-PROPERTY"
MODEL_TITLE = 'Title'
MODEL_TRACK_NUMBER = 'Track Number'
MODEL_VIDEO_NUMBER = 'Video Number'
MODEL_RELEASE_DATE = 'Release Date'
MODEL_VERSION = 'Version'
MODEL_EXPLICIT = 'Explicit'
MODEL_ALBUM = 'Album'
MODEL_ID = 'ID'
MODEL_NAME = 'Name'
MODEL_TYPE = 'Type'
+126
View File
@@ -0,0 +1,126 @@
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File : filipino.py
@Time : 2020/08/21
@Author : Ni Ño
@Version : 1.0
@Contact :
@Desc :
'''
class LangFilipino(object):
SETTING = "SETTINGS"
VALUE = "VALUE"
SETTING_DOWNLOAD_PATH = "Paroroonan ng Download"
SETTING_ONLY_M4A = "I-convert ang mp4 bilang m4a"
SETTING_ADD_EXPLICIT_TAG = "Lagyan ng explicit tag"
SETTING_ADD_HYPHEN = "Lagyan ng hyphen"
SETTING_ADD_YEAR = "Lagyan ng taon bago ang album-folder"
SETTING_USE_TRACK_NUM = "Lagyan ng bilang ng user track"
SETTING_AUDIO_QUALITY = "Kalidad ng Audio"
SETTING_VIDEO_QUALITY = "Kalidad ng Video"
SETTING_CHECK_EXIST = "Suriin kung mayroon na"
SETTING_ARTIST_BEFORE_TITLE = "Pangalan ng artist bago ang pamagat ng kanta"
SETTING_ALBUMID_BEFORE_FOLDER = "Id bago ang album-folder"
SETTING_INCLUDE_EP = "Isama ang single at ep"
SETTING_SAVE_COVERS = "I-save ang mga cover"
SETTING_LANGUAGE = "Lenggwahe"
SETTING_USE_PLAYLIST_FOLDER = "Use playlist folder"
SETTING_MULITHREAD_DOWNLOAD = "Multi thread download"
SETTING_ALBUM_FOLDER_FORMAT = "Album folder format"
SETTING_PLAYLIST_FOLDER_FORMAT = "Playlist folder format"
SETTING_TRACK_FILE_FORMAT = "Track file format"
SETTING_VIDEO_FILE_FORMAT = "Video file format"
SETTING_SHOW_PROGRESS = "Show progress"
SETTING_SHOW_TRACKINFO = "Show Track Info"
SETTING_SAVE_ALBUMINFO = "Save AlbumInfo.txt"
SETTING_DOWNLOAD_VIDEOS = "Download videos"
SETTING_ADD_LYRICS = "Add lyrics"
SETTING_LYRICS_SERVER_PROXY = "Lyrics server proxy"
SETTING_ADD_LRC_FILE = "Save timed lyrics (.lrc file)"
SETTING_PATH = "Settings path"
SETTING_APIKEY = "APIKey support"
SETTING_ADD_TYPE_FOLDER = "Add Type-Folder"
SETTING_DOWNLOAD_DELAY = "Use Download Delay"
CHOICE = "PAGPIPILIAN"
FUNCTION = "SILBI"
CHOICE_ENTER = "Ilagay"
CHOICE_ENTER_URLID = "Ilagay ang 'Url/ID':"
CHOICE_EXIT = "Mag Exit"
CHOICE_LOGIN = "Check AccessToken"
CHOICE_SETTINGS = "Settings"
CHOICE_SET_ACCESS_TOKEN = "I-set ang AccessToken"
CHOICE_DOWNLOAD_BY_URL = "Mag download gamit ang url o id"
CHOICE_LOGOUT = "Logout"
CHOICE_APIKEY = "Select APIKey"
PRINT_ERR = "[ERR]"
PRINT_INFO = "[INFO]"
PRINT_SUCCESS = "[TAPOS NA]"
PRINT_ENTER_CHOICE = "Pumili ng sagot:"
PRINT_LATEST_VERSION = "Pinakabagong Version:"
# PRINT_USERNAME = "username:"
# PRINT_PASSWORD = "password:"
CHANGE_START_SETTINGS = "Simulan ang settings('0'-Bumalik,'1'-Oo):"
CHANGE_DOWNLOAD_PATH = "Paroroonan ng Download('0' walang babaguhin):"
CHANGE_AUDIO_QUALITY = "Kalidad ng Audio('0'-Normal,'1'-High,'2'-HiFi,'3'-Master,'4'-Max):"
CHANGE_VIDEO_QUALITY = "Kalidad ng Audio Video(1080, 720, 480, 360):"
CHANGE_ONLYM4A = "I-convert ang mp4 bilang m4a('0'-Hindi,'1'-Oo):"
CHANGE_ADD_EXPLICIT_TAG = "Lagyan ng explicit tag sa pangalan ng files('0'-Hindi,'1'-Oo):"
CHANGE_ADD_HYPHEN = "Gamitin ang hyphens kesa sa spaces sa pangalan ng files('0'-Hindi,'1'-Oo):"
CHANGE_ADD_YEAR = "Lagyan ng taon sa pangalan ng album folder('0'-Hindi,'1'-Oo):"
CHANGE_USE_TRACK_NUM = "Lagyan ng bilang ng track bago ang pangalan ng files('0'-Hindi,'1'-Oo):"
CHANGE_CHECK_EXIST = "Suriin kung naidownload na bago mag download muli('0'-Hindi,'1'-Oo):"
CHANGE_ARTIST_BEFORE_TITLE = "Lagyan ng pangalan ng artist bago ang pamagat ng kanta('0'-Hindi,'1'-Oo):"
CHANGE_INCLUDE_EP = "Isama ang singles at EPs sa pagdownload ng mga album mula sa artist('0'-Hindi,'1'-Oo):"
CHANGE_ALBUMID_BEFORE_FOLDER = "Lagyan ng id bago ang album folder('0'-Hindi,'1'-Oo):"
CHANGE_SAVE_COVERS = "I-save ang mga covers('0'-Hindi,'1'-Oo):"
CHANGE_LANGUAGE = "Pumili ng lenggwahe"
CHANGE_ALBUM_FOLDER_FORMAT = "Album folder format('0' not modify,'default'-to set default):"
CHANGE_PLAYLIST_FOLDER_FORMAT = "Playlist folder format('0'-not modify,'default'-to set default):"
CHANGE_TRACK_FILE_FORMAT = "Track file format('0' not modify,'default'-to set default):"
CHANGE_VIDEO_FILE_FORMAT = "Video file format('0'-not modify,'default'-to set default):"
CHANGE_SHOW_PROGRESS = "Show progress('0'-No,'1'-Yes):"
CHANGE_SHOW_TRACKINFO = "Show track info('0'-No,'1'-Yes):"
CHANGE_SAVE_ALBUM_INFO = "Save AlbumInfo.txt('0'-No,'1'-Yes):"
CHANGE_DOWNLOAD_VIDEOS = "Download videos (when downloading playlists, albums, mixes)('0'-No,'1'-Yes):"
CHANGE_ADD_LYRICS = "Add lyrics('0'-No,'1'-Yes):"
CHANGE_LYRICS_SERVER_PROXY = "Lyrics server proxy('0'-not modify):"
CHANGE_ADD_LRC_FILE = "Save timed lyrics .lrc file ('0'-No,'1'-Yes):"
CHANGE_ADD_TYPE_FOLDER = "Add Type-Folder,eg Album/Video/Playlist('0'-No,'1'-Yes):"
CHANGE_MULITHREAD_DOWNLOAD = "Multi thread download('0'-No,'1'-Yes):"
CHANGE_USE_DOWNLOAD_DELAY = "Use Download Delay('0'-No,'1'-Yes):"
# {} are required in these strings
AUTH_START_LOGIN = "Starting login process..."
AUTH_LOGIN_CODE = "Your login code is {}"
AUTH_NEXT_STEP = "Go to {} within the next {} to complete setup."
AUTH_WAITING = "Waiting for authorization..."
AUTH_TIMEOUT = "Operation timed out."
MSG_VALID_ACCESSTOKEN = "AccessToken good for {}."
MSG_INVALID_ACCESSTOKEN = "Expired AccessToken. Attempting to refresh it."
MSG_PATH_ERR = "May error sa paroroonan ng download!"
MSG_INPUT_ERR = "May error sa pag-input!"
MODEL_ALBUM_PROPERTY = "PROPERTY NG ALBUM"
MODEL_TRACK_PROPERTY = "PROPERTY NG TRACK"
MODEL_VIDEO_PROPERTY = "PROPERTY NG VIDEO"
MODEL_ARTIST_PROPERTY = "PROPERTY NG ARTIST"
MODEL_PLAYLIST_PROPERTY = "PROPERTY NG PLAYLIST"
MODEL_TITLE = 'Pamagat'
MODEL_TRACK_NUMBER = 'Bilang ng Track'
MODEL_VIDEO_NUMBER = 'Bilang ng Video'
MODEL_RELEASE_DATE = 'Petsa ng Pag-release'
MODEL_VERSION = 'Bersyon'
MODEL_EXPLICIT = 'Explicit'
MODEL_ALBUM = 'Album'
MODEL_ID = 'ID'
MODEL_NAME = 'Pangalan'
MODEL_TYPE = 'Uri'
+126
View File
@@ -0,0 +1,126 @@
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File : french.py
@Time : 2020/10/25
@Authors : flamme-demon & joyel24
@Version : 0.3
@Contact :
@Desc :
'''
class LangFrench(object):
SETTING = "RÉGLAGES"
VALUE = "VALEUR"
SETTING_DOWNLOAD_PATH = "Emplacement des téléchargements"
SETTING_ONLY_M4A = "Convertir mp4 en m4a"
SETTING_ADD_EXPLICIT_TAG = "Ajout du tag Explicit - Dossier"
SETTING_ADD_HYPHEN = "Ajouter un trait d'union"
SETTING_ADD_YEAR = "Ajouter l'année avant le nom de l'album - Dossier"
SETTING_USE_TRACK_NUM = "Ajouter le numéro de piste de l'album"
SETTING_AUDIO_QUALITY = "Qualité Audio"
SETTING_VIDEO_QUALITY = "Qualité Video"
SETTING_CHECK_EXIST = "Vérifier l'existence"
SETTING_ARTIST_BEFORE_TITLE = "Nom de l'artiste avant le titre du morceau - Fichier"
SETTING_ALBUMID_BEFORE_FOLDER = "Id avant le nom d'album - Dossier"
SETTING_INCLUDE_EP = "Inclure les singles & EPs"
SETTING_SAVE_COVERS = "Sauvegarder les couvertures"
SETTING_LANGUAGE = "Langue"
SETTING_USE_PLAYLIST_FOLDER = "Utiliser dossier de playlist"
SETTING_MULITHREAD_DOWNLOAD = "Téléchargement multithread"
SETTING_ALBUM_FOLDER_FORMAT = "Format du dossier d'album"
SETTING_PLAYLIST_FOLDER_FORMAT = "Playlist folder format"
SETTING_TRACK_FILE_FORMAT = "Format du fichier de tracklist"
SETTING_VIDEO_FILE_FORMAT = "Video file format"
SETTING_SHOW_PROGRESS = "Afficher la Progression"
SETTING_SHOW_TRACKINFO = "Afficher les information de la musique"
SETTING_SAVE_ALBUMINFO = "Enregistrer AlbumInfo.txt"
SETTING_DOWNLOAD_VIDEOS = "Download videos"
SETTING_ADD_LYRICS = "Inclure les paroles"
SETTING_LYRICS_SERVER_PROXY = "Proxy du serveur de paroles"
SETTING_ADD_LRC_FILE = "Enregistrer les paroles synchronisées (fichier .lrc)"
SETTING_PATH = "Emplacement des paramètres"
SETTING_APIKEY = "Prise en charge de la clé API"
SETTING_ADD_TYPE_FOLDER = "Ajouter un dossier de type"
SETTING_DOWNLOAD_DELAY = "Use Download Delay"
CHOICE = "CHOIX"
FUNCTION = "FONCTION"
CHOICE_ENTER = "Saisir"
CHOICE_ENTER_URLID = "Saisir 'Url/ID':"
CHOICE_EXIT = "Quitter"
CHOICE_LOGIN = "Vérifier le token d'accès"
CHOICE_SETTINGS = "Réglages"
CHOICE_SET_ACCESS_TOKEN = "Définir le jeton d'accès"
CHOICE_DOWNLOAD_BY_URL = "Téléchargement par url ou id"
CHOICE_LOGOUT = "Déconnexion"
CHOICE_APIKEY = "Choisir la clé d'API"
PRINT_ERR = "[ERR]"
PRINT_INFO = "[INFO]"
PRINT_SUCCESS = "[SUCCES]"
PRINT_ENTER_CHOICE = "Saisir le choix:"
PRINT_LATEST_VERSION = "Dernière version:"
# PRINT_USERNAME = "Utilisateur:"
# PRINT_PASSWORD = "Mot de passe:"
CHANGE_START_SETTINGS = "Commencer les réglages ('0'-Retour,'1'-Oui):"
CHANGE_DOWNLOAD_PATH = "Emplacement des téléchargements('0' ne pas modifier):"
CHANGE_AUDIO_QUALITY = "Qualité audio('0'-Normal,'1'-High,'2'-HiFi,'3'-Master,'4'-Max):"
CHANGE_VIDEO_QUALITY = "Qualité Video(1080, 720, 480, 360):"
CHANGE_ONLYM4A = "Convertir mp4 en m4a('0'-Non,'1'-Oui):"
CHANGE_ADD_EXPLICIT_TAG = "Ajout du tag Explicit - Fichier('0'-Non,'1'-Oui):"
CHANGE_ADD_HYPHEN = "Utilisez des traits d'union au lieu d'espaces dans les noms de fichiers('0'-Non,'1'-Oui):"
CHANGE_ADD_YEAR = "Ajouter l'année aux noms des dossiers des albums('0'-Non,'1'-Oui):"
CHANGE_USE_TRACK_NUM = "Ajouter le numéro de piste avant le nom des fichiers('0'-Non,'1'-Oui):"
CHANGE_CHECK_EXIST = "Vérifier l'existence du fichier avant le téléchargement('0'-Non,'1'-Oui):"
CHANGE_ARTIST_BEFORE_TITLE = "Ajouter le nom de l'artiste avant le titre de la piste('0'-Non,'1'-Oui):"
CHANGE_INCLUDE_EP = "Inclure les singles et les EPs lors du téléchargement des albums d'un artiste('0'-Non,'1'-Oui):"
CHANGE_ALBUMID_BEFORE_FOLDER = "Ajouter un identifiant avant le dossier album('0'-Non,'1'-Oui):"
CHANGE_SAVE_COVERS = "Sauvegarder les couvertures('0'-Non,'1'-Oui):"
CHANGE_LANGUAGE = "Sélectionnez une langue"
CHANGE_ALBUM_FOLDER_FORMAT = "Format du dossier d'album('0' ne pas modifier):"
CHANGE_PLAYLIST_FOLDER_FORMAT = "Playlist folder format('0'-not modify,'default'-to set default):"
CHANGE_TRACK_FILE_FORMAT = "Format du fichier de tracklist('0' ne pas modifier):"
CHANGE_VIDEO_FILE_FORMAT = "Video file format('0'-not modify,'default'-to set default):"
CHANGE_SHOW_PROGRESS = "Afficher la progression('0'-Non,'1'-Oui):"
CHANGE_SHOW_TRACKINFO = "Afficher les information de la piste ('0'-Non,'1'-Oui):"
CHANGE_SAVE_ALBUM_INFO = "Enregistrer AlbumInfo.txt('0'-Non,'1'-Oui):"
CHANGE_DOWNLOAD_VIDEOS = "Download videos (when downloading playlists, albums, mixes)('0'-No,'1'-Yes):"
CHANGE_ADD_LYRICS = "Ajouter les paroles ('0'-Non,'1'-Oui):"
CHANGE_LYRICS_SERVER_PROXY = "Proxy du serveur de paroles('0'-not modify):"
CHANGE_ADD_LRC_FILE = "Enregistrer les paroles synchronisées (fichier.lrc) ('0'-Non,'1'-Oui):"
CHANGE_ADD_TYPE_FOLDER = "Ajouter un dossier de type,Ex: Album/Video/Playlist('0'-Non,'1'-Oui):"
CHANGE_MULITHREAD_DOWNLOAD = "Multi thread download('0'-Non,'1'-Oui):"
CHANGE_USE_DOWNLOAD_DELAY = "Use Download Delay('0'-No,'1'-Yes):"
# {} are required in these strings
AUTH_START_LOGIN = "Démarrage du processus de connexion..."
AUTH_LOGIN_CODE = "Votre code de connection est le suivant: {}"
AUTH_NEXT_STEP = "Allez à {} avant {} pour finir la configuration."
AUTH_WAITING = "En attente d'autorisation..."
AUTH_TIMEOUT = "Temps écoulé."
MSG_VALID_ACCESSTOKEN = "Token d'accès valable {}."
MSG_INVALID_ACCESSTOKEN = "Token d'accès expiré. Tentative de renouvellement automatique."
MSG_PATH_ERR = "Erreur du chemin d'accès"
MSG_INPUT_ERR = "Erreur de saisie !"
MODEL_ALBUM_PROPERTY = "PROPRIETES-ALBUM"
MODEL_TRACK_PROPERTY = "PROPRIETES-PISTES-AUDIO"
MODEL_VIDEO_PROPERTY = "PROPRIETES-VIDEO"
MODEL_ARTIST_PROPERTY = "PROPRIETES-ARTISTE"
MODEL_PLAYLIST_PROPERTY = "PROPERTES-PLAYLIST"
MODEL_TITLE = 'Titre'
MODEL_TRACK_NUMBER = 'Numéro de piste'
MODEL_VIDEO_NUMBER = 'Numéro de la vidéo'
MODEL_RELEASE_DATE = 'Date de publication'
MODEL_VERSION = 'Version'
MODEL_EXPLICIT = 'Explicit'
MODEL_ALBUM = 'Album'
MODEL_ID = 'ID'
MODEL_NAME = 'Nom'
MODEL_TYPE = 'Type'
+126
View File
@@ -0,0 +1,126 @@
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File : german.py
@Time : 2022/11/8
@Authors : Sematre, MineClashTV, Click1701
@Version : 1.1
@Contact :
@Desc :
'''
class LangGerman(object):
SETTING = "EINSTELLUNG"
VALUE = "WERT"
SETTING_DOWNLOAD_PATH = "Download Pfad"
SETTING_ONLY_M4A = "mp4 in m4a konvertieren"
SETTING_ADD_EXPLICIT_TAG = "Explicit Tag hinzufügen"
SETTING_ADD_HYPHEN = "Bindestrich hinzufügen"
SETTING_ADD_YEAR = "Jahr vor Album-Ordner hinzufügen"
SETTING_USE_TRACK_NUM = "Benutzerdefinierte Titelnummer hinzufügen"
SETTING_AUDIO_QUALITY = "Tonqualität"
SETTING_VIDEO_QUALITY = "Videoqualität"
SETTING_CHECK_EXIST = "Existenz überprüfen"
SETTING_ARTIST_BEFORE_TITLE = "Künstlername vor Songtitel"
SETTING_ALBUMID_BEFORE_FOLDER = "ID vor Album-Ordner"
SETTING_INCLUDE_EP = "Singles & EPs einschließen"
SETTING_SAVE_COVERS = "Cover speichern"
SETTING_LANGUAGE = "Sprache"
SETTING_USE_PLAYLIST_FOLDER = "Playlist-Ordner verwenden"
SETTING_MULITHREAD_DOWNLOAD = "Multi-Thread Download"
SETTING_ALBUM_FOLDER_FORMAT = "Album-Ordnerformat"
SETTING_PLAYLIST_FOLDER_FORMAT = "Playlist-Ordnerformat"
SETTING_TRACK_FILE_FORMAT = "Track-Dateiformat"
SETTING_VIDEO_FILE_FORMAT = "Video-Dateiformat"
SETTING_SHOW_PROGRESS = "Fortschritt anzeigen"
SETTING_SHOW_TRACKINFO = "Titelinformationen anzeigen"
SETTING_SAVE_ALBUMINFO = "AlbumInfo.txt speichern"
SETTING_DOWNLOAD_VIDEOS = "Download videos"
SETTING_ADD_LYRICS = "Songtexte hinzufügen"
SETTING_LYRICS_SERVER_PROXY = "Songtext Proxy-Server"
SETTING_ADD_LRC_FILE = "Songtext mit Zeitcode speichern (.lrc Datei)"
SETTING_PATH = "Speicherort der Einstellungen"
SETTING_APIKEY = "APIKey Unterstützung"
SETTING_ADD_TYPE_FOLDER = "Unterordner für jede Kategorie erstellen"
SETTING_DOWNLOAD_DELAY = "Downloads zeitverzögert starten"
CHOICE = "AUSWAHL"
FUNCTION = "FUNKTION"
CHOICE_ENTER = "Mit"
CHOICE_ENTER_URLID = "'Url/ID' eingeben:"
CHOICE_EXIT = "Beenden"
CHOICE_LOGIN = "AccessToken überprüfen"
CHOICE_SETTINGS = "Einstellungen"
CHOICE_SET_ACCESS_TOKEN = "AccessToken setzen"
CHOICE_DOWNLOAD_BY_URL = "Download per URL oder ID"
CHOICE_LOGOUT = "Ausloggen"
CHOICE_APIKEY = "APIKey Auswahl"
PRINT_ERR = "[FEHLER]"
PRINT_INFO = "[INFO]"
PRINT_SUCCESS = "[ERFOLG]"
PRINT_ENTER_CHOICE = "Auswahl:"
PRINT_LATEST_VERSION = "Neueste Version:"
# PRINT_USERNAME = "Benutzername:"
# PRINT_PASSWORD = "Passwort:"
CHANGE_START_SETTINGS = "Einstellungen starten ('0'-Zurück, '1'-Ja):"
CHANGE_DOWNLOAD_PATH = "Downloadpfad ('0' nicht ändern):"
CHANGE_AUDIO_QUALITY = "Tonqualität ('0'-Normal, '1'-Hoch, '2'-HiFi, '3'-Master,'4'-Max):"
CHANGE_VIDEO_QUALITY = "Videoqualität (1080, 720, 480, 360):"
CHANGE_ONLYM4A = "mp4 in m4a konvertieren ('0'-Nein, '1'-Ja):"
CHANGE_ADD_EXPLICIT_TAG = "Explicit Tag zum Dateiname hinzufügen ('0'-Nein, '1'-Ja):"
CHANGE_ADD_HYPHEN = "Im Dateinamen Bindestriche statt Leerzeichen verwenden ('0'-Nein, '1'-Ja):"
CHANGE_ADD_YEAR = "Jahr zu Album-Ordnernamen hinzufügen ('0'-Nein, '1'-Ja):"
CHANGE_USE_TRACK_NUM = "Titelnummer vor Dateinamen hinzufügen ('0'-Nein, '1'-Ja):"
CHANGE_CHECK_EXIST = "Vor dem Download überprüfen, ob die Datei existiert ('0'-Nein, '1'-Ja):"
CHANGE_ARTIST_BEFORE_TITLE = "Künstlername vor den Songtitel hinzufügen ('0'-Nein, '1'-Ja):"
CHANGE_INCLUDE_EP = "Singles und EPs beim Download von Alben eines Künstlers einbeziehen ('0'-Nein, '1'-Ja):"
CHANGE_ALBUMID_BEFORE_FOLDER = "ID vor Album-Ordner hinzufügen ('0'-Nein, '1'-Ja):"
CHANGE_SAVE_COVERS = "Cover speichern ('0'-Nein, '1'-Ja):"
CHANGE_LANGUAGE = "Sprache auswählen"
CHANGE_ALBUM_FOLDER_FORMAT = "Album-Ordnerformat ('0' überspringen):"
CHANGE_PLAYLIST_FOLDER_FORMAT = "Playlist Ordner-Format ('0'-nicht ändern, 'default'-für Standard):"
CHANGE_TRACK_FILE_FORMAT = "Track-Dateiformat ('0' überspringen):"
CHANGE_VIDEO_FILE_FORMAT = "Video-Dateiformat ('0'-nicht ändern, 'default'-für Standard):"
CHANGE_SHOW_PROGRESS = "Fortschritt anzeigen ('0'-Nein, '1'-Ja):"
CHANGE_SHOW_TRACKINFO = "Song-Informationen anzeigen ('0'-Nein, '1'-Ja):"
CHANGE_SAVE_ALBUM_INFO = "AlbumInfo.txt speichern ('0'-Nein, '1'-Ja):"
CHANGE_DOWNLOAD_VIDEOS = "Download videos (when downloading playlists, albums, mixes)('0'-No,'1'-Yes):"
CHANGE_ADD_LYRICS = "Songtexte hinzufügen ('0'-No, '1'-Yes):"
CHANGE_LYRICS_SERVER_PROXY = "Songtext Proxy-Server ('0'-not modify):"
CHANGE_ADD_LRC_FILE = "Songtexte mit Zeitcode speichern (.lrc Datei) ('0'-Nein, '1'-Ja):"
CHANGE_ADD_TYPE_FOLDER = "Unterordner für jede Kategorie erstellen, Z.B. Album/Video/Playlist('0'-Nein, '1'-Ja):"
CHANGE_MULITHREAD_DOWNLOAD = "Multi-Thread Download('0'-Nein, '1'-Ja):"
CHANGE_USE_DOWNLOAD_DELAY = "Downloads zeitverzögert starten ('0'-nein, '1'-ja):"
# {} are required in these strings
AUTH_START_LOGIN = "Starte Loginprozess..."
AUTH_LOGIN_CODE = "Dein Logincode ist {}"
AUTH_NEXT_STEP = "Gehe auf {} in den nächsten {} um das Setup abzuschließen."
AUTH_WAITING = "Warte auf Autorisierung..."
AUTH_TIMEOUT = "Zeitüberschreitung der Operation."
MSG_VALID_ACCESSTOKEN = "AccessToken gültig für {}."
MSG_INVALID_ACCESSTOKEN = "AccessToken abgelaufen. Er muss erneuert werden."
MSG_PATH_ERR = "Ungültiger Pfad!"
MSG_INPUT_ERR = "Eingabefehler!"
MODEL_ALBUM_PROPERTY = "ALBUM-EIGENSCHAFT"
MODEL_TRACK_PROPERTY = "TRACK-EIGENSCHAFT"
MODEL_VIDEO_PROPERTY = "VIDEO-EIGENSCHAFT"
MODEL_ARTIST_PROPERTY = "KÜNSTLER-EIGENSCHAFT"
MODEL_PLAYLIST_PROPERTY = "PLAYLIST-EIGENSCHAFT"
MODEL_TITLE = 'Titel'
MODEL_TRACK_NUMBER = 'Titelnummer'
MODEL_VIDEO_NUMBER = 'Videonummer'
MODEL_RELEASE_DATE = 'Veröffentlichungsdatum'
MODEL_VERSION = 'Version'
MODEL_EXPLICIT = 'Explicit'
MODEL_ALBUM = 'Album'
MODEL_ID = 'ID'
MODEL_NAME = 'Name'
MODEL_TYPE = 'Typ'
+126
View File
@@ -0,0 +1,126 @@
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File : hungarian.py
@Time : 2022/08/01
@Author : Shanahan
@Version : 1.2
@Contact :
@Desc :
'''
class LangHungarian(object):
SETTING = "BEÁLLÍTÁSOK"
VALUE = "ÉRTÉK"
SETTING_DOWNLOAD_PATH = "Letöltési útvonal"
SETTING_ONLY_M4A = "mp4 konvertálása m4a-ra"
SETTING_ADD_EXPLICIT_TAG = "Explicit tag hozzáadása"
SETTING_ADD_HYPHEN = "Kötőjel hozzáadása"
SETTING_ADD_YEAR = "Év hozzáadása az album-mappa előtt"
SETTING_USE_TRACK_NUM = "Add user track number"
SETTING_AUDIO_QUALITY = "Audió minősége"
SETTING_VIDEO_QUALITY = "Videó minősége"
SETTING_CHECK_EXIST = "Ellenőrizze, hogy létezik-e"
SETTING_ARTIST_BEFORE_TITLE = "Előadó neve a szám címe előtt"
SETTING_ALBUMID_BEFORE_FOLDER = "Azonosító (ID) az album-mappa előtt"
SETTING_INCLUDE_EP = "Tartalmazza a single&ep"
SETTING_SAVE_COVERS = "Borítókép mentése"
SETTING_LANGUAGE = "Nyelv"
SETTING_USE_PLAYLIST_FOLDER = "Lejátszási lista mappa használata"
SETTING_MULITHREAD_DOWNLOAD = "Többszálú letöltés"
SETTING_ALBUM_FOLDER_FORMAT = "Album mappa formátum"
SETTING_PLAYLIST_FOLDER_FORMAT = "Playlist folder format"
SETTING_TRACK_FILE_FORMAT = "Track fájlformátum"
SETTING_VIDEO_FILE_FORMAT = "Videó fájlformátum"
SETTING_SHOW_PROGRESS = "Haladás megjelenítése"
SETTING_SHOW_TRACKINFO = "Track infók megjelenítése"
SETTING_SAVE_ALBUMINFO = "AlbumInfo.txt mentése"
SETTING_DOWNLOAD_VIDEOS = "Download videos"
SETTING_ADD_LYRICS = "Dalszöveg hozzáadása"
SETTING_LYRICS_SERVER_PROXY = "Dalszöveg kiszolgáló proxy"
SETTING_ADD_LRC_FILE = "Dalszövegek mentése (.lrc fájl)"
SETTING_PATH = "Beállítási útvonal"
SETTING_APIKEY = "APIKey támogatás"
SETTING_ADD_TYPE_FOLDER = "Mappa típus hozzáadása"
SETTING_DOWNLOAD_DELAY = "Use Download Delay"
CHOICE = "VÁLASZTÁS"
FUNCTION = "FUNKCIÓ"
CHOICE_ENTER = "Írja be a"
CHOICE_ENTER_URLID = "Adja meg az 'Url/ID'-t:"
CHOICE_EXIT = "Kilépés"
CHOICE_LOGIN = "AccessToken ellenőrzése"
CHOICE_SETTINGS = "Beállítások"
CHOICE_SET_ACCESS_TOKEN = "AccessToken beállítása"
CHOICE_DOWNLOAD_BY_URL = "Letöltés URL vagy ID alapján"
CHOICE_LOGOUT = "Kijelentkezés"
CHOICE_APIKEY = "APIKey kiválasztása"
PRINT_ERR = "[HIBA]"
PRINT_INFO = "[INFÓ]"
PRINT_SUCCESS = "[SIKERES]"
PRINT_ENTER_CHOICE = "Válasszon:"
PRINT_LATEST_VERSION = "Legújabb verzió:"
# PRINT_USERNAME = "felhasználónév:"
# PRINT_PASSWORD = "jelszó:"
CHANGE_START_SETTINGS = "Beállítások indítása('0'- Vissza, '1'-Igen):"
CHANGE_DOWNLOAD_PATH = "Letöltési útvonal('0' nincs módosítás):"
CHANGE_AUDIO_QUALITY = "Audió minőség('0'-Normal,'1'-High,'2'-HiFi,'3'-Master,'4'-Max):"
CHANGE_VIDEO_QUALITY = "Videó minőség(1080, 720, 480, 360):"
CHANGE_ONLYM4A = "mp4 átalakítása m4a-ra('0'-Nem,'1'-Igen):"
CHANGE_ADD_EXPLICIT_TAG = "Explicit tag hozzáadása a fájlnevekhez('0'-Nem,'1'-Igen):"
CHANGE_ADD_HYPHEN = "Kötőjel használata szóköz helyett a fájlnevekben('0'-Nem,'1'-Igen):"
CHANGE_ADD_YEAR = "Évszám hozzáadása az album mappanevekhez('0'-Nem,'1'-Igen):"
CHANGE_USE_TRACK_NUM = "Track szám hozzáadása a fájlnevek előtt('0'-Nem,'1'-Igen):"
CHANGE_CHECK_EXIST = "Létező fájl ellenőrzése letöltés előtt('0'-Nem,'1'-Igen):"
CHANGE_ARTIST_BEFORE_TITLE = "Előadó hozzáadása a szám címe előtt('0'-Nem,'1'-Igen):"
CHANGE_INCLUDE_EP = "A kislemezek és EP-k letöltése('0'-Nem, '1'-Igen):"
CHANGE_ALBUMID_BEFORE_FOLDER = "Azonosító (ID) az album mappa előtt('0'-Nem,'1'-Igen):"
CHANGE_SAVE_COVERS = "Borító mentése('0'-Nem, '1'-Igen):"
CHANGE_LANGUAGE = "Nyelv kiválasztása"
CHANGE_ALBUM_FOLDER_FORMAT = "Album mappa formátum('0' nincs módosítás,'default' az alapértelmezett beállításhoz):"
CHANGE_PLAYLIST_FOLDER_FORMAT = "Playlist folder format('0'-not modify,'default'-to set default):"
CHANGE_TRACK_FILE_FORMAT = "Track fájl neve('0' nincs módosítás,'default' az alapértelmezett beállításhoz):"
CHANGE_VIDEO_FILE_FORMAT = "Video file format('0'-nincs módosítás,'default' az alapértelmezett beállításhoz):"
CHANGE_SHOW_PROGRESS = "Haladás megjelenítése('0'-Nem, '1'-Igen):"
CHANGE_SHOW_TRACKINFO = "Track infók megjelenítése('0'-Nem,'1'-Igen):"
CHANGE_SAVE_ALBUM_INFO = "AlbumInfo.txt mentése('0'-Nem, '1'-Igen):"
CHANGE_DOWNLOAD_VIDEOS = "Download videos (when downloading playlists, albums, mixes)('0'-No,'1'-Yes):"
CHANGE_ADD_LYRICS = "Dalszöveg hozzáadása('0'-Nem,'1'-Igen):"
CHANGE_LYRICS_SERVER_PROXY = "Dalszöveg kiszolgáló proxy('0' nincs módosítás):"
CHANGE_ADD_LRC_FILE = "Dalszöveg mentése időbélyeggel .lrc fájl('0'-Nem,'1'-Igen):"
CHANGE_ADD_TYPE_FOLDER = "Mappa típus hozzáadása, pl. Album/Video/Playlist('0'-Nem,'1'-Igen):"
CHANGE_MULITHREAD_DOWNLOAD = "Többszálas letöltés('0'-Nem,'1'-Igen):"
CHANGE_USE_DOWNLOAD_DELAY = "Use Download Delay('0'-No,'1'-Yes):"
# {} are required in these strings
AUTH_START_LOGIN = "Bejelentkezési folyamat elindítása..."
AUTH_LOGIN_CODE = "A bejelentkezési kódod {}"
AUTH_NEXT_STEP = "Menj a {} a következő {} a beállítás befejezéséhez."
AUTH_WAITING = "Engedélyre várva..."
AUTH_TIMEOUT = "A művelet leállt."
MSG_VALID_ACCESSTOKEN = "AccessToken érvényessége {}."
MSG_INVALID_ACCESSTOKEN = "Lejárt AccessToken. Megpróbálom frissíteni."
MSG_PATH_ERR = "Az útvonal hibás!"
MSG_INPUT_ERR = "Beviteli hiba!"
MODEL_ALBUM_PROPERTY = "ALBUM-INFÓ"
MODEL_TRACK_PROPERTY = "TRACK-INFÓ"
MODEL_VIDEO_PROPERTY = "VIDEO-INFÓ"
MODEL_ARTIST_PROPERTY = "ELŐADÓ-INFÓ"
MODEL_PLAYLIST_PROPERTY = "LEJÁTSZÁSI LISTA-INFÓ"
MODEL_TITLE = 'Cím'
MODEL_TRACK_NUMBER = 'Track száma'
MODEL_VIDEO_NUMBER = 'Videó száma'
MODEL_RELEASE_DATE = 'Megjelenés dátuma'
MODEL_VERSION = 'Verzió'
MODEL_EXPLICIT = 'Explicit'
MODEL_ALBUM = 'Album'
MODEL_ID = 'ID'
MODEL_NAME = 'Név'
MODEL_TYPE = 'Típus'
+126
View File
@@ -0,0 +1,126 @@
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File : italian.py
@Time : 2020/08/20
@Author : Normando
@Version : 1.0
@Contact : normando@me.com
@Desc :
'''
class LangItalian(object):
SETTING = "IMPOSTAZIONI"
VALUE = "VALORE"
SETTING_DOWNLOAD_PATH = "Percorso Download"
SETTING_ONLY_M4A = "Convertire mp4 in m4a"
SETTING_ADD_EXPLICIT_TAG = "Aggiungere tag 'Contenuto esplicito'"
SETTING_ADD_HYPHEN = "Aggiungere trattino"
SETTING_ADD_YEAR = "Aggiungere anno nella cartella album"
SETTING_USE_TRACK_NUM = "Aggiungere numero traccia utente"
SETTING_AUDIO_QUALITY = "Qualità Audio"
SETTING_VIDEO_QUALITY = "Video Video"
SETTING_CHECK_EXIST = "Controlla esistenza"
SETTING_ARTIST_BEFORE_TITLE = "Nome artista prima del titolo della traccia"
SETTING_ALBUMID_BEFORE_FOLDER = "Numero Id nell cartella album"
SETTING_INCLUDE_EP = "Includere singolo&ep"
SETTING_SAVE_COVERS = "Salva copertine"
SETTING_LANGUAGE = "Lingua"
SETTING_USE_PLAYLIST_FOLDER = "Use playlist folder"
SETTING_MULITHREAD_DOWNLOAD = "Multi thread download"
SETTING_ALBUM_FOLDER_FORMAT = "Album folder format"
SETTING_PLAYLIST_FOLDER_FORMAT = "Playlist folder format"
SETTING_TRACK_FILE_FORMAT = "Track file format"
SETTING_VIDEO_FILE_FORMAT = "Video file format"
SETTING_SHOW_PROGRESS = "Show progress"
SETTING_SHOW_TRACKINFO = "Show Track Info"
SETTING_SAVE_ALBUMINFO = "Save AlbumInfo.txt"
SETTING_DOWNLOAD_VIDEOS = "Download videos"
SETTING_ADD_LYRICS = "Add lyrics"
SETTING_LYRICS_SERVER_PROXY = "Lyrics server proxy"
SETTING_ADD_LRC_FILE = "Save timed lyrics (.lrc file)"
SETTING_PATH = "Settings path"
SETTING_APIKEY = "APIKey support"
SETTING_ADD_TYPE_FOLDER = "Add Type-Folder"
SETTING_DOWNLOAD_DELAY = "Use Download Delay"
CHOICE = "SCELTA"
FUNCTION = "FUNZIONE"
CHOICE_ENTER = "Inserire"
CHOICE_ENTER_URLID = "Inserire 'Url/ID':"
CHOICE_EXIT = "Uscita"
CHOICE_LOGIN = "Check AccessToken"
CHOICE_SETTINGS = "Impostazioni"
CHOICE_SET_ACCESS_TOKEN = "Imposta AccessToken"
CHOICE_DOWNLOAD_BY_URL = "Scarica per URL o Id"
CHOICE_LOGOUT = "Logout"
CHOICE_APIKEY = "Select APIKey"
PRINT_ERR = "[ERR]"
PRINT_INFO = "[INFO]"
PRINT_SUCCESS = "[SUCCESSO]"
PRINT_ENTER_CHOICE = "Inserire scelta:"
PRINT_LATEST_VERSION = "Ultima versione:"
# PRINT_USERNAME = "username:"
# PRINT_PASSWORD = "password:"
CHANGE_START_SETTINGS = "Impostazioni all'avvio ('0'-Ritorna,'1'-Sì):"
CHANGE_DOWNLOAD_PATH = "Percorso Download ('0' non modificare):"
CHANGE_AUDIO_QUALITY = "Qualità Audio ('0'-Normale, '1'-Alta, '2'-HiFi, '3'-Master,'4'-Max):"
CHANGE_VIDEO_QUALITY = "Qualità Video (1080, 720, 480, 360):"
CHANGE_ONLYM4A = "Convertire mp4 in m4a ('0'-No,'1'-):"
CHANGE_ADD_EXPLICIT_TAG = "Aggiungi tag 'Contenuto Esplicito' ai nomi dei file ('0'-No,'1'-Sì):"
CHANGE_ADD_HYPHEN = "Usare trattini al posto degli spazi nei nomi dei file ('0'-No,'1'-Sì):"
CHANGE_ADD_YEAR = "Aggiungere l'anno al nome della cartella dell'album ('0'-No,'1'-Sì):"
CHANGE_USE_TRACK_NUM = "Aggiungere il numero traccia prima del nome dei file ('0'-No,'1'-Sì):"
CHANGE_CHECK_EXIST = "Controllare se il file esiste prima di scaricare la traccia ('0'-No,'1'-Sì):"
CHANGE_ARTIST_BEFORE_TITLE = "Aggiungere il nome dell'artista prima del titolo della traccia ('0'-No,'1'-Sì):"
CHANGE_INCLUDE_EP = "Includere singoli e EP quando si scaricano gli album di un artista ('0'-No,'1'-Sì):"
CHANGE_ALBUMID_BEFORE_FOLDER = "Aggiungere ID prima del nome della cartella per l'album ('0'-No,'1'-Sì):"
CHANGE_SAVE_COVERS = "Salve copertine ('0'-No,'1'-Sì):"
CHANGE_LANGUAGE = "Selezionare lingua"
CHANGE_ALBUM_FOLDER_FORMAT = "Album folder format('0' not modify,'default'-to set default):"
CHANGE_PLAYLIST_FOLDER_FORMAT = "Playlist folder format('0'-not modify,'default'-to set default):"
CHANGE_TRACK_FILE_FORMAT = "Track file format('0' not modify,'default'-to set default):"
CHANGE_VIDEO_FILE_FORMAT = "Video file format('0'-not modify,'default'-to set default):"
CHANGE_SHOW_PROGRESS = "Show progress('0'-No,'1'-Yes):"
CHANGE_SHOW_TRACKINFO = "Show track info('0'-No,'1'-Yes):"
CHANGE_SAVE_ALBUM_INFO = "Save AlbumInfo.txt('0'-No,'1'-Yes):"
CHANGE_DOWNLOAD_VIDEOS = "Download videos (when downloading playlists, albums, mixes)('0'-No,'1'-Yes):"
CHANGE_ADD_LYRICS = "Add lyrics('0'-No,'1'-Yes):"
CHANGE_LYRICS_SERVER_PROXY = "Lyrics server proxy('0'-not modify):"
CHANGE_ADD_LRC_FILE = "Save timed lyrics .lrc file ('0'-No,'1'-Yes):"
CHANGE_ADD_TYPE_FOLDER = "Add Type-Folder,eg Album/Video/Playlist('0'-No,'1'-Yes):"
CHANGE_MULITHREAD_DOWNLOAD = "Multi thread download('0'-No,'1'-Yes):"
CHANGE_USE_DOWNLOAD_DELAY = "Use Download Delay('0'-No,'1'-Yes):"
# {} are required in these strings
AUTH_START_LOGIN = "Starting login process..."
AUTH_LOGIN_CODE = "Your login code is {}"
AUTH_NEXT_STEP = "Go to {} within the next {} to complete setup."
AUTH_WAITING = "Waiting for authorization..."
AUTH_TIMEOUT = "Operation timed out."
MSG_VALID_ACCESSTOKEN = "AccessToken good for {}."
MSG_INVALID_ACCESSTOKEN = "Expired AccessToken. Attempting to refresh it."
MSG_PATH_ERR = "Percorso errato!"
MSG_INPUT_ERR = "Inserimento errato!"
MODEL_ALBUM_PROPERTY = "PROPRIETÀ-ALBUM"
MODEL_TRACK_PROPERTY = "PROPRIETÀ-TRACCIA"
MODEL_VIDEO_PROPERTY = "PROPRIETÀ-VIDEO"
MODEL_ARTIST_PROPERTY = "PROPRIETÀ-ARTISTA"
MODEL_PLAYLIST_PROPERTY = "PROPRIETÀ-PLAYLIST"
MODEL_TITLE = 'Titolo'
MODEL_TRACK_NUMBER = 'Numero Traccia'
MODEL_VIDEO_NUMBER = 'Numero Video'
MODEL_RELEASE_DATE = 'Data uscita'
MODEL_VERSION = 'Versione'
MODEL_EXPLICIT = 'Contenuto Esplicito'
MODEL_ALBUM = 'Album'
MODEL_ID = 'ID'
MODEL_NAME = 'Nome'
MODEL_TYPE = 'Tipo'
+126
View File
@@ -0,0 +1,126 @@
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File : japanese.py
@Time : 2021/11/30
@Author : jee019
@Version : 1.0
@Contact : qwer010910@gmail.com
@Desc :
'''
class LangJapanese(object):
SETTING = "設定"
VALUE = ""
SETTING_DOWNLOAD_PATH = "ダウンロードパス"
SETTING_ONLY_M4A = "mp4をm4aに変換する"
SETTING_ADD_EXPLICIT_TAG = "explicitタグ付けする"
SETTING_ADD_HYPHEN = "ハイフンを追加"
SETTING_ADD_YEAR = "Add year before album-folder"
SETTING_USE_TRACK_NUM = "ユーザートラック番号を追加"
SETTING_AUDIO_QUALITY = "オーディオ品質"
SETTING_VIDEO_QUALITY = "ビデオ品質"
SETTING_CHECK_EXIST = "Check exist"
SETTING_ARTIST_BEFORE_TITLE = "ArtistName before track-title"
SETTING_ALBUMID_BEFORE_FOLDER = "Id before album-folder"
SETTING_INCLUDE_EP = "含む singles & EPs"
SETTING_SAVE_COVERS = "カバーを保存"
SETTING_LANGUAGE = "言語"
SETTING_USE_PLAYLIST_FOLDER = "Use playlist folder"
SETTING_MULITHREAD_DOWNLOAD = "Multi thread download"
SETTING_ALBUM_FOLDER_FORMAT = "Album folder format"
SETTING_PLAYLIST_FOLDER_FORMAT = "Playlist folder format"
SETTING_TRACK_FILE_FORMAT = "Track file format"
SETTING_VIDEO_FILE_FORMAT = "Video file format"
SETTING_SHOW_PROGRESS = "Show progress"
SETTING_SHOW_TRACKINFO = "Show Track Info"
SETTING_SAVE_ALBUMINFO = "Save AlbumInfo.txt"
SETTING_DOWNLOAD_VIDEOS = "Download videos"
SETTING_ADD_LYRICS = "歌詞を追加"
SETTING_LYRICS_SERVER_PROXY = "Lyrics server proxy"
SETTING_ADD_LRC_FILE = "Save timed lyrics (.lrc file)"
SETTING_PATH = "設定パス"
SETTING_APIKEY = "APIKey support"
SETTING_ADD_TYPE_FOLDER = "Add Type-Folder"
SETTING_DOWNLOAD_DELAY = "Use Download Delay"
CHOICE = "選択"
FUNCTION = "関数"
CHOICE_ENTER = "エンター"
CHOICE_ENTER_URLID = "エンター 'Url/ID':"
CHOICE_EXIT = "エグジット"
CHOICE_LOGIN = "AccessTokenを確認してください"
CHOICE_SETTINGS = "セッティング"
CHOICE_SET_ACCESS_TOKEN = "AccessTokenを設定する"
CHOICE_DOWNLOAD_BY_URL = "UrlまたはIDでダウンロード"
CHOICE_LOGOUT = "ログアウト"
CHOICE_APIKEY = "Select APIKey"
PRINT_ERR = "[エラー]"
PRINT_INFO = "[情報]"
PRINT_SUCCESS = "[サクセス]"
PRINT_ENTER_CHOICE = "エンター 選択:"
PRINT_LATEST_VERSION = "最新バージョン:"
# PRINT_USERNAME = "ユーザー名:"
# PRINT_PASSWORD = "パスワード:"
CHANGE_START_SETTINGS = "設定を開始('0'-戻る,'1'-はい):"
CHANGE_DOWNLOAD_PATH = "ダウンロードパス('0'-変更しない):"
CHANGE_AUDIO_QUALITY = "オーディオ品質('0'-Normal,'1'-High,'2'-HiFi,'3'-Master,'4'-Max):"
CHANGE_VIDEO_QUALITY = "ビデオ品質(1080, 720, 480, 360):"
CHANGE_ONLYM4A = "mp4をm4aに変換する('0'-いいえ,'1'-はい):"
CHANGE_ADD_EXPLICIT_TAG = "Add explicit tag to file names('0'-いいえ,'1'-はい):"
CHANGE_ADD_HYPHEN = "Use hyphens instead of spaces in file names('0'-いいえ,'1'-はい):"
CHANGE_ADD_YEAR = "Add year to album folder names('0'-いいえ,'1'-はい):"
CHANGE_USE_TRACK_NUM = "Add track number before file names('0'-いいえ,'1'-はい):"
CHANGE_CHECK_EXIST = "Check exist file before download track('0'-いいえ,'1'-はい):"
CHANGE_ARTIST_BEFORE_TITLE = "Add artistName before track title('0'-いいえ,'1'-はい):"
CHANGE_INCLUDE_EP = "Include singles and EPs when downloading an artist's albums('0'-いいえ,'1'-はい):"
CHANGE_ALBUMID_BEFORE_FOLDER = "Add id before album folder('0'-いいえ,'1'-はい):"
CHANGE_SAVE_COVERS = "カバーを保存('0'-いいえ,'1'-はい):"
CHANGE_LANGUAGE = "言語を選択する"
CHANGE_ALBUM_FOLDER_FORMAT = "Album folder format('0'-変更しない,'default'-デフォルトを設定するには):"
CHANGE_PLAYLIST_FOLDER_FORMAT = "Playlist folder format('0'-not modify,'default'-to set default):"
CHANGE_TRACK_FILE_FORMAT = "Track file format('0'-変更しない,'default'-デフォルトを設定するには):"
CHANGE_VIDEO_FILE_FORMAT = "Video file format('0'-not modify,'default'-to set default):"
CHANGE_SHOW_PROGRESS = "Show progress('0'-いいえ,'1'-はい):"
CHANGE_SHOW_TRACKINFO = "Show track info('0'-いいえ,'1'-はい):"
CHANGE_SAVE_ALBUM_INFO = "Save AlbumInfo.txt('0'-いいえ,'1'-はい):"
CHANGE_DOWNLOAD_VIDEOS = "Download videos (when downloading playlists, albums, mixes)('0'-No,'1'-Yes):"
CHANGE_ADD_LYRICS = "歌詞を追加('0'-いいえ,'1'-はい):"
CHANGE_LYRICS_SERVER_PROXY = "Lyrics server proxy('0'-変更しない):"
CHANGE_ADD_LRC_FILE = "Save timed lyrics .lrc file ('0'-いいえ,'1'-はい):"
CHANGE_ADD_TYPE_FOLDER = "Add Type-Folder,eg Album/Video/Playlist('0'-No,'1'-Yes):"
CHANGE_MULITHREAD_DOWNLOAD = "Multi thread download('0'-No,'1'-Yes):"
CHANGE_USE_DOWNLOAD_DELAY = "Use Download Delay('0'-No,'1'-Yes):"
# {} are required in these strings
AUTH_START_LOGIN = "Starting login process..."
AUTH_LOGIN_CODE = "Your login code is {}"
AUTH_NEXT_STEP = "Go to {} within the next {} to complete setup."
AUTH_WAITING = "Waiting for authorization..."
AUTH_TIMEOUT = "Operation timed out."
MSG_VALID_ACCESSTOKEN = "AccessToken good for {}."
MSG_INVALID_ACCESSTOKEN = "Expired AccessToken. Attempting to refresh it."
MSG_PATH_ERR = "パスはエラーです!"
MSG_INPUT_ERR = "入力エラー!"
MODEL_ALBUM_PROPERTY = "アルバム-情報"
MODEL_TRACK_PROPERTY = "トラック-情報"
MODEL_VIDEO_PROPERTY = "ビデオ-情報"
MODEL_ARTIST_PROPERTY = "アーティスト-情報"
MODEL_PLAYLIST_PROPERTY = "プレイリスト-情報"
MODEL_TITLE = '題名'
MODEL_TRACK_NUMBER = 'トラック番号'
MODEL_VIDEO_NUMBER = 'ビデオ番号'
MODEL_RELEASE_DATE = '発売日'
MODEL_VERSION = 'バージョン'
MODEL_EXPLICIT = 'Explicit'
MODEL_ALBUM = 'アルバム'
MODEL_ID = 'ID'
MODEL_NAME = '名前'
MODEL_TYPE = 'タイプ'
+126
View File
@@ -0,0 +1,126 @@
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File : korean.py
@Time : 2021/11/24
@Author : jee019
@Version : 1.1
@Contact : qwer010910@gmail.com
@Desc :
'''
class LangKorean(object):
SETTING = "설정"
VALUE = ""
SETTING_DOWNLOAD_PATH = "다운로드 경로"
SETTING_ONLY_M4A = "mp4를 m4a로 변환"
SETTING_ADD_EXPLICIT_TAG = "explicit 태그 추가"
SETTING_ADD_HYPHEN = "하이픈 추가"
SETTING_ADD_YEAR = "앨범 폴더 앞에 연도 추가"
SETTING_USE_TRACK_NUM = "사용자 트랙 번호 추가"
SETTING_AUDIO_QUALITY = "음질"
SETTING_VIDEO_QUALITY = "영상 화질"
SETTING_CHECK_EXIST = "존재 유무 확인"
SETTING_ARTIST_BEFORE_TITLE = "트랙 제목 앞 아티스트 이름"
SETTING_ALBUMID_BEFORE_FOLDER = "앨범 폴더 앞 ID"
SETTING_INCLUDE_EP = "싱글 및 EP 포함"
SETTING_SAVE_COVERS = "커버 저장"
SETTING_LANGUAGE = "언어"
SETTING_USE_PLAYLIST_FOLDER = "재생목록 폴더 사용"
SETTING_MULITHREAD_DOWNLOAD = "다중 스레드 다운로드"
SETTING_ALBUM_FOLDER_FORMAT = "앨범 폴더 형식"
SETTING_PLAYLIST_FOLDER_FORMAT = "Playlist folder format"
SETTING_TRACK_FILE_FORMAT = "트랙 파일 형식"
SETTING_VIDEO_FILE_FORMAT = "Video file format"
SETTING_SHOW_PROGRESS = "진행 상태 표시"
SETTING_SHOW_TRACKINFO = "트랙 정보 표시"
SETTING_SAVE_ALBUMINFO = "AlbumInfo.txt 저장"
SETTING_DOWNLOAD_VIDEOS = "Download videos"
SETTING_ADD_LYRICS = "가사 추가"
SETTING_LYRICS_SERVER_PROXY = "가사 서버 프록시"
SETTING_ADD_LRC_FILE = "timed 가사 저장 (.lrc 파일)"
SETTING_PATH = "설정 경로"
SETTING_APIKEY = "APIKey support"
SETTING_ADD_TYPE_FOLDER = "Add Type-Folder"
SETTING_DOWNLOAD_DELAY = "Use Download Delay"
CHOICE = "선택"
FUNCTION = "기능"
CHOICE_ENTER = "엔터"
CHOICE_ENTER_URLID = "'Url/ID' 입력:"
CHOICE_EXIT = "종료"
CHOICE_LOGIN = "액세스 토큰 확인"
CHOICE_SETTINGS = "설정"
CHOICE_SET_ACCESS_TOKEN = "액세스 토큰 설정"
CHOICE_DOWNLOAD_BY_URL = "Url 또는 id로 다운로드"
CHOICE_LOGOUT = "로그아웃"
CHOICE_APIKEY = "Select APIKey"
PRINT_ERR = "[에러]"
PRINT_INFO = "[정보]"
PRINT_SUCCESS = "[성공]"
PRINT_ENTER_CHOICE = "선택 입력:"
PRINT_LATEST_VERSION = "최신 버전:"
# PRINT_USERNAME = "유저 이름:"
# PRINT_PASSWORD = "비밀번호:"
CHANGE_START_SETTINGS = "설정 시작('0'-뒤로가기,'1'-예):"
CHANGE_DOWNLOAD_PATH = "다운로드 경로('0'-변경 안 함):"
CHANGE_AUDIO_QUALITY = "음질('0'-보통,'1'-높음,'2'-HiFi,'3'-Master,'4'-Max):"
CHANGE_VIDEO_QUALITY = "영상 화질(1080, 720, 480, 360):"
CHANGE_ONLYM4A = "mp4를 m4a로 변환('0'-아니요,'1'-예):"
CHANGE_ADD_EXPLICIT_TAG = "파일 이름에 explicit 태그 추가('0'-아니요,'1'-예):"
CHANGE_ADD_HYPHEN = "파일 이름에 공백 대신 하이픈 사용('0'-아니요,'1'-예):"
CHANGE_ADD_YEAR = "앨범 폴더 이름에 연도 추가('0'-아니요,'1'-예):"
CHANGE_USE_TRACK_NUM = "파일 이름 앞에 트랙 번호 추가('0'-아니요,'1'-예):"
CHANGE_CHECK_EXIST = "다운로드 트랙 전에 존재하는 파일 확인('0'-아니요,'1'-예):"
CHANGE_ARTIST_BEFORE_TITLE = "트랙 제목 앞에 아티스트 이름 추가('0'-아니요,'1'-예):"
CHANGE_INCLUDE_EP = "아티스트 앨범 다운로드시 싱글 및 EP 포함('0'-아니요,'1'-예):"
CHANGE_ALBUMID_BEFORE_FOLDER = "앨범 폴더 앞에 ID 추가('0'-아니요,'1'-예):"
CHANGE_SAVE_COVERS = "커버 저장('0'-아니요,'1'-예):"
CHANGE_LANGUAGE = "언어 선택"
CHANGE_ALBUM_FOLDER_FORMAT = "앨범 폴더 형식('0'-변경 안 함,'default'-기본 설정):"
CHANGE_PLAYLIST_FOLDER_FORMAT = "Playlist folder format('0'-not modify,'default'-to set default):"
CHANGE_TRACK_FILE_FORMAT = "트랙 파일 형식('0'-변경 안 함,'default'-기본 설정):"
CHANGE_VIDEO_FILE_FORMAT = "Video file format('0'-not modify,'default'-to set default):"
CHANGE_SHOW_PROGRESS = "진행 상태 표시('0'-아니요,'1'-예):"
CHANGE_SHOW_TRACKINFO = "트랙 정보 표시('0'-아니요,'1'-예):"
CHANGE_SAVE_ALBUM_INFO = "AlbumInfo.txt 저장('0'-아니요,'1'-예):"
CHANGE_DOWNLOAD_VIDEOS = "Download videos (when downloading playlists, albums, mixes)('0'-No,'1'-Yes):"
CHANGE_ADD_LYRICS = "가사 추가('0'-아니요,'1'-예):"
CHANGE_LYRICS_SERVER_PROXY = "가사 서버 프록시('0'-변경 안 함):"
CHANGE_ADD_LRC_FILE = "timed 가사 .lrc 파일 저장 ('0'-아니요,'1'-예):"
CHANGE_ADD_TYPE_FOLDER = "Add Type-Folder,eg Album/Video/Playlist('0'-No,'1'-Yes):"
CHANGE_MULITHREAD_DOWNLOAD = "Multi thread download('0'-No,'1'-Yes):"
CHANGE_USE_DOWNLOAD_DELAY = "Use Download Delay('0'-No,'1'-Yes):"
# {} are required in these strings
AUTH_START_LOGIN = "로그인 중..."
AUTH_LOGIN_CODE = "로그인 코드는 다음과 같습니다. {}"
AUTH_NEXT_STEP = "설치를 완료하려면 {}로 이동하십시오. 다음 {} 내에 있습니다."
AUTH_WAITING = "승인 대기 중..."
AUTH_TIMEOUT = "작업 시간 초과"
MSG_VALID_ACCESSTOKEN = "{}에 대해 액세스 토큰이 유효합니다."
MSG_INVALID_ACCESSTOKEN = "만료된 액세스 토큰입니다. 새로 고침 중입니다."
MSG_PATH_ERR = "경로 오류!"
MSG_INPUT_ERR = "입력 오류!"
MODEL_ALBUM_PROPERTY = "앨범-정보"
MODEL_TRACK_PROPERTY = "트랙-정보"
MODEL_VIDEO_PROPERTY = "영상-정보"
MODEL_ARTIST_PROPERTY = "아티스트-정보"
MODEL_PLAYLIST_PROPERTY = "재생목록-정보"
MODEL_TITLE = '제목'
MODEL_TRACK_NUMBER = '트랙 넘버'
MODEL_VIDEO_NUMBER = '영상 넘버'
MODEL_RELEASE_DATE = '발매일'
MODEL_VERSION = '버전'
MODEL_EXPLICIT = 'Explicit'
MODEL_ALBUM = '앨범'
MODEL_ID = '아이디'
MODEL_NAME = '이름'
MODEL_TYPE = '형식'
+95
View File
@@ -0,0 +1,95 @@
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File : language.py
@Time : 2020/08/19
@Author : Yaronzz
@Version : 1.0
@Contact : yaronhuang@foxmail.com
@Desc :
'''
from lang.arabic import LangArabic
from lang.chinese import LangChinese
from lang.croatian import LangCroatian
from lang.czech import LangCzech
from lang.danish import LangDanish
from lang.dutch import LangDutch
from lang.english import LangEnglish
from lang.filipino import LangFilipino
from lang.french import LangFrench
from lang.german import LangGerman
from lang.hungarian import LangHungarian
from lang.italian import LangItalian
from lang.norwegian import LangNorwegian
from lang.polish import LangPolish
from lang.portuguese import LangPortuguese
from lang.russian import LangRussian
from lang.spanish import LangSpanish
from lang.turkish import LangTurkish
from lang.ukrainian import LangUkrainian
from lang.vietnamese import LangVietnamese
from lang.korean import LangKorean
from lang.japanese import LangJapanese
_ALL_LANGUAGE_ = [
['English', LangEnglish()],
['中文', LangChinese()],
['Turkish', LangTurkish()],
['Italian', LangItalian()],
['Czech', LangCzech()],
['Arabic', LangArabic()],
['Russian', LangRussian()],
['Filipino', LangFilipino()],
['Croatian', LangCroatian()],
['Spanish', LangSpanish()],
['Portuguese', LangPortuguese()],
['Ukrainian', LangUkrainian()],
['Vietnamese', LangVietnamese()],
['French', LangFrench()],
['German', LangGerman()],
['Danish', LangDanish()],
['Hungarian', LangHungarian()],
['Korean', LangKorean()],
['Japanese', LangJapanese()],
['Dutch', LangDutch()],
['Polish', LangPolish()],
['Norwegian', LangNorwegian()],
]
class Language(object):
def __init__(self) -> None:
self.select = LangEnglish()
def __toInt__(self, str):
try:
return int(str)
except:
return 0
def setLang(self, index):
index = self.__toInt__(index)
if index >= 0 and index < len(_ALL_LANGUAGE_):
self.select = _ALL_LANGUAGE_[index][1]
else:
self.select = LangEnglish()
def getLangName(self, index):
index = self.__toInt__(index)
if index >= 0 and index < len(_ALL_LANGUAGE_):
return _ALL_LANGUAGE_[index][0]
return ""
def getLangChoicePrint(self):
array = []
index = 0
while True:
name = self.getLangName(index)
if name == "":
break
array.append('\'' + str(index) + '\'-' + name)
index += 1
return ','.join(array)
LANG = Language()
+126
View File
@@ -0,0 +1,126 @@
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File : norwegian.py
@Time : 2021/03/25
@Author : roberts91
@Version : 1.0
@Contact :
@Desc :
'''
class LangNorwegian(object):
SETTING = "INNSTILLINGER"
VALUE = "Verdi"
SETTING_DOWNLOAD_PATH = "Nedlastingssti"
SETTING_ONLY_M4A = "Konverter MP4 til M4A"
SETTING_ADD_EXPLICIT_TAG = "Legg til eksplisitt tag"
SETTING_ADD_HYPHEN = "Legg til bindestrek"
SETTING_ADD_YEAR = "Legg til år før albummappenavn"
SETTING_USE_TRACK_NUM = "Legg til spornummer"
SETTING_AUDIO_QUALITY = "Lydkvalitet"
SETTING_VIDEO_QUALITY = "Videokvalitet"
SETTING_CHECK_EXIST = "Kontroller eksistens"
SETTING_ARTIST_BEFORE_TITLE = "Artistnavn før spornummer"
SETTING_ALBUMID_BEFORE_FOLDER = "Id før album mappe"
SETTING_INCLUDE_EP = "Inkluder single&EP"
SETTING_SAVE_COVERS = "Lagre cover"
SETTING_LANGUAGE = "Språk"
SETTING_USE_PLAYLIST_FOLDER = "Bruk spillelistemappe"
SETTING_MULITHREAD_DOWNLOAD = "Last ned flere samtidig"
SETTING_ALBUM_FOLDER_FORMAT = "Albummappens format"
SETTING_PLAYLIST_FOLDER_FORMAT = "Spillelistemappens format"
SETTING_TRACK_FILE_FORMAT = "Spor filformat"
SETTING_VIDEO_FILE_FORMAT = "Video filformat"
SETTING_SHOW_PROGRESS = "Vis fremgang"
SETTING_SHOW_TRACKINFO = "Vis sporinformasjon"
SETTING_SAVE_ALBUMINFO = "Lagre AlbumInfo.txt"
SETTING_DOWNLOAD_VIDEOS = "Last ned video"
SETTING_ADD_LYRICS = "Legg til sangtekst"
SETTING_LYRICS_SERVER_PROXY = "Sangtekst server proxy"
SETTING_ADD_LRC_FILE = "Lagre sangtekster med tidsreferanser (.lrc fil)"
SETTING_PATH = "Innstillinger sti"
SETTING_APIKEY = "API-nøkkel støtte"
SETTING_ADD_TYPE_FOLDER = "Legg til Type-Folder"
SETTING_DOWNLOAD_DELAY = "Use Download Delay"
CHOICE = "VALG"
FUNCTION = "FUNKSJON"
CHOICE_ENTER = "Tast inn"
CHOICE_ENTER_URLID = "Tast inn 'Url/ID':"
CHOICE_EXIT = "Avslutt"
CHOICE_LOGIN = "Kontroller AccessToken"
CHOICE_SETTINGS = "Innstillinger"
CHOICE_SET_ACCESS_TOKEN = "Sett AccessToken"
CHOICE_DOWNLOAD_BY_URL = "Last ned via URL eller ID"
CHOICE_LOGOUT = "Logg ut"
CHOICE_APIKEY = "Velg APIKey"
PRINT_ERR = "[FEIL]"
PRINT_INFO = "[INFO]"
PRINT_SUCCESS = "[SUCCES]"
PRINT_ENTER_CHOICE = "Tast inn valg:"
PRINT_LATEST_VERSION = "Seneste versjon:"
# PRINT_USERNAME = "username:"
# PRINT_PASSWORD = "password:"
CHANGE_START_SETTINGS = "Start innstillinger('0'-Tilbake,'1'-Ja):"
CHANGE_DOWNLOAD_PATH = "Nedlastingssti('0'-ikke endre):"
CHANGE_AUDIO_QUALITY = "Lydkvalitet('0'-Normal,'1'-Høy,'2'-HiFi,'3'-Master,'4'-Max):"
CHANGE_VIDEO_QUALITY = "Videokvalitet(1080, 720, 480, 360):"
CHANGE_ONLYM4A = "Konverter MP4 til M4A('0'-Nei,'1'-Ja):"
CHANGE_ADD_EXPLICIT_TAG = "Legg til eksplisitt tag i filnavn('0'-Nei,'1'-Ja):"
CHANGE_ADD_HYPHEN = "Bruk bindestreker i stedet for mellomrom i filnavn('0'-Nei,'1'-Ja):"
CHANGE_ADD_YEAR = "Legg til år i albumnavn('0'-Nei,'1'-Ja):"
CHANGE_USE_TRACK_NUM = "Legg til spornummer før filnavn('0'-Nei,'1'-Ja):"
CHANGE_CHECK_EXIST = "Kontrollér filens eksistens før nedlasting('0'-Nei,'1'-Ja):"
CHANGE_ARTIST_BEFORE_TITLE = "Legg til artistnavn før sportittel('0'-Nei,'1'-Ja):"
CHANGE_INCLUDE_EP = "Inkluder singler og EP'er når man laster ned en artists album('0'-Nei,'1'-Ja):"
CHANGE_ALBUMID_BEFORE_FOLDER = "Legg til ID før albummappe('0'-Nei,'1'-Ja):"
CHANGE_SAVE_COVERS = "Lagre cover('0'-Nei,'1'-Ja):"
CHANGE_LANGUAGE = "Velg språk"
CHANGE_ALBUM_FOLDER_FORMAT = "Albummappe format('0'-ikke endre, 'default'-for å sette til standardverdi):"
CHANGE_PLAYLIST_FOLDER_FORMAT = "Spillelistemappe format('0'-ikke endre, 'default'-for å sette til standardverdi):"
CHANGE_TRACK_FILE_FORMAT = "Sportittel filformat('0'-ikke endre, 'default'-for å sette til standardverdi):"
CHANGE_VIDEO_FILE_FORMAT = "Videofil format('0'-ikke endre, 'default'-for å sette til standardverdi):"
CHANGE_SHOW_PROGRESS = "Vis fremgang('0'-Nei,'1'-Ja):"
CHANGE_SHOW_TRACKINFO = "Vis sporinformasjon('0'-Nei,'1'-Ja):"
CHANGE_SAVE_ALBUM_INFO = "Lagre AlbumInfo.txt('0'-Nei,'1'-Ja):"
CHANGE_DOWNLOAD_VIDEOS = "Last ned videers (i spillelister, album, mikser)('0'-No,'1'-Yes):"
CHANGE_ADD_LYRICS = "Legg til sangtekst('0'-Nei,'1'-Ja):"
CHANGE_LYRICS_SERVER_PROXY = "Sangtekst server proxy('0'-not modify):"
CHANGE_ADD_LRC_FILE = "Lagre sangtekster med tidsreferanser .lrc fil ('0'-Nei,'1'-Ja):"
CHANGE_ADD_TYPE_FOLDER = "Legg til Type-mappe, f.eks. Album/Video/Spilleliste('0'-Nei,'1'-Ja):"
CHANGE_MULITHREAD_DOWNLOAD = "Last ned flere samtidig('0'-Nei,'1'-Ja):"
CHANGE_USE_DOWNLOAD_DELAY = "Use Download Delay('0'-No,'1'-Yes):"
# {} are required in these strings
AUTH_START_LOGIN = "Starter login-prosessen."
AUTH_LOGIN_CODE = "Din login kode er {}"
AUTH_NEXT_STEP = "Gå til {} innen de neste {} for å avslutte setup."
AUTH_WAITING = "Venter på godkjennelse..."
AUTH_TIMEOUT = "Tiden gikk ut."
MSG_VALID_ACCESSTOKEN = "AccessToken tilgjengelig for {}."
MSG_INVALID_ACCESSTOKEN = "AccessToken utløpt. Forøsker å oppdatere"
MSG_PATH_ERR = "Sti feil!"
MSG_INPUT_ERR = "Inntastningsfeol!"
MODEL_ALBUM_PROPERTY = "ALBUM-PROPERTY"
MODEL_TRACK_PROPERTY = "TRACK-PROPERTY"
MODEL_VIDEO_PROPERTY = "VIDEO-PROPERTY"
MODEL_ARTIST_PROPERTY = "ARTIST-PROPERTY"
MODEL_PLAYLIST_PROPERTY = "PLAYLIST-PROPERTY"
MODEL_TITLE = 'Tittel'
MODEL_TRACK_NUMBER = 'Spornummer'
MODEL_VIDEO_NUMBER = 'Videonummer'
MODEL_RELEASE_DATE = 'Utgivelsesdato'
MODEL_VERSION = 'Versjon'
MODEL_EXPLICIT = 'Eksplisitt'
MODEL_ALBUM = 'Album'
MODEL_ID = 'ID'
MODEL_NAME = 'Navn'
MODEL_TYPE = 'Type'
+126
View File
@@ -0,0 +1,126 @@
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File : polish.py
@Time : 2022/03/04
@Author : PatrykMis
@Version : 1.0
@Contact : patryk.mis@member.fsf.org
@Desc :
'''
class LangPolish(object):
SETTING = "USTAWIENIA"
VALUE = "WARTOŚĆ"
SETTING_DOWNLOAD_PATH = "Ścieżka pobierania"
SETTING_ONLY_M4A = "Konwertuj mp4 do m4a"
SETTING_ADD_EXPLICIT_TAG = "Dodaj tag jednoznaczne"
SETTING_ADD_HYPHEN = "Dodaj myslnik"
SETTING_ADD_YEAR = "Dodaj rok porzed folderem albumu"
SETTING_USE_TRACK_NUM = "Dodaj numer utworu użytkownika"
SETTING_AUDIO_QUALITY = "Jakość audio"
SETTING_VIDEO_QUALITY = "Jakość wideo"
SETTING_CHECK_EXIST = "Sprawdź istnienie"
SETTING_ARTIST_BEFORE_TITLE = "Nazwa artysty przed tytułem utworu"
SETTING_ALBUMID_BEFORE_FOLDER = "Id przed folderem albumu"
SETTING_INCLUDE_EP = "Uwzględnij single i EP"
SETTING_SAVE_COVERS = "Zapisz okładki"
SETTING_LANGUAGE = "Język"
SETTING_USE_PLAYLIST_FOLDER = "Użyj folder playlisty"
SETTING_MULITHREAD_DOWNLOAD = "Pobieranie wielowątkowe"
SETTING_ALBUM_FOLDER_FORMAT = "Format folderu albumu"
SETTING_PLAYLIST_FOLDER_FORMAT = "Playlist folder format"
SETTING_TRACK_FILE_FORMAT = "Format pliku utworu"
SETTING_VIDEO_FILE_FORMAT = "Video file format"
SETTING_SHOW_PROGRESS = "Pokaż postęp"
SETTING_SHOW_TRACKINFO = "Pokaż informacje o utworze"
SETTING_SAVE_ALBUMINFO = "Zapisz AlbumInfo.txt"
SETTING_DOWNLOAD_VIDEOS = "Download videos"
SETTING_ADD_LYRICS = "Dodaj teksty utworów"
SETTING_LYRICS_SERVER_PROXY = "Serwer proxy dla tekstów"
SETTING_ADD_LRC_FILE = "Zapisz czasowe teksty utworów (plik .lrc)"
SETTING_PATH = "Ścieżka ustawień"
SETTING_APIKEY = "Obsługa APIKey"
SETTING_ADD_TYPE_FOLDER = "Dodaj folder typu"
SETTING_DOWNLOAD_DELAY = "Use Download Delay"
CHOICE = "WYBÓR"
FUNCTION = "FUNKCJA"
CHOICE_ENTER = "Wpisz"
CHOICE_ENTER_URLID = "Wpisz 'Url/ID':"
CHOICE_EXIT = "Wyjdź"
CHOICE_LOGIN = "Sprawdź AccessToken"
CHOICE_SETTINGS = "Ustawienia"
CHOICE_SET_ACCESS_TOKEN = "Ustaw AccessToken"
CHOICE_DOWNLOAD_BY_URL = "Pobierz według adresu URL lub ID"
CHOICE_LOGOUT = "Wyloguj"
CHOICE_APIKEY = "Wybierz APIKey"
PRINT_ERR = "[BŁĄD]"
PRINT_INFO = "[INFO]"
PRINT_SUCCESS = "[SUKCES]"
PRINT_ENTER_CHOICE = "Wprowadź Wybór:"
PRINT_LATEST_VERSION = "Najnowsza wersja:"
# PRINT_USERNAME = "nazwa użytkownika:"
# PRINT_PASSWORD = "hasło:"
CHANGE_START_SETTINGS = "Uruchomić ustawienia('0'-Powrót,'1'-Tak):"
CHANGE_DOWNLOAD_PATH = "Ścieżka pobierania('0'-bez zmian):"
CHANGE_AUDIO_QUALITY = "Jakość audio('0'-Normalna,'1'-Wysoka,'2'-HiFi,'3'-Master,'4'-Max):"
CHANGE_VIDEO_QUALITY = "Jakość wideo(1080, 720, 480, 360):"
CHANGE_ONLYM4A = "Konwertuj mp4 do m4a('0'-Nie,'1'-Tak):"
CHANGE_ADD_EXPLICIT_TAG = "Dodaj tag jednoznaczne do nazwy pliku('0'-Nie,'1'-Tak):"
CHANGE_ADD_HYPHEN = "Używaj myślników zamiast spacji w nazwach plików('0'-Nie,'1'-Tak):"
CHANGE_ADD_YEAR = "Dodaj rok do nazw folderów albumów('0'-Nie,'1'-Tak):"
CHANGE_USE_TRACK_NUM = "Dodaj numer utworu przed nazwami plików('0'-Nie,'1'-Tak):"
CHANGE_CHECK_EXIST = "Sprawdź istniejący plik przed pobraniem utworu('0'-Nie,'1'-Tak):"
CHANGE_ARTIST_BEFORE_TITLE = "Dodaj nazwę artysty przed tytułem utworu('0'-Nie,'1'-Tak):"
CHANGE_INCLUDE_EP = "Uwzględnij single i EP podczas pobierania albumów wykonawcy('0'-Nie,'1'-Tak):"
CHANGE_ALBUMID_BEFORE_FOLDER = "Dodaj ID przed folderem albumu('0'-Nie,'1'-Tak):"
CHANGE_SAVE_COVERS = "Zapisz okładki('0'-Nie,'1'-Tak):"
CHANGE_LANGUAGE = "Wybierz język"
CHANGE_ALBUM_FOLDER_FORMAT = "Format folderu albumu('0'-nie modyfikuj,'default'-by ustawić domyślny):"
CHANGE_PLAYLIST_FOLDER_FORMAT = "Playlist folder format('0'-not modify,'default'-to set default):"
CHANGE_TRACK_FILE_FORMAT = "Format pliku utworu('0'-nie modyfikuj,'default'-by ustawić domyślny):"
CHANGE_VIDEO_FILE_FORMAT = "Video file format('0'-not modify,'default'-to set default):"
CHANGE_SHOW_PROGRESS = "Pokaż postęp('0'-Nie,'1'-Tak):"
CHANGE_SHOW_TRACKINFO = "Pokaż informacje o utworze('0'-Nie,'1'-Tak):"
CHANGE_SAVE_ALBUM_INFO = "Zapisz AlbumInfo.txt('0'-Nie,'1'-Tak):"
CHANGE_DOWNLOAD_VIDEOS = "Download videos (when downloading playlists, albums, mixes)('0'-No,'1'-Yes):"
CHANGE_ADD_LYRICS = "Dodaj teksty utworów('0'-Nie,'1'-Tak):"
CHANGE_LYRICS_SERVER_PROXY = "Serwer proxy dla tekstów('0'-nie modyfikuj):"
CHANGE_ADD_LRC_FILE = "Zapisz plik .lrc czasowych tekstów utworów ('0'-Nie,'1'-Tak):"
CHANGE_ADD_TYPE_FOLDER = "Dodaj folder typu, np. Album/wideo/lista odtwarzania('0'-Nie,'1'-Tak):"
CHANGE_MULITHREAD_DOWNLOAD = "Multi thread download('0'-No,'1'-Yes):"
CHANGE_USE_DOWNLOAD_DELAY = "Use Download Delay('0'-No,'1'-Yes):"
# {} are required in these strings
AUTH_START_LOGIN = "Rozpoczęcie procesu logowania..."
AUTH_LOGIN_CODE = "Twój kod logowania to {}"
AUTH_NEXT_STEP = "Przejdź do {} w ciągu następnych {} aby zakończyć konfigurację."
AUTH_WAITING = "Oczekiwanie na autoryzację..."
AUTH_TIMEOUT = "Przekroczono limit czasu operacji."
MSG_VALID_ACCESSTOKEN = "AccessToken dobry przez {}."
MSG_INVALID_ACCESSTOKEN = "AccessToken wygasł. Próba jego odświeżenia."
MSG_PATH_ERR = "Ścieżka jest błędna!"
MSG_INPUT_ERR = "Błąd wejścia!"
MODEL_ALBUM_PROPERTY = "ALBUM-WŁAŚCIWOŚĆ"
MODEL_TRACK_PROPERTY = "UTWÓR-WŁAŚCIWOŚĆ"
MODEL_VIDEO_PROPERTY = "WIDEO-WŁAŚCIWOŚĆ"
MODEL_ARTIST_PROPERTY = "ARTYSTA-WŁAŚCIWOŚĆ"
MODEL_PLAYLIST_PROPERTY = "PLAYLISTA-WŁAŚCIWOŚĆ"
MODEL_TITLE = 'Tytuł'
MODEL_TRACK_NUMBER = 'Numer Utworu'
MODEL_VIDEO_NUMBER = 'Numer Wideo'
MODEL_RELEASE_DATE = 'Data Wydania'
MODEL_VERSION = 'Wersja'
MODEL_EXPLICIT = 'Jednoznaczny'
MODEL_ALBUM = 'Album'
MODEL_ID = 'ID'
MODEL_NAME = 'Nazwa'
MODEL_TYPE = 'Typ'
+126
View File
@@ -0,0 +1,126 @@
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File : portuguese.py
@Time : 2020/08/19
@Author : BR8N0BL4CK & João
@Version : 1.0
@Contact :
@Desc :
'''
class LangPortuguese(object):
SETTING = "Configurações"
VALUE = "VALOR"
SETTING_DOWNLOAD_PATH = "Caminho do download"
SETTING_ONLY_M4A = "Converter mp4 para m4a"
SETTING_ADD_EXPLICIT_TAG = "Adicionar etiqueta explícito"
SETTING_ADD_HYPHEN = "Adicionar hífen"
SETTING_ADD_YEAR = "Adicionar ano antes do nome do álbum na pasta"
SETTING_USE_TRACK_NUM = "Adicionar Número da Faixa"
SETTING_AUDIO_QUALITY = "Qualidade Do Áudio"
SETTING_VIDEO_QUALITY = "Qualidade Do Vídeo"
SETTING_CHECK_EXIST = "Verificar Existência"
SETTING_ARTIST_BEFORE_TITLE = "ArtistaNome Antes do Track-Título"
SETTING_ALBUMID_BEFORE_FOLDER = "Número De Identificação do Álbum antes na Pasta"
SETTING_INCLUDE_EP = "Incluir Single & EP"
SETTING_SAVE_COVERS = "Salvar Capas"
SETTING_LANGUAGE = "idioma"
SETTING_USE_PLAYLIST_FOLDER = "Usar pasta de lista de reprodução"
SETTING_MULITHREAD_DOWNLOAD = "Download de vários tópicos"
SETTING_ALBUM_FOLDER_FORMAT = "Formato da pasta do álbum"
SETTING_PLAYLIST_FOLDER_FORMAT = "Playlist folder format"
SETTING_TRACK_FILE_FORMAT = "Track file format"
SETTING_VIDEO_FILE_FORMAT = "Video file format"
SETTING_SHOW_PROGRESS = "Mostrar progresso"
SETTING_SHOW_TRACKINFO = "Mostrar informações da faixa"
SETTING_SAVE_ALBUMINFO = "Salvar AlbumInfo.txt"
SETTING_DOWNLOAD_VIDEOS = "Download videos"
SETTING_ADD_LYRICS = "Adicionar Letra da Música"
SETTING_LYRICS_SERVER_PROXY = "Proxy do servidor de letras"
SETTING_ADD_LRC_FILE = "Salvar letras cronometradas (.lrc file)"
SETTING_PATH = "Settings path"
SETTING_APIKEY = "Suporte APIKey"
SETTING_ADD_TYPE_FOLDER = "Adicionar tipo de pasta"
SETTING_DOWNLOAD_DELAY = "Use Download Delay"
CHOICE = "ESCOLHER"
FUNCTION = "FUNÇÃO"
CHOICE_ENTER = "Entrar"
CHOICE_ENTER_URLID = "ADICIONAR 'Url/ID':"
CHOICE_EXIT = "SAIR"
CHOICE_LOGIN = "Verificar o token de acesso"
CHOICE_SETTINGS = "Configurações"
CHOICE_SET_ACCESS_TOKEN = "Adicionar Token de Acesso"
CHOICE_DOWNLOAD_BY_URL = "Download Por url ou id"
CHOICE_LOGOUT = "Logout"
CHOICE_APIKEY = "Selecione a APIKey"
PRINT_ERR = "[ERRO]"
PRINT_INFO = "[INFORMAÇÕES]"
PRINT_SUCCESS = "[SUCESSO]"
PRINT_ENTER_CHOICE = "Entrar em Escolher:"
PRINT_LATEST_VERSION = "Última Versão:"
# PRINT_USERNAME = "Nome De Usuário:"
# PRINT_PASSWORD = "Senha:"
CHANGE_START_SETTINGS = "Configurações Iniciais('0'-Retornar,'1'-Sim):"
CHANGE_DOWNLOAD_PATH = "Caminho do download('0' Não Modificar):"
CHANGE_AUDIO_QUALITY = "Qualidade De Áudio('0'-Normal,'1'-Alta,'2'-HiFi,'3'-Master,'4'-Max):"
CHANGE_VIDEO_QUALITY = "Qualidade Do Vídeo(1080, 720, 480, 360):"
CHANGE_ONLYM4A = "Converter mp4 para m4a('0'-Não,'1'-Sim):"
CHANGE_ADD_EXPLICIT_TAG = "Adicionar Etiqueta Explícito para os nomes dos arquivos('0'-Não,'1'-Sim):"
CHANGE_ADD_HYPHEN = "Usar hífen em vez de espaços nos nomes dos arquivos('0'-Não,'1'-Sim):"
CHANGE_ADD_YEAR = "Adicionar Ano aos nomes das pastas dos álbums('0'-Não,'1'-Sim):"
CHANGE_USE_TRACK_NUM = "Adicionar número da faixa antes do nome do arquivo('0'-Não,'1'-Sim):"
CHANGE_CHECK_EXIST = "Verificar existência do arquivo antes de baixar a faixa('0'-Não,'1'-Sim):"
CHANGE_ARTIST_BEFORE_TITLE = "Adicionar o nome do artista antes do título da faixa('0'-Não,'1'-Sim):"
CHANGE_INCLUDE_EP = "Incluir singles e EPs quando baixar álbums de um artista('0'-Não,'1'-Sim):"
CHANGE_ALBUMID_BEFORE_FOLDER = "Adicionar id antes no nome da pasta do álbum('0'-Não,'1'-Sim):"
CHANGE_SAVE_COVERS = "Salvar Capas('0'-Não,'1'-Sim):"
CHANGE_LANGUAGE = "Selecionar idioma"
CHANGE_ALBUM_FOLDER_FORMAT = "Formato da pasta do álbum ('0' não modificar)"
CHANGE_PLAYLIST_FOLDER_FORMAT = "Playlist folder format('0'-not modify,'default'-to set default):"
CHANGE_TRACK_FILE_FORMAT = "Formato do arquivo de trilha ('0' não modificar):"
CHANGE_VIDEO_FILE_FORMAT = "Video file format('0'-not modify,'default'-to set default):"
CHANGE_SHOW_PROGRESS = "Mostrar progresso('0'-Não,'1'-Sim):"
CHANGE_SHOW_TRACKINFO = "Mostrar informações da faixa('0'-Não,'1'-Sim):"
CHANGE_SAVE_ALBUM_INFO = "Salvar AlbumInfo.txt('0'-Não,'1'-Sim):"
CHANGE_DOWNLOAD_VIDEOS = "Download videos (when downloading playlists, albums, mixes)('0'-No,'1'-Yes):"
CHANGE_ADD_LYRICS = "Adicionar letras('0'-Não,'1'-Sim):"
CHANGE_LYRICS_SERVER_PROXY = "Proxy do servidor de letras ('0' não modificar):"
CHANGE_ADD_LRC_FILE = "Salvar arquivo .lrc de letras cronometradas ('0'-Não,'1'-Sim):"
CHANGE_ADD_TYPE_FOLDER = "Adicionar Tipo de Pasta, por exemplo, Álbum/Vídeo/Lista de Reprodução('0'-Não,'1'-Sim):"
CHANGE_MULITHREAD_DOWNLOAD = "Multi thread download('0'-No,'1'-Yes):"
CHANGE_USE_DOWNLOAD_DELAY = "Use Download Delay('0'-No,'1'-Yes):"
# {} are required in these strings
AUTH_START_LOGIN = "Iniciando o processo de login..."
AUTH_LOGIN_CODE = "Seu código de login é {}"
AUTH_NEXT_STEP = "Vá para {} no próximo {} para concluir a configuração."
AUTH_WAITING = "Espera da autorização..."
AUTH_TIMEOUT = "A operação expirou."
MSG_VALID_ACCESSTOKEN = "Token de acesso bom por {}."
MSG_INVALID_ACCESSTOKEN = "Token de acesso expirado. Tentando atualizá-lo."
MSG_PATH_ERR = "Erro no local de salvamento dos arquivos!"
MSG_INPUT_ERR = "Erro de Entrada!"
MODEL_ALBUM_PROPERTY = "ÁLBUM-PROPRIEDADE"
MODEL_TRACK_PROPERTY = "FAIXA-PROPRIEDADE"
MODEL_VIDEO_PROPERTY = "VÍDEO-PROPRIEDADE"
MODEL_ARTIST_PROPERTY = "ARTISTA-PROPRIEDADE"
MODEL_PLAYLIST_PROPERTY = "PLAYLIST-PPROPRIEDADE"
MODEL_TITLE = 'Título'
MODEL_TRACK_NUMBER = 'Número Da Faixa'
MODEL_VIDEO_NUMBER = 'Número Do Vídeo'
MODEL_RELEASE_DATE = 'Data De Lançamento'
MODEL_VERSION = 'Versão'
MODEL_EXPLICIT = 'Explícito'
MODEL_ALBUM = 'Álbum'
MODEL_ID = 'ID'
MODEL_NAME = 'Nome'
MODEL_TYPE = 'Tipo'
+126
View File
@@ -0,0 +1,126 @@
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File : russian.py
@Time : 2020/11/29
@Author : sergey.seve-s
@Version : 1.0
@Contact :
@Desc :
'''
class LangRussian(object):
SETTING = "НАСТРОЙКА"
VALUE = "УСТАНОВКА"
SETTING_DOWNLOAD_PATH = "Место сохранения"
SETTING_ONLY_M4A = "Сохранять mp4 как m4a"
SETTING_ADD_EXPLICIT_TAG = "Добавить тег Нецензурно"
SETTING_ADD_HYPHEN = "Добавить дефис"
SETTING_ADD_YEAR = "Добавить год перед именем папки-альбома"
SETTING_USE_TRACK_NUM = "Добавить номер трека"
SETTING_AUDIO_QUALITY = "Качество аудио"
SETTING_VIDEO_QUALITY = "Качество видео"
SETTING_CHECK_EXIST = "Проверять наличие"
SETTING_ARTIST_BEFORE_TITLE = "Исполнитель перед названием трека"
SETTING_ALBUMID_BEFORE_FOLDER = "ID перед названием папки"
SETTING_INCLUDE_EP = "Включить сингл и миньон"
SETTING_SAVE_COVERS = "Добавлять обложку"
SETTING_LANGUAGE = "Язык"
SETTING_USE_PLAYLIST_FOLDER = "Плейлисты в отдельную папку"
SETTING_MULITHREAD_DOWNLOAD = "Многопоточная загрузка"
SETTING_ALBUM_FOLDER_FORMAT = "Маска имени альбома"
SETTING_PLAYLIST_FOLDER_FORMAT = "Playlist folder format"
SETTING_TRACK_FILE_FORMAT = "Маска имени трека"
SETTING_VIDEO_FILE_FORMAT = "Video file format"
SETTING_SHOW_PROGRESS = "Показывать процесс загрузки"
SETTING_SHOW_TRACKINFO = "Show Track Info"
SETTING_SAVE_ALBUMINFO = "Сохранять AlbumInfo.txt"
SETTING_DOWNLOAD_VIDEOS = "Download videos"
SETTING_ADD_LYRICS = "Добавлять текст песень"
SETTING_LYRICS_SERVER_PROXY = "Прокси сервер для текстов песен"
SETTING_ADD_LRC_FILE = "Save timed lyrics (.lrc file)"
SETTING_PATH = "Путь для настроек"
SETTING_APIKEY = "APIKey support"
SETTING_ADD_TYPE_FOLDER = "Add Type-Folder"
SETTING_DOWNLOAD_DELAY = "Use Download Delay"
CHOICE = "ВЫБРАТЬ"
FUNCTION = "ФУНКЦИИ"
CHOICE_ENTER = "Ввод"
CHOICE_ENTER_URLID = "Ввод 'Url/ID':"
CHOICE_EXIT = "Выход"
CHOICE_LOGIN = "Проверить AccessToken"
CHOICE_SETTINGS = "Настройки"
CHOICE_SET_ACCESS_TOKEN = "Применить AccessToken"
CHOICE_DOWNLOAD_BY_URL = "Использовать ссылку для загрузки"
CHOICE_LOGOUT = "Переподключение"
CHOICE_APIKEY = "Select APIKey"
PRINT_ERR = "[ОШИБКА]"
PRINT_INFO = "[СВЕДЕНИЯ]"
PRINT_SUCCESS = "[ГОТОВО]"
PRINT_ENTER_CHOICE = "Выбор функции:"
PRINT_LATEST_VERSION = "Последняя версия:"
# PRINT_USERNAME = "Имя:"
# PRINT_PASSWORD = "Пароль:"
CHANGE_START_SETTINGS = "Начальная настройка('0'-Отмена,'1'-Да):"
CHANGE_DOWNLOAD_PATH = "Место сохранения('0'-Отмена):"
CHANGE_AUDIO_QUALITY = "Качество аудио('0'-Стандарт,'1'-Высокое,'2'-HiFi,'3'-MQA,'4'-Max):"
CHANGE_VIDEO_QUALITY = "Качество видео(1080, 720, 480, 360):"
CHANGE_ONLYM4A = "Сохранять mp4 как m4a('0'-Нет,'1'-Да):"
CHANGE_ADD_EXPLICIT_TAG = "Добавить тег 'Нецензурно' ('0'-Нет,'1'-Да):"
CHANGE_ADD_HYPHEN = "Использовать дефис вместо пробела в имени трека('0'-Нет,'1'-Да):"
CHANGE_ADD_YEAR = "Добавлять год перед названием альбома('0'-Нет,'1'-Да):"
CHANGE_USE_TRACK_NUM = "Добавить номер перед названием трека('0'-Нет,'1'-Да):"
CHANGE_CHECK_EXIST = "Проверять наличие перед загрузкой('0'-Нет,'1'-Да):"
CHANGE_ARTIST_BEFORE_TITLE = "Добавить имя артиста перед названием трека('0'-Нет,'1'-Да):"
CHANGE_INCLUDE_EP = "Включать синглы и миньоны в дискографию('0'-Нет'1'-Да):"
CHANGE_ALBUMID_BEFORE_FOLDER = "Добавить ID перед названием альбома('0'-Нет,'1'-Да):"
CHANGE_SAVE_COVERS = "Сохранять обложки('0'-Нет,'1'-Да):"
CHANGE_LANGUAGE = "Выбрать язык"
CHANGE_ALBUM_FOLDER_FORMAT = "Маска имени альбома('0' не менять):"
CHANGE_PLAYLIST_FOLDER_FORMAT = "Playlist folder format('0'-not modify,'default'-to set default):"
CHANGE_TRACK_FILE_FORMAT = "Маска имени трека('0' не менять):"
CHANGE_VIDEO_FILE_FORMAT = "Video file format('0'-not modify,'default'-to set default):"
CHANGE_SHOW_PROGRESS = "Показывать процесс загрузки('0'-Нет,'1'-Да):"
CHANGE_SHOW_TRACKINFO = "Show track info('0'-No,'1'-Yes):"
CHANGE_SAVE_ALBUM_INFO = "Сохранять AlbumInfo.txt('0'-Нет,'1'-Да):"
CHANGE_DOWNLOAD_VIDEOS = "Download videos (when downloading playlists, albums, mixes)('0'-No,'1'-Yes):"
CHANGE_ADD_LYRICS = "Добавлять тексты песень ('0'-Нет,'1'-Да):"
CHANGE_LYRICS_SERVER_PROXY = "Прокси для сервера с текстом песень('0' не менять):"
CHANGE_ADD_LRC_FILE = "Save timed lyrics .lrc file ('0'-No,'1'-Yes):"
CHANGE_ADD_TYPE_FOLDER = "Add Type-Folder,eg Album/Video/Playlist('0'-No,'1'-Yes):"
CHANGE_MULITHREAD_DOWNLOAD = "Multi thread download('0'-No,'1'-Yes):"
CHANGE_USE_DOWNLOAD_DELAY = "Use Download Delay('0'-No,'1'-Yes):"
# {} are required in these strings
AUTH_START_LOGIN = "Входим в сервис..."
AUTH_LOGIN_CODE = "Ваш код для входа {}"
AUTH_NEXT_STEP = "Перейдите к {} в течении {}, для завершения настройки."
AUTH_WAITING = "Ожидание авторизации..."
AUTH_TIMEOUT = "Закончилось время ожидания."
MSG_VALID_ACCESSTOKEN = "AccessToken успешно применён {}."
MSG_INVALID_ACCESSTOKEN = "Срок действия AccessToken истек. Попытка обновления."
MSG_PATH_ERR = "Неверное место!"
MSG_INPUT_ERR = "Ошибка ввода!"
MODEL_ALBUM_PROPERTY = "ALBUM-PROPERTY"
MODEL_TRACK_PROPERTY = "TRACK-PROPERTY"
MODEL_VIDEO_PROPERTY = "VIDEO-PROPERTY"
MODEL_ARTIST_PROPERTY = "ARTIST-PROPERTY"
MODEL_PLAYLIST_PROPERTY = "PLAYLIST-PROPERTY"
MODEL_TITLE = 'Название'
MODEL_TRACK_NUMBER = 'Номер трека'
MODEL_VIDEO_NUMBER = 'Номер видео'
MODEL_RELEASE_DATE = 'Дата издания'
MODEL_VERSION = 'Версия'
MODEL_EXPLICIT = 'Нецензурно'
MODEL_ALBUM = 'Альбом'
MODEL_ID = 'ID'
MODEL_NAME = 'Имя'
MODEL_TYPE = 'Тип'
+126
View File
@@ -0,0 +1,126 @@
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File : spanish.py
@Time : 2022/07/07
@Author : Frikilinux & JavierSC
@Version : 2.3
@Contact :
@Desc :
'''
class LangSpanish(object):
SETTING = "AJUSTES"
VALUE = "VALORES"
SETTING_DOWNLOAD_PATH = "Ruta de descarga"
SETTING_ONLY_M4A = "Convertir mp4 a m4a"
SETTING_ADD_EXPLICIT_TAG = "Agregar etiqueta de 'Contenido explícito'"
SETTING_ADD_HYPHEN = "Agregar guión"
SETTING_ADD_YEAR = "Agregar año en la carpeta del álbum"
SETTING_USE_TRACK_NUM = "Agregar número de la pista"
SETTING_AUDIO_QUALITY = "Calidad de audio"
SETTING_VIDEO_QUALITY = "Calidad de video"
SETTING_CHECK_EXIST = "Verificar si existe"
SETTING_ARTIST_BEFORE_TITLE = "Nombre del artista en el título de la pista"
SETTING_ALBUMID_BEFORE_FOLDER = "Añadir ID de la carpeta del álbum"
SETTING_INCLUDE_EP = "Incluir sencillos y EPs"
SETTING_SAVE_COVERS = "Guardar carátulas"
SETTING_LANGUAGE = "Idioma"
SETTING_USE_PLAYLIST_FOLDER = "Usar directorio de la lista de reproducción"
SETTING_MULITHREAD_DOWNLOAD = "Descarga Multi-hilo"
SETTING_ALBUM_FOLDER_FORMAT = "Formato del nombre de carpeta del álbum"
SETTING_PLAYLIST_FOLDER_FORMAT = "Playlist folder format"
SETTING_TRACK_FILE_FORMAT = "Formato del nombre de archivo de la pista"
SETTING_VIDEO_FILE_FORMAT = "Video file format"
SETTING_SHOW_PROGRESS = "Mostrar progreso"
SETTING_SHOW_TRACKINFO = "Mostrar información de pista"
SETTING_SAVE_ALBUMINFO = "Guardar AlbumInfo.txt"
SETTING_DOWNLOAD_VIDEOS = "Download videos"
SETTING_ADD_LYRICS = "Añadir letras"
SETTING_LYRICS_SERVER_PROXY = "Proxy del servidor de letras"
SETTING_ADD_LRC_FILE = "Añadir letras cronometradas (archivo .lrc)"
SETTING_PATH = "Ruta de ajustes"
SETTING_APIKEY = "Soporte de la APIKey"
SETTING_ADD_TYPE_FOLDER = "Añadir tipo de carpeta"
SETTING_DOWNLOAD_DELAY = "Use Download Delay"
CHOICE = "SELECCIÓN"
FUNCTION = "FUNCIÓN"
CHOICE_ENTER = "Ingresar"
CHOICE_ENTER_URLID = "Ingresar 'Url/ID':"
CHOICE_EXIT = "Salir"
CHOICE_LOGIN = "Verificar el token de acceso"
CHOICE_SETTINGS = "Ajustes"
CHOICE_SET_ACCESS_TOKEN = "Establecer AccessToken"
CHOICE_DOWNLOAD_BY_URL = "Descargar por Url o ID"
CHOICE_LOGOUT = "Cerrar sesión"
CHOICE_APIKEY = "Seleccionar APIKey"
PRINT_ERR = "[ERROR]"
PRINT_INFO = "[INFO]"
PRINT_SUCCESS = "[ÉXITO]"
PRINT_ENTER_CHOICE = "Ingresar Selección:"
PRINT_LATEST_VERSION = "Última versión:"
# PRINT_USERNAME = "nombre de usuario:"
# PRINT_PASSWORD = "contraseña:"
CHANGE_START_SETTINGS = "¿Iniciar ajustes? ('0'-Volver,'1'-Sí):"
CHANGE_DOWNLOAD_PATH = "Ruta de descarga ('0' No modificar):"
CHANGE_AUDIO_QUALITY = "Calidad de audio ('0'-Normal,'1'-High,'2'-HiFi,'3'-Master,'4'-Max):"
CHANGE_VIDEO_QUALITY = "Calidad de video (1080, 720, 480, 360):"
CHANGE_ONLYM4A = "¿Convertir mp4 a m4a? ('0'-No,'1'-Sí):"
CHANGE_ADD_EXPLICIT_TAG = "¿Agregar etiqueta de contenido explícito a los nombres de archivo? ('0'-No,'1'-Sí):"
CHANGE_ADD_HYPHEN = "¿Usar guiones en lugar de espacios en el nombre de los archivos? ('0'-No,'1'-Sí):"
CHANGE_ADD_YEAR = "¿Agregar año a el nombre de las carpetas del álbum? ('0'-No,'1'-Sí):"
CHANGE_USE_TRACK_NUM = "¿Agregar número de la pista? ('0'-No,'1'-Sí):"
CHANGE_CHECK_EXIST = "¿Verificar si el archivo existe antes de descargar la pista? ('0'-No,'1'-Sí):"
CHANGE_ARTIST_BEFORE_TITLE = "¿Añadir el nombre del artista en el título de la pista? ('0'-No,'1'-Sí):"
CHANGE_INCLUDE_EP = "¿Incluir Sencillos y EPs al descargar el álbum del artista? ('0'-No,'1'-Sí):"
CHANGE_ALBUMID_BEFORE_FOLDER = "¿Añadir ID de la carpeta del álbum? ('0'-No,'1'-Sí):"
CHANGE_SAVE_COVERS = "¿Guardar carátulas?('0'-No,'1'-Sí):"
CHANGE_LANGUAGE = "Seleccione el idioma"
CHANGE_ALBUM_FOLDER_FORMAT = "Formato del nombre de carpeta del álbum ('0' No modificar):"
CHANGE_PLAYLIST_FOLDER_FORMAT = "Playlist folder format('0'-not modify,'default'-to set default):"
CHANGE_TRACK_FILE_FORMAT = "Formato del nombre de archivo de la pista ('0' No modificar):"
CHANGE_VIDEO_FILE_FORMAT = "Formato del archivo de video('0'-No modificar,'default'-por defecto):"
CHANGE_SHOW_PROGRESS = "¿Mostrar progreso? ('0'-No,'1'-Sí):"
CHANGE_SHOW_TRACKINFO = "¿Mostrar información de pista?('0'-No,'1'-Sí):"
CHANGE_SAVE_ALBUM_INFO = "¿Guardar AlbumInfo.txt?('0'-No,'1'-Sí):"
CHANGE_DOWNLOAD_VIDEOS = "Download videos (when downloading playlists, albums, mixes)('0'-No,'1'-Yes):"
CHANGE_ADD_LYRICS = "¿Añadir letras?('0'-No,'1'-Sí):"
CHANGE_LYRICS_SERVER_PROXY = "¿Proxy del servidor de letras?('0' no modificar):"
CHANGE_ADD_LRC_FILE = "¿Añadir letras cronometradas en un archivo .lrc? ('0'-No,'1'-Sí):"
CHANGE_ADD_TYPE_FOLDER = "Añadir tipo de carpeta, ej: Album/Video/Playlist('0'-No,'1'-Sí):"
CHANGE_MULITHREAD_DOWNLOAD = "¿Descarga Multi-hilo?('0'-No,'1'-Sí:"
CHANGE_USE_DOWNLOAD_DELAY = "Use Download Delay('0'-No,'1'-Yes):"
# {} are required in these strings
AUTH_START_LOGIN = "Iniciando sesión..."
AUTH_LOGIN_CODE = "Su código para autorizar la sesión es {}"
AUTH_NEXT_STEP = "Diríjase a {} en los próximos {} para completar la autorización."
AUTH_WAITING = "Esperando la autorización..."
AUTH_TIMEOUT = "Se superó el tiempo de espera."
MSG_VALID_ACCESSTOKEN = "Token de acceso válido por {}."
MSG_INVALID_ACCESSTOKEN = "El token de acceso ha expirado. Tratando de renovarlo."
MSG_PATH_ERR = "¡La ruta no es correcta!"
MSG_INPUT_ERR = "¡Error de entrada!"
MODEL_ALBUM_PROPERTY = "PROPIEDAD-DE-ÁLBUM"
MODEL_TRACK_PROPERTY = "PROPIEDAD-DE-PISTA"
MODEL_VIDEO_PROPERTY = "PROPIEDAD-DE-VIDEO"
MODEL_ARTIST_PROPERTY = "PROPIEDAD-DE-ARTISTA"
MODEL_PLAYLIST_PROPERTY = "PROPIEDAD-DE-PLAYLIST"
MODEL_TITLE = 'Título'
MODEL_TRACK_NUMBER = 'Número de pistas'
MODEL_VIDEO_NUMBER = 'Número de videos'
MODEL_RELEASE_DATE = 'Fecha de lanzamiento'
MODEL_VERSION = 'Versión'
MODEL_EXPLICIT = 'Explícito'
MODEL_ALBUM = 'Álbum'
MODEL_ID = 'ID'
MODEL_NAME = 'Nombre'
MODEL_TYPE = 'Tipo'
+126
View File
@@ -0,0 +1,126 @@
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File : turkish.py
@Time : 2020/09/13
@Author : Gorgeous & shhade for hack & Mutlu ŞEN
@Version : 1.0
@Contact : realmutlusen@gmail.com
@Desc : Yanlış çeviri ya da düzenleme için 'realmutlusen@gmail.com'a mail atabilirsiniz.
'''
class LangTurkish(object):
SETTING = "AYARLAR"
VALUE = "VERİLER"
SETTING_DOWNLOAD_PATH = "İndirme konumu:"
SETTING_ONLY_M4A = ".mp4 uzantısı m4a'ya çevrilsin:"
SETTING_ADD_EXPLICIT_TAG = "'Küfürlü' etiketi eklensin:"
SETTING_ADD_HYPHEN = "Boşluk yerine '-' eklensin:"
SETTING_ADD_YEAR = "Yıl eklensin:"
SETTING_USE_TRACK_NUM = "Artist numarası eklensin:"
SETTING_AUDIO_QUALITY = "Ses kalitesi:"
SETTING_VIDEO_QUALITY = "Video kalitesi:"
SETTING_CHECK_EXIST = "İndirilmiş mi diye kontrol edilsin:"
SETTING_ARTIST_BEFORE_TITLE = "Artist adı eklensin:"
SETTING_ALBUMID_BEFORE_FOLDER = "ID eklensin:"
SETTING_INCLUDE_EP = "Single'leri ve EP'leri dahil edisin:"
SETTING_SAVE_COVERS = "Albüm kapağı indirilsin:"
SETTING_LANGUAGE = "Kullanılan lisan:"
SETTING_USE_PLAYLIST_FOLDER = "Albümler klasör halinde indirilsin mi ?"
SETTING_MULITHREAD_DOWNLOAD = "Şarkılar tek tek indirilsin mi?"
SETTING_ALBUM_FOLDER_FORMAT = "Klasör ismi formatı:"
SETTING_PLAYLIST_FOLDER_FORMAT = "Playlist folder format"
SETTING_TRACK_FILE_FORMAT = "Dosya ismi formatı:"
SETTING_VIDEO_FILE_FORMAT = "Video file format"
SETTING_SHOW_PROGRESS = "İndirme Çubuğu Görüntüleme:"
SETTING_SHOW_TRACKINFO = "Show Track Info"
SETTING_SAVE_ALBUMINFO = "Save AlbumInfo.txt"
SETTING_DOWNLOAD_VIDEOS = "Download videos"
SETTING_ADD_LYRICS = "Add lyrics"
SETTING_LYRICS_SERVER_PROXY = "Lyrics server proxy"
SETTING_ADD_LRC_FILE = "Save timed lyrics (.lrc file)"
SETTING_PATH = "Settings path"
SETTING_APIKEY = "APIKey support"
SETTING_ADD_TYPE_FOLDER = "Add Type-Folder"
SETTING_DOWNLOAD_DELAY = "Use Download Delay"
CHOICE = "Seçim"
FUNCTION = "İşlemler"
CHOICE_ENTER = "Enter"
CHOICE_ENTER_URLID = "'Url/ID' Gir:"
CHOICE_EXIT = "Çıkış"
CHOICE_LOGIN = "AccessToken kontrolü"
CHOICE_SETTINGS = "Ayarlar'ı Düzenle"
CHOICE_SET_ACCESS_TOKEN = "'AccessToken' Gir"
CHOICE_DOWNLOAD_BY_URL = "URL ya da ID ile indir"
CHOICE_LOGOUT = "Çıkış"
CHOICE_APIKEY = "Select APIKey"
PRINT_ERR = "[HATA OLUŞTU]"
PRINT_INFO = "[BİLGİ]"
PRINT_SUCCESS = "[İNDİRİLDİ]"
PRINT_ENTER_CHOICE = "Seçim Gir: "
PRINT_LATEST_VERSION = "Güncelleme Mevcut:"
# PRINT_USERNAME = "Kullanıcı Adı ya da Mail Adresi:"
# PRINT_PASSWORD = "Şifre:"
CHANGE_START_SETTINGS = ">>> Ayarları düzenlemek istediğine emin misin ? ('0'-Geri Dön,'1'-Evet): "
CHANGE_DOWNLOAD_PATH = ">>> İndirme Konumu ('0' aynı kalsın): "
CHANGE_AUDIO_QUALITY = ">>> Ses Kalitesi ('0'-Normal,'1'-Yüksek,'2'-HiFi,'3'-[M]aster,'4'-Max): "
CHANGE_VIDEO_QUALITY = ">>> Video Kalitesi (1080, 720, 480, 360): "
CHANGE_ONLYM4A = ">>> .mp4 uzantılı dosyalar .m4a'ya çevrilsin mi?('0'-Hayır,'1'-Evet): "
CHANGE_ADD_EXPLICIT_TAG = ">>> 'Explicit' yani 'küfürlü' etiketi eklensin mi?('0'-Hayır,'1'-Evet): "
CHANGE_ADD_HYPHEN = ">>> Şarkı dosyasının isminde boşluk yerine '-' eklensin mi ?('0'-Hayır,'1'-Evet): "
CHANGE_ADD_YEAR = ">>> Albüm klasörünün isminde yıl olsun mu ?('0'-Hayır,'1'-Evet): "
CHANGE_USE_TRACK_NUM = ">>> Şarkı dosyasının isminde albümdeki sırası yazsın mı ?('0'-Hayır,'1'-Evet): "
CHANGE_CHECK_EXIST = ">>> Dosya daha önce indirilmiş mi diye kontrol edilsin mi ?('0'-Hayır,'1'-Evet): "
CHANGE_ARTIST_BEFORE_TITLE = ">>> Şarkı dosyasının ismine sanatçının adı eklensin mi?('0'-Hayır,'1'-Evet): "
CHANGE_INCLUDE_EP = ">>> Artist'in tüm albümlerini indirirken Single'leri ve EP'leri de dahil edilsin mi ?('0'-Hayır,'1'-Evet): "
CHANGE_ALBUMID_BEFORE_FOLDER = ">>> Albüm klasörünün ismine ID eklensin mi ?('0'-Hayır,'1'-Evet): "
CHANGE_SAVE_COVERS = ">>> Albüm kapağı indirilsin mi?('0'-Hayır,'1'-Evet): "
CHANGE_LANGUAGE = ">>> Lisan Seç "
CHANGE_ALBUM_FOLDER_FORMAT = "Albüm Klasör İsmi Formatı('0' aynı kalsın):"
CHANGE_PLAYLIST_FOLDER_FORMAT = "Playlist folder format('0'-not modify,'default'-to set default):"
CHANGE_TRACK_FILE_FORMAT = "Dosya İsmi Formatı('0' aynı kalsın):"
CHANGE_VIDEO_FILE_FORMAT = "Video file format('0'-not modify,'default'-to set default):"
CHANGE_SHOW_PROGRESS = "İndirme Çubuğu Görüntülensin mi?('0'-Hayır,'1'-Evet):"
CHANGE_SHOW_TRACKINFO = "Show track info('0'-No,'1'-Yes):"
CHANGE_SAVE_ALBUM_INFO = "Save AlbumInfo.txt('0'-No,'1'-Yes):"
CHANGE_DOWNLOAD_VIDEOS = "Download videos (when downloading playlists, albums, mixes)('0'-No,'1'-Yes):"
CHANGE_ADD_LYRICS = "Add lyrics('0'-No,'1'-Yes):"
CHANGE_LYRICS_SERVER_PROXY = "Lyrics server proxy('0'-not modify):"
CHANGE_ADD_LRC_FILE = "Save timed lyrics .lrc file ('0'-No,'1'-Yes):"
CHANGE_ADD_TYPE_FOLDER = "Add Type-Folder,eg Album/Video/Playlist('0'-No,'1'-Yes):"
CHANGE_MULITHREAD_DOWNLOAD = "Multi thread download('0'-No,'1'-Yes):"
CHANGE_USE_DOWNLOAD_DELAY = "Use Download Delay('0'-No,'1'-Yes):"
# {} are required in these strings
AUTH_START_LOGIN = "Giriş işlemleri başlatıldı..."
AUTH_LOGIN_CODE = "Girmen gereken kod: {}"
AUTH_NEXT_STEP = "Bu siteden {} hesabınıza giriş yapınız ve üstteki kodu giriniz. ({} dakikanız var.)"
AUTH_WAITING = "İşlemleri tamamlamanız bekleniyor..."
AUTH_TIMEOUT = "Lütfen size verilen süre içerisinde işlemleriniz tamamlayınız."
MSG_VALID_ACCESSTOKEN = "AccessToken good for {}."
MSG_INVALID_ACCESSTOKEN = "Expired AccessToken. Attempting to refresh it."
MSG_PATH_ERR = "İndirme konumu ile alakalı bir sorun var! ('/storage/emulated/0/Download/' şeklinde girebilirsiniz.)"
MSG_INPUT_ERR = "Giriş Hatalı!"
MODEL_ALBUM_PROPERTY = "ALBÜM-BİLGİLERİ"
MODEL_TRACK_PROPERTY = "ŞARKI-BİLGİLERİ"
MODEL_VIDEO_PROPERTY = "VİDEO-BİLGİLERİ"
MODEL_ARTIST_PROPERTY = "ARTİST-BİLGİLERİ"
MODEL_PLAYLIST_PROPERTY = "OYNATMA LİSTESİ-BİLGİLERİ"
MODEL_TITLE = 'Şarkı/Albüm Adı:'
MODEL_TRACK_NUMBER = 'Şarkı Sayısı'
MODEL_VIDEO_NUMBER = 'Video Sayısı'
MODEL_RELEASE_DATE = 'Çıkış Yılı:'
MODEL_VERSION = 'Versiyon'
MODEL_EXPLICIT = 'Küfürlü'
MODEL_ALBUM = 'Albüm'
MODEL_ID = 'ID'
MODEL_NAME = 'İsim'
MODEL_TYPE = 'Türü'
+126
View File
@@ -0,0 +1,126 @@
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File : ukrainian.py
@Time : 2022/02/20
@Author : Montyzzz & 9uyone
@Version : 1.2
@Contact : ---
@Desc :
'''
class LangUkrainian(object):
SETTING = "НАЛАШТУВАННЯ"
VALUE = "ЗНАЧЕННЯ"
SETTING_DOWNLOAD_PATH = "Шлях завантаження"
SETTING_ONLY_M4A = "Перетворювати mp4 на m4a"
SETTING_ADD_EXPLICIT_TAG = "Додавати тег Нецензурно"
SETTING_ADD_HYPHEN = "Додавати дефіс"
SETTING_ADD_YEAR = "Додавати рік перед ім'ям папки альбому"
SETTING_USE_TRACK_NUM = "Додавати номер треку"
SETTING_AUDIO_QUALITY = "Якість аудіо"
SETTING_VIDEO_QUALITY = "Якість відео"
SETTING_CHECK_EXIST = "Перевіряти наявність"
SETTING_ARTIST_BEFORE_TITLE = "Виконавець перед назвою треку"
SETTING_ALBUMID_BEFORE_FOLDER = "ID перед назвою папки"
SETTING_INCLUDE_EP = "Включати сингли та міньйони (EP)"
SETTING_SAVE_COVERS = "Зберігати обкладинки"
SETTING_LANGUAGE = "Мова"
SETTING_USE_PLAYLIST_FOLDER = "Використовувати папку плейлиста"
SETTING_MULITHREAD_DOWNLOAD = "Багатопоточне завантаження"
SETTING_ALBUM_FOLDER_FORMAT = "Формат папки альбому"
SETTING_PLAYLIST_FOLDER_FORMAT = "Playlist folder format"
SETTING_TRACK_FILE_FORMAT = "Формат файлу треку"
SETTING_VIDEO_FILE_FORMAT = "Video file format"
SETTING_SHOW_PROGRESS = "Показувати прогрес"
SETTING_SHOW_TRACKINFO = "Показувати інформацію про трек"
SETTING_SAVE_ALBUMINFO = "Зберігати AlbumInfo.txt"
SETTING_DOWNLOAD_VIDEOS = "Download videos"
SETTING_ADD_LYRICS = "Додавати тексти пісень"
SETTING_LYRICS_SERVER_PROXY = "Проксі для сервера з текстами пісень"
SETTING_ADD_LRC_FILE = "Зберігати тексти з відмітками часу (.lrc файл)"
SETTING_PATH = "Шлях налаштувань"
SETTING_APIKEY = "Підтримка ключа API"
SETTING_ADD_TYPE_FOLDER = "Додавати папку-тип"
SETTING_DOWNLOAD_DELAY = "Use Download Delay"
CHOICE = "ВИБІР"
FUNCTION = "ФУНКЦІЇ"
CHOICE_ENTER = "Ввід"
CHOICE_ENTER_URLID = "Ввід 'URL/ID':"
CHOICE_EXIT = "Вихід"
CHOICE_LOGIN = "Перевірити AccessToken"
CHOICE_SETTINGS = "Налаштування"
CHOICE_SET_ACCESS_TOKEN = "Застосувати власний AccessToken"
CHOICE_DOWNLOAD_BY_URL = "Завантажити за URL-адресою або ідентифікатором"
CHOICE_LOGOUT = "Деавторизація"
CHOICE_APIKEY = "Вибрати ключ API"
PRINT_ERR = "[ПОМИЛКА]"
PRINT_INFO = "[ІНФОРМАЦІЯ]"
PRINT_SUCCESS = "[УСПІХ]"
PRINT_ENTER_CHOICE = "Вибір вводу:"
PRINT_LATEST_VERSION = "Остання версія:"
# PRINT_USERNAME = "ім'я користувача:"
# PRINT_PASSWORD = "пароль:"
CHANGE_START_SETTINGS = "Запуск налаштувань('0'-Повернутися,'1'-Так):"
CHANGE_DOWNLOAD_PATH = "Шлях завантаження('0'-не змінювати):"
CHANGE_AUDIO_QUALITY = "Якість аудіо('0'-Звичайна,'1'-Висока,'2'-HiFi,'3'-MQA,'4'-Max):"
CHANGE_VIDEO_QUALITY = "Якість відео(1080,720,480,360):"
CHANGE_ONLYM4A = "Перетворювати mp4 на m4a('0'-Ні,'1'-Так):"
CHANGE_ADD_EXPLICIT_TAG = "Додавати тег 'Нецензурно'('0'-Ні,'1'-Так):"
CHANGE_ADD_HYPHEN = "Використати дефіс замість пробілів в іменах файлів('0'-Ні,'1'-Так):"
CHANGE_ADD_YEAR = "Додавати рік до назв тек альбомів('0'-Ні,'1'-Так):"
CHANGE_USE_TRACK_NUM = "Додавати номер доріжки перед назвами файлів('0'-Ні,'1'-Так):"
CHANGE_CHECK_EXIST = "Перевіряти наявний файл перед завантаженням треку('0'-Ні,'1'-Так):"
CHANGE_ARTIST_BEFORE_TITLE = "Додати ім’я виконавця перед заголовком треку('0'-Ні,'1'-Так):"
CHANGE_INCLUDE_EP = "Включати сингли та міньйони під час завантаження альбомів виконавця('0'-Ні,'1'-Так):"
CHANGE_ALBUMID_BEFORE_FOLDER = "Додати ідентифікатор перед текою альбому('0'-Ні,'1'-Так):"
CHANGE_SAVE_COVERS = "Зберігати обкладинки('0'-Ні,'1'-Так):"
CHANGE_LANGUAGE = "Обрати мову"
CHANGE_ALBUM_FOLDER_FORMAT = "Формат теки альбому('0'-не змінювати):"
CHANGE_PLAYLIST_FOLDER_FORMAT = "Playlist folder format('0'-not modify,'default'-to set default):"
CHANGE_TRACK_FILE_FORMAT = "Формат файлу треку('0'-не змінювати):"
CHANGE_VIDEO_FILE_FORMAT = "Video file format('0'-not modify,'default'-to set default):"
CHANGE_SHOW_PROGRESS = "Показувати прогрес('0'-Ні,'1'-Так):"
CHANGE_SHOW_TRACKINFO = "Показувати інформацію про трек('0'-Ні,'1'-Так):"
CHANGE_SAVE_ALBUM_INFO = "Зберігати AlbumInfo.txt('0'-Ні,'1'-Так):"
CHANGE_DOWNLOAD_VIDEOS = "Download videos (when downloading playlists, albums, mixes)('0'-No,'1'-Yes):"
CHANGE_ADD_LYRICS = "Додавати тексти пісень('0'-Ні,'1'-Так):"
CHANGE_LYRICS_SERVER_PROXY = "Проксі для сервера з текстами пісень('0'-не змінювати):"
CHANGE_ADD_LRC_FILE = "Зберігати тексти пісень з відмітками часу в .lrc файл('0'-Ні,'1'-Так):"
CHANGE_ADD_TYPE_FOLDER = "Додавати теку-тип,наприклад Альбом/Відео/Плейлист('0'-Ні,'1'-Так):"
CHANGE_MULITHREAD_DOWNLOAD = "Multi thread download('0'-No,'1'-Yes):"
CHANGE_USE_DOWNLOAD_DELAY = "Use Download Delay('0'-No,'1'-Yes):"
# {} are required in these strings
AUTH_START_LOGIN = "Початок процесу авторизації..."
AUTH_LOGIN_CODE = "Ваш логін-код: {}"
AUTH_NEXT_STEP = "Зайдіть на {} протягом наступних {} для завершення налаштування."
AUTH_WAITING = "Очікування авторизації..."
AUTH_TIMEOUT = "Час очікування минув."
MSG_VALID_ACCESSTOKEN = "AccessToken хороший упродовж {}."
MSG_INVALID_ACCESSTOKEN = "Термін дії AccessToken'а закінчився. Пробуємо оновити його."
MSG_PATH_ERR = "Невірний шлях!"
MSG_INPUT_ERR = "Помилка введення!"
MODEL_ALBUM_PROPERTY = "АЛЬБОМ-ВЛАСТИВІСТЬ"
MODEL_TRACK_PROPERTY = "ТРЕК-ВЛАСТИВІСТЬ"
MODEL_VIDEO_PROPERTY = "ВІДЕО-ВЛАСТИВІСТЬ"
MODEL_ARTIST_PROPERTY = "АРТИСТ-ВЛАСТИВІСТЬ"
MODEL_PLAYLIST_PROPERTY = "ПЛЕЙЛИСТ-ВЛАСТИВІСТЬ"
MODEL_TITLE = 'Назва'
MODEL_TRACK_NUMBER = 'Номер доріжки'
MODEL_VIDEO_NUMBER = 'Номер відео'
MODEL_RELEASE_DATE = 'Дата релізу'
MODEL_VERSION = 'Версія'
MODEL_EXPLICIT = 'Нецензурно'
MODEL_ALBUM = 'Альбом'
MODEL_ID = 'ID'
MODEL_NAME = 'Ім\'я'
MODEL_TYPE = 'Тип'
+126
View File
@@ -0,0 +1,126 @@
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File : vietnamese.py
@Time : 2022/2/9
@Author : MinhNgo, CDzungx
@Version : 1.0
@Contact : iam.minhnc@outlook.com
@Desc :
'''
class LangVietnamese(object):
SETTING = "THIẾT LẬP"
VALUE = "GIÁ TRỊ"
SETTING_DOWNLOAD_PATH = "Đường dẫn tải về"
SETTING_ONLY_M4A = "Đổi mp4 sang m4a"
SETTING_ADD_EXPLICIT_TAG = "Thêm tag explicit"
SETTING_ADD_HYPHEN = "Thêm dấu nối"
SETTING_ADD_YEAR = "Thêm năm trước thư mục album"
SETTING_USE_TRACK_NUM = "Thêm số thứ tự bài"
SETTING_AUDIO_QUALITY = "Chất lượng âm thanh"
SETTING_VIDEO_QUALITY = "Chất lượng video"
SETTING_CHECK_EXIST = "Kiểm tra tồn tại"
SETTING_ARTIST_BEFORE_TITLE = "Tên nghệ sĩ phía trước tựa bài hát"
SETTING_ALBUMID_BEFORE_FOLDER = "Id trước thư mục album"
SETTING_INCLUDE_EP = "Bao gồm đĩa đơn & ep"
SETTING_SAVE_COVERS = "Tải ảnh bìa"
SETTING_LANGUAGE = "Ngôn ngữ"
SETTING_USE_PLAYLIST_FOLDER = "Thư mục cho danh sách phát"
SETTING_MULITHREAD_DOWNLOAD = "Tải về đa luồng"
SETTING_ALBUM_FOLDER_FORMAT = "Định dạng thư mục album"
SETTING_PLAYLIST_FOLDER_FORMAT = "Playlist folder format"
SETTING_TRACK_FILE_FORMAT = "Định dạng tên tệp nhạc"
SETTING_VIDEO_FILE_FORMAT = "Video file format"
SETTING_SHOW_PROGRESS = "Hiện tiến trình"
SETTING_SHOW_TRACKINFO = "Hiện thông tin bài"
SETTING_SAVE_ALBUMINFO = "Lưu AlbumInfo.txt"
SETTING_DOWNLOAD_VIDEOS = "Download videos"
SETTING_ADD_LYRICS = "Thêm lời bài hát"
SETTING_LYRICS_SERVER_PROXY = "Máy chủ proxy cho lyrics"
SETTING_ADD_LRC_FILE = "Lưu timed lyrics (tệp .lrc)"
SETTING_PATH = "Đường dẫn cài đặt"
SETTING_APIKEY = "Hỗ trợ APIKey"
SETTING_ADD_TYPE_FOLDER = "Thêm Loại-Thư mục"
SETTING_DOWNLOAD_DELAY = "Use Download Delay"
CHOICE = "LỰA CHỌN"
FUNCTION = "CHỨC NĂNG"
CHOICE_ENTER = "Nhập"
CHOICE_ENTER_URLID = "Nhập 'Url/ID':"
CHOICE_EXIT = "Thoát"
CHOICE_LOGIN = "Kiểm tra AccessToken"
CHOICE_SETTINGS = "Thiết lập"
CHOICE_SET_ACCESS_TOKEN = "Nhập AccessToken"
CHOICE_DOWNLOAD_BY_URL = "Tải về qua url hoặc id"
CHOICE_LOGOUT = "Đăng xuất"
CHOICE_APIKEY = "Chọn APIKey"
PRINT_ERR = "[LỖI]"
PRINT_INFO = "[THÔNG TIN]"
PRINT_SUCCESS = "[XONG]"
PRINT_ENTER_CHOICE = "Nhập lựa chọn:"
PRINT_LATEST_VERSION = "Bản mới nhất:"
# PRINT_USERNAME = "tên đăng nhập:"
# PRINT_PASSWORD = "mật khẩu:"
CHANGE_START_SETTINGS = "Bắt đầu thiết lập('0'-Về,'1'-Có):"
CHANGE_DOWNLOAD_PATH = "Đường dẫn tải về('0' không đổi):"
CHANGE_AUDIO_QUALITY = "Chất lượng âm thanh('0'-Normal,'1'-High,'2'-HiFi,'3'-Master,'4'-Max):"
CHANGE_VIDEO_QUALITY = "Chất lượng video(1080, 720, 480, 360):"
CHANGE_ONLYM4A = "Đổi mp4 sang m4a('0'-Không,'1'-Có):"
CHANGE_ADD_EXPLICIT_TAG = "Thêm tag explicit vào tên tệp('0'-Không,'1'-Có):"
CHANGE_ADD_HYPHEN = "Dùng gạch nối thay vì dấu cách trong tên tệp('0'-Không,'1'-Có):"
CHANGE_ADD_YEAR = "Thêm năm phía trước tên thư mục album('0'-Không,'1'-Có):"
CHANGE_USE_TRACK_NUM = "Thêm số thứ tự bài ở đầu tên tệp('0'-Không,'1'-Có):"
CHANGE_CHECK_EXIST = "Kiểm tra tệp đã tồn tại chưa trước khi tải('0'-Không,'1'-Có):"
CHANGE_ARTIST_BEFORE_TITLE = "Thêm tên nghệ sĩ trước tựa đề('0'-Không,'1'-Có):"
CHANGE_INCLUDE_EP = "Bao gồm đĩa đơn và EPs khi tải tất cả nhạc của nghệ sĩ('0'-Không,'1'-Có):"
CHANGE_ALBUMID_BEFORE_FOLDER = "Thêm id phía trước tên thư mục album('0'-Không,'1'-Có):"
CHANGE_SAVE_COVERS = "Tải ảnh bìa('0'-Không,'1'-Có):"
CHANGE_LANGUAGE = "Chọn ngôn ngữ"
CHANGE_ALBUM_FOLDER_FORMAT = "Định dạng thư mục album('0' không đổi,'default' để đặt về mặc định):"
CHANGE_PLAYLIST_FOLDER_FORMAT = "Playlist folder format('0'-not modify,'default'-to set default):"
CHANGE_TRACK_FILE_FORMAT = "Định dạng tên tệp nhạc('0' không đổi,'default' để đặt về mặc định):"
CHANGE_VIDEO_FILE_FORMAT = "Video file format('0'-not modify,'default'-to set default):"
CHANGE_SHOW_PROGRESS = "Hiện tiến trình('0'-Không,'1'-Có):"
CHANGE_SHOW_TRACKINFO = "Hiện thông tin bài('0'-Không,'1'-Có):"
CHANGE_SAVE_ALBUM_INFO = "Lưu AlbumInfo.txt('0'-Không,'1'-Có):"
CHANGE_DOWNLOAD_VIDEOS = "Download videos (when downloading playlists, albums, mixes)('0'-No,'1'-Yes):"
CHANGE_ADD_LYRICS = "Thêm lời bài hát('0'-Không,'1'-Có):"
CHANGE_LYRICS_SERVER_PROXY = "Máy chủ proxy cho lyrics('0' không đổi):"
CHANGE_ADD_LRC_FILE = "Lưu timed lyrics tệp .lrc ('0'-Không,'1'-Có):"
CHANGE_ADD_TYPE_FOLDER = "Thêm Loại-Thư mục, ví dụ Album/Video/Playlist('0'-Không,'1'-Có):"
CHANGE_MULITHREAD_DOWNLOAD = "Multi thread download('0'-No,'1'-Yes):"
CHANGE_USE_DOWNLOAD_DELAY = "Use Download Delay('0'-No,'1'-Yes):"
# {} are required in these strings
AUTH_START_LOGIN = "Đang bắt đầu đăng nhập..."
AUTH_LOGIN_CODE = "Mã đăng nhập của bạn là {}"
AUTH_NEXT_STEP = "Vào trang {} trong vòng {} để hoàn tất thiết lập."
AUTH_WAITING = "Đang chờ xác minh..."
AUTH_TIMEOUT = "Đã vượt quá thời gian chờ."
MSG_VALID_ACCESSTOKEN = "AccessToken vẫn tốt trong {}."
MSG_INVALID_ACCESSTOKEN = "AccessToken hết hạn. Đang cố làm mới."
MSG_PATH_ERR = "Lỗi đường dẫn!"
MSG_INPUT_ERR = "Lỗi nhập!"
MODEL_ALBUM_PROPERTY = "THÔNG-TIN-ALBUM"
MODEL_TRACK_PROPERTY = "THÔNG-TIN-BÀI"
MODEL_VIDEO_PROPERTY = "THÔNG-TIN-VIDEO"
MODEL_ARTIST_PROPERTY = "THÔNG-TIN-NGHỆ-SĨ"
MODEL_PLAYLIST_PROPERTY = "THÔNG-TIN-DANH-SÁCH-PHÁT"
MODEL_TITLE = 'Tựa Đề'
MODEL_TRACK_NUMBER = 'Số Bài'
MODEL_VIDEO_NUMBER = 'Số Video'
MODEL_RELEASE_DATE = 'Ngày Phát Hành'
MODEL_VERSION = 'Phiên Bản'
MODEL_EXPLICIT = 'Explicit'
MODEL_ALBUM = 'Album'
MODEL_ID = 'ID'
MODEL_NAME = 'Tên'
MODEL_TYPE = 'Loại'
+208
View File
@@ -0,0 +1,208 @@
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File : model.py
@Time : 2020/08/08
@Author : Yaronzz
@Version : 3.0
@Contact : yaronhuang@foxmail.com
@Desc :
'''
import aigpy
class StreamUrl(aigpy.model.ModelBase):
def __init__(self) -> None:
super().__init__()
self.trackid = None
self.url = None
self.urls = None
self.codec = None
self.encryptionKey = None
self.soundQuality = None
class VideoStreamUrl(aigpy.model.ModelBase):
def __init__(self) -> None:
super().__init__()
self.codec = None
self.resolution = None
self.resolutions = None
self.m3u8Url = None
class Artist(aigpy.model.ModelBase):
def __init__(self) -> None:
super().__init__()
self.id = None
self.name = None
self.type = None
self.picture = None
class Album(aigpy.model.ModelBase):
def __init__(self) -> None:
super().__init__()
self.id = None
self.title = None
self.duration = 0
self.numberOfTracks = 0
self.numberOfVideos = 0
self.numberOfVolumes = 0
self.releaseDate = None
self.type = None
self.version = None
self.cover = None
self.explicit = False
self.audioQuality = None
self.audioModes = None
self.artist = Artist()
self.artists = Artist()
class Playlist(aigpy.model.ModelBase):
def __init__(self) -> None:
super().__init__()
self.uuid = None
self.title = None
self.numberOfTracks = 0
self.numberOfVideos = 0
self.description = None
self.duration = 0
self.image = None
self.squareImage = None
class Track(aigpy.model.ModelBase):
def __init__(self) -> None:
super().__init__()
self.id = None
self.title = None
self.duration = 0
self.trackNumber = 0
self.volumeNumber = 0
self.trackNumberOnPlaylist = 0
self.version = None
self.isrc = None
self.explicit = False
self.audioQuality = None
self.copyRight = None
self.artist = Artist()
self.artists = Artist()
self.album = Album()
self.allowStreaming = False
self.playlist = None
class Video(aigpy.model.ModelBase):
def __init__(self) -> None:
super().__init__()
self.id = None
self.title = None
self.duration = 0
self.imageID = None
self.trackNumber = 0
self.releaseDate = None
self.version = None
self.quality = None
self.explicit = False
self.artist = Artist()
self.artists = Artist()
self.album = Album()
self.allowStreaming = False
self.playlist = None
class Mix(aigpy.model.ModelBase):
def __init__(self) -> None:
super().__init__()
self.id = None
self.tracks = Track()
self.videos = Video()
class Lyrics(aigpy.model.ModelBase):
def __init__(self) -> None:
super().__init__()
self.trackId = None
self.lyricsProvider = None
self.providerCommontrackId = None
self.providerLyricsId = None
self.lyrics = None
self.subtitles = None
class SearchDataBase(aigpy.model.ModelBase):
def __init__(self) -> None:
super().__init__()
self.limit = 0
self.offset = 0
self.totalNumberOfItems = 0
class SearchAlbums(SearchDataBase):
def __init__(self) -> None:
super().__init__()
self.items = Album()
class SearchArtists(SearchDataBase):
def __init__(self) -> None:
super().__init__()
self.items = Artist()
class SearchTracks(SearchDataBase):
def __init__(self) -> None:
super().__init__()
self.items = Track()
class SearchVideos(SearchDataBase):
def __init__(self) -> None:
super().__init__()
self.items = Video()
class SearchPlaylists(SearchDataBase):
def __init__(self) -> None:
super().__init__()
self.items = Playlist()
class SearchResult(aigpy.model.ModelBase):
def __init__(self) -> None:
super().__init__()
self.artists = SearchArtists()
self.albums = SearchAlbums()
self.tracks = SearchTracks()
self.videos = SearchVideos()
self.playlists = SearchPlaylists()
class LoginKey(aigpy.model.ModelBase):
def __init__(self) -> None:
super().__init__()
self.deviceCode = None
self.userCode = None
self.verificationUrl = None
self.authCheckTimeout = None
self.authCheckInterval = None
self.userId = None
self.countryCode = None
self.accessToken = None
self.refreshToken = None
self.expiresIn = None
class StreamRespond(aigpy.model.ModelBase):
def __init__(self) -> None:
super().__init__()
self.trackid = None
self.videoid = None
self.streamType = None
self.assetPresentation = None
self.audioMode = None
self.audioQuality = None
self.videoQuality = None
self.manifestMimeType = None
self.manifest = None
+199
View File
@@ -0,0 +1,199 @@
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
"""
@File : paths.py
@Date : 2022/06/10
@Author : Yaronzz
@Version : 1.0
@Contact : yaronhuang@foxmail.com
@Desc :
"""
import os
import aigpy
import datetime
from tidal import *
from settings import *
def __fixPath__(name: str):
return aigpy.path.replaceLimitChar(name, '-').strip()
def __getYear__(releaseDate: str):
if releaseDate is None or releaseDate == '':
return ''
return aigpy.string.getSubOnlyEnd(releaseDate, '-')
def __getDurationStr__(seconds):
time_string = str(datetime.timedelta(seconds=seconds))
if time_string.startswith('0:'):
time_string = time_string[2:]
return time_string
def __getExtension__(stream: StreamUrl):
if '.flac' in stream.url:
return '.flac'
if '.mp4' in stream.url:
if 'ac4' in stream.codec or 'mha1' in stream.codec:
return '.mp4'
elif 'flac' in stream.codec:
return '.flac'
return '.m4a'
return '.m4a'
def getAlbumPath(album):
artistName = __fixPath__(TIDAL_API.getArtistsName(album.artists))
albumArtistName = __fixPath__(album.artist.name) if album.artist is not None else ""
# album folder pre: [ME]
flag = TIDAL_API.getFlag(album, Type.Album, True, "")
if SETTINGS.audioQuality != AudioQuality.Master and SETTINGS.audioQuality != AudioQuality.Max:
flag = flag.replace("M", "")
if flag != "":
flag = "[" + flag + "] "
# album and addyear
albumName = __fixPath__(album.title)
year = __getYear__(album.releaseDate)
# retpath
retpath = SETTINGS.albumFolderFormat
if retpath is None or len(retpath) <= 0:
retpath = SETTINGS.getDefaultAlbumFolderFormat()
retpath = retpath.replace(R"{ArtistName}", artistName)
retpath = retpath.replace(R"{AlbumArtistName}", albumArtistName)
retpath = retpath.replace(R"{Flag}", flag)
retpath = retpath.replace(R"{AlbumID}", str(album.id))
retpath = retpath.replace(R"{AlbumYear}", year)
retpath = retpath.replace(R"{AlbumTitle}", albumName)
retpath = retpath.replace(R"{AudioQuality}", album.audioQuality)
retpath = retpath.replace(R"{DurationSeconds}", str(album.duration))
retpath = retpath.replace(R"{Duration}", __getDurationStr__(album.duration))
retpath = retpath.replace(R"{NumberOfTracks}", str(album.numberOfTracks))
retpath = retpath.replace(R"{NumberOfVideos}", str(album.numberOfVideos))
retpath = retpath.replace(R"{NumberOfVolumes}", str(album.numberOfVolumes))
retpath = retpath.replace(R"{ReleaseDate}", str(album.releaseDate))
retpath = retpath.replace(R"{RecordType}", album.type)
retpath = retpath.replace(R"{None}", "")
retpath = retpath.strip()
return f"{SETTINGS.downloadPath}/{retpath}"
def getPlaylistPath(playlist):
playlistName = __fixPath__(playlist.title)
# retpath
retpath = SETTINGS.playlistFolderFormat
if retpath is None or len(retpath) <= 0:
retpath = SETTINGS.getDefaultPlaylistFolderFormat()
retpath = retpath.replace(R"{PlaylistUUID}", str(playlist.uuid))
retpath = retpath.replace(R"{PlaylistName}", playlistName)
return f"{SETTINGS.downloadPath}/{retpath}"
def getTrackPath(track, stream, album=None, playlist=None):
base = './'
number = str(track.trackNumber).rjust(2, '0')
if album is not None:
base = getAlbumPath(album)
if album.numberOfVolumes > 1:
base += f'/CD{str(track.volumeNumber)}'
if playlist is not None and SETTINGS.usePlaylistFolder:
base = getPlaylistPath(playlist)
number = str(track.trackNumberOnPlaylist).rjust(2, '0')
# artist
artists = __fixPath__(TIDAL_API.getArtistsName(track.artists))
artist = __fixPath__(track.artist.name) if track.artist is not None else ""
# title
title = __fixPath__(track.title)
if not aigpy.string.isNull(track.version):
title += f' ({__fixPath__(track.version)})'
# explicit
explicit = "(Explicit)" if track.explicit else ''
# album and addyear
albumName = __fixPath__(album.title) if album is not None else ''
year = __getYear__(album.releaseDate) if album is not None else ''
# extension
extension = __getExtension__(stream)
retpath = SETTINGS.trackFileFormat
if retpath is None or len(retpath) <= 0:
retpath = SETTINGS.getDefaultTrackFileFormat()
retpath = retpath.replace(R"{TrackNumber}", number)
retpath = retpath.replace(R"{ArtistName}", artist)
retpath = retpath.replace(R"{ArtistsName}", artists)
retpath = retpath.replace(R"{TrackTitle}", title)
retpath = retpath.replace(R"{ExplicitFlag}", explicit)
retpath = retpath.replace(R"{AlbumYear}", year)
retpath = retpath.replace(R"{AlbumTitle}", albumName)
retpath = retpath.replace(R"{AudioQuality}", track.audioQuality)
retpath = retpath.replace(R"{DurationSeconds}", str(track.duration))
retpath = retpath.replace(R"{Duration}", __getDurationStr__(track.duration))
retpath = retpath.replace(R"{TrackID}", str(track.id))
retpath = retpath.strip()
return f"{base}/{retpath}{extension}"
def getVideoPath(video, album=None, playlist=None):
base = SETTINGS.downloadPath + '/Video/'
if album is not None and album.title is not None:
base = getAlbumPath(album)
elif playlist is not None:
base = getPlaylistPath(playlist)
# get number
number = str(video.trackNumber).rjust(2, '0')
# get artist
artists = __fixPath__(TIDAL_API.getArtistsName(video.artists))
artist = __fixPath__(video.artist.name) if video.artist is not None else ""
# explicit
explicit = "(Explicit)" if video.explicit else ''
# title and year and extension
title = __fixPath__(video.title)
year = __getYear__(video.releaseDate)
extension = ".mp4"
retpath = SETTINGS.videoFileFormat
if retpath is None or len(retpath) <= 0:
retpath = SETTINGS.getDefaultVideoFileFormat()
retpath = retpath.replace(R"{VideoNumber}", number)
retpath = retpath.replace(R"{ArtistName}", artist)
retpath = retpath.replace(R"{ArtistsName}", artists)
retpath = retpath.replace(R"{VideoTitle}", title)
retpath = retpath.replace(R"{ExplicitFlag}", explicit)
retpath = retpath.replace(R"{VideoYear}", year)
retpath = retpath.replace(R"{VideoID}", str(video.id))
retpath = retpath.strip()
return f"{base}/{retpath}{extension}"
def __getHomePath__():
if "XDG_CONFIG_HOME" in os.environ:
return os.environ['XDG_CONFIG_HOME']
elif "HOME" in os.environ:
return os.environ['HOME']
elif "HOMEDRIVE" in os.environ and "HOMEPATH" in os.environ:
return os.environ['HOMEDRIVE'] + os.environ['HOMEPATH']
else:
return os.path.abspath("./")
def getLogPath():
return __getHomePath__() + '/.tidal-dl.log'
def getTokenPath():
return __getHomePath__() + '/.tidal-dl.token.json'
def getProfilePath():
return __getHomePath__() + '/.tidal-dl.json'
+309
View File
@@ -0,0 +1,309 @@
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File : printf.py
@Time : 2020/08/16
@Author : Yaronzz
@Version : 3.0
@Contact : yaronhuang@foxmail.com
@Desc :
'''
from pickle import GLOBAL
import threading
import aigpy
import logging
import prettytable
import apiKey as apiKey
from model import *
from paths import *
from settings import *
from lang.language import *
VERSION = '2022.10.31.1'
__LOGO__ = f'''
/$$$$$$$$ /$$ /$$ /$$ /$$ /$$
|__ $$__/|__/ | $$ | $$ | $$| $$
| $$ /$$ /$$$$$$$ /$$$$$$ | $$ /$$$$$$$| $$
| $$ | $$ /$$__ $$ |____ $$| $$ /$$$$$$ /$$__ $$| $$
| $$ | $$| $$ | $$ /$$$$$$$| $$|______/| $$ | $$| $$
| $$ | $$| $$ | $$ /$$__ $$| $$ | $$ | $$| $$
| $$ | $$| $$$$$$$| $$$$$$$| $$ | $$$$$$$| $$
|__/ |__/ \_______/ \_______/|__/ \_______/|__/
https://github.com/yaronzz/Tidal-Media-Downloader
{VERSION}
'''
print_mutex = threading.Lock()
class Printf(object):
@staticmethod
def logo():
print(__LOGO__)
logging.info(__LOGO__)
@staticmethod
def __gettable__(columns, rows):
tb = prettytable.PrettyTable()
tb.field_names = list(aigpy.cmd.green(item) for item in columns)
tb.align = 'l'
for item in rows:
tb.add_row(item)
return tb
@staticmethod
def usage():
print("=============TIDAL-DL HELP==============")
tb = Printf.__gettable__(["OPTION", "DESC"], [
["-h or --help", "show help-message"],
["-v or --version", "show version"],
["-g or --gui", "show simple-gui"],
["-o or --output", "download path"],
["-l or --link", "url/id/filePath"],
["-q or --quality", "track quality('Normal','High,'HiFi','Master')"],
["-r or --resolution", "video resolution('P1080', 'P720', 'P480', 'P360')"]
])
print(tb)
@staticmethod
def checkVersion():
onlineVer = aigpy.pip.getLastVersion('tidal-dl')
if onlineVer is not None:
icmp = aigpy.system.cmpVersion(onlineVer, VERSION)
if icmp > 0:
Printf.info(LANG.select.PRINT_LATEST_VERSION + ' ' + onlineVer)
@staticmethod
def settings():
data = SETTINGS
tb = Printf.__gettable__([LANG.select.SETTING, LANG.select.VALUE], [
#settings - path and format
[LANG.select.SETTING_PATH, getProfilePath()],
[LANG.select.SETTING_DOWNLOAD_PATH, data.downloadPath],
[LANG.select.SETTING_ALBUM_FOLDER_FORMAT, data.albumFolderFormat],
[LANG.select.SETTING_PLAYLIST_FOLDER_FORMAT, data.playlistFolderFormat],
[LANG.select.SETTING_TRACK_FILE_FORMAT, data.trackFileFormat],
[LANG.select.SETTING_VIDEO_FILE_FORMAT, data.videoFileFormat],
#settings - quality
[LANG.select.SETTING_AUDIO_QUALITY, data.audioQuality],
[LANG.select.SETTING_VIDEO_QUALITY, data.videoQuality],
#settings - else
[LANG.select.SETTING_USE_PLAYLIST_FOLDER, data.usePlaylistFolder],
[LANG.select.SETTING_CHECK_EXIST, data.checkExist],
[LANG.select.SETTING_SHOW_PROGRESS, data.showProgress],
[LANG.select.SETTING_SHOW_TRACKINFO, data.showTrackInfo],
[LANG.select.SETTING_SAVE_ALBUMINFO, data.saveAlbumInfo],
[LANG.select.SETTING_DOWNLOAD_VIDEOS, data.downloadVideos],
[LANG.select.SETTING_SAVE_COVERS, data.saveCovers],
[LANG.select.SETTING_INCLUDE_EP, data.includeEP],
[LANG.select.SETTING_LANGUAGE, LANG.getLangName(data.language)],
[LANG.select.SETTING_ADD_LRC_FILE, data.lyricFile],
[LANG.select.SETTING_MULITHREAD_DOWNLOAD, data.multiThread],
[LANG.select.SETTING_APIKEY, f"[{data.apiKeyIndex}]" + apiKey.getItem(data.apiKeyIndex)['formats']],
[LANG.select.SETTING_DOWNLOAD_DELAY, data.downloadDelay],
])
print(tb)
@staticmethod
def choices():
print("====================================================")
tb = Printf.__gettable__([LANG.select.CHOICE, LANG.select.FUNCTION], [
[aigpy.cmd.green(LANG.select.CHOICE_ENTER + " '0':"), LANG.select.CHOICE_EXIT],
[aigpy.cmd.green(LANG.select.CHOICE_ENTER + " '1':"), LANG.select.CHOICE_LOGIN],
[aigpy.cmd.green(LANG.select.CHOICE_ENTER + " '2':"), LANG.select.CHOICE_LOGOUT],
[aigpy.cmd.green(LANG.select.CHOICE_ENTER + " '3':"), LANG.select.CHOICE_SET_ACCESS_TOKEN],
[aigpy.cmd.green(LANG.select.CHOICE_ENTER + " '4':"), LANG.select.CHOICE_SETTINGS + '-Path'],
[aigpy.cmd.green(LANG.select.CHOICE_ENTER + " '5':"), LANG.select.CHOICE_SETTINGS + '-Quality'],
[aigpy.cmd.green(LANG.select.CHOICE_ENTER + " '6':"), LANG.select.CHOICE_SETTINGS + '-Else'],
[aigpy.cmd.green(LANG.select.CHOICE_ENTER + " '7':"), LANG.select.CHOICE_APIKEY],
[aigpy.cmd.green(LANG.select.CHOICE_ENTER_URLID), LANG.select.CHOICE_DOWNLOAD_BY_URL],
])
tb.set_style(prettytable.PLAIN_COLUMNS)
print(tb)
print("====================================================")
@staticmethod
def enter(string):
aigpy.cmd.colorPrint(string, aigpy.cmd.TextColor.Yellow, None)
ret = input("")
return ret
@staticmethod
def enterBool(string):
aigpy.cmd.colorPrint(string, aigpy.cmd.TextColor.Yellow, None)
ret = input("")
return ret == '1'
@staticmethod
def enterPath(string, errmsg, retWord='0', default=""):
while True:
ret = aigpy.cmd.inputPath(aigpy.cmd.yellow(string), retWord)
if ret == retWord:
return default
elif ret == "":
print(aigpy.cmd.red(LANG.select.PRINT_ERR + " ") + errmsg)
else:
break
return ret
@staticmethod
def enterLimit(string, errmsg, limit=[]):
while True:
ret = aigpy.cmd.inputLimit(aigpy.cmd.yellow(string), limit)
if ret is None:
print(aigpy.cmd.red(LANG.select.PRINT_ERR + " ") + errmsg)
else:
break
return ret
@staticmethod
def enterFormat(string, current, default):
ret = Printf.enter(string)
if ret == '0' or aigpy.string.isNull(ret):
return current
if ret.lower() == 'default':
return default
return ret
@staticmethod
def err(string):
global print_mutex
print_mutex.acquire()
print(aigpy.cmd.red(LANG.select.PRINT_ERR + " ") + string)
# logging.error(string)
print_mutex.release()
@staticmethod
def info(string):
global print_mutex
print_mutex.acquire()
print(aigpy.cmd.blue(LANG.select.PRINT_INFO + " ") + string)
print_mutex.release()
@staticmethod
def success(string):
global print_mutex
print_mutex.acquire()
print(aigpy.cmd.green(LANG.select.PRINT_SUCCESS + " ") + string)
print_mutex.release()
@staticmethod
def album(data: Album):
tb = Printf.__gettable__([LANG.select.MODEL_ALBUM_PROPERTY, LANG.select.VALUE], [
[LANG.select.MODEL_TITLE, data.title],
["ID", data.id],
[LANG.select.MODEL_TRACK_NUMBER, data.numberOfTracks],
[LANG.select.MODEL_VIDEO_NUMBER, data.numberOfVideos],
[LANG.select.MODEL_RELEASE_DATE, data.releaseDate],
[LANG.select.MODEL_VERSION, data.version],
[LANG.select.MODEL_EXPLICIT, data.explicit],
])
print(tb)
logging.info("====album " + str(data.id) + "====\n" +
"title:" + data.title + "\n" +
"track num:" + str(data.numberOfTracks) + "\n" +
"video num:" + str(data.numberOfVideos) + "\n" +
"==================================")
@staticmethod
def track(data: Track, stream: StreamUrl = None):
tb = Printf.__gettable__([LANG.select.MODEL_TRACK_PROPERTY, LANG.select.VALUE], [
[LANG.select.MODEL_TITLE, data.title],
["ID", data.id],
[LANG.select.MODEL_ALBUM, data.album.title],
[LANG.select.MODEL_VERSION, data.version],
[LANG.select.MODEL_EXPLICIT, data.explicit],
["Max-Q", data.audioQuality],
])
if stream is not None:
tb.add_row(["Get-Q", str(stream.soundQuality)])
tb.add_row(["Get-Codec", str(stream.codec)])
print(tb)
logging.info("====track " + str(data.id) + "====\n" + \
"title:" + data.title + "\n" + \
"version:" + str(data.version) + "\n" + \
"==================================")
@staticmethod
def video(data: Video, stream: VideoStreamUrl = None):
tb = Printf.__gettable__([LANG.select.MODEL_VIDEO_PROPERTY, LANG.select.VALUE], [
[LANG.select.MODEL_TITLE, data.title],
[LANG.select.MODEL_ALBUM, data.album.title if data.album != None else None],
[LANG.select.MODEL_VERSION, data.version],
[LANG.select.MODEL_EXPLICIT, data.explicit],
["Max-Q", data.quality],
])
if stream is not None:
tb.add_row(["Get-Q", str(stream.resolution)])
tb.add_row(["Get-Codec", str(stream.codec)])
print(tb)
logging.info("====video " + str(data.id) + "====\n" +
"title:" + data.title + "\n" +
"version:" + str(data.version) + "\n" +
"==================================")
@staticmethod
def artist(data: Artist, num):
tb = Printf.__gettable__([LANG.select.MODEL_ARTIST_PROPERTY, LANG.select.VALUE], [
[LANG.select.MODEL_ID, data.id],
[LANG.select.MODEL_NAME, data.name],
["Number of albums", num],
[LANG.select.MODEL_TYPE, str(data.type)],
])
print(tb)
logging.info("====artist " + str(data.id) + "====\n" +
"name:" + data.name + "\n" +
"album num:" + str(num) + "\n" +
"==================================")
@staticmethod
def playlist(data):
tb = Printf.__gettable__([LANG.select.MODEL_PLAYLIST_PROPERTY, LANG.select.VALUE], [
[LANG.select.MODEL_TITLE, data.title],
[LANG.select.MODEL_TRACK_NUMBER, data.numberOfTracks],
[LANG.select.MODEL_VIDEO_NUMBER, data.numberOfVideos],
])
print(tb)
logging.info("====playlist " + str(data.uuid) + "====\n" +
"title:" + data.title + "\n" +
"track num:" + str(data.numberOfTracks) + "\n" +
"video num:" + str(data.numberOfVideos) + "\n" +
"==================================")
@staticmethod
def mix(data):
tb = Printf.__gettable__([LANG.select.MODEL_PLAYLIST_PROPERTY, LANG.select.VALUE], [
[LANG.select.MODEL_ID, data.id],
[LANG.select.MODEL_TRACK_NUMBER, len(data.tracks)],
[LANG.select.MODEL_VIDEO_NUMBER, len(data.videos)],
])
print(tb)
logging.info("====Mix " + str(data.id) + "====\n" +
"track num:" + str(len(data.tracks)) + "\n" +
"video num:" + str(len(data.videos)) + "\n" +
"==================================")
@staticmethod
def apikeys(items):
print("-------------API-KEYS---------------")
tb = prettytable.PrettyTable()
tb.field_names = [aigpy.cmd.green('Index'),
aigpy.cmd.green('Valid'),
aigpy.cmd.green('Platform'),
aigpy.cmd.green('Formats'), ]
tb.align = 'l'
for index, item in enumerate(items):
tb.add_row([str(index),
aigpy.cmd.green('True') if item["valid"] == "True" else aigpy.cmd.red('False'),
item["platform"],
item["formats"]])
print(tb)
-72
View File
@@ -1,72 +0,0 @@
# -*- coding: utf-8 -*-
from aigpy import cmdHelper
from aigpy import systemHelper
def printErr(length, elsestr):
cmdHelper.myprint("[ERR]".ljust(length), cmdHelper.TextColor.Red, None)
print(elsestr)
def printWarning(length, elsestr):
cmdHelper.myprint("[WARNING]".ljust(length), cmdHelper.TextColor.Red, None)
print(elsestr)
def printSUCCESS(length, elsestr):
cmdHelper.myprint("[SUCCESS]".ljust(length), cmdHelper.TextColor.Green, None)
print(elsestr)
def printChoice(string, isInt=False, default=None):
tmpstr = ""
cmdHelper.myprint(string, cmdHelper.TextColor.Yellow, None)
if not isInt:
return cmdHelper.myinput(tmpstr)
else:
return cmdHelper.myinputInt(tmpstr, default)
def printChoice2(string, default=None):
ret = printChoice(string, False, default)
try:
iret = int(ret)
return ret, iret
except:
return ret, default
def printMenu():
print("=====================Choice=========================")
cmdHelper.myprint(" Enter '0' : ", cmdHelper.TextColor.Green, None)
print("Exit.")
cmdHelper.myprint(" Enter '1' : ", cmdHelper.TextColor.Green, None)
print("LogIn And Get SessionID.")
cmdHelper.myprint(" Enter '2' : ", cmdHelper.TextColor.Green, None)
print("Change Settings.")
cmdHelper.myprint(" Enter '3' : ", cmdHelper.TextColor.Green, None)
print("Download an Album.")
cmdHelper.myprint(" Enter '4' : ", cmdHelper.TextColor.Green, None)
print("Download a Track.")
cmdHelper.myprint(" Enter '5' : ", cmdHelper.TextColor.Green, None)
print("Download a PlayList.")
cmdHelper.myprint(" Enter '6' : ", cmdHelper.TextColor.Green, None)
print("Download a Video.")
cmdHelper.myprint(" Enter '7' : ", cmdHelper.TextColor.Green, None)
print("Download a Favorite.")
cmdHelper.myprint(" Enter '8' : ", cmdHelper.TextColor.Green, None)
print("Download All Albums by an Artist.")
cmdHelper.myprint(" Enter '9' : ", cmdHelper.TextColor.Green, None)
print("Show Current Config.")
cmdHelper.myprint(" Enter URL : ", cmdHelper.TextColor.Green, None)
print("Download By URL.")
cmdHelper.myprint(" Enter Path: ", cmdHelper.TextColor.Green, None)
print("Download By File.")
print("====================================================")
LOG = '''
/$$$$$$$$ /$$ /$$ /$$ /$$ /$$
|__ $$__/|__/ | $$ | $$ | $$| $$
| $$ /$$ /$$$$$$$ /$$$$$$ | $$ /$$$$$$$| $$
| $$ | $$ /$$__ $$ |____ $$| $$ /$$$$$$ /$$__ $$| $$
| $$ | $$| $$ | $$ /$$$$$$$| $$|______/| $$ | $$| $$
| $$ | $$| $$ | $$ /$$__ $$| $$ | $$ | $$| $$
| $$ | $$| $$$$$$$| $$$$$$$| $$ | $$$$$$$| $$
|__/ |__/ \_______/ \_______/|__/ \_______/|__/
https://github.com/yaronzz/Tidal-Media-Downloader
'''
+132
View File
@@ -0,0 +1,132 @@
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File : settings.py
@Time : 2020/11/08
@Author : Yaronzz
@Version : 3.0
@Contact : yaronhuang@foxmail.com
@Desc :
'''
import json
import aigpy
import base64
from lang.language import *
from enums import *
class Settings(aigpy.model.ModelBase):
checkExist = True
includeEP = True
saveCovers = True
language = 0
lyricFile = False
apiKeyIndex = 0
showProgress = True
showTrackInfo = True
saveAlbumInfo = False
downloadVideos = True
multiThread = False
downloadDelay = True
downloadPath = "./download/"
audioQuality = AudioQuality.Normal
videoQuality = VideoQuality.P360
usePlaylistFolder = True
albumFolderFormat = R"{ArtistName}/{Flag} {AlbumTitle} [{AlbumID}] [{AlbumYear}]"
playlistFolderFormat = R"Playlist/{PlaylistName} [{PlaylistUUID}]"
trackFileFormat = R"{TrackNumber} - {ArtistName} - {TrackTitle}{ExplicitFlag}"
videoFileFormat = R"{VideoNumber} - {ArtistName} - {VideoTitle}{ExplicitFlag}"
def getDefaultPathFormat(self, type: Type):
if type == Type.Album:
return R"{ArtistName}/{Flag} {AlbumTitle} [{AlbumID}] [{AlbumYear}]"
elif type == Type.Playlist:
return R"Playlist/{PlaylistName} [{PlaylistUUID}]"
elif type == Type.Track:
return R"{TrackNumber} - {ArtistName} - {TrackTitle}{ExplicitFlag}"
elif type == Type.Video:
return R"{VideoNumber} - {ArtistName} - {VideoTitle}{ExplicitFlag}"
return ""
def getAudioQuality(self, value):
for item in AudioQuality:
if item.name == value:
return item
return AudioQuality.Normal
def getVideoQuality(self, value):
for item in VideoQuality:
if item.name == value:
return item
return VideoQuality.P360
def read(self, path):
self._path_ = path
txt = aigpy.file.getContent(self._path_)
if len(txt) > 0:
data = json.loads(txt)
if aigpy.model.dictToModel(data, self) is None:
return
self.audioQuality = self.getAudioQuality(self.audioQuality)
self.videoQuality = self.getVideoQuality(self.videoQuality)
if self.albumFolderFormat is None:
self.albumFolderFormat = self.getDefaultPathFormat(Type.Album)
if self.trackFileFormat is None:
self.trackFileFormat = self.getDefaultPathFormat(Type.Track)
if self.playlistFolderFormat is None:
self.playlistFolderFormat = self.getDefaultPathFormat(Type.Playlist)
if self.videoFileFormat is None:
self.videoFileFormat = self.getDefaultPathFormat(Type.Video)
if self.apiKeyIndex is None:
self.apiKeyIndex = 0
LANG.setLang(self.language)
def save(self):
data = aigpy.model.modelToDict(self)
data['audioQuality'] = self.audioQuality.name
data['videoQuality'] = self.videoQuality.name
txt = json.dumps(data)
aigpy.file.write(self._path_, txt, 'w+')
class TokenSettings(aigpy.model.ModelBase):
userid = None
countryCode = None
accessToken = None
refreshToken = None
expiresAfter = 0
def __encode__(self, string):
sw = bytes(string, 'utf-8')
st = base64.b64encode(sw)
return st
def __decode__(self, string):
try:
sr = base64.b64decode(string)
st = sr.decode()
return st
except:
return string
def read(self, path):
self._path_ = path
txt = aigpy.file.getContent(self._path_)
if len(txt) > 0:
data = json.loads(self.__decode__(txt))
aigpy.model.dictToModel(data, self)
def save(self):
data = aigpy.model.modelToDict(self)
txt = json.dumps(data)
aigpy.file.write(self._path_, self.__encode__(txt), 'wb')
# Singleton
SETTINGS = Settings()
TOKEN = TokenSettings()
File diff suppressed because it is too large Load Diff
+496 -229
View File
@@ -1,229 +1,496 @@
#### 2020-05-19
- by Command(eg. tidal-dl https://tidal.com/browse/track/70973230)
- Add label [M] before albumtitle
- Update token
#### 2020-05-15
- Cloud token
#### 2020-05-14
- Update token
#### 2020-05-04
- Hide password
#### 2020-03-23
- Fix downloading redirects that can be obtained through the
/playbackinfopostpaywall method.
- When downloading, download to a .part file, which is then
either decrypted or renamed into place, to avoid leaving broken files.
#### 2020-3-17
- Fix bug of download ArtistAlbum
#### 2020-03-11
- Fix bug of 'Asset is not ready for playback'
#### 2020-03-10
- Update token
#### 2020-02-28
- Fix bug of savepath
- Add Year: before/After
- save covers(settings)
- Flac: add isrc
- Fixno version in Tag
#### 2020-02-14
- Fix bug of download track
- ByUrl: add artist
- ByUrl: support 'https://tidal.com/browse/'
#### 2020-01-22
- Download artist album include singles(settings)
- Download by file include artist
- Fix english typos
- Fix bug of tracknumber(download playlist)
#### 2020-01-17
- Artists hyphen ';' to ', '
- Fix bug of download playlist
- Fix bug of download artwork
- Added Explicit to the file name(settings)
- Playlist organized with artist folder(settings)
- Playlist: add tracknum before tracktitle
#### v2019-10-26
- Download playlist by url
- Config 'AddYear' before album dir
- Download playlist track-picture
#### v2019-09-27
- Add skip switch when download atrist/file
- Fix bug of download playlist
#### v2019-09-10
- Fix bug of download videos
- Add version to title
- Add hyphen between number and title(settings)
#### v2019-09-02
- Fix bug of parse link
- Download by file
#### v2019-08-19
- Show Config
- Tag: add composer
#### v2019-08-17
- Download ArtistAlbum: Add EP&Singles
#### v2019-08-12
- Fix bug of tag
- Add setting-showprogress (Only enable when threadnum=1)
#### v2019-08-11
- Fix tag of title
- Download album videos
#### v2019-08-07
- Fix Bug: login;threadnum
#### v2019-08-05
- Support python 2.7
#### v2019-07-30
- Add Setting-OnlyM4a(auto covert mp4 To m4a)
- Fix some bug when first login
- Check ffmpeg status
#### v2019-07-23
- CLI: add a serial number before the file name
#### v2019-07-22
- Fix Some Bug
#### v2019-07-18
- Fix Bug: Set Metadata
#### v2019-07-12
- Fix Some Bug
#### v2019-07-11
- Add Func:Download By Url
#### v2019-07-01
- Add HI_RES Quality
#### v2019-06-24
- Fix Bug When Downloading Playlist
#### v2019-06-16
- Fix Bug Of Track Tag
#### v2019-06-01
- Fix Encoding BUG
- Add Cover To Track
#### v2019-05-08
- Update FFmpegTool
#### v2019-05-06
- Change 'Track' TargetDir
- Download 'Playlist'&'Track' Image
- Fuc: Download ArtistAlbums
#### v2019-04-23
- Add 'Resolution' To Config
- Change Playlist Items TrackNum
#### v2019-04-22
- Download Album: Track Title Append Version
#### v2019-04-16
- Change Album TargetDir
- Add 'ReleaseDate' to Track Metadata
- Remove BUG:Playlist Path
#### v2019-04-11
- Remove BUG:Download Playlist Video
#### v2019-04-08
- Change Tmp File Flag
#### v2019-04-02
- Highlight(Only Linux)
#### v2019-04-01
- Remove Encoding Err
#### v2019-03-29
- Dl Album:If Exist TrackFile. Support ReDownload Or Ignore
#### v2019-03-28
- Check After Set Metadata
#### v2019-03-13
- Deal Err: Get pip version failed
#### v2019-03-11
- Check Files After Download Playlist
- Show Last Version
#### v2019-03-06
- Add Config 'ThreadNum'
- Support Linux
- Add 'requirements.txt'
- Show Tool Version
- Set Metadata in Linux
#### v2019-03-04
- Simplified Code
#### v2019-02-27
- Download FavoriteVideos
#### v2019-02-26
- Download Playlist:Deal with err 'Too Big Page'
#### v2019-02-25
- Playlist LimitNum = 9999
- Download FavoriteTracks
#### v2019-02-19
- Print more err message
#### v2019-02-19
- Download AlbumCover
- Set Track Metadata
#### v2019-02-14
- Set music-filetype by StreamUrlInfo
#### v2019-01-28
- Add decryption.py -- Download LOSSLESS music
#### v2018-12-28
- Add Progressbar - Download Video
#### v2018-12-19
- Update ffmpegHelper
- Simplified Code
#### v2018-12-11
- Fuc: Download Playlist Video
#### v2018-12-01
- Optimized Code
- Multithreading Download Video
- Fuc: Download Playlist
#### v2018-11-22
- Multithreading Download
- Fuc: Download Track
- Fuc: Download Video
#### v2018-11-21
- Func: Download Album
- Func: Get SessionID By Account
- Upload Version To PIP Server : pip install tidal-dl
TYPE tidal-dl
USE pip3 install tidal-dl --upgrade
#### v2022-10-31
- [X] Add delay setting by @grzekru
#### v2022-08-29
- [X] Fix #931
#### v2022-07-06
- [X] Mulithread download
#### v2022-06-23
- [X] remove redundant configuration
- [X] add simple-gui
- [X] optimize code
#### v2022-03-04
- [X] fix "file name contain *" #844
- [X] Update Vietnamese
- [X] update Hungarian
- [X] Update Ukrainian
- [X] Update Dutch
- [X] fix bug of setting path
#### v2022-02-07
- [X] update api key by 1nikolas
#### v2022-01-21
- [X] update api key by @morguldir
- [X] Fix bug of "ReleaseDate"
#### v2022-01-18
- [X] Gui: search view
- [X] Gui: download view
#### v2022-01-11
- [X] Settings: add type-folder(eg Album/Video/Playlist)
- [X] Album folder format support: {None}
#### v2021-11-30
- [X] Add language:Japanese
- [X] Support select apikey(Different keys support different formats)
#### v2021-11-15
- [X] Add language:Korean
- [X] Update vietnamese
- [X] Additional tags for album path and track name
#### v2021-09-23
- [X] Get lyrics from tidal
- [X] Support mixes
#### v2021-09-10
- [X] Add settings: show track-info
- [X] Fix bug of "Illegal characters in path"
#### v2021-05-31
- [X] Add lyrics
#### v2021-04-30
- [X] Add 'album info.txt'
- [X] Fix bug of download video
#### v2021-04-23
- [X] Show get-quality
- [X] Update language
- [X] Update settings: usePlaylistFolder
#### v2021-03-24
- [X] Fix bug of download video
- [X] Fix bug of 'Command line download'
#### v2021-02-20
- [X] Add log
#### v2020-12-17
- [X] Show DOLBY_ATMOS flag [A]
- [X] Fix bug of "Connection aborted"(Linux platform)
- [X] Fix bug of download failed "stat: path should be string, bytes, os.PathLike or integer, not list"
#### v2020-12-10
- [X] Add feature: set the accessToken manually
#### v2020-12-01
- [X] Fix bug of settings-path
- [X] Ability to download multiple urls at a time.
#### v2020-11-13
- [X] Change settings-file save path: XDG_CONFIG_HOME or HOME
- [X] Fix bug of multiThreadDownload
- [X] Choice: logout
#### v2020-11-09
- [X] New login-method: get the accessToken by opening the link, accessToken good for one week and auto refresh
#### v2020-10-22
- [X] Settings: album folder format、track file format
- [X] Settings: show progress
- [X] Support language: german
- [X] Tag: composer
- [X] Add command opts: username\password\accessToken\quality\resolution
#### v2020-09-26
- [X] Fix: download video failed. Resolution parse error.
- [X] Windows: auto get accessToken from tidal-desktop cache
- [X] Download playlist to playlist folder
- [X] Fix: check exist
- [X] Support language vietnamese
- [X] Fix: download cover error (no album-cover)
- [X] Settings: usePlaylistFolder、 multiThreadDownload
- [X] Support language french
#### v2020-09-06
- usage by command: tidal-dl --help
#### v2020-08-30
- support language portuguese
- multithreading download a track
#### v2020-08-24
- add errmessage when downloading failed
- fix: macos - download failed
#### v2020-08-22
- support language spanish\croatian
#### v2020-08-21
- fix: get album path
- support download by file
- support language arabic\czech\itlian\russian\turkish\filipino
#### v2020-08-20
- fix: download playlist
- fix: settings
- fix: lack of multi-language module
#### v2020-08-19
- code rebuild
- multi-language
#### v2020-07-16
- Enter 10:Set AccessToken(authorization)
#### v2020-07-03
- Add label [E] before albumtitle #264
- Volume to CD
- Fix bug of ssl
#### v2020-06-28
- Fix bug of download-playlist
- ArtistName before title(settings)
- AlbumID before AlbumFolderName(settings)
- Add require-libs
- Add errmessage when download err
#### v2020-06-14
- Reduce the number of logins
- Use another login method(from Redsea)
- Download Dolby Atmos(AC4 Codec\Low Quality\Mp4 format)
- Download SONY_360RA(MHA1 Codec\Low Quality\Mp4 format)
- Skip convert to mp4 if File-Codec is AC4 or MHA1
- Fixed the bug of Download-HIRES
#### v2020-05-31
- Use CDN request
- Fix bug of redownload(download artist-albums)
- Add errmessage when login-err
- Fix bug of save-cover MacOs
#### v2020-05-19
- by Command(eg. tidal-dl https://tidal.com/browse/track/70973230)
- Add label [M] before albumtitle
- Update token
#### v2020-05-15
- Cloud token
#### v2020-05-14
- Update token
#### v2020-05-04
- Hide password
#### v2020-03-23
- Fix downloading redirects that can be obtained through the
/playbackinfopostpaywall method.
- When downloading, download to a .part file, which is then
either decrypted or renamed into place, to avoid leaving broken files.
#### v2020-3-17
- Fix bug of download ArtistAlbum
#### v2020-03-11
- Fix bug of 'Asset is not ready for playback'
#### v2020-03-10
- Update token
#### v2020-02-28
- Fix bug of savepath
- Add Year: before/After
- save covers(settings)
- Flac: add isrc
- Fixno version in Tag
#### v2020-02-14
- Fix bug of download track
- ByUrl: add artist
- ByUrl: support 'https://tidal.com/browse/'
#### v2020-01-22
- Download artist album include singles(settings)
- Download by file include artist
- Fix english typos
- Fix bug of tracknumber(download playlist)
#### v2020-01-17
- Artists hyphen ';' to ', '
- Fix bug of download playlist
- Fix bug of download artwork
- Added Explicit to the file name(settings)
- Playlist organized with artist folder(settings)
- Playlist: add tracknum before tracktitle
#### v2019-10-26
- Download playlist by url
- Config 'AddYear' before album dir
- Download playlist track-picture
#### v2019-09-27
- Add skip switch when download atrist/file
- Fix bug of download playlist
#### v2019-09-10
- Fix bug of download videos
- Add version to title
- Add hyphen between number and title(settings)
#### v2019-09-02
- Fix bug of parse link
- Download by file
#### v2019-08-19
- Show Config
- Tag: add composer
#### v2019-08-17
- Download ArtistAlbum: Add EP&Singles
#### v2019-08-12
- Fix bug of tag
- Add setting-showprogress (Only enable when threadnum=1)
#### v2019-08-11
- Fix tag of title
- Download album videos
#### v2019-08-07
- Fix Bug: login;threadnum
#### v2019-08-05
- Support python 2.7
#### v2019-07-30
- Add Setting-OnlyM4a(auto covert mp4 To m4a)
- Fix some bug when first login
- Check ffmpeg status
#### v2019-07-23
- CLI: add a serial number before the file name
#### v2019-07-22
- Fix Some Bug
#### v2019-07-18
- Fix Bug: Set Metadata
#### v2019-07-12
- Fix Some Bug
#### v2019-07-11
- Add Func:Download By Url
#### v2019-07-01
- Add HI_RES Quality
#### v2019-06-24
- Fix Bug When Downloading Playlist
#### v2019-06-16
- Fix Bug Of Track Tag
#### v2019-06-01
- Fix Encoding BUG
- Add Cover To Track
#### v2019-05-08
- Update FFmpegTool
#### v2019-05-06
- Change 'Track' TargetDir
- Download 'Playlist'&'Track' Image
- Fuc: Download ArtistAlbums
#### v2019-04-23
- Add 'Resolution' To Config
- Change Playlist Items TrackNum
#### v2019-04-22
- Download Album: Track Title Append Version
#### v2019-04-16
- Change Album TargetDir
- Add 'ReleaseDate' to Track Metadata
- Remove BUG:Playlist Path
#### v2019-04-11
- Remove BUG:Download Playlist Video
#### v2019-04-08
- Change Tmp File Flag
#### v2019-04-02
- Highlight(Only Linux)
#### v2019-04-01
- Remove Encoding Err
#### v2019-03-29
- Dl Album:If Exist TrackFile. Support ReDownload Or Ignore
#### v2019-03-28
- Check After Set Metadata
#### v2019-03-13
- Deal Err: Get pip version failed
#### v2019-03-11
- Check Files After Download Playlist
- Show Last Version
#### v2019-03-06
- Add Config 'ThreadNum'
- Support Linux
- Add 'requirements.txt'
- Show Tool Version
- Set Metadata in Linux
#### v2019-03-04
- Simplified Code
#### v2019-02-27
- Download FavoriteVideos
#### v2019-02-26
- Download Playlist:Deal with err 'Too Big Page'
#### v2019-02-25
- Playlist LimitNum = 9999
- Download FavoriteTracks
#### v2019-02-19
- Print more err message
#### v2019-02-19
- Download AlbumCover
- Set Track Metadata
#### v2019-02-14
- Set music-filetype by StreamUrlInfo
#### v2019-01-28
- Add decryption.py -- Download LOSSLESS music
#### v2018-12-28
- Add Progressbar - Download Video
#### v2018-12-19
- Update ffmpegHelper
- Simplified Code
#### v2018-12-11
- Fuc: Download Playlist Video
#### v2018-12-01
- Optimized Code
- Multithreading Download Video
- Fuc: Download Playlist
#### v2018-11-22
- Multithreading Download
- Fuc: Download Track
- Fuc: Download Video
#### v2018-11-21
- Func: Download Album
- Func: Get SessionID By Account
- Upload Version To PIP Server : pip install tidal-dl
-27
View File
@@ -1,27 +0,0 @@
REM cd to workdir
cd %~dp0
REM remove old dir
rmdir /s/q dist
rmdir /s/q build
rmdir /s/q exe
rmdir /s/q tidal_dl.egg-info
mkdir exe
REM pack
python setup.py sdist bdist_wheel
REM creat exe file
pyinstaller -F tidal_dl/__main__.py
REM rename exe name
cd dist
ren __main__.exe tidal-dl.exe
move tidal-dl.exe ../exe/
cd ..
pip uninstall -y tidal-dl
REM python setup.py install
REM upload version to pip server
twine upload dist/*
-34
View File
@@ -1,34 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29709.97
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TIDALDL-UI", "TIDALDL-UI\TIDALDL-UI.csproj", "{87F39F78-056F-4747-A835-12BA03FE575A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
CD_ROM|Any CPU = CD_ROM|Any CPU
Debug|Any CPU = Debug|Any CPU
DVD-5|Any CPU = DVD-5|Any CPU
Release|Any CPU = Release|Any CPU
SingleImage|Any CPU = SingleImage|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{87F39F78-056F-4747-A835-12BA03FE575A}.CD_ROM|Any CPU.ActiveCfg = Release|Any CPU
{87F39F78-056F-4747-A835-12BA03FE575A}.CD_ROM|Any CPU.Build.0 = Release|Any CPU
{87F39F78-056F-4747-A835-12BA03FE575A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{87F39F78-056F-4747-A835-12BA03FE575A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{87F39F78-056F-4747-A835-12BA03FE575A}.DVD-5|Any CPU.ActiveCfg = Debug|Any CPU
{87F39F78-056F-4747-A835-12BA03FE575A}.DVD-5|Any CPU.Build.0 = Debug|Any CPU
{87F39F78-056F-4747-A835-12BA03FE575A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{87F39F78-056F-4747-A835-12BA03FE575A}.Release|Any CPU.Build.0 = Release|Any CPU
{87F39F78-056F-4747-A835-12BA03FE575A}.SingleImage|Any CPU.ActiveCfg = Release|Any CPU
{87F39F78-056F-4747-A835-12BA03FE575A}.SingleImage|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {EE9828BC-5446-4422-83D6-9103517072A3}
EndGlobalSection
EndGlobal
-14
View File
@@ -1,14 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="ICSharpCode.SharpZipLib" publicKeyToken="1b03e6acf1164f73" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.2.0.246" newVersion="1.2.0.246" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
Binary file not shown.
-17
View File
@@ -1,17 +0,0 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
namespace TIDALDL_UI
{
/// <summary>
/// App.xaml 的交互逻辑
/// </summary>
public partial class App : Application
{
}
}
Binary file not shown.
-277
View File
@@ -1,277 +0,0 @@
using AIGS.Helper;
using NPinyin;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TIDALDL_UI.Else
{
public class CloudMusicArtist
{
public int id { get; set; }
public string name { get; set; }
public string picUrl { get; set; }
public List<string> alias { get; set; }
public List<string> alia { get; set; }
public int albumSize { get; set; }
public string picId { get; set; }
public string img1v1Url { get; set; }
public string img1v1 { get; set; }
public int mvSize { get; set; }
public bool followed { get; set; }
public string trans { get; set; }
}
public class CloudMusicAlbum
{
public int id { get; set; }
public string name { get; set; }
public string type { get; set; }
public int size { get; set; }
public string picId { get; set; }
public string blurPicUrl { get; set; }
public string pic { get; set; }
public string picUrl { get; set; }
public string publishTime { get; set; }
public string description { get; set; }
public int companyId { get; set; }
public List<string> tags { get; set; }
public string company { get; set; }
public string briefDesc { get; set; }
public CloudMusicArtist artist { get; set; }
public List<CloudMusicSong> songs { get; set; }
public List<string> alias { get; set; }
public int status { get; set; }
public int copyrightId { get; set; }
public string commentThreadId { get; set; }
public List<CloudMusicArtist> artists { get; set; }
public string picId_str { get; set; }
}
public class CloudMusicSong
{
public string name { get; set; }
public int id { get; set; }
public bool starred { get; set; }
public int starredNum { get; set; }
public int playedNum { get; set; }
public int dayPlays { get; set; }
public int hearTime { get; set; }
public double popularity { get; set; }
public string mp3Url { get; set; }
public string rtUrls { get; set; }
public int mark { get; set; }
public List<CloudMusicArtist> artists { get; set; }
public List<string> alias { get; set; }
public int mvid { get; set; }
public int duration { get; set; }
public int position { get; set; }
}
public class DoubanMusicRecord
{
public string alt_title { get; set; }
public string image { get; set; }
public string mobile_link { get; set; }
public string title { get; set; }
public string alt { get; set; }
public string id { get; set; }
public DoubanMusicAttr attrs { get; set; }
public DoubanMusicRating rating { get; set; }
public List<DoubanMusicAuthor> author { get; set; }
public List<DoubanMusicTag> tags { get; set; }
}
public class DoubanMusicRating
{
public int max { get; set; }
public int min { get; set; }
public int numRaters { get; set; }
public string average { get; set; }
}
public class DoubanMusicAuthor
{
public string name { get; set; }
}
public class DoubanMusicTag
{
public string name { get; set; }
public int count { get; set; }
}
public class DoubanMusicAttr
{
public List<string> publisher { get; set; }
public List<string> singer { get; set; }
public List<string> version { get; set; }
public List<string> pubdate { get; set; }
public List<string> title { get; set; }
public List<string> media { get; set; }
public List<string> tracks { get; set; }
public List<string> discs { get; set; }
}
public class Chinese
{
/// <summary>
/// 根据专辑和歌手获取匹配的网易云专辑
/// </summary>
/// <param name="sAlbumName">专辑名</param>
/// <param name="sArtistName">歌手</param>
/// <returns></returns>
public static CloudMusicAlbum matchAlbum(string sAlbumName, string sArtistName)
{
//使用豆瓣接口搜索专辑,支持英文、中文、繁体搜索
string serr;
string stxt = (string)HttpHelper.GetOrPost("https://api.douban.com/v2/music/search?q=" + sAlbumName, out serr);
List<DoubanMusicRecord> pDoubans = JsonHelper.ConverStringToObject<List<DoubanMusicRecord>>(stxt, "musics");
//使用网易云接口搜索歌手
string stxt2 = (string)HttpHelper.GetOrPost(string.Format("http://music.163.com/api/search/pc?s={0}&type=100&limit=10&offset=0", sArtistName), out serr);
List<CloudMusicArtist> pClounds = JsonHelper.ConverStringToObject<List<CloudMusicArtist>>(stxt2, "result", "artists");
//匹配
int iIndex1 = -1;
int iIndex2 = -1;
for (int i = 0; pClounds != null && i < pClounds.Count && iIndex1 == -1; i++)
{
string skey = pClounds[i].name;
for (int j = 0; pDoubans != null && j < pDoubans.Count && iIndex1 == -1; j++)
{
for (int k = 0; pDoubans[j].author != null && k < pDoubans[j].author.Count; k++)
{
string stmp = converSimpleChinese(pDoubans[j].author[k].name);
if (skey == stmp || skey.Contains(stmp) || stmp.Contains(skey) || stmp == sArtistName)
{
iIndex1 = i;
iIndex2 = j;
break;
}
}
}
}
if (iIndex1 < 0)
return null;
string sname = converSimpleChinese(pDoubans[iIndex2].title);
string stxt3 = (string)HttpHelper.GetOrPost(string.Format("http://music.163.com/api/search/pc?s={0}&type=10&limit=30&offset=0", sname), out serr);
List<CloudMusicAlbum> pCloundAlbums = JsonHelper.ConverStringToObject<List<CloudMusicAlbum>>(stxt3, "result", "albums");
//匹配
int iIndex3 = -1;
for (int i = 0; pCloundAlbums != null && i < pCloundAlbums.Count; i++)
{
if (pCloundAlbums[i].artist.name == pClounds[iIndex1].name &&
pCloundAlbums[i].name == sname)
{
iIndex3 = i;
break;
}
}
if (iIndex3 < 0)
return null;
string stxt4 = (string)HttpHelper.GetOrPost(string.Format("http://music.163.com/api/album/{0}?ext=true&id={1}&offset=0&total=true&limit=10", pCloundAlbums[iIndex3].id.ToString(), pCloundAlbums[0].id.ToString()), out serr);
CloudMusicAlbum pAlbum = JsonHelper.ConverStringToObject<CloudMusicAlbum>(stxt4, "album");
return pAlbum;
}
/// <summary>
/// 从专辑信息中获取歌曲的中文名
/// </summary>
/// <param name="sName"></param>
/// <param name="pAlbum"></param>
/// <returns></returns>
public static string convertSongTitle(string sName, CloudMusicAlbum pAlbum)
{
if (pAlbum == null || pAlbum.songs.Count <= 0)
return sName;
int iIndex = -1;
int iWeight = 0;
for (int i = 0; i < pAlbum.songs.Count; i++)
{
int iTmp = calcWeight(sName, pAlbum.songs[i].name);
if (iTmp > iWeight)
{
iIndex = i;
iWeight = iTmp;
}
}
if (iIndex < 0)
return sName;
return pAlbum.songs[iIndex].name;
}
/// <summary>
/// 计算匹配度权重值
/// </summary>
/// <param name="sEngName"></param>
/// <param name="sChnName"></param>
/// <returns></returns>
static int calcWeight(string sEngName, string sChnName)
{
//转拼音
StringBuilder sPinyinName = new StringBuilder();
for (int i = 0; i < sChnName.Length; i++)
{
if (StringHelper.IsChinese(sChnName[i]))
sPinyinName.Append(Pinyin.GetPinyin(sChnName[i]) + ' ');
else
sPinyinName.Append(sChnName[i]);
}
int iRet = 0;
//删除括号
if (sEngName.IndexOf('(') >= 0)
sEngName = sEngName.Substring(0, sEngName.IndexOf('('));
if (sChnName.IndexOf('(') >= 0)
sChnName = sChnName.Substring(0, sChnName.IndexOf('('));
sEngName = sEngName.Trim().ToLower();
sChnName = sPinyinName.ToString().Trim().ToLower();
if (sEngName.Contains(sChnName) || sChnName.Contains(sEngName))
iRet += 100;
string[] sArr1 = sEngName.Split(' ');
string[] sArr2 = sChnName.ToString().Trim().ToLower().Split(' ');
for (int i = 0; i < sArr1.Count() && i < sArr2.Count(); i++)
{
string sitem = sArr1[i];
string sitem2 = sArr2[i];
for (int j = 0; j < sitem.Length && j < sitem2.Length; j++)
{
if (sitem[j] == sitem2[j])
iRet++;
}
}
if (iRet <= 0)
return 0;
if (sArr1.Count() == sArr2.Count())
iRet += 100;
return iRet;
}
/// <summary>
/// 繁体转简体
/// </summary>
static string converSimpleChinese(string str)
{
StringBuilder ret = new StringBuilder();
for (int i = 0; i < str.Length; i++)
{
if (StringHelper.IsChinese(str[i]))
ret.Append(Microsoft.VisualBasic.Strings.StrConv(str[i].ToString(), Microsoft.VisualBasic.VbStrConv.SimplifiedChinese, 0));
else
ret.Append(str[i]);
}
return ret.ToString();
}
}
}
-355
View File
@@ -1,355 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AIGS.Common;
using AIGS.Helper;
using System.Collections.ObjectModel;
namespace TIDALDL_UI.Else
{
public class Config
{
private static string CONFIGPATH = "./tidal-dl.ini";
private static string BASEGROUP = "base";
private static string HISTORYGROUP = "history";
private static string SetOrGet(string Key, string SetValue = null, string GetDefault = "", string Group = null)
{
if (Group.IsBlank())
Group = BASEGROUP;
if (SetValue.IsBlank())
return ConfigHelper.GetValue(Key, GetDefault, Group, CONFIGPATH);
else
ConfigHelper.SetValue(Key, SetValue, Group, CONFIGPATH);
return null;
}
private static string SetOrGetPrivate(string Key, string SetValue = null, string GetDefault = "", string Group = null)
{
if (Group.IsBlank())
Group = BASEGROUP;
if (SetValue.IsBlank())
{
string sTmp = ConfigHelper.GetValue(Key, GetDefault, Group, CONFIGPATH);
return Decode(sTmp);
}
else
ConfigHelper.SetValue(Key, Encode(SetValue), Group, CONFIGPATH);
return null;
}
#region Base Config
public static string Version(string Setvalue = null)
{
return SetOrGet("version", Setvalue, "null");
}
public static string OutputDir(string Setvalue = null)
{
return SetOrGet("outputdir", Setvalue, "./");
}
public static bool OnlyM4a(string Setvalue = null)
{
string sValue = SetOrGet("onlym4a", Setvalue, "true");
if (sValue == null || sValue.ToLower() != "true")
return false;
return true;
}
public static bool AddExplicitTag(string Setvalue = null)
{
string sValue = SetOrGet("addexplicit", Setvalue, "false");
if (sValue == null || sValue.ToLower() != "true")
return false;
return true;
}
public static bool IncludeEP(string Setvalue = null)
{
string sValue = SetOrGet("includesingle", Setvalue, "false");
if (sValue == null || sValue.ToLower() != "true")
return false;
return true;
}
public static bool SaveCovers(string Setvalue = null)
{
string sValue = SetOrGet("savephoto", Setvalue, "true");
if (sValue == null || sValue.ToLower() != "true")
return false;
return true;
}
public static bool AddHyphen(string Setvalue = null)
{
string sValue = SetOrGet("addhyphen", Setvalue, "true");
if (sValue == null || sValue.ToLower() != "true")
return false;
return true;
}
public static bool UseTrackNumber(string Setvalue = null)
{
string sValue = SetOrGet("useTrackNumber", Setvalue, "true");
if (sValue == null || sValue.ToLower() != "true")
return false;
return true;
}
public static string Quality(string Setvalue = null)
{
return SetOrGet("quality", Setvalue, "HIGH");
}
public static int AddYear(int Setvalue = -1)
{
if (Setvalue == -1)
{
string sValue = SetOrGet("addyear", null, "No").ToLower();
if (sValue == "before")
return 1;
else if (sValue == "after")
return 2;
return 0;
}
else
{
string sValue = "No";
if (Setvalue == 1)
sValue = "Before";
if (Setvalue == 2)
sValue = "After";
SetOrGet("addyear", sValue, "No");
return 0;
}
}
public static Dictionary<int, string> QualityList()
{
return AIGS.Common.Convert.ConverEnumToDictionary(typeof(Tidal.eSoundQuality));
}
public static int QualityIndex()
{
string sValue = Config.Quality();
Dictionary<int, string> pList = QualityList();
for (int i = 0; i < pList.Count; i++)
{
if (sValue.ToUpper() == pList.ElementAt(i).Value)
return i;
}
return 0;
}
public static string ThreadNum(string Setvalue = null)
{
return SetOrGet("threadnum", Setvalue, "1");
//SetOrGet("threadnum", Setvalue, "1");
//return "1";
}
public static string SearchNum(string Setvalue = null)
{
return SetOrGet("searchnum", Setvalue, "30");
}
public static string Username(string Setvalue = null)
{
return SetOrGet("username", Setvalue, "");
}
public static string Password(string Setvalue = null)
{
return SetOrGetPrivate("password", Setvalue, "");
}
public static string Sessionid(string Setvalue = null)
{
return SetOrGet("sessionid", Setvalue, "");
}
public static string Countrycode(string Setvalue = null)
{
return SetOrGet("countrycode", Setvalue, "");
}
public static string Userid(string Setvalue = null)
{
return SetOrGet("userid", Setvalue, "");
}
public static bool Remember(string Setvalue = null)
{
string sRet = SetOrGet("remember", Setvalue, "true");
if (sRet.IsNotBlank() && sRet.ToLower() == "true")
return true;
return false;
}
public static bool ToChinese(string Setvalue = null)
{
string sRet = SetOrGet("tochinese", Setvalue, "false");
if (sRet.IsNotBlank() && sRet.ToLower() == "true")
return true;
return false;
}
public static bool CheckExist(string Setvalue = null)
{
string sRet = SetOrGet("checkexist", Setvalue, "false");
if (sRet.IsNotBlank() && sRet.ToLower() == "true")
return true;
return false;
}
public static bool ArtistBeforeTitle(string Setvalue = null)
{
string sRet = SetOrGet("artistbeforetitle", Setvalue, "false");
if (sRet.IsNotBlank() && sRet.ToLower() == "true")
return true;
return false;
}
public static bool AutoLogin(string Setvalue = null)
{
string sRet = SetOrGet("autologin", Setvalue, "true");
if (sRet.IsNotBlank() && sRet.ToLower() == "true")
return true;
return false;
}
public static string Resolution(string Setvalue = null)
{
return SetOrGet("resolution", Setvalue, "e720P");
}
public static bool ProxyEnable(string Setvalue = null)
{
string sRet = SetOrGet("proxyenable", Setvalue, "false");
if (sRet.IsNotBlank() && sRet.ToLower() == "true")
return true;
return false;
}
public static string ProxyHost(string Setvalue = null)
{
return SetOrGet("proxyhost", Setvalue, "");
}
public static int ProxyPort(string Setvalue = null)
{
string sValue = SetOrGet("proxyport", Setvalue, "");
return AIGS.Common.Convert.ConverStringToInt(sValue, 0);
}
public static string ProxyUser(string Setvalue = null)
{
return SetOrGet("proxyuser", Setvalue, "");
}
public static string ProxyPwd(string Setvalue = null)
{
return SetOrGet("proxypwd", Setvalue, "");
}
#endregion
#region History Account
/// <summary>
/// Get History Account List
/// </summary>
public static List<Property> HistoryAccounts()
{
List<Property> pRet = new List<Property>();
string sValue = SetOrGet("historyusernum", null, "", HISTORYGROUP);
int iNum = AIGS.Common.Convert.ConverStringToInt(sValue, 0);
for (int i = 0; i < iNum; i++)
{
string sUser = SetOrGet("historyuser" + i, null, "", HISTORYGROUP);
string sPwd = SetOrGetPrivate("historypwd" + i, null, "", HISTORYGROUP);
if (sUser.IsNotBlank() && pRet.FindIndex((Property user) => user.Key.ToString() == sUser) < 0)
pRet.Add(new Property(sUser, sPwd));
}
return pRet;
}
/// <summary>
/// Add Account To Config File
/// </summary>
public static void AddHistoryAccount(string sUsername, string sPassword)
{
List<Property> pArray = HistoryAccounts();
int iIndex = pArray.FindIndex((Property user) => user.Key.ToString() == sUsername);
if (iIndex >= 0)
pArray.RemoveAt(iIndex);
pArray.Insert(0, new Property(sUsername, sPassword));
for (int i = 0; i < pArray.Count; i++)
{
SetOrGet("historyuser" + i, pArray[i].Key.ToString(), "", HISTORYGROUP);
SetOrGetPrivate("historypwd" + i, pArray[i].Value.ToString(), "", HISTORYGROUP);
}
SetOrGet("historyusernum", pArray.Count.ToString(), "", HISTORYGROUP);
Username(sUsername);
Password(sPassword);
}
#endregion
#region History Search
/// <summary>
/// Get History Search List
/// </summary>
public static ObservableCollection<string> HistorySearchs()
{
ObservableCollection<string> pRet = new ObservableCollection<string>();
string sValue = SetOrGet("historysearchnum", null, "", HISTORYGROUP);
int iNum = AIGS.Common.Convert.ConverStringToInt(sValue, 0);
for (int i = 0; i < iNum; i++)
{
string sStr = SetOrGet("historysearch" + i, null, "", HISTORYGROUP);
if (sStr.IsNotBlank() && pRet.IndexOf(sStr) < 0)
pRet.Add(sStr);
}
return pRet;
}
/// <summary>
/// Add Search To Config File
/// </summary>
public static void AddHistorySearch(string sNewStr)
{
ObservableCollection<string> pArray = HistorySearchs();
int iIndex = pArray.IndexOf(sNewStr);
if (iIndex >= 0)
pArray.RemoveAt(iIndex);
pArray.Insert(0, sNewStr);
for (int i = 0; i < pArray.Count; i++)
SetOrGet("historysearch" + i, pArray[i], "", HISTORYGROUP);
SetOrGet("historysearchnum", pArray.Count.ToString(), "", HISTORYGROUP);
}
#endregion
#region Encryption
private static string EncryptionFlag = "Ax*~!9";
private static string Encode(string sStr)
{
if (sStr.IsBlank())
return sStr;
string sTmp = EncryptHelper.Encode(sStr, Tidal.TidalTool.USER_INFO_KEY);
return EncryptionFlag + sTmp;
}
private static string Decode(string data)
{
if (data.IsBlank())
return data;
if (data.IndexOf(EncryptionFlag) != 0)
return data;
string sTmp = data.Substring(EncryptionFlag.Length);
return EncryptHelper.Decode(sTmp, Tidal.TidalTool.USER_INFO_KEY);
}
#endregion
}
}
-282
View File
@@ -1,282 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Tidal;
using AIGS.Common;
using AIGS.Helper;
using Stylet;
using TagLib;
using System.IO;
using System.Collections.ObjectModel;
namespace TIDALDL_UI.Else
{
public class DownloadItem : Screen
{
public Playlist TidalPlaylist { get; set; }
public Album TidalAlbum { get; set; }
public Track TidalTrack { get; set; }
public Video TidalVideo { get; set; }
/// <summary>
/// Item Para - OutputDir | FilePath | Track Quality | Title | Type
/// </summary>
public string OutputDir { get; set; }
public string FilePath { get; set; }
public eSoundQuality Quality { get; set; }
public eResolution Resolution { get; set; }
public int Index { get; set; }
public string Title { get; set; }
public string sType { get; set; }
public int ErrlabelHeight { get; set; }
public bool OnlyM4a { get; set; }
public bool AddHyphen { get; set; }
public bool UseTrackNumber { get; set; }
public string Own { get; set; }
public bool ToChinese { get; set; }
public bool CheckExist { get; set; }
public bool ArtistBeforeTitle { get; set; }
public bool AddExplict { get; set; }
public int AddYear { get; set; }
///// <summary>
///// Progress
///// </summary>
public ProgressHelper Progress { get; set; }
public DownloadItem(int index, Track track = null, Video video = null, Album album = null, Playlist plist = null)
{
TidalPlaylist = plist;
TidalAlbum = album;
TidalVideo = video;
TidalTrack = track;
Quality = TidalTool.getQuality(Config.Quality());
Resolution = TidalTool.getResolution(Config.Resolution());
OutputDir = Config.OutputDir();
Index = index;
Progress = new ProgressHelper();
OnlyM4a = Config.OnlyM4a();
AddHyphen = Config.AddHyphen();
UseTrackNumber = Config.UseTrackNumber();
Own = album == null?null : album.Title;
ToChinese = Config.ToChinese();
CheckExist = Config.CheckExist();
ArtistBeforeTitle = Config.ArtistBeforeTitle();
AddExplict = Config.AddExplicitTag();
AddYear = Config.AddYear();
if (TidalTrack != null)
{
Title = track.Title;
sType = "MusicCircle";
}
else
{
Title = video.Title;
sType = "PlayCircle";
}
}
#region Method
public void Start()
{
//Add to threadpool
ThreadTool.AddWork((object[] data) =>
{
if (Progress.GetStatus() != ProgressHelper.STATUS.WAIT)
return;
ErrlabelHeight = 0;
Progress.SetStatus(ProgressHelper.STATUS.RUNNING);
if (TidalTrack != null)
DownloadTrack();
else
DownloadVideo();
});
}
public void Cancel()
{
if (Progress.GetStatus() != ProgressHelper.STATUS.COMPLETE)
Progress.SetStatus(ProgressHelper.STATUS.CANCLE);
}
public void Restart()
{
ProgressHelper.STATUS status = Progress.GetStatus();
if (status == ProgressHelper.STATUS.CANCLE || status == ProgressHelper.STATUS.ERROR)
{
Progress.Clear();
Start();
}
}
#endregion
#region DownloadVideo
public bool ProgressNotify(long lCurSize, long lAllSize)
{
Progress.Update(lCurSize, lAllSize);
if (Progress.GetStatus() != ProgressHelper.STATUS.RUNNING)
return false;
return true;
}
public void DownloadVideo()
{
//GetStream
Progress.StatusMsg = "GetStream...";
string Errlabel = "";
string[] TidalVideoUrls = TidalTool.getVideoDLUrls(TidalVideo.ID.ToString(), Resolution, out Errlabel);
if (Errlabel.IsNotBlank())
goto ERR_RETURN;
string TsFilePath = TidalTool.getVideoPath(OutputDir, TidalVideo, TidalAlbum, ".ts", hyphen: AddHyphen, plist: TidalPlaylist, artistBeforeTitle:ArtistBeforeTitle, addYear:AddYear);
//Download
Progress.StatusMsg = "Start...";
if(!(bool)M3u8Helper.Download(TidalVideoUrls, TsFilePath, ProgressNotify, Proxy:TidalTool.PROXY))
{
Errlabel = "Download failed!";
goto ERR_RETURN;
}
//Convert
FilePath = TidalTool.getVideoPath(OutputDir, TidalVideo, TidalAlbum, hyphen:AddHyphen, plist:TidalPlaylist, artistBeforeTitle: ArtistBeforeTitle, addYear: AddYear);
if(!FFmpegHelper.IsExist())
{
Errlabel = "FFmpeg is not exist!";
goto ERR_RETURN;
}
if (!FFmpegHelper.Convert(TsFilePath, FilePath))
{
Errlabel = "Convert failed!";
goto ERR_RETURN;
}
System.IO.File.Delete(TsFilePath);
Progress.SetStatus(ProgressHelper.STATUS.COMPLETE);
return;
ERR_RETURN:
if (Progress.GetStatus() == ProgressHelper.STATUS.CANCLE)
return;
ErrlabelHeight = 15;
Progress.SetStatus(ProgressHelper.STATUS.ERROR);
Progress.Errmsg = Errlabel;
}
#endregion
#region DownloadTrack
public void DownloadTrack()
{
string Errlabel = "";
//GetStream
Progress.StatusMsg = "GetStream...";
StreamUrl TidalStream = TidalTool.getStreamUrl(TidalTrack.ID.ToString(), Quality, out Errlabel);
if (Errlabel.IsNotBlank())
goto ERR_RETURN;
//Get path
FilePath = TidalTool.getTrackPath(OutputDir, TidalAlbum, TidalTrack, TidalStream.Url,
AddHyphen, TidalPlaylist, artistBeforeTitle: ArtistBeforeTitle, addexplicit: AddExplict,
addYear: AddYear, useTrackNumber: UseTrackNumber);
//Check if song is downloaded already
string CheckName = OnlyM4a ? FilePath.Replace(".mp4", ".m4a") : FilePath;
if (CheckExist && System.IO.File.Exists(CheckName))
{
Progress.Update(100, 100);
Progress.SetStatus(ProgressHelper.STATUS.COMPLETE);
return;
}
//Get contributors
ObservableCollection<Contributor> pContributors = TidalTool.getTrackContributors(TidalTrack.ID.ToString(), out Errlabel);
//To chinese
if (ToChinese)
{
CloudMusicAlbum cloalbum = Chinese.matchAlbum(TidalAlbum.Title, TidalAlbum.Artist.Name);
string chnname = Chinese.convertSongTitle(TidalTrack.Title, cloalbum);
if (chnname != TidalTrack.Title)
{
FilePath = TidalTool.getTrackPath(OutputDir, TidalPlaylist != null ? null : TidalAlbum, TidalTrack, TidalStream.Url,
AddHyphen, TidalPlaylist, chnname, artistBeforeTitle: ArtistBeforeTitle, addexplicit: AddExplict,
addYear: AddYear, useTrackNumber: UseTrackNumber);
TidalTrack.Title = chnname;
}
}
//Download
Progress.StatusMsg = "Start...";
for (int i = 0; i < 100 && Progress.GetStatus() != ProgressHelper.STATUS.CANCLE; i++)
{
if ((bool)DownloadFileHepler.Start(TidalStream.Url, FilePath, Timeout: 5 * 1000, UpdateFunc: UpdateDownloadNotify, ErrFunc: ErrDownloadNotify, Proxy:TidalTool.PROXY))
{
//Decrypt
if (!TidalTool.DecryptTrackFile(TidalStream, FilePath))
{
Errlabel = "Decrypt failed!";
goto ERR_RETURN;
}
if(OnlyM4a)
{
string sNewName;
if (!TidalTool.ConvertMp4ToM4a(FilePath, out sNewName))
{
Errlabel = "Convert mp4 to m4a failed!";
goto ERR_RETURN;
}
else
FilePath = sNewName;
}
//SetMetaData
if (TidalAlbum == null && TidalTrack.Album != null)
{
string sErrcode = null;
TidalAlbum = TidalTool.getAlbum(TidalTrack.Album.ID.ToString(), out sErrcode);
}
string sLabel = TidalTool.SetMetaData(FilePath, TidalAlbum, TidalTrack, TidalTool.getAlbumCoverPath(OutputDir, TidalAlbum, AddYear), pContributors);
if (sLabel.IsNotBlank())
{
Errlabel = "Set metadata failed!";
goto ERR_RETURN;
}
Progress.SetStatus(ProgressHelper.STATUS.COMPLETE);
return;
}
}
Errlabel = "Download failed!";
ERR_RETURN:
if (Progress.GetStatus() == ProgressHelper.STATUS.CANCLE)
return;
ErrlabelHeight = 15;
Progress.SetStatus(ProgressHelper.STATUS.ERROR);
Progress.Errmsg = Errlabel;
}
public void ErrDownloadNotify(long lTotalSize, long lAlreadyDownloadSize, string sErrMsg, object data)
{
return;
}
public bool UpdateDownloadNotify(long lTotalSize, long lAlreadyDownloadSize, long lIncreSize, object data)
{
Progress.Update(lAlreadyDownloadSize, lTotalSize);
if (Progress.GetStatus() != ProgressHelper.STATUS.RUNNING)
return false;
return true;
}
#endregion
}
}
-52
View File
@@ -1,52 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AIGS.Helper;
using AIGS.Common;
using System.Threading;
namespace TIDALDL_UI.Else
{
public class ThreadTool
{
private static ThreadPoolManager Pool = new ThreadPoolManager(1);
public static void SetThreadNum(int iNum)
{
if (iNum < 1)
iNum = 1;
Pool.SetPoolSize(iNum);
}
public static int GetThreadNum()
{
if (Pool == null)
return 0;
return Pool.GetPoolSize();
}
/// <summary>
/// Add Download
/// </summary>
public static bool AddWork(ThreadPoolManager.EventFunc Func, object[] data=null)
{
if (Pool == null)
return false;
Pool.AddWork(Func, data);
return true;
}
/// <summary>
/// End
/// </summary>
public static void Close()
{
if (Pool == null)
return;
Pool.CloseAll(true);
}
}
}
-10
View File
@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<PropertyChanged/>
<Costura>
<ExcludeAssemblies>
Foo
Bar
</ExcludeAssemblies>
</Costura>
</Weavers>
-140
View File
@@ -1,140 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="PropertyChanged" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="InjectOnPropertyNameChanged" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to control if the On_PropertyName_Changed feature is enabled.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="EventInvokerNames" type="xs:string">
<xs:annotation>
<xs:documentation>Used to change the name of the method that fires the notify event. This is a string that accepts multiple values in a comma separated form.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="CheckForEquality" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to control if equality checks should be inserted. If false, equality checking will be disabled for the project.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="CheckForEqualityUsingBaseEquals" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to control if equality checks should use the Equals method resolved from the base class.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="UseStaticEqualsFromBase" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to control if equality checks should use the static Equals method resolved from the base class.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
<xs:element name="Costura" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:all>
<xs:element minOccurs="0" maxOccurs="1" name="ExcludeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="IncludeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="Unmanaged32Assemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of unmanaged 32 bit assembly names to include, delimited with line breaks.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="Unmanaged64Assemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of unmanaged 64 bit assembly names to include, delimited with line breaks.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="PreloadOrder" type="xs:string">
<xs:annotation>
<xs:documentation>The order of preloaded assemblies, delimited with line breaks.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:all>
<xs:attribute name="CreateTemporaryAssemblies" type="xs:boolean">
<xs:annotation>
<xs:documentation>This will copy embedded files to disk before loading them into memory. This is helpful for some scenarios that expected an assembly to be loaded from a physical file.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="IncludeDebugSymbols" type="xs:boolean">
<xs:annotation>
<xs:documentation>Controls if .pdbs for reference assemblies are also embedded.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="DisableCompression" type="xs:boolean">
<xs:annotation>
<xs:documentation>Embedded assemblies are compressed by default, and uncompressed when they are loaded. You can turn compression off with this option.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="DisableCleanup" type="xs:boolean">
<xs:annotation>
<xs:documentation>As part of Costura, embedded assemblies are no longer included as part of the build. This cleanup can be turned off.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="LoadAtModuleInit" type="xs:boolean">
<xs:annotation>
<xs:documentation>Costura by default will load as part of the module initialization. This flag disables that behavior. Make sure you call CosturaUtility.Initialize() somewhere in your code.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="IgnoreSatelliteAssemblies" type="xs:boolean">
<xs:annotation>
<xs:documentation>Costura will by default use assemblies with a name like 'resources.dll' as a satellite resource and prepend the output path. This flag disables that behavior.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="ExcludeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with |</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="IncludeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of assembly names to include from the default action of "embed all Copy Local references", delimited with |.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="Unmanaged32Assemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of unmanaged 32 bit assembly names to include, delimited with |.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="Unmanaged64Assemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of unmanaged 64 bit assembly names to include, delimited with |.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="PreloadOrder" type="xs:string">
<xs:annotation>
<xs:documentation>The order of preloaded assemblies, delimited with |.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>
@@ -1,47 +0,0 @@
<Window x:Class="TIDALDL_UI.Pages.AboutView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:local="clr-namespace:TIDALDL_UI"
xmlns:pages="clr-namespace:TIDALDL_UI.Pages"
xmlns:s="https://github.com/canton7/Stylet"
mc:Ignorable="d"
Width="335"
Height="400"
WindowStartupLocation="CenterOwner"
WindowStyle="None"
Background="{x:Null}"
AllowsTransparency="True"
ShowInTaskbar="False"
d:DataContext="{d:DesignInstance pages:AboutViewModel}">
<materialDesign:Card Name="m_CMainCard" materialDesign:ShadowAssist.ShadowDepth="Depth3" VerticalAlignment="Stretch" BorderThickness="3" BorderBrush="#FF171616" Margin="20,20,20,20">
<materialDesign:DialogHost Identifier="RootDialog" SnackbarMessageQueue="{Binding ElementName=MainSnackbar, Path=MessageQueue}" Background="{x:Null}">
<Grid Margin="8">
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="240*" />
<RowDefinition Height="47"/>
</Grid.RowDefinitions>
<Label Content="About" Grid.Row="0" FontSize="30" VerticalAlignment="Top" Height="50" HorizontalContentAlignment="Center" BorderThickness="0,0,0,1" BorderBrush="#FFDEDEDE"/>
<Grid Height="282" Grid.Row="1">
<Image Margin="94,13,93,177" Source="pack://application:,,,/resource/tidal.jpg" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<Label Content="TIDAL-GUI" Margin="103,105,102,151" HorizontalAlignment="Center" FontWeight="Bold" Width="74"/>
<Label Content="Copyright 2019-2020 Yaron Inc." Margin="54,131,57,124" HorizontalAlignment="Center" Width="168"/>
<Label Content="All Rights Reserved." Margin="77,158,77,100" HorizontalAlignment="Center" Width="125"/>
<Label Content="{Binding Version}" Margin="77,182,77,76" HorizontalAlignment="Center" Width="125" HorizontalContentAlignment="Center"/>
<Button Margin="127,211,122,41" HorizontalAlignment="Center"
Style="{StaticResource MaterialDesignFloatingActionAccentButton}"
Background="White"
BorderBrush="#FFEA0000"
Command="{s:Action GotoProject}" Width="30" Height="Auto">
<materialDesign:PackIcon Kind="GithubCircle" Height="24" Width="24"/>
</Button>
</Grid>
<Button Command="{s:Action Confirm}" s:View.ActionTarget="{Binding}" Grid.Row="2" IsDefault="True" Style="{DynamicResource MaterialDesignRaisedButton}" Content="OK" Margin="10,0,10,10" Height="27" VerticalAlignment="Bottom"/>
</Grid>
</materialDesign:DialogHost>
</materialDesign:Card>
</Window>
@@ -1,29 +0,0 @@
using MaterialDesignThemes.Wpf;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace TIDALDL_UI.Pages
{
/// <summary>
/// Password.xaml 的交互逻辑
/// </summary>
public partial class AboutView : Window
{
public AboutView()
{
InitializeComponent();
}
}
}
@@ -1,27 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Stylet;
using AIGS.Helper;
using TIDALDL_UI.Properties;
using System.Windows.Media.Imaging;
namespace TIDALDL_UI.Pages
{
public class AboutViewModel:Screen
{
public string Version { get; set; } = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
public void Confirm()
{
RequestClose();
}
public void GotoProject()
{
NetHelper.OpenWeb("https://github.com/yaronzz/Tidal-Media-Downloader");
}
}
}
@@ -1,68 +0,0 @@
<Window x:Class="TIDALDL_UI.Pages.DllistView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TIDALDL_UI.Pages"
xmlns:s="https://github.com/canton7/Stylet"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
TextElement.FontWeight="Regular"
TextElement.FontSize="13"
TextOptions.TextFormattingMode="Ideal"
TextOptions.TextRenderingMode="Auto"
FontFamily="pack://application:,,,/MaterialDesignThemes.Wpf;component/Resources/Roboto/#Roboto"
WindowStartupLocation="CenterOwner"
WindowStyle="None"
Background="{x:Null}"
AllowsTransparency="True"
Width="920"
Height="540"
ShowInTaskbar="False"
mc:Ignorable="d"
Title="FilelistView"
d:DataContext="{d:DesignInstance local:DllistViewModel}">
<materialDesign:Card Name="m_CMainCard" materialDesign:ShadowAssist.ShadowDepth="Depth3" VerticalAlignment="Stretch" BorderThickness="3" BorderBrush="#FF171616" Margin="20,20,20,20">
<materialDesign:DialogHost Identifier="RootDialog" SnackbarMessageQueue="{Binding ElementName=MainSnackbar, Path=MessageQueue}" Background="{x:Null}">
<Grid Margin="16">
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="*" />
<RowDefinition Height="47" />
</Grid.RowDefinitions>
<!--head-->
<Label Content="DownloadList" Grid.Row="0" FontSize="30" VerticalAlignment="Top" Height="50" HorizontalContentAlignment="Center" BorderThickness="0,0,0,1" BorderBrush="#FFDEDEDE"/>
<!--body-->
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="359*"/>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="439*"/>
</Grid.ColumnDefinitions>
<TextBox Text="{Binding Text}" Grid.Column="0" AcceptsReturn="True" TextWrapping="Wrap" VerticalScrollBarVisibility="Auto" Background="Gainsboro" VerticalContentAlignment="Top"/>
<Button Command="{s:Action Convert}" Grid.Column="1" s:View.ActionTarget="{Binding}" Style="{DynamicResource MaterialDesignRaisedButton}" VerticalAlignment="Center" Margin="3,170,7,169" Padding="2,0" HorizontalAlignment="Center" Width="40">
<materialDesign:PackIcon Kind="ArrowRightBold" Foreground="White" Height="32" Width="32"/>
</Button>
<DataGrid Grid.Column="2" ItemsSource="{Binding Items}" CanUserSortColumns="False" CanUserAddRows="False" AutoGenerateColumns="False" Background="White"
materialDesign:DataGridAssist.CellPadding="4 2 2 2" SelectionUnit="FullRow"
materialDesign:DataGridAssist.ColumnHeaderPadding="4 2 2 2" GridLinesVisibility="Horizontal" BorderBrush="#FFDEDEDE"
VerticalGridLinesBrush="#FFDEDEDE" RowHeaderWidth="80" BorderThickness="1" Height="Auto">
<DataGrid.Columns>
<!--<DataGridCheckBoxColumn Binding="{Binding Check}" Header="Check" ElementStyle="{StaticResource MaterialDesignDataGridCheckBoxColumnStyle}" EditingElementStyle="{StaticResource MaterialDesignDataGridCheckBoxColumnEditingStyle}"/>-->
<DataGridTextColumn Header="#" Binding="{Binding Number}" IsReadOnly="True"/>
<DataGridTextColumn Header="ID/URL" Binding="{Binding Name}" IsReadOnly="True"/>
<DataGridTextColumn Header="Type" Binding="{Binding Type}" IsReadOnly="True"/>
<DataGridTextColumn Header="Status" Binding="{Binding Status}" IsReadOnly="True"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
<!--button-->
<materialDesign:Badged Badge="{Binding Errlabel}" Grid.Row="2" Margin="414,10,0,0" Width="197" BadgePlacementMode="TopLeft">
<Button Command="{s:Action Confirm}" s:View.ActionTarget="{Binding}" Style="{DynamicResource MaterialDesignRaisedButton}" Content="OK" Height="27" VerticalAlignment="Bottom" Width="197"/>
</materialDesign:Badged>
<Button Command="{s:Action Cancel}" s:View.ActionTarget="{Binding}" Grid.Row="2" IsDefault="True" Style="{DynamicResource MaterialDesignRaisedButton}" Content="CANCEL" Margin="0,0,10,10" Height="27" VerticalAlignment="Bottom" HorizontalAlignment="Right" Width="197"/>
</Grid>
</materialDesign:DialogHost>
</materialDesign:Card>
</Window>
@@ -1,27 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace TIDALDL_UI.Pages
{
/// <summary>
/// DllistView.xaml 的交互逻辑
/// </summary>
public partial class DllistView : Window
{
public DllistView()
{
InitializeComponent();
}
}
}
@@ -1,146 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TIDALDL_UI.Properties;
using Tidal;
using AIGS.Common;
using AIGS.Helper;
using System.Collections.ObjectModel;
using System.Threading;
using System.Windows;
using Stylet;
namespace TIDALDL_UI.Pages
{
public class DllistItem : Screen
{
public bool Check { get; set; }
public int Number { get; set; }
public string Name { get; set; }
public eObjectType Type { get; set; }
public string Status { get; set; } //wait-parse-err-success
public object Data { get; set; }
public DllistItem(int number, string name, eObjectType type)
{
Number = number;
Check = true;
Name = name;
Type = type;
Status = "Wait";
Data = null;
}
}
public class DllistViewModel : Screen
{
public string Errlabel { get; set; }
public string Text { get; set; } = Resources.DllistExample;
public ObservableCollection<DllistItem> Items { get; set; } = new ObservableCollection<DllistItem>();
private Thread ThreadHandle;
#region Button
public void Convert()
{
if (Text.IsBlank())
return;
Dllist plist = Tidal.TidalTool.getDllist(Text);
for (int i = 0; i < plist.AlbumIds.Count; i++)
{
AddToItems(Items.Count, plist.AlbumIds[i], eObjectType.ALBUM);
}
for (int i = 0; i < plist.TrackIds.Count; i++)
{
AddToItems(Items.Count, plist.TrackIds[i], eObjectType.TRACK);
}
for (int i = 0; i < plist.VideoIds.Count; i++)
{
AddToItems(Items.Count, plist.VideoIds[i], eObjectType.VIDEO);
}
for (int i = 0; i < plist.Urls.Count; i++)
{
AddToItems(Items.Count, plist.Urls[i], eObjectType.None);
}
for (int i = 0; i < plist.ArtistIds.Count; i++)
{
AddToItems(Items.Count, plist.ArtistIds[i], eObjectType.ARTIST);
}
if (ThreadHandle == null)
ThreadHandle = ThreadHelper.Start(ThreadFunc);
}
public void Confirm()
{
Errlabel = null;
for (int i = 0; i < Items.Count; i++)
{
if(Items[i].Status == "Wait" || Items[i].Status == "Parse")
{
Errlabel = "Some items in parsing.";
return;
}
}
ThreadHelper.Abort(ThreadHandle);
ThreadHandle = null;
RequestClose();
}
public void Cancel()
{
Errlabel = null;
Items.Clear();
ThreadHelper.Abort(ThreadHandle);
ThreadHandle = null;
RequestClose();
}
#endregion
~DllistViewModel()
{
ThreadHelper.Abort(ThreadHandle);
ThreadHandle = null;
}
private void AddToItems(int iNumber, string sName, eObjectType sType)
{
for (int i = 0; i < Items.Count; i++)
{
if (sName == Items[i].Name)
return;
}
Items.Add(new DllistItem(iNumber, sName, sType));
}
public void ThreadFunc(object[] data)
{
while (true)
{
for (int i = 0; i < Items.Count; i++)
{
if (Items[i].Status != "Wait")
continue;
Items[i].Status = "Parse";
//Get
eObjectType eType;
object Data = TidalTool.tryGet(Items[i].Name, out eType, Items[i].Type);
//Result
if (eType == eObjectType.None || Data == null)
Items[i].Status = "Err";
else
{
Items[i].Type = eType;
Items[i].Data = Data;
Items[i].Status = "Success";
}
}
Thread.Sleep(3000);
}
}
}
}
-87
View File
@@ -1,87 +0,0 @@
<Window x:Class="TIDALDL_UI.Pages.InfoView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:local="clr-namespace:TIDALDL_UI"
xmlns:pages="clr-namespace:TIDALDL_UI.Pages"
xmlns:s="https://github.com/canton7/Stylet"
mc:Ignorable="d"
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
TextElement.FontWeight="Regular"
TextElement.FontSize="13"
TextOptions.TextFormattingMode="Ideal"
TextOptions.TextRenderingMode="Auto"
FontFamily="pack://application:,,,/MaterialDesignThemes.Wpf;component/Resources/Roboto/#Roboto"
Width="620"
WindowStartupLocation="CenterOwner"
WindowStyle="None"
Background="{x:Null}"
AllowsTransparency="True"
Height="540"
ShowInTaskbar="False"
d:DataContext="{d:DesignInstance pages:InfoViewModel}">
<materialDesign:Card Name="m_CMainCard" materialDesign:ShadowAssist.ShadowDepth="Depth3" VerticalAlignment="Stretch" BorderThickness="3" BorderBrush="#FF171616" Margin="20,20,20,20">
<materialDesign:DialogHost Identifier="RootDialog" SnackbarMessageQueue="{Binding ElementName=MainSnackbar, Path=MessageQueue}" Background="{x:Null}">
<Grid Margin="16">
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="180" />
<RowDefinition Height="47*" />
</Grid.RowDefinitions>
<Label Content="{Binding Header}" Grid.Row="0" FontSize="30" VerticalAlignment="Top" Height="50" HorizontalContentAlignment="Center" BorderThickness="0,0,0,1" BorderBrush="#FFDEDEDE"/>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="180"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Image Source="{Binding Cover}" Margin="0,10,0,0"/>
<Label Content="{Binding Title}" FontSize="28" VerticalAlignment="Top" Grid.Column="1" Height="45" FontWeight="ExtraBlack" />
<Label Content="{Binding Intro}" FontSize="13" VerticalAlignment="Top" Margin="0,45,0,0" Grid.Column="1" Height="25" />
<Label Content="{Binding ReleaseDate}" FontSize="13" VerticalAlignment="Top" Margin="0,70,0,0" Grid.Column="1" Height="25" />
<Button Grid.Column="1" IsDefault="True" Style="{DynamicResource MaterialDesignRaisedButton}"
Command="{s:Action Confirm}"
Content="Download"
Height="27" VerticalAlignment="Bottom" Margin="5,0,189,8"/>
<Button Grid.Column="1" IsDefault="True" Style="{DynamicResource MaterialDesignRaisedButton}"
Command="{s:Action Cancel}"
Content="Cancel"
Height="27" VerticalAlignment="Bottom" Margin="184,0,23,8"/>
</Grid>
<!--<ListView Grid.Row="3" ItemsSource="{Binding ItemList}" ScrollViewer.HorizontalScrollBarVisibility="Hidden" >
<ListView.View>
<GridView>
<GridViewColumn Header="#" Width="40" DisplayMemberBinding="{Binding Number}"/>
<GridViewColumn Header="TITLE" Width="230" DisplayMemberBinding="{Binding Title}"/>
<GridViewColumn Header="ALBUM" Width="130" DisplayMemberBinding="{Binding AlbumTitle}"/>
<GridViewColumn Header="TIME" DisplayMemberBinding="{Binding Duration}"/>
</GridView>
</ListView.View>
</ListView>-->
<DataGrid Grid.Row="3" ItemsSource="{Binding ItemList}" CanUserSortColumns="False" CanUserAddRows="False" AutoGenerateColumns="False" Background="White"
materialDesign:DataGridAssist.CellPadding="12 6 8 4" RowHeight="32" SelectionUnit="FullRow"
materialDesign:DataGridAssist.ColumnHeaderPadding="4" GridLinesVisibility="Horizontal"
VerticalGridLinesBrush="#FFDEDEDE" RowHeaderWidth="80" BorderThickness="0" Height="Auto">
<DataGrid.Columns>
<DataGridCheckBoxColumn Binding="{Binding Check}" Header="#" ElementStyle="{StaticResource MaterialDesignDataGridCheckBoxColumnStyle}" EditingElementStyle="{StaticResource MaterialDesignDataGridCheckBoxColumnEditingStyle}"/>
<DataGridTextColumn Header="#" Width="40" Binding="{Binding Number}" IsReadOnly="True"/>
<DataGridTextColumn Header="#" Width="40" Binding="{Binding Flag}" IsReadOnly="True"/>
<DataGridTextColumn Header="TITLE" Width="205" Binding="{Binding Title}" IsReadOnly="True"/>
<DataGridTextColumn Header="ALBUM" Width="115" Binding="{Binding AlbumTitle}" IsReadOnly="True"/>
<DataGridTextColumn Header="TIME" Binding="{Binding Duration}" IsReadOnly="True"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
</materialDesign:DialogHost>
</materialDesign:Card>
</Window>
@@ -1,30 +0,0 @@
using AIGS.Helper;
using MaterialDesignThemes.Wpf;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace TIDALDL_UI.Pages
{
/// <summary>
/// AlbumInfo.xaml 的交互逻辑
/// </summary>
public partial class InfoView : Window
{
public InfoView()
{
InitializeComponent();
}
}
}
@@ -1,196 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media.Imaging;
using Tidal;
using AIGS.Helper;
using AIGS.Common;
using System.Collections.ObjectModel;
using TIDALDL_UI.Else;
using Stylet;
using System.Windows;
namespace TIDALDL_UI.Pages
{
public class InfoItem : Screen
{
public int Number { get; set; }
public string Title { get; set; }
public string Type { get; set; }
public string Flag { get; set; }
public string Duration { get; set; }
public string AlbumTitle { get; set; }
public bool Check { get; set; }
public object Data { get; set; }
public InfoItem(int number, string title, string duration, string albumtitle,object data = null, string type="TRACK", string flag = "")
{
Check = true;
Number = number;
Flag = flag;
Title = title;
Type = type;
Duration = duration;
AlbumTitle = albumtitle;
Data = data;
}
}
public class InfoViewModel:Screen
{
public string Header { get; private set; }
public string Title { get; private set; }
public string Intro { get; private set; }
public string ReleaseDate { get; private set; }
public BitmapImage Cover { get; private set; }
public bool Result { get; set; }
public object Data { get; set; }
/// <summary>
/// Item List
/// </summary>
public ObservableCollection<InfoItem> ItemList { get; private set; }
#region Button
public void Confirm()
{
Result = RemoveItems();
RequestClose();
}
public void Cancel()
{
Result = false;
RequestClose();
}
#endregion
public object Load(object data)
{
Data = data;
if (data.GetType() == typeof(Playlist))
{
Playlist plist = (Playlist)data;
Header = "PLAYLISTINFO";
Title = plist.Title;
//Intro = string.Format("by {0}-{1} Tracks-{2} Videos-{3}", plist.Created, TimeHelper.ConverIntToString(plist.Duration), plist.NumberOfTracks, plist.NumberOfVideos);
Intro = string.Format("{0} Tracks-{1} Videos-{2}", TimeHelper.ConverIntToString(plist.Duration), plist.NumberOfTracks, plist.NumberOfVideos);
Cover = AIGS.Common.Convert.ConverByteArrayToBitmapImage(plist.CoverData);
ReleaseDate = "";
ItemList = new ObservableCollection<InfoItem>();
if (plist.Tracks != null)
{
foreach (Track item in plist.Tracks)
ItemList.Add(new InfoItem(plist.Tracks.IndexOf(item) + 1, item.Title, TimeHelper.ConverIntToString(item.Duration), item.Album.Title, item, flag:TidalTool.getFlag(item)));
}
if (plist.Videos != null)
{
foreach (Video item in plist.Videos)
ItemList.Add(new InfoItem(plist.Tracks.Count + plist.Videos.IndexOf(item) + 1, item.Title, TimeHelper.ConverIntToString(item.Duration), item.Title, item, "VIDEO"));
}
}
else if (data.GetType() == typeof(Artist))
{
Artist artist = (Artist)data;
Header = "ARTISTINFO";
Title = artist.Name;
Intro = string.Format("by {0} Albums-{1}", artist.Name, artist.Albums.Count);
Cover = AIGS.Common.Convert.ConverByteArrayToBitmapImage(artist.CoverData);
ReleaseDate = "";
ItemList = new ObservableCollection<InfoItem>();
if (artist.Albums != null)
{
foreach (Album item in artist.Albums)
ItemList.Add(new InfoItem(artist.Albums.IndexOf(item) + 1, item.Title, TimeHelper.ConverIntToString(item.Duration), item.Title, item, "ALBUM", flag: TidalTool.getFlag(item)));
}
}
else if (data.GetType() == typeof(Album))
{
Album album = (Album)data;
Header = "ALBUMINFO";
Title = album.Title;
Intro = string.Format("by {0}-{1} Tracks-{2} Videos-{3}", album.Artist.Name, TimeHelper.ConverIntToString(album.Duration), album.NumberOfTracks, album.NumberOfVideos);
Cover = AIGS.Common.Convert.ConverByteArrayToBitmapImage(album.CoverData);
ReleaseDate = "Release date " + album.ReleaseDate;
ItemList = new ObservableCollection<InfoItem>();
if (album.Tracks != null)
{
foreach (Track item in album.Tracks)
ItemList.Add(new InfoItem(item.TrackNumber, item.Title, TimeHelper.ConverIntToString(item.Duration), item.Album.Title, item, flag: TidalTool.getFlag(item)));
}
if (album.Videos != null)
{
foreach (Video item in album.Videos)
ItemList.Add(new InfoItem(item.TrackNumber, item.Title, TimeHelper.ConverIntToString(item.Duration), item.Album.Title, item, "VIDEO"));
}
}
else if (data.GetType() == typeof(Video))
{
Video video = (Video)data;
Header = "VIDEOINFO";
Title = video.Title;
Cover = AIGS.Common.Convert.ConverByteArrayToBitmapImage(video.CoverData);
Intro = string.Format("by {0}-{1}", video.Artist.Name, TimeHelper.ConverIntToString(video.Duration));
ReleaseDate = "Release date " + video.ReleaseDate;
ItemList = new ObservableCollection<InfoItem>();
ItemList.Add(new InfoItem(0, video.Title, TimeHelper.ConverIntToString(video.Duration), video.Album == null ? "" : video.Album.Title, data, "VIDEO"));
}
return data;
}
private bool RemoveItems()
{
for (int i = 0; i < ItemList.Count; i++)
{
if (ItemList[i].Check)
continue;
if (Data.GetType() == typeof(Video) || Data.GetType() == typeof(Track))
return false;
if (Data.GetType() == typeof(Album))
{
Album album = (Album)Data;
if (ItemList[i].Type == "TRACK")
album.Tracks.Remove((Track)ItemList[i].Data);
else
album.Videos.Remove((Video)ItemList[i].Data);
}
if (Data.GetType() == typeof(Playlist))
{
Playlist plist = (Playlist)Data;
if (ItemList[i].Type == "TRACK")
plist.Tracks.Remove((Track)ItemList[i].Data);
else
plist.Videos.Remove((Video)ItemList[i].Data);
}
if (Data.GetType() == typeof(Artist))
{
Artist artist = (Artist)Data;
artist.Albums.Remove((Album)ItemList[i].Data);
}
}
if (Data.GetType() == typeof(Album))
{
Album album = (Album)Data;
if (album.Tracks.Count <= 0 && album.Videos.Count <= 0)
return false;
}
if (Data.GetType() == typeof(Artist))
{
Artist artist = (Artist)Data;
if (artist.Albums.Count <= 0)
return false;
}
if (Data.GetType() == typeof(Playlist))
{
Playlist plist = (Playlist)Data;
if (plist.Tracks.Count <= 0 && plist.Videos.Count <= 0)
return false;
}
return true;
}
}
}
-104
View File
@@ -1,104 +0,0 @@
<Window x:Class="TIDALDL_UI.Pages.LoginView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:s="https://github.com/canton7/Stylet"
xmlns:local="clr-namespace:TIDALDL_UI"
xmlns:pages="clr-namespace:TIDALDL_UI.Pages"
xmlns:else="clr-namespace:TIDALDL_UI.Else"
xmlns:aigsc="clr-namespace:AIGS.Control;assembly=AIGS"
xmlns:aigs="clr-namespace:AIGS.Common;assembly=AIGS"
mc:Ignorable="d"
TextElement.FontWeight="Regular"
TextElement.FontSize="13"
TextOptions.TextFormattingMode="Ideal"
TextOptions.TextRenderingMode="Auto"
FontFamily="pack://application:,,,/MaterialDesignThemes.Wpf;component/Resources/Roboto/#Roboto"
Title="Tidal-gui"
Width="515"
Height="415" WindowStyle="None" AllowsTransparency="True" Background="{x:Null}"
d:DataContext="{d:DesignInstance pages:LoginViewModel}">
<Grid>
<materialDesign:Card materialDesign:ShadowAssist.ShadowDepth="Depth3" VerticalAlignment="Top" HorizontalAlignment="Left" Width="430" BorderThickness="3" BorderBrush="#FF171616" Margin="45,40,0,0" Height="330">
<materialDesign:DialogHost Identifier="RootDialog" SnackbarMessageQueue="{Binding ElementName=MainSnackbar, Path=MessageQueue}">
<Grid Height="329" >
<Grid.RowDefinitions>
<RowDefinition Height="182"/>
<RowDefinition/>
</Grid.RowDefinitions>
<!--Cover Grid-->
<Grid Background="Black" MouseLeftButtonDown="Grid_MouseLeftButtonDown" Margin="0,-10,0,124" Grid.RowSpan="2" Grid.ColumnSpan="2">
<Image Margin="-10,-10,0,0" Source="pack://application:,,,/resource/tidal.jpg" />
<!--<Button Command="{s:Action RequestClose}" s:View.ActionTarget="{Binding}" Margin="404,0,0,180" VerticalAlignment="Bottom" HorizontalAlignment="Left" Width="26" Padding="0" Height="25" BorderBrush="{x:Null}" Background="{x:Null}">
<materialDesign:PackIcon Kind="Close" Height="22" Width="26" Foreground="White" />
</Button>
<Button Command="{s:Action Setting}" s:View.ActionTarget="{Binding}" Margin="380,0,0,180" VerticalAlignment="Bottom" HorizontalAlignment="Left" Width="24" Padding="0" Height="25" BorderBrush="{x:Null}" Background="{x:Null}">
<materialDesign:PackIcon Kind="CloudSync" Height="22" Width="26" Foreground="White" />
</Button>-->
</Grid>
<!--Login Page-->
<Grid Grid.Row="1" Background="White" Grid.ColumnSpan="2">
<ComboBox Margin="115,10,0,0" materialDesign:HintAssist.Hint=" UserName" Background="White" IsEditable="True" VerticalAlignment="Top" BorderThickness="1" Height="28" Width="195" HorizontalAlignment="Left"
Text="{Binding Username, UpdateSourceTrigger=PropertyChanged}"
DisplayMemberPath="Key"
SelectedValuePath="Key"
SelectedIndex="{Binding SelectIndex, UpdateSourceTrigger=PropertyChanged}"
SelectionChanged="{s:Action SelectChange}"
ItemsSource="{Binding PersonList, UpdateSourceTrigger=PropertyChanged}" Padding="2,6,0,6" BorderBrush="#899C9494"/>
<PasswordBox Margin="115,38,0,0" materialDesign:HintAssist.Hint=" Password" Background="White" Height="28" Width="195" aigsc:PasswordBoxHelper.Attach="True" aigsc:PasswordBoxHelper.Password="{Binding Path=Password,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" BorderThickness="1,1,1,1" HorizontalAlignment="Left" VerticalAlignment="Top" BorderBrush="#899C9494" />
<CheckBox Content="Remember" Margin="115,66,0,56" HorizontalAlignment="Left" Width="90" IsChecked="{Binding Remember,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
<CheckBox Content="AutoLogin" Margin="216,66,0,56" HorizontalAlignment="Left" Width="94" IsChecked="{Binding AutoLogin,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
<materialDesign:Badged Badge="{Binding Errlabel, UpdateSourceTrigger=PropertyChanged}" Margin="115,96,0,0">
<Button Command="{s:Action Confirm}" s:View.ActionTarget="{Binding}" Name="m_CLogin" Content="LOG IN" HorizontalAlignment="Left" Width="195" Height="30" IsDefault="True"/>
</materialDesign:Badged>
</Grid>
<!--Wait Page-->
<Grid Grid.Row="1" Background="White" Name="m_CWaitPage" Visibility="{Binding WaitVisibility, UpdateSourceTrigger=PropertyChanged}" Grid.ColumnSpan="2">
<materialDesign:Chip
Background="LightGray"
Content="{Binding Username, UpdateSourceTrigger=PropertyChanged}"
IconBackground="{DynamicResource PrimaryHueDarkBrush}"
IconForeground="{DynamicResource PrimaryHueDarkForegroundBrush}" Margin="105,38,0,74" Height="Auto" Width="215">
<materialDesign:Chip.Icon>
<materialDesign:PackIcon Kind="AccountCircle" Height="25" Width="30" />
</materialDesign:Chip.Icon>
</materialDesign:Chip>
<Button Command="{s:Action Cancle}" Content="CANCLE" Margin="115,0,0,24" HorizontalAlignment="Left" Width="195" Height="27" VerticalAlignment="Bottom"/>
</Grid>
<!--Proxy Page-->
<Grid Grid.RowSpan="2" Background="LightGray" Visibility="{Binding ProxyViewShow,UpdateSourceTrigger=PropertyChanged,Converter={x:Static s:BoolToVisibilityConverter.Instance}}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="29*"/>
<ColumnDefinition Width="57*"/>
</Grid.ColumnDefinitions>
<Label Content="HttpProxy" FontSize="15" VerticalAlignment="Top" HorizontalContentAlignment="Right" Height="30" Margin="0,95,0,0" />
<Label Content="Host" FontSize="15" VerticalAlignment="Top" HorizontalContentAlignment="Right" Height="30" Margin="0,125,0,0" />
<Label Content="Port" FontSize="15" VerticalAlignment="Top" HorizontalContentAlignment="Right" Height="30" Margin="0,155,0,0" />
<Label Content="Username" FontSize="15" VerticalAlignment="Top" HorizontalContentAlignment="Right" Height="30" Margin="0,185,0,0" />
<Label Content="Password" FontSize="15" VerticalAlignment="Top" HorizontalContentAlignment="Right" Height="30" Margin="0,215,0,0" />
<ToggleButton Grid.Column="1" IsChecked="{Binding ProxyEnable}" Style="{StaticResource MaterialDesignSwitchToggleButton}" Margin="0,95,220,204" Height="30"/>
<TextBox Grid.Column="1" Text="{Binding ProxyHost}" IsEnabled="{Binding ProxyEnable}" Margin="10,126,80,173" Height="30"/>
<TextBox Grid.Column="1" Text="{Binding ProxyPort}" IsEnabled="{Binding ProxyEnable}" Margin="10,154,80,145" Height="30"/>
<TextBox Grid.Column="1" Text="{Binding ProxyUser}" IsEnabled="{Binding ProxyEnable}" Margin="10,184,80,115" Height="30"/>
<TextBox Grid.Column="1" Text="{Binding ProxyPwd}" IsEnabled="{Binding ProxyEnable}" Margin="10,214,80,85" Height="30"/>
</Grid>
<Button Command="{s:Action RequestClose}" s:View.ActionTarget="{Binding}" VerticalAlignment="Top" HorizontalAlignment="Right" Width="26" Padding="0" Height="25" BorderBrush="{x:Null}" Background="{x:Null}">
<materialDesign:PackIcon Kind="Close" Height="22" Width="26" Foreground="White" />
</Button>
<Button Command="{s:Action Setting}" s:View.ActionTarget="{Binding}" VerticalAlignment="Top" Width="24" Padding="0" Height="25" BorderBrush="{x:Null}" Background="{x:Null}" Margin="375,0,31,0">
<materialDesign:PackIcon Kind="CloudSync" Height="22" Width="26" Foreground="White" />
</Button>
</Grid>
</materialDesign:DialogHost>
</materialDesign:Card>
</Grid>
</Window>
@@ -1,29 +0,0 @@
using MaterialDesignThemes.Wpf;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace TIDALDL_UI.Pages
{
public partial class LoginView
{
public LoginView()
{
InitializeComponent();
}
private void Grid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
DragMove();
}
}
}
@@ -1,149 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using Stylet;
using System.ComponentModel;
using System.Collections.ObjectModel;
using AIGS.Common;
using AIGS.Helper;
using Tidal;
using System.Windows;
using TIDALDL_UI.Else;
using System.Windows.Threading;
namespace TIDALDL_UI.Pages
{
public class LoginViewModel: Screen
{
public string Errlabel { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public bool Remember { get; set; }
public bool AutoLogin { get; set; }
/// <summary>
/// History AccountList
/// </summary>
public ObservableCollection<Property> PersonList { get; private set; }
public int SelectIndex { get; set; }
/// <summary>
/// Show Wait Page
/// </summary>
public Visibility WaitVisibility { get; set; }
/// <summary>
/// Proxy
/// </summary>
public bool ProxyViewShow { get;set; } = false;
public bool ProxyEnable { get;set; } = Config.ProxyEnable();
public string ProxyHost { get; set; } = Config.ProxyHost();
public int ProxyPort { get; set; } = Config.ProxyPort();
public string ProxyUser { get; set; } = Config.ProxyUser();
public string ProxyPwd { get; set; } = Config.ProxyPwd();
/// <summary>
/// View
/// </summary>
private IWindowManager Manager;
private MainViewModel VMMain;
public LoginViewModel(IWindowManager manager, MainViewModel vmmain)
{
Manager = manager;
VMMain = vmmain;
PersonList = new ObservableCollection<Property>();
Remember = Config.Remember();
AutoLogin = Config.AutoLogin();
ShowMainPage(true);
//Read History Account
List<Property> pList = Config.HistoryAccounts();
for (int i = 0; i < pList.Count; i++)
PersonList.Add(pList[i]);
//If AutoLogin
if(AutoLogin && pList.Count > 0)
{
Username = pList[0].Key.ToString();
Password = pList[0].Value.ToString();
Confirm();
}
return;
}
#region Common
public void SelectChange()
{
if (SelectIndex >= 0 && SelectIndex <= PersonList.Count)
Password = PersonList[SelectIndex].Value.ToString();
}
public void ShowMainPage(bool bFlag)
{
WaitVisibility = bFlag ? Visibility.Hidden : Visibility.Visible;
}
#endregion
#region Button
public async void Confirm()
{
Errlabel = "";
if (Username.IsBlank() || Password.IsBlank())
{
Errlabel = "Username or password is err!";
return;
}
Config.AddHistoryAccount(Username, Password);
ShowMainPage(false);
//Proxy
TidalTool.PROXY = ProxyEnable ? new HttpHelper.ProxyInfo(ProxyHost, ProxyPort, ProxyUser, ProxyPwd) : null;
bool bRet = await Task.Run(() => { return TidalTool.login(Username, Password);});
if (!bRet)
Errlabel = "Login Err! " + TidalTool.loginErrlabel;
else
{
//DEBUG
//eObjectType eType = eObjectType.None;
//object obj = Tidal.TidalTool.tryGet("19297475", out eType, eObjectType.ALBUM);
//Artist obj = (Artist)Tidal.TidalTool.tryGet("eason chan", out eType, eObjectType.ARTIST);
VMMain.SetLogViewModel(this);
Manager.ShowWindow(VMMain);
RequestClose();
}
ShowMainPage(true);
return;
}
public void Cancle()
{
ShowMainPage(true);
}
public void Setting()
{
if(!ProxyViewShow)
{
ProxyViewShow = true;
return;
}
else
{
ProxyViewShow = false;
Config.ProxyEnable(ProxyEnable.ToString());
Config.ProxyHost(ProxyHost);
Config.ProxyPort(ProxyPort.ToString());
Config.ProxyUser(ProxyUser);
Config.ProxyPwd(ProxyPwd);
}
}
#endregion
}
}
@@ -1,92 +0,0 @@
<UserControl x:Class="TIDALDL_UI.Pages.MainListItemView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:TIDALDL_UI"
xmlns:pages="clr-namespace:TIDALDL_UI.Pages"
xmlns:s="https://github.com/canton7/Stylet"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
mc:Ignorable="d"
Background="Red"
d:DataContext="{d:DesignInstance pages:MainListItemViewModel}">
<Border Padding="0" BorderThickness="0 0 0 1" BorderBrush="{DynamicResource MaterialDesignDivider}">
<Expander ExpandDirection="Down" Padding="0" IsExpanded="True">
<Expander.Header>
<Grid Height="64" Margin="-20,-8">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<!-- Thumbnail -->
<Image Grid.Column="0" Source="{Binding Cover}" Width="64" Margin="0"/>
<!-- Title -->
<StackPanel Margin="8 0 0 0" Grid.Column="1">
<TextBlock Text="{Binding Title}" FontSize="15" FontWeight="Bold" TextTrimming="CharacterEllipsis"/>
<TextBlock Text="{Binding Desc}" FontSize="12" />
</StackPanel>
<!-- Progress and completion status -->
<!--<TextBlock Grid.Column="2" Margin="4" Width="80" VerticalAlignment="Center"
Text="{Binding Progress.Status, UpdateSourceTrigger=PropertyChanged}"
Foreground="{Binding Progress.StatusColor,UpdateSourceTrigger=PropertyChanged}"/>-->
<!-- Button -->
<StackPanel Grid.Column="3" Margin="4" VerticalAlignment="Center" Orientation="Horizontal">
<Button Command="{s:Action CancelAndRestart}" Padding="4,0,4,0" ToolTip="{Binding ButtonTip}" VerticalAlignment="Center" Style="{DynamicResource MaterialDesignFlatButton}">
<materialDesign:PackIcon Width="24" Height="24" Kind="{Binding ButtonKind}" />
</Button>
<Button Command="{s:Action Delete}" Padding="4,0,4,0" ToolTip="Delete" VerticalAlignment="Center" Style="{DynamicResource MaterialDesignFlatButton}">
<materialDesign:PackIcon Width="24" Height="24" Kind="TrashCircle" />
</Button>
<Button Command="{s:Action OpenBasePath}" Padding="4,0,4,0" VerticalAlignment="Center" ToolTip="Open" Style="{DynamicResource MaterialDesignFlatButton}">
<materialDesign:PackIcon Width="24" Height="24 " Kind="FileFind" />
</Button>
</StackPanel>
</Grid>
</Expander.Header>
<!-- Download List -->
<Grid Background="{DynamicResource {x:Static SystemColors.InactiveBorderBrushKey}}" >
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto" Visibility="{Binding DLItemList.Count, Converter={x:Static s:BoolToVisibilityConverter.Instance}}">
<ItemsControl ItemsSource="{Binding DLItemList}" Grid.IsSharedSizeScope="True">
<ItemsControl.ItemTemplate>
<DataTemplate >
<Border Padding="0" BorderThickness="0 1 0 1" BorderBrush="{DynamicResource MaterialDesignDivider}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="39*"/>
<RowDefinition Height="{Binding ErrlabelHeight,UpdateSourceTrigger=PropertyChanged}"/>
</Grid.RowDefinitions>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Index}" TextAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" Width="30"/>
<TextBlock Grid.Column="1" Text="{Binding Title}" FontWeight="Bold" VerticalAlignment="Center"/>
<TextBlock Grid.Column="2" Text="{Binding Own}" VerticalAlignment="Center" Padding="5,0" FontStretch="Expanded" FontStyle="Italic"/>
<!--<TextBlock Grid.Column="3" Text="{Binding sType}" VerticalAlignment="Center" Padding="5,0"/>-->
<materialDesign:PackIcon Grid.Column="3" Width="24" Height="24" Kind="{Binding sType}" VerticalAlignment="Center" Margin="5,0"/>
<ProgressBar Grid.Column="4" Width="200" Height="10" Margin="0,13,0,13"
Maximum="100"
Value="{Binding Progress.Value,Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" />
<TextBlock Grid.Column="5" Margin="4" Width="80" VerticalAlignment="Center"
Text="{Binding Progress.StatusMsg,UpdateSourceTrigger=PropertyChanged}"
Foreground="{Binding Progress.StatusColor,UpdateSourceTrigger=PropertyChanged}"/>
</Grid>
<TextBlock Grid.Row="1" Grid.Column="0" Text="{Binding Progress.Errmsg,UpdateSourceTrigger=PropertyChanged}" Width="Auto" Margin="30,0,157,0" Foreground="#FFF72A2A"/>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
</Expander>
</Border>
</UserControl>
@@ -1,28 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace TIDALDL_UI.Pages
{
/// <summary>
/// MainListItemView.xaml 的交互逻辑
/// </summary>
public partial class MainListItemView : UserControl
{
public MainListItemView()
{
InitializeComponent();
}
}
}
@@ -1,137 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AIGS.Helper;
using AIGS.Common;
using Stylet;
using System.Windows.Media.Imaging;
using Tidal;
using System.Diagnostics;
using TIDALDL_UI.Else;
using System.Collections.ObjectModel;
using System.Windows;
using System.IO;
namespace TIDALDL_UI.Pages
{
public class MainListItemViewModel : Screen
{
public string Title { get; private set; }
public string Desc { get; set; }
public BitmapImage Cover { get; private set; }
public string BasePath { get; private set; }
public int AddYear { get; set; }
public ObservableCollection<DownloadItem> DLItemList { get; set; }
private BindableCollection<MainListItemViewModel> Parents { get; set; }
public string ButtonKind { get; set; } = "CloseCircle";
public string ButtonTip { get; set; } = "Cancel";
public MainListItemViewModel(object data, BindableCollection<MainListItemViewModel> parents)
{
AddYear = Config.AddYear();
Parents = parents;
DLItemList = new ObservableCollection<DownloadItem>();
if (data.GetType() == typeof(Album))
{
Album album = (Album)data;
Title = album.Title;
BasePath = TidalTool.getAlbumFolder(Config.OutputDir(), album, AddYear);
Desc = string.Format("by {0}-{1} Tracks-{2} Videos-{3}", album.Artist.Name, TimeHelper.ConverIntToString(album.Duration), album.NumberOfTracks, album.NumberOfVideos);
Cover = AIGS.Common.Convert.ConverByteArrayToBitmapImage(album.CoverData);
AddAlbum(album);
}
else if (data.GetType() == typeof(Video))
{
Video video = (Video)data;
Title = video.Title;
BasePath = TidalTool.getVideoFolder(Config.OutputDir());
Desc = string.Format("by {0}-{1}", video.Artist.Name, TimeHelper.ConverIntToString(video.Duration));
Cover = AIGS.Common.Convert.ConverByteArrayToBitmapImage(video.CoverData);
DLItemList.Add(new DownloadItem(DLItemList.Count + 1, null, video, null));
}
else if(data.GetType() == typeof(Artist))
{
Artist artist = (Artist)data;
Title = artist.Name;
BasePath = TidalTool.getArtistFolder(Config.OutputDir(), artist);
Desc = string.Format("by {0} Albums-{1}", artist.Name, artist.Albums.Count);
Cover = AIGS.Common.Convert.ConverByteArrayToBitmapImage(artist.CoverData);
foreach (var item in artist.Albums)
AddAlbum(item);
}
else if(data.GetType() == typeof(Playlist))
{
Playlist plist = (Playlist)data;
Title = plist.Title;
BasePath = TidalTool.getPlaylistFolder(Config.OutputDir(), plist);
//Desc = string.Format("by {0}-{1} Tracks-{2} Videos-{3}", plist.Created, TimeHelper.ConverIntToString(plist.Duration), plist.NumberOfTracks, plist.NumberOfVideos);
Desc = string.Format("{0} Tracks-{1} Videos-{2}", TimeHelper.ConverIntToString(plist.Duration), plist.NumberOfTracks, plist.NumberOfVideos);
Cover = AIGS.Common.Convert.ConverByteArrayToBitmapImage(plist.CoverData);
foreach (Track item in plist.Tracks)
DLItemList.Add(new DownloadItem(DLItemList.Count + 1, item, null, album: null, plist:plist));
foreach (Video item in plist.Videos)
DLItemList.Add(new DownloadItem(DLItemList.Count + 1, null, item, album: null, plist: plist));
}
PathHelper.Mkdirs(BasePath);
}
private void AddAlbum(Album album)
{
if (Config.SaveCovers())
{
string CoverPath = TidalTool.getAlbumCoverPath(Config.OutputDir(), album, AddYear);
FileHelper.Write(album.CoverData, true, CoverPath);
}
foreach (Track item in album.Tracks)
DLItemList.Add(new DownloadItem(DLItemList.Count +1, item, null, album: album));
foreach (Video item in album.Videos)
DLItemList.Add(new DownloadItem(DLItemList.Count + 1, null, item, album: album));
}
public void StartWork()
{
foreach (DownloadItem item in DLItemList)
item.Start();
}
#region Button
public void CancelAndRestart()
{
if (ButtonKind == "CloseCircle")
{
foreach (DownloadItem item in DLItemList)
item.Cancel();
ButtonKind = "Restart";
ButtonTip = "Restart";
}
else
{
foreach (DownloadItem item in DLItemList)
item.Restart();
ButtonKind = "CloseCircle";
ButtonTip = "Cancel";
}
}
public void Delete()
{
foreach (DownloadItem item in DLItemList)
item.Cancel();
Parents.Remove(this);
}
public void OpenBasePath()
{
Process.Start(BasePath);
}
#endregion
}
}
-118
View File
@@ -1,118 +0,0 @@
<Window x:Class="TIDALDL_UI.Pages.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:local="clr-namespace:TIDALDL_UI"
xmlns:pages="clr-namespace:TIDALDL_UI.Pages"
xmlns:aigs="clr-namespace:AIGS.Common;assembly=AIGS"
xmlns:s="https://github.com/canton7/Stylet"
mc:Ignorable="d"
WindowStyle="None"
Background="{x:Null}"
AllowsTransparency="True"
Title="Tidal-gui" Height="710" Width="1060"
d:DataContext="{d:DesignInstance pages:MainViewModel}">
<Window.Resources>
<aigs:UnBoolConverter x:Key="ConverterUnbool" />
<aigs:StringNotEmptyToBallConverter x:Key="ConverterStringNotEmpty" />
</Window.Resources>
<Grid>
<materialDesign:Card materialDesign:ShadowAssist.ShadowDepth="Depth3" VerticalAlignment="Stretch" BorderThickness="3" BorderBrush="#FF171616" Margin="20,20,20,20">
<materialDesign:DialogHost Identifier="RootDialog" SnackbarMessageQueue="{Binding ElementName=MainSnackbar, Path=MessageQueue}" Background="{x:Null}">
<Grid>
<!--Head Part-->
<materialDesign:ColorZone Mode="PrimaryMid" Padding="10" MouseLeftButtonDown="ColorZone_MouseLeftButtonDown" >
<DockPanel>
<Button DockPanel.Dock="Right" Command="{s:Action WindowClose}" s:View.ActionTarget="{Binding}" Padding="0" Width="24" Height="24" Background="Red">
<materialDesign:PackIcon Kind="Close" Height="22" Width="22" Foreground="White" />
</Button>
<Button DockPanel.Dock="Right" Command="{s:Action WindowMax}" s:View.ActionTarget="{Binding}" Padding="0" Width="24" Height="24" Background="{x:Null}">
<materialDesign:PackIcon Kind="WindowMaximize" Height="22" Width="22" />
</Button>
<Button DockPanel.Dock="Right" Command="{s:Action WindowMin}" s:View.ActionTarget="{Binding}" Padding="0" Width="24" Height="24" Background="{x:Null}">
<materialDesign:PackIcon Kind="WindowMinimize" Height="22" Width="22" />
</Button>
<materialDesign:PopupBox DockPanel.Dock="Right" PlacementMode="BottomAndAlignRightEdges" Padding="0" Height="24" Width="35">
<StackPanel>
<Button Content="Logout" Click="{s:Action Logout}"></Button>
<Button Content="Setting" Click="{s:Action Setting}"></Button>
<Button Content="About" Click="{s:Action About}"></Button>
<Button Content="FeedBack" Click="{s:Action FeedBack}"></Button>
</StackPanel>
</materialDesign:PopupBox>
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" materialDesign:RippleAssist.IsCentered="True">
<materialDesign:PackIcon Kind="MusicCircleOutline" Height="Auto" Width="30" HorizontalAlignment="Left" Padding="0,4" VerticalAlignment="Stretch"/>
<TextBlock Text="TIDAL-GUI" FontWeight="Bold" VerticalAlignment="Center" Margin="0 0 0 0" FontSize="18" Padding="4,0,0,0"/>
<materialDesign:ColorZone IsEnabled="{Binding Path=InSearch, Converter={StaticResource ConverterUnbool}}" Mode="Standard" Padding="4 0 4 0" Panel.ZIndex="1" Margin="16 0 0 0" materialDesign:ShadowAssist.ShadowDepth="Depth1" Width="673">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="26" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Style="{DynamicResource MaterialDesignToolButton}" ToolTip="{Binding SearchHelperTip}">
<materialDesign:PackIcon Kind="QuestionMarkCircle" Opacity=".56" />
</Button>
<TextBox Grid.Column="1"
Margin="2,4,26,4"
Text="{Binding SearchStr, UpdateSourceTrigger=PropertyChanged}"
materialDesign:HintAssist.Hint="Enter ID\Title\Url"
materialDesign:TextFieldAssist.DecorationVisibility="Hidden"
BorderThickness="0"
MinWidth="200"
PreviewMouseDoubleClick="TextBox_PreviewMouseDoubleClick"
VerticalAlignment="Center" Grid.ColumnSpan="2" />
<Button Grid.Column="2" Command="{s:Action Search}" s:View.ActionTarget="{Binding}" Style="{DynamicResource MaterialDesignToolButton}" IsDefault="True" Margin="0,2,31,2" HorizontalAlignment="Right" Width="29">
<materialDesign:PackIcon Kind="Magnify" Opacity=".56" />
</Button>
<Button Grid.Column="2" Command="{s:Action OpenDllist}" s:View.ActionTarget="{Binding}" Style="{DynamicResource MaterialDesignToolButton}" Margin="0,2" HorizontalAlignment="Right" Width="31">
<materialDesign:PackIcon Kind="FileDocumentBoxOutline" Opacity=".56" />
</Button>
</Grid>
</materialDesign:ColorZone>
<ProgressBar Style="{StaticResource MaterialDesignCircularProgressBar}" Visibility="{Binding InSearch, Converter={x:Static s:BoolToVisibilityConverter.Instance}}" Value="0" IsIndeterminate="True" Height="22" Width="20" Foreground="#FFFDFEFF" Margin="5,0,0,0" BorderBrush="#FFF9F7F7" />
</StackPanel>
</DockPanel>
</materialDesign:ColorZone>
<!--Content-->
<Grid Margin="0,52,0,35">
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto"
Visibility="{Binding ItemList.Count, Converter={x:Static s:BoolToVisibilityConverter.Instance}}">
<ItemsControl Padding="8" Background="{DynamicResource MaterialDesignCardBackground}"
ItemsSource="{Binding ItemList}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<ContentControl Margin="0,0,0,8" s:View.Model="{Binding}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
<!--Err Label IsActive="{Binding ShowErrlabel}"-->
<materialDesign:Snackbar IsActive='{Binding Path=Errlabel, Converter={StaticResource ConverterStringNotEmpty}}' Margin="230,0,230,35" Width="560">
<materialDesign:SnackbarMessage Content="{Binding Errlabel}" ActionContent="OK" ActionClick="{s:Action CloseErrlabel}"/>
</materialDesign:Snackbar>
<StatusBar HorizontalAlignment="Left" Height="35" Margin="0,635,0,0" VerticalAlignment="Bottom" Width="1020" Background="White" BorderThickness="0,1,0,0" BorderBrush="#FF999191">
<materialDesign:PackIcon Kind="Music" />
<ComboBox ItemsSource="{Binding QualityList}"
SelectedIndex="{Binding SelectQualityIndex , UpdateSourceTrigger=PropertyChanged}"
SelectionChanged="{s:Action QualityChanged}"
VerticalAlignment="Top" Height="30" Padding="6,6,0,6"/>
<materialDesign:PackIcon Kind="VideoFilm" />
<ComboBox ItemsSource="{Binding ResolutionList}"
SelectedIndex="{Binding SelectResolutionIndex , UpdateSourceTrigger=PropertyChanged}"
SelectionChanged="{s:Action ResolutionChanged}"
VerticalAlignment="Top" Height="30" Padding="6,6,0,6"/>
</StatusBar>
</Grid>
</materialDesign:DialogHost>
</materialDesign:Card>
</Grid>
</Window>
@@ -1,39 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using AIGS.Helper;
namespace TIDALDL_UI.Pages
{
/// <summary>
/// MainView.xaml 的交互逻辑
/// </summary>
public partial class MainView
{
public MainView()
{
InitializeComponent();
}
private void ColorZone_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
DragMove();
}
private void TextBox_PreviewMouseDoubleClick(object sender, MouseButtonEventArgs e)
{
TextBox ctrl = (TextBox)sender;
ctrl.SelectAll();
}
}
}
@@ -1,275 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Stylet;
using AIGS.Common;
using AIGS.Helper;
using Tidal;
using TIDALDL_UI.Else;
using MaterialDesignThemes.Wpf;
using System.Threading;
using System.Windows;
using System.Collections.ObjectModel;
using System.IO;
using ICSharpCode.SharpZipLib.Zip;
using System.Windows.Controls;
namespace TIDALDL_UI.Pages
{
public class MainViewModel : Screen
{
public string Errlabel { get; set; }
public string SearchStr { get; set; }
public bool InSearch { get; set; }
public string SearchHelperTip { get; set; } =
"You can search album\\track\\video\\artist\\playlist! Example:\n\n" +
"ID : 71121869 (from https://listen.tidal.com/albums/71121869) \n" +
"Title: Adele (or track\\video\\album title) \n" +
"Url : https://listen.tidal.com/albums/71121869";
/// <summary>
/// Download Items
/// </summary>
public BindableCollection<MainListItemViewModel> ItemList { get; } = new BindableCollection<MainListItemViewModel>();
public Thread UpdateThread;
/// <summary>
/// Combox
/// </summary>
public List<string> QualityList { get; set; }
public int SelectQualityIndex { get; set; }
public List<string> ResolutionList { get; set; }
public int SelectResolutionIndex { get; set; }
private IWindowManager Manager;
private LoginViewModel VMLogin;
private SettingViewModel VMSetting;
private AboutViewModel VMAbout;
private InfoViewModel VMInfo;
private SearchViewModel VMSearch;
private DllistViewModel VMDllist;
public MainViewModel(IWindowManager manager,
SettingViewModel setting,
AboutViewModel about,
InfoViewModel albuminfo,
SearchViewModel search,
DllistViewModel dllist)
{
Manager = manager;
VMSetting = setting;
VMAbout = about;
VMInfo = albuminfo;
VMSearch = search;
VMDllist = dllist;
ThreadTool.SetThreadNum(int.Parse(Config.ThreadNum()));
UpdateThread = new Thread(ThreadUpdateFunc);
UpdateThread.IsBackground = true;
UpdateThread.Start();
QualityList = TidalTool.getQualityList();
SelectQualityIndex = QualityList.IndexOf(Config.Quality().ToUpper());
if (SelectQualityIndex < 0)
SelectQualityIndex = 0;
ResolutionList = TidalTool.getResolutionList();
SelectResolutionIndex = ResolutionList.IndexOf(Config.Resolution().ToUpper());
if (SelectResolutionIndex < 0)
SelectResolutionIndex = 0;
TidalTool.SetSearchMaxNum(int.Parse(Config.SearchNum()));
//test
//VMDllist.Convert();
//return;
}
public void SetLogViewModel(LoginViewModel model)
{
VMLogin = model;
}
public void WindowClose()
{
ThreadTool.Close();
ThreadHelper.Abort(UpdateThread);
RequestClose();
}
//protected override void OnInitialActivate()
//{
// //show about page
// if (Config.Version() != VersionHelper.GetSelfVersion())
// {
// Config.Version(VersionHelper.GetSelfVersion());
// Manager.ShowDialog(VMAbout);
// }
//}
public void QualityChanged(object sender, SelectionChangedEventArgs e)
{
Config.Quality(QualityList[SelectQualityIndex].ToLower());
}
public void ResolutionChanged(object sender, SelectionChangedEventArgs e)
{
Config.Resolution(ResolutionList[SelectResolutionIndex]);
}
#region Button
public async void Search()
{
if (InSearch)
return;
if (SearchStr.IsBlank())
{
Errlabel = "Search string is empty!";
return;
}
//Search
InSearch = true;
eObjectType SearchType = eObjectType.None;
object SearchObj = await Task.Run(() => { return TidalTool.tryGet(SearchStr, out SearchType); });
InSearch = false;
if (SearchType == eObjectType.None)
{
Errlabel = "Search Err!";
return;
}
if (SearchType == Tidal.eObjectType.SEARCH)
{
VMSearch.Load((Tidal.SearchResult)SearchObj);
Manager.ShowDialog(VMSearch);
SearchType = VMSearch.ResultType;
SearchObj = VMSearch.ResultObject;
if (SearchType == eObjectType.None)
return;
}
SearchObj = VMInfo.Load(SearchObj);
Manager.ShowDialog(VMInfo);
if (VMInfo.Result)
{
MainListItemViewModel newNode = new MainListItemViewModel(SearchObj, ItemList);
ItemList.Add(newNode);
newNode.StartWork();
}
}
public void OpenDllist()
{
VMDllist.Items.Clear();
Manager.ShowDialog(VMDllist);
for (int i = 0; i < VMDllist.Items.Count; i++)
{
if (VMDllist.Items[i].Type == eObjectType.None)
continue;
MainListItemViewModel newNode = new MainListItemViewModel(VMDllist.Items[i].Data, ItemList);
ItemList.Add(newNode);
newNode.StartWork();
}
}
public void Logout()
{
TidalTool.logout();
Manager.ShowWindow(VMLogin);
WindowClose();
}
public void Setting()
{
VMSetting.RefreshSetting();
Manager.ShowDialog(VMSetting);
string sValue = Config.ThreadNum();
ThreadTool.SetThreadNum(int.Parse(sValue));
SelectQualityIndex = QualityList.IndexOf(Config.Quality().ToUpper());
SelectResolutionIndex = ResolutionList.IndexOf(Config.Resolution().ToUpper());
}
public void About()
{
Manager.ShowDialog(VMAbout);
}
public void FeedBack()
{
NetHelper.OpenWeb("https://github.com/yaronzz/Tidal-Media-Downloader/issues");
}
public void CloseErrlabel()
{
Errlabel = null;
}
public void WindowMin()
{
((MainView)this.View).WindowState = WindowState.Minimized;
}
public void WindowMax()
{
ScreenShotHelper.MaxWindow((Window)this.View);
}
#endregion
#region Version Update Thread
public void ThreadUpdateFunc()
{
string PATH = Path.GetFullPath("./tidal_new/");
string VERF = PATH + "version";
string BATF = PATH + "update.bat";
string sSelfVer = VersionHelper.GetSelfVersion();
//Replace new version
string sDlVer = FileHelper.Read(VERF);
if (sDlVer.IsNotBlank() && VersionHelper.Compare(sSelfVer, sDlVer) < 0 && File.Exists(PATH + "tidal-gui.exe") && File.Exists(BATF))
{
MessageBoxResult ret = MessageBox.Show("Update new version?", "Info", MessageBoxButton.YesNo, MessageBoxImage.Information);
if (ret == MessageBoxResult.No)
return;
if (Application.Current != null)
{
Application.Current.Dispatcher.BeginInvoke((Action)delegate ()
{
CmdHelper.StartExe(BATF, null, IsShowWindow: false);
WindowClose();
});
}
return;
}
//Get github new version
string sLastVer = GithubHelper.getLastReleaseVersion("yaronzz", "Tidal-Media-Downloader");
if (VersionHelper.Compare(sSelfVer, sLastVer) >= 0)
return;
if (Directory.Exists(PATH))
Directory.Delete(PATH, true);
PathHelper.Mkdirs(PATH);
if (GithubHelper.getLastReleaseFile("yaronzz", "Tidal-Media-Downloader", "tidal-gui.zip", PATH + "tidal-gui.zip"))
{
FastZip fz = new FastZip();
try
{
fz.ExtractZip(PATH + "tidal-gui.zip", PATH, null);
if (File.Exists(PATH + "tidal-gui.exe"))
{
string sBat = "ping -n 5 127.0.0.1\n";
sBat += string.Format("move {0}tidal-gui.exe {0}..\\tidal-gui.exe\n", PATH);
sBat += string.Format("start {0}..\\tidal-gui.exe\n", PATH);
FileHelper.Write(sBat, true, BATF);
FileHelper.Write(sLastVer, true, VERF);
}
}
catch
{
return;
}
}
}
#endregion
}
}
@@ -1,79 +0,0 @@
<Window x:Class="TIDALDL_UI.Pages.SearchView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:local="clr-namespace:TIDALDL_UI"
xmlns:pages="clr-namespace:TIDALDL_UI.Pages"
xmlns:s="https://github.com/canton7/Stylet"
xmlns:aigsc="clr-namespace:AIGS.Control;assembly=AIGS"
mc:Ignorable="d"
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
TextElement.FontWeight="Regular"
TextElement.FontSize="13"
TextOptions.TextFormattingMode="Ideal"
TextOptions.TextRenderingMode="Auto"
FontFamily="pack://application:,,,/MaterialDesignThemes.Wpf;component/Resources/Roboto/#Roboto"
Width="850"
WindowStartupLocation="CenterOwner"
WindowStyle="None"
Background="{x:Null}"
AllowsTransparency="True"
Height="575"
ShowInTaskbar="False"
d:DataContext="{d:DesignInstance pages:SearchViewModel}">
<materialDesign:Card Name="m_CMainCard" materialDesign:ShadowAssist.ShadowDepth="Depth3" VerticalAlignment="Stretch" BorderThickness="3" BorderBrush="#FF171616" Margin="20,20,20,20">
<materialDesign:DialogHost Identifier="RootDialog" SnackbarMessageQueue="{Binding ElementName=MainSnackbar, Path=MessageQueue}" Background="{x:Null}">
<Grid Margin="16,16,16,10">
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="44" />
<RowDefinition/>
<RowDefinition Height="44" />
</Grid.RowDefinitions>
<Label Content="{Binding Header}" Grid.Row="0" FontSize="30" VerticalAlignment="Top" Height="50" HorizontalContentAlignment="Center" BorderThickness="0,0,0,1" BorderBrush="#FFDEDEDE"/>
<materialDesign:ColorZone Mode="PrimaryMid" Grid.Row="1">
<StackPanel Orientation="Horizontal" Margin="2">
<RadioButton Content="ALBUM" IsChecked="{Binding bCheckAlbum}" Style="{StaticResource MaterialDesignTabRadioButton}" Margin="4"/>
<RadioButton Content="TRACK" IsChecked="{Binding bCheckTrack}" Style="{StaticResource MaterialDesignTabRadioButton}" Margin="4"/>
<RadioButton Content="VIDEO" IsChecked="{Binding bCheckVideo}" Style="{StaticResource MaterialDesignTabRadioButton}" Margin="4"/>
<RadioButton Content="ARTIST" IsChecked="{Binding bCheckArtist}" Style="{StaticResource MaterialDesignTabRadioButton}" Margin="4"/>
<RadioButton Content="PLAYLIST" IsChecked="{Binding bCheckPlaylist}" Style="{StaticResource MaterialDesignTabRadioButton}" Margin="4"/>
</StackPanel>
</materialDesign:ColorZone>
<Grid Grid.Row="2" Background="WhiteSmoke">
<ListView Grid.Row="2" ItemsSource="{Binding BindList}" SelectedIndex="{Binding SelectIndex}" ScrollViewer.HorizontalScrollBarVisibility="Hidden" SelectionMode="Single" >
<ListView.View>
<GridView>
<GridViewColumn Header="#" Width="50" DisplayMemberBinding="{Binding Index}"/>
<GridViewColumn Header="#" Width="30" DisplayMemberBinding="{Binding Flag}"/>
<GridViewColumn Header="TITLE" Width="350" DisplayMemberBinding="{Binding Title}"/>
<GridViewColumn Header="ARTIST" Width="260" DisplayMemberBinding="{Binding Artist}"/>
<GridViewColumn Header="TIME" DisplayMemberBinding="{Binding Duration}"/>
</GridView>
</ListView.View>
</ListView>
</Grid>
<Grid Grid.Row="3">
<Button IsDefault="True" Style="{DynamicResource MaterialDesignRaisedButton}"
Command="{s:Action Confirm}"
Content="Confirm"
Height="27" VerticalAlignment="Bottom" Margin="380,0,214,7"/>
<Button IsDefault="True" Style="{DynamicResource MaterialDesignRaisedButton}"
Command="{s:Action Cancel}"
Content="Cancel"
Height="27" VerticalAlignment="Bottom" Margin="584,0,10,7"/>
</Grid>
<Grid Grid.Row="2" Grid.RowSpan="2" Background="White" Visibility="{Binding ShowWait}">
<ProgressBar Style="{StaticResource MaterialDesignCircularProgressBar}" IsIndeterminate="True" Value="60" Height="Auto" Margin="280,98,284,209" Width="Auto"/>
</Grid>
</Grid>
</materialDesign:DialogHost>
</materialDesign:Card>
</Window>
@@ -1,30 +0,0 @@
using AIGS.Helper;
using MaterialDesignThemes.Wpf;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace TIDALDL_UI.Pages
{
/// <summary>
/// AlbumInfo.xaml 的交互逻辑
/// </summary>
public partial class SearchView : Window
{
public SearchView()
{
InitializeComponent();
}
}
}
@@ -1,134 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media.Imaging;
using AIGS.Helper;
using AIGS.Common;
using System.Collections.ObjectModel;
using TIDALDL_UI.Else;
using Stylet;
using System.Windows;
using Tidal;
namespace TIDALDL_UI.Pages
{
public class SearchItem
{
public string Title { get; set; }
public string Artist { get; set; }
public string Duration { get; set; }
public int Index { get; set; }
public string Flag { get; set; }//Quality or else
public SearchItem(int index, string title, string artist, string duration, string flag=null)
{
Index = index;
Title = title;
Artist = artist;
Duration = duration;
Flag = flag;
}
}
public class SearchViewModel : Screen
{
public string Header { get; private set; } = "SEARCH";
public int SelectIndex { get; set; } = 0;
public bool bCheckPlaylist { get; set; } = false;
public bool bCheckArtist { get; set; } = false;
public bool bCheckAlbum { get; set; } = true;
public bool bCheckTrack { get; set; } = false;
public bool bCheckVideo { get; set; } = false;
public Visibility ShowWait { get; set; } = Visibility.Hidden;
public List<SearchItem> PlayList { get; set; } = new List<SearchItem>();
public List<SearchItem> ArtistList { get; set; } = new List<SearchItem>();
public List<SearchItem> AlbumList { get; set; } = new List<SearchItem>();
public List<SearchItem> TrackList { get; set; } = new List<SearchItem>();
public List<SearchItem> VideoList { get; set; } = new List<SearchItem>();
public List<SearchItem> BindList
{
set { return; }
get
{
if (bCheckPlaylist) return PlayList;
if (bCheckArtist) return ArtistList;
if (bCheckAlbum) return AlbumList;
if (bCheckTrack) return TrackList;
return VideoList;
}
}
public SearchResult SearchInfo = null;
public eObjectType ResultType = eObjectType.None;
public object ResultObject = null;
#region Button
public async void Confirm()
{
string ResultID = null;
if (SelectIndex >= 0)
{
if (bCheckPlaylist && SearchInfo.Playlists.Count > 0)
{
ResultID = SearchInfo.Playlists[SelectIndex].UUID.ToString();
ResultType = eObjectType.PLAYLIST;
}
if (bCheckArtist && SearchInfo.Artists.Count > 0)
{
ResultID = SearchInfo.Artists[SelectIndex].ID.ToString();
ResultType = eObjectType.ARTIST;
}
if (bCheckAlbum && SearchInfo.Albums.Count > 0)
{
ResultID = SearchInfo.Albums[SelectIndex].ID.ToString();
ResultType = eObjectType.ALBUM;
}
if (bCheckTrack && SearchInfo.Tracks.Count > 0)
{
ResultID = SearchInfo.Tracks[SelectIndex].ID.ToString();
ResultType = eObjectType.TRACK;
}
if (bCheckVideo && SearchInfo.Videos.Count > 0)
{
ResultID = SearchInfo.Videos[SelectIndex].ID.ToString();
ResultType = eObjectType.VIDEO;
}
ShowWait = Visibility.Visible;
await Task.Run(() =>
{
ResultObject = TidalTool.tryGet(ResultID, out ResultType, ResultType);
});
}
RequestClose();
}
public void Cancel()
{
ResultType = eObjectType.None;
RequestClose();
}
#endregion
public void Load(SearchResult SearchInfo)
{
ShowWait = Visibility.Hidden;
PlayList = new List<SearchItem>();
ArtistList = new List<SearchItem>();
AlbumList = new List<SearchItem>();
TrackList = new List<SearchItem>();
VideoList = new List<SearchItem>();
this.SearchInfo = SearchInfo;
foreach (Playlist item in SearchInfo.Playlists)
PlayList.Add(new SearchItem(SearchInfo.Playlists.IndexOf(item) + 1, item.Title, item.Title, TimeHelper.ConverIntToString(item.Duration), TidalTool.getFlag(item)));
foreach (Artist item in SearchInfo.Artists)
ArtistList.Add(new SearchItem(SearchInfo.Artists.IndexOf(item) + 1, item.Name, item.Name, ""));
foreach (Album item in SearchInfo.Albums)
AlbumList.Add(new SearchItem(SearchInfo.Albums.IndexOf(item) + 1, item.Title, item.Artists[0].Name, TimeHelper.ConverIntToString(item.Duration), TidalTool.getFlag(item)));
foreach (Track item in SearchInfo.Tracks)
TrackList.Add(new SearchItem(SearchInfo.Tracks.IndexOf(item) + 1, item.Title, item.Artists[0].Name, TimeHelper.ConverIntToString(item.Duration), TidalTool.getFlag(item)));
foreach (Video item in SearchInfo.Videos)
VideoList.Add(new SearchItem(SearchInfo.Videos.IndexOf(item) + 1, item.Title, item.Artists[0].Name, TimeHelper.ConverIntToString(item.Duration), TidalTool.getFlag(item)));
}
}
}
@@ -1,133 +0,0 @@
<Window x:Class="TIDALDL_UI.Pages.SettingView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:local="clr-namespace:TIDALDL_UI"
xmlns:pages="clr-namespace:TIDALDL_UI.Pages"
xmlns:s="https://github.com/canton7/Stylet"
mc:Ignorable="d"
Width="575"
Height="415"
WindowStartupLocation="CenterOwner"
WindowStyle="None"
Background="{x:Null}"
AllowsTransparency="True"
d:DataContext="{d:DesignInstance pages:SettingViewModel}" ShowInTaskbar="False">
<materialDesign:Card Name="m_CMainCard" materialDesign:ShadowAssist.ShadowDepth="Depth3" VerticalAlignment="Stretch" BorderThickness="3" BorderBrush="#FF171616" Margin="20,20,20,20">
<materialDesign:DialogHost Identifier="RootDialog" SnackbarMessageQueue="{Binding ElementName=MainSnackbar, Path=MessageQueue}" Background="{x:Null}">
<Grid Margin="8">
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="240*" />
<RowDefinition Height="47"/>
</Grid.RowDefinitions>
<Label Content="SETTINGS" Grid.Row="0" FontSize="30" VerticalAlignment="Top" Height="50" HorizontalContentAlignment="Center" BorderThickness="0,0,0,1" BorderBrush="#FFDEDEDE"/>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="105"/>
<ColumnDefinition Width="382*"/>
</Grid.ColumnDefinitions>
<Border BorderThickness="0,0,1,0" BorderBrush="#FFDEDEDE">
<StackPanel >
<RadioButton Content="COMMON" IsChecked="{Binding CheckCommon}" Style="{StaticResource MaterialDesignTabRadioButton}" HorizontalContentAlignment="Right" BorderBrush="#FF0C2C53"/>
<RadioButton Content="TRACK" IsChecked="{Binding CheckTrack}" Style="{StaticResource MaterialDesignTabRadioButton}" HorizontalContentAlignment="Right" BorderBrush="#FF0C2C53"/>
<RadioButton Content="VIDEO" IsChecked="{Binding CheckVideo}" Style="{StaticResource MaterialDesignTabRadioButton}" HorizontalContentAlignment="Right" BorderBrush="#FF0C2C53"/>
</StackPanel>
</Border>
<!--Common config Visibility="{Binding CheckCommon, Converter={x:Static s:BoolToVisibilityConverter.Instance}}"-->
<Grid Grid.Column="1" Visibility="{Binding CheckCommon, Converter={x:Static s:BoolToVisibilityConverter.Instance}}">
<Label Content="OutputDir" FontSize="15" VerticalAlignment="Top" HorizontalContentAlignment="Right" Margin="10,33,312,0" />
<Button Style="{StaticResource MaterialDesignFlatButton}"
Name="m_CPath"
ToolTip="Choose Path"
Content="{Binding OutputDir, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Click="{s:Action SetOutputDir}"
FontSize="15"
Margin="107,32,22,0"
HorizontalContentAlignment="Left"
VerticalAlignment="Top" Height="30" Padding="0,4,16,4" BorderThickness="0,0,0,1" BorderBrush="#89000000"/>
<Label Content="ThreadNum" FontSize="15" VerticalAlignment="Top" HorizontalContentAlignment="Right" Margin="10,67,307,0" Height="30" />
<Label Content="SearchNum" FontSize="15" VerticalAlignment="Top" HorizontalContentAlignment="Right" Margin="10,97,307,0" Height="30" />
<ComboBox SelectedIndex="{Binding ThreadNum, UpdateSourceTrigger=PropertyChanged}" Margin="107,67,22,168">
<ComboBoxItem>1</ComboBoxItem>
<ComboBoxItem>2</ComboBoxItem>
<ComboBoxItem>3</ComboBoxItem>
</ComboBox>
<ComboBox SelectedIndex="{Binding SearchNum, UpdateSourceTrigger=PropertyChanged}" Margin="107,94,22,141">
<ComboBoxItem>10</ComboBoxItem>
<ComboBoxItem>20</ComboBoxItem>
<ComboBoxItem>30</ComboBoxItem>
<ComboBoxItem>40</ComboBoxItem>
<ComboBoxItem>50</ComboBoxItem>
</ComboBox>
<Label Content="AddYear" FontSize="15" VerticalAlignment="Top" HorizontalContentAlignment="Right" Margin="10,127,307,0" Height="30" />
<ComboBox SelectedIndex="{Binding AddYearIndex, UpdateSourceTrigger=PropertyChanged}" Margin="107,126,22,109">
<ComboBoxItem>No</ComboBoxItem>
<ComboBoxItem>Before</ComboBoxItem>
<ComboBoxItem>After</ComboBoxItem>
</ComboBox>
<Label Content="Artist-Title" FontSize="15" VerticalAlignment="Top" HorizontalContentAlignment="Right" Margin="0,157,312,0" Height="30" />
<ToggleButton Style="{StaticResource MaterialDesignSwitchToggleButton}" IsChecked="{Binding ArtistBeforeTitle, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Height="30" VerticalAlignment="Top" Margin="107,157,262,0"/>
<Label Content="IncludeSingle" FontSize="15" VerticalAlignment="Top" HorizontalContentAlignment="Right" Margin="0,187,307,0" Height="30" />
<ToggleButton Style="{StaticResource MaterialDesignSwitchToggleButton}" IsChecked="{Binding IncludeEPSingle, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Height="30" VerticalAlignment="Top" Margin="107,187,262,0"/>
<Label Content="SaveCovers" FontSize="15" VerticalAlignment="Top" HorizontalContentAlignment="Right" Margin="0,217,307,0" Height="30" />
<ToggleButton Style="{StaticResource MaterialDesignSwitchToggleButton}" IsChecked="{Binding SaveCovers, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Height="30" VerticalAlignment="Top" Margin="107,217,262,0"/>
</Grid>
<!--Track config Visibility="{Binding CheckTrack, Converter={x:Static s:BoolToVisibilityConverter.Instance}}"-->
<Grid Grid.Column="1" Visibility="{Binding CheckTrack, Converter={x:Static s:BoolToVisibilityConverter.Instance}}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="Quality" FontSize="15" VerticalAlignment="Center" HorizontalContentAlignment="Right"/>
<Label Grid.Row="1" Grid.Column="0" Content="OnlyM4a" FontSize="15" VerticalAlignment="Center" HorizontalContentAlignment="Right"/>
<Label Grid.Row="2" Grid.Column="0" Content="AddHyphen" FontSize="15" VerticalAlignment="Center" HorizontalContentAlignment="Right"/>
<Label Grid.Row="3" Grid.Column="0" Content="CheckExist" FontSize="15" VerticalAlignment="Center" HorizontalContentAlignment="Right"/>
<Label Grid.Row="4" Grid.Column="0" Content="AddExplicit" FontSize="15" VerticalAlignment="Center" HorizontalContentAlignment="Right"/>
<Label Grid.Row="5" Grid.Column="0" Content="Use Track number" FontSize="15" VerticalAlignment="Center" HorizontalContentAlignment="Right"/>
<ComboBox Grid.Row="0" Grid.Column="1" ItemsSource="{Binding QualityList}"
SelectedIndex="{Binding SelectQualityIndex , UpdateSourceTrigger=PropertyChanged}"
VerticalAlignment="Center" Padding="6,6,0,6"/>
<ToggleButton Grid.Row="1" Grid.Column="1" Style="{StaticResource MaterialDesignSwitchToggleButton}" IsChecked="{Binding OnlyM4a, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center" />
<ToggleButton Grid.Row="2" Grid.Column="1" Style="{StaticResource MaterialDesignSwitchToggleButton}" IsChecked="{Binding AddHyphen, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center" />
<ToggleButton Grid.Row="3" Grid.Column="1" Style="{StaticResource MaterialDesignSwitchToggleButton}" IsChecked="{Binding CheckExist, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center" />
<ToggleButton Grid.Row="4" Grid.Column="1" Style="{StaticResource MaterialDesignSwitchToggleButton}" IsChecked="{Binding AddExplicitTag, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center" />
<ToggleButton Grid.Row="5" Grid.Column="1" Style="{StaticResource MaterialDesignSwitchToggleButton}" IsChecked="{Binding UseTrackNumber, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center" />
</Grid>
<!--Video config-->
<Grid Grid.Column="1" Visibility="{Binding CheckVideo, Converter={x:Static s:BoolToVisibilityConverter.Instance}}">
<Label Content="Resolution" FontSize="15" VerticalAlignment="Top" HorizontalContentAlignment="Right" Margin="10,33,312,0" />
<ComboBox ItemsSource="{Binding ResolutionList}"
SelectedIndex="{Binding SelectResolutionIndex , UpdateSourceTrigger=PropertyChanged}"
Margin="107,32,87,0" VerticalAlignment="Top" Height="30" Padding="6,6,0,6">
</ComboBox>
</Grid>
</Grid>
<Button Command="{s:Action Confirm}" s:View.ActionTarget="{Binding}" Grid.Row="2" IsDefault="True" Style="{DynamicResource MaterialDesignRaisedButton}" Content="OK" Margin="10,0,10,10" Height="27" VerticalAlignment="Bottom"/>
</Grid>
</materialDesign:DialogHost>
</materialDesign:Card>
</Window>
@@ -1,29 +0,0 @@
using MaterialDesignThemes.Wpf;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace TIDALDL_UI.Pages
{
/// <summary>
/// Password.xaml 的交互逻辑
/// </summary>
public partial class SettingView : Window
{
public SettingView()
{
InitializeComponent();
}
}
}
@@ -1,109 +0,0 @@
using Stylet;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TIDALDL_UI.Else;
using AIGS.Common;
using System.IO;
using Tidal;
using System.Windows.Forms;
using AIGS.Helper;
namespace TIDALDL_UI.Pages
{
public class SettingViewModel: Stylet.Screen
{
public string OutputDir { get; set; }
public int ThreadNum { get; set; }
public int SearchNum { get; set; }
public int SelectQualityIndex { get; set; }
public int SelectResolutionIndex { get; set; }
public bool OnlyM4a { get; set; }
public bool AddHyphen { get; set; }
public bool UseTrackNumber { get; set; }
public bool ToChinese { get; set; }
public bool CheckExist { get; set; }
public bool ArtistBeforeTitle { get; set; }
public bool AddExplicitTag { get; set; }
public bool IncludeEPSingle { get; set; }
public int AddYearIndex { get; set; }
public bool SaveCovers { get; set; }
public bool CheckCommon { get; set; } = true;
public bool CheckTrack { get; set; } = false;
public bool CheckVideo { get; set; } = false;
public List<string> QualityList { get; set; }
public List<string> ResolutionList { get; set; }
public SettingViewModel()
{
RefreshSetting();
}
public void RefreshSetting()
{
OutputDir = Config.OutputDir();
OnlyM4a = Config.OnlyM4a();
AddExplicitTag = Config.AddExplicitTag();
IncludeEPSingle = Config.IncludeEP();
AddHyphen = Config.AddHyphen();
SaveCovers = Config.SaveCovers();
ToChinese = Config.ToChinese();
CheckExist = Config.CheckExist();
ArtistBeforeTitle = Config.ArtistBeforeTitle();
AddYearIndex = Config.AddYear();
ThreadNum = AIGS.Common.Convert.ConverStringToInt(Config.ThreadNum()) - 1;
SearchNum = AIGS.Common.Convert.ConverStringToInt(Config.SearchNum()) / 10 - 1;
QualityList = TidalTool.getQualityList();
ResolutionList = TidalTool.getResolutionList();
SelectQualityIndex = QualityList.IndexOf(Config.Quality().ToUpper());
SelectResolutionIndex = ResolutionList.IndexOf(Config.Resolution().ToUpper());
UseTrackNumber = Config.UseTrackNumber();
if (SelectQualityIndex < 0)
SelectQualityIndex = 0;
if (SelectResolutionIndex < 0)
SelectResolutionIndex = 0;
if (ThreadNum < 0)
ThreadNum = 0;
if (SearchNum < 0 || SearchNum > 5)
SearchNum = 0;
}
public void SetOutputDir()
{
FolderBrowserDialog openFileDialog = new FolderBrowserDialog();
if (openFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
OutputDir = openFileDialog.SelectedPath;
}
public void Confirm()
{
Config.ThreadNum((ThreadNum + 1).ToString());
Config.SearchNum(((SearchNum + 1)*10).ToString());
Config.OnlyM4a(OnlyM4a.ToString());
Config.AddExplicitTag(AddExplicitTag.ToString());
Config.SaveCovers(SaveCovers.ToString());
Config.IncludeEP(IncludeEPSingle.ToString());
Config.ToChinese(ToChinese.ToString());
Config.CheckExist(CheckExist.ToString());
Config.ArtistBeforeTitle(ArtistBeforeTitle.ToString());
Config.AddHyphen(AddHyphen.ToString());
Config.AddYear(AddYearIndex);
Config.Quality(QualityList[SelectQualityIndex].ToLower());
Config.Resolution(ResolutionList[SelectResolutionIndex]);
Config.OutputDir(OutputDir);
Config.UseTrackNumber(UseTrackNumber.ToString());
TidalTool.SetSearchMaxNum(int.Parse(Config.SearchNum()));
ThreadTool.SetThreadNum(ThreadNum + 1);
RequestClose();
}
}
}
-24
View File
@@ -1,24 +0,0 @@
<UserControl x:Class="TIDALDL_UI.Wait"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
mc:Ignorable="d"
MaxWidth="400" Width="116" Height="116">
<Grid Margin="16">
<Grid.RowDefinitions>
<RowDefinition Height="70*" />
<RowDefinition Height="53" />
</Grid.RowDefinitions>
<ProgressBar Style="{StaticResource MaterialDesignCircularProgressBar}"
Value="0"
IsIndeterminate="True" />
<Button Grid.Row="1"
IsDefault="True" Style="{DynamicResource MaterialDesignFlatButton}"
Content="CANCLE"
Margin="-2,17,0,0"
Click="Button_Click"
Height="Auto" VerticalAlignment="Top" HorizontalContentAlignment="Center"/>
</Grid>
</UserControl>

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