Compare commits
206 Commits
2021.11.15.1
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| f4854f4b74 | |||
| 8352f0f6e2 | |||
| a8da5c0ff3 | |||
| df7c444487 | |||
| d88dca4da6 | |||
| 88b5b61328 | |||
| 56c9cf5695 | |||
| 379eca8458 | |||
| 7d6f9fc6e1 | |||
| 87eabab36f | |||
| 288c75bcc7 | |||
| 62d83b5975 | |||
| 251af9e745 | |||
| 0751c37b35 | |||
| 4f32b14441 | |||
| 97928ef207 | |||
| 9edd5967f0 | |||
| 8449b85d81 | |||
| 2f4ad82421 | |||
| 513be57c3d | |||
| 3eb11252c2 | |||
| b972f7cda8 | |||
| b1b643109c | |||
| c15ad63542 | |||
| 09321db35e | |||
| 132e516250 | |||
| a771c598ae | |||
| db76e84123 | |||
| 7eb4419177 | |||
| df3c405667 | |||
| 951fd102ad | |||
| 252076f6dd | |||
| 11828a0e8e | |||
| 93f363f405 | |||
| 12a96d8a46 | |||
| 238b2da4b3 | |||
| 76313d68c9 | |||
| 4e8751ceb1 | |||
| 2dfcbad8f0 | |||
| 07d18ce2d6 | |||
| 7fdd307176 | |||
| 11805382cc | |||
| 044a847e78 | |||
| 6e49253e99 | |||
| 0c83717469 | |||
| 7f1afb27f1 | |||
| 18efb49213 | |||
| a275275cb6 | |||
| 7e5b6d22c4 | |||
| 96742046ba | |||
| 3199dcedc6 | |||
| 2cf59b3195 | |||
| be84a3631a | |||
| 9ce35af72f | |||
| 9d904a0fea | |||
| 5e05afd775 | |||
| dece506d58 | |||
| c2cc170988 | |||
| 3cab9ea295 | |||
| 5cf094d227 | |||
| 2e1e15ed3f | |||
| 7434470216 | |||
| 2ce2a310ae | |||
| dfc7af7796 | |||
| 63bf063dd3 | |||
| 3e8a3436b4 | |||
| e08e5efc88 | |||
| 7f3758e18c | |||
| 3e2d74a37f | |||
| 69ccd65025 | |||
| 81b82e6c29 | |||
| 346befda6d | |||
| 450102bfea | |||
| a966b3d93d | |||
| 55df515256 | |||
| 242747719a | |||
| e3c5886a02 | |||
| 33c49b83db | |||
| ed13b9b92d | |||
| e45f649e46 | |||
| 0172301769 | |||
| a7aa38e563 | |||
| fd97a2b966 | |||
| e1ee47b93c | |||
| 61b9dd3af8 | |||
| 628a42b058 | |||
| 2c392f0e22 | |||
| dc57d4d01d | |||
| 8ed83b1672 | |||
| 3099820956 | |||
| d643de43e9 | |||
| 39db4730c5 | |||
| 937aa7ca8f | |||
| 84b9f6f6bc | |||
| b1ebd6f0b2 | |||
| e1562ba30e | |||
| 8876be13b6 | |||
| 30a6c8c55a | |||
| eb01de7f3a | |||
| e652556de2 | |||
| 00ef2f906f | |||
| aba9493201 | |||
| c78a56fff0 | |||
| 56bf0f9510 | |||
| 2ebf80869c | |||
| bb5be5e5fb | |||
| 5c2a13d4d1 | |||
| c61be4bbf3 | |||
| a969583d79 | |||
| 9f9a4f9aef | |||
| 3b3af6a174 | |||
| 166961297e | |||
| 1f5343569f | |||
| 9e9d47f470 | |||
| 6870a8c37f | |||
| 4d368dd04d | |||
| 64b98ee117 | |||
| 5ec77efb19 | |||
| 65da2f7272 | |||
| a5fb92db92 | |||
| 81e244f230 | |||
| 6a1b931340 | |||
| 8a21b01c1d | |||
| 96f46c2b59 | |||
| ffe335c17e | |||
| 79b537c186 | |||
| a806785609 | |||
| 06ff60ca74 | |||
| b34013129e | |||
| f1a5b1d764 | |||
| d52980506c | |||
| 34bab40d3d | |||
| 747d06c7b4 | |||
| 41573b7b39 | |||
| d7e078db2e | |||
| 363a854428 | |||
| ad00099c9d | |||
| 6676a380e1 | |||
| bab13ff718 | |||
| 9707c5c276 | |||
| 48206d675a | |||
| f877c184bb | |||
| 59b360b285 | |||
| 1a09571788 | |||
| 2484a8d4d8 | |||
| 5e73ad35fa | |||
| 8503a622b0 | |||
| ab479300ea | |||
| 96fb847479 | |||
| 5484669333 | |||
| e366edbbea | |||
| e8ef25183d | |||
| c94c5283a7 | |||
| 77803c0b41 | |||
| b5bd4af56d | |||
| 0a28baad64 | |||
| 6a1cd1d1d1 | |||
| 25e72aa45e | |||
| 90f869fcdb | |||
| 72a2cb804a | |||
| 752fb9e719 | |||
| ac745e1434 | |||
| cbb4480d1e | |||
| a410370f45 | |||
| b8c4333d4e | |||
| 7e165f6c17 | |||
| c9ae7bfebd | |||
| 1d5b8cd8f6 | |||
| d41c8ddcae | |||
| 3d4b143c74 | |||
| 5892525593 | |||
| ff0e794b8c | |||
| 5f42afa31a | |||
| 2a56bee611 | |||
| 685b7cb1f8 | |||
| b0df00c0a3 | |||
| 30917d1b0f | |||
| 3848c4cf89 | |||
| 753b6f6f76 | |||
| d6739dc63e | |||
| 4e14fb0501 | |||
| 397ad9f823 | |||
| d2218c58c1 | |||
| 7627c2a0f7 | |||
| 69a7ff6813 | |||
| 133def9722 | |||
| 1b3afaabd0 | |||
| 9cb690378b | |||
| dd4b7254d9 | |||
| 394506e40d | |||
| 6399cab7c4 | |||
| ba1a559a4b | |||
| 41d7e30df5 | |||
| 94139c9f79 | |||
| 5d4f8fb314 | |||
| beae239007 | |||
| f20c84eb6e | |||
| 588482707a | |||
| 2ebb283119 | |||
| 3bfa300fad | |||
| 8ca30f65f3 | |||
| fa6a9fbbf8 | |||
| 8af25e0600 | |||
| 944b98c4b4 | |||
| 8254a61389 | |||
| d016c433ff |
@@ -3,7 +3,7 @@
|
||||
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: # Replace with a single Ko-fi 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
|
||||
|
||||
@@ -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
|
||||
@@ -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**
|
||||
@@ -0,0 +1 @@
|
||||
blank_issues_enabled: false
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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**
|
||||
@@ -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
|
||||
@@ -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/*
|
||||
|
||||
|
||||
|
||||
@@ -163,3 +163,18 @@ download/Playlist/Boy Bands- K-Pop Kings/Tmp0/22.part
|
||||
.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
|
||||
|
||||
@@ -14,8 +14,9 @@
|
||||
"console": "integratedTerminal",
|
||||
// "python": "python3",
|
||||
"env": {
|
||||
"PYTHONPATH": "${workspaceRoot}/TIDALDL-PY/"
|
||||
"PYTHONPATH": "${workspaceRoot}/TIDALDL-PY/tidal_dl/"
|
||||
},
|
||||
"justMyCode": false
|
||||
},
|
||||
{
|
||||
"name": "Python: common line",
|
||||
@@ -25,7 +26,7 @@
|
||||
"console": "integratedTerminal",
|
||||
// "python": "python3",
|
||||
"env": {
|
||||
"PYTHONPATH": "${workspaceRoot}/TIDALDL-PY/"
|
||||
"PYTHONPATH": "${workspaceRoot}/TIDALDL-PY/tidal_dl/"
|
||||
},
|
||||
"args": [
|
||||
"--link",
|
||||
@@ -33,7 +34,8 @@
|
||||
"-o",
|
||||
"e:\\test",
|
||||
"-q",
|
||||
"0"
|
||||
"0",
|
||||
"-g"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -44,7 +46,7 @@
|
||||
"console": "integratedTerminal",
|
||||
// "python": "python3",
|
||||
"env": {
|
||||
"PYTHONPATH": "${workspaceRoot}/TIDALDL-PY/"
|
||||
"PYTHONPATH": "${workspaceRoot}/TIDALDL-PY/tidal_dl/"
|
||||
},
|
||||
"justMyCode": false
|
||||
|
||||
@@ -53,11 +55,11 @@
|
||||
"name": "Python: gui",
|
||||
"type": "python",
|
||||
"request": "launch",
|
||||
"program": "${workspaceRoot}/TIDALDL-GUI/tidal_gui/__init__.py",
|
||||
"program": "${workspaceRoot}/TIDALDL-PY/tidal_gui/__init__.py",
|
||||
"console": "integratedTerminal",
|
||||
// "python": "python3",
|
||||
"env": {
|
||||
"PYTHONPATH": "${workspaceRoot}/TIDALDL-GUI/"
|
||||
"PYTHONPATH": "${workspaceRoot}/TIDALDL-PY/tidal_dl/"
|
||||
},
|
||||
"justMyCode": false
|
||||
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
<br>
|
||||
<a href="https://github.com/yaronzz/Tidal-Media-Downloader-PRO">[GUI-REPOSITORY]</a>
|
||||
<br>
|
||||
|
||||

|
||||
|
||||
|
||||
<div align="center">
|
||||
<h1>Tidal-Media-Downloader</h1>
|
||||
<a href="https://github.com/yaronzz/Tidal-Media-Downloader/blob/master/LICENSE">
|
||||
@@ -18,27 +22,41 @@
|
||||
<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://yaronzz.com/post/tidal_dl_installation/">Documentation</a> |
|
||||
<a href="https://yaronzz.com/post/tidal_dl_installation_chn/">中文文档</a> |
|
||||
<a href="https://t.me/Tidal_Media_Downloader">Channel</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
|
||||
| Name | platform | Install |
|
||||
| -------------- | --------------------------------- | ------------------------------------------------------------ |
|
||||
| tidal-gui | Windows | [GUI Repository](https://github.com/yaronzz/Tidal-Media-Downloader-PRO) |
|
||||
| tidal-dl (cli) | Windows \ Linux \ Macos \ Android | ```pip3 install tidal-dl --upgrade```<br />[Detailed Description](https://yaronzz.com/post/tidal_dl_installation/#Install) |
|
||||
|
||||
## 📡 Telegram
|
||||
```shell
|
||||
pip3 install tidal-dl --upgrade
|
||||
```
|
||||
|
||||
- [Group](https://t.me/tidal_group) : Feed back
|
||||
- [Channel](https://t.me/Tidal_Media_Downloader) : Notify the new version
|
||||
| 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
|
||||
@@ -51,6 +69,8 @@
|
||||
|
||||
<img src="https://i.loli.net/2020/08/19/gqW6zHI1SrKlomC.png" alt="image" style="zoom: 50%;" />
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## Settings - Possible Tags
|
||||
@@ -73,6 +93,7 @@
|
||||
| {NumberOfVolumes} | 1 |
|
||||
| {ReleaseDate} | 1963-03-22 |
|
||||
| {RecordType} | ALBUM |
|
||||
| {None} | |
|
||||
|
||||
### Track
|
||||
|
||||
@@ -80,6 +101,7 @@
|
||||
| ----------------- | ------------------------------------------ |
|
||||
| {TrackNumber} | 01 |
|
||||
| {ArtistName} | The Beatles |
|
||||
| {ArtistsName} | The Beatles |
|
||||
| {TrackTitle} | I Saw Her Standing There (Remastered 2009) |
|
||||
| {ExplicitFlag} | (*Explicit*) |
|
||||
| {AlbumYear} | 1963 |
|
||||
@@ -87,6 +109,19 @@
|
||||
| {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
|
||||
|
||||
@@ -96,6 +131,7 @@ If you really like my projects and want to support me, you can buy me a coffee 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
|
||||
@@ -118,4 +154,3 @@ pip3 uninstall tidal-dl
|
||||
pip3 install -r requirements.txt --user
|
||||
python3 setup.py install
|
||||
```
|
||||
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- encoding: utf-8 -*-
|
||||
"""
|
||||
@File : __init__.py
|
||||
@Date : 2021/05/08
|
||||
@Author : Yaronzz
|
||||
@Version : 1.0
|
||||
@Contact : yaronhuang@foxmail.com
|
||||
@Desc :
|
||||
"""
|
||||
import sys
|
||||
|
||||
from PyQt5.QtWidgets import QApplication
|
||||
|
||||
from tidal_gui import theme
|
||||
from tidal_gui.viewModel.loginModel import LoginModel
|
||||
from tidal_gui.viewModel.mainModel import MainModel
|
||||
|
||||
|
||||
def main():
|
||||
qss = theme.getThemeQssContent()
|
||||
app = QApplication(sys.argv)
|
||||
app.setStyleSheet(qss)
|
||||
|
||||
mainView = MainModel()
|
||||
mainView.show()
|
||||
|
||||
sys.exit(app.exec_())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,10 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- encoding: utf-8 -*-
|
||||
"""
|
||||
@File : __init__.py
|
||||
@Date : 2021/05/08
|
||||
@Author : Yaronzz
|
||||
@Version : 1.0
|
||||
@Contact : yaronhuang@foxmail.com
|
||||
@Desc :
|
||||
"""
|
||||
@@ -1,19 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- encoding: utf-8 -*-
|
||||
"""
|
||||
@File : checkBox.py
|
||||
@Date : 2021/05/08
|
||||
@Author : Yaronzz
|
||||
@Version : 1.0
|
||||
@Contact : yaronhuang@foxmail.com
|
||||
@Desc :
|
||||
"""
|
||||
|
||||
from PyQt5.QtWidgets import QCheckBox
|
||||
|
||||
|
||||
class CheckBox(QCheckBox):
|
||||
def __init__(self, text: str = "", checked: bool = False):
|
||||
super(CheckBox, self).__init__()
|
||||
self.setChecked(checked)
|
||||
self.setText(text)
|
||||
@@ -1,27 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- encoding: utf-8 -*-
|
||||
"""
|
||||
@File : comboBox.py
|
||||
@Date : 2021/8/17
|
||||
@Author : Yaronzz
|
||||
@Version : 1.0
|
||||
@Contact : yaronhuang@foxmail.com
|
||||
@Desc :
|
||||
"""
|
||||
from PyQt5.QtWidgets import QComboBox, QListView
|
||||
from PyQt5.QtCore import Qt
|
||||
|
||||
|
||||
class ComboBox(QComboBox):
|
||||
def __init__(self, items: list):
|
||||
super(ComboBox, self).__init__()
|
||||
self.setItems(items)
|
||||
self.setFixedWidth(200)
|
||||
self.setView(QListView())
|
||||
# remove shadow
|
||||
self.view().window().setWindowFlags(Qt.Popup | Qt.FramelessWindowHint | Qt.NoDropShadowWindowHint)
|
||||
self.view().window().setAttribute(Qt.WA_TranslucentBackground)
|
||||
|
||||
def setItems(self, items):
|
||||
for item in items:
|
||||
self.addItem(str(item))
|
||||
@@ -1,118 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- encoding: utf-8 -*-
|
||||
"""
|
||||
@File : framelessWidget.py
|
||||
@Date : 2021/05/08
|
||||
@Author : Yaronzz
|
||||
@Version : 1.0
|
||||
@Contact : yaronhuang@foxmail.com
|
||||
@Desc :
|
||||
"""
|
||||
from PyQt5.QtCore import Qt, QPoint
|
||||
from PyQt5.QtGui import QMouseEvent
|
||||
from PyQt5.QtWidgets import QWidget, QGridLayout, QHBoxLayout
|
||||
|
||||
from tidal_gui.control.pushButton import PushButton
|
||||
from tidal_gui.style import ButtonStyle
|
||||
|
||||
|
||||
class FramelessWidget(QWidget):
|
||||
def __init__(self):
|
||||
super(FramelessWidget, self).__init__()
|
||||
self.setWindowFlags(Qt.FramelessWindowHint)
|
||||
|
||||
self.borderWidget = QWidget()
|
||||
self.borderWidget.setObjectName("widgetMain")
|
||||
self.borderWidget.setStyleSheet("QWidget#widgetMain{border: 1px solid #000000;};")
|
||||
|
||||
self.contentGrid = QGridLayout()
|
||||
self.contentGrid.setContentsMargins(1, 1, 1, 1)
|
||||
|
||||
self.windowBtnGrid = self.__createWindowsButtonLayout__()
|
||||
self.enableMove = True
|
||||
self.validMoveWidget = None
|
||||
self.clickPos = None
|
||||
|
||||
self.grid = QGridLayout()
|
||||
self.grid.setSpacing(0)
|
||||
self.grid.setContentsMargins(0, 0, 0, 0)
|
||||
self.grid.addWidget(self.borderWidget, 0, 0)
|
||||
self.grid.addLayout(self.contentGrid, 0, 0)
|
||||
self.setLayout(self.grid)
|
||||
|
||||
def __showMaxWindows__(self):
|
||||
if self.windowState() == Qt.WindowMaximized:
|
||||
self.showNormal()
|
||||
else:
|
||||
self.showMaximized()
|
||||
|
||||
def __createWindowsButtonLayout__(self):
|
||||
self.closeBtn = PushButton('', ButtonStyle.CloseWindow)
|
||||
self.maxBtn = PushButton('', ButtonStyle.MaxWindow)
|
||||
self.minBtn = PushButton('', ButtonStyle.MinWindow)
|
||||
|
||||
self.closeBtn.clicked.connect(self.close)
|
||||
self.minBtn.clicked.connect(self.showMinimized)
|
||||
self.maxBtn.clicked.connect(self.__showMaxWindows__)
|
||||
|
||||
layout = QHBoxLayout()
|
||||
layout.setSpacing(0)
|
||||
layout.setContentsMargins(1, 1, 1, 1)
|
||||
layout.addWidget(self.minBtn)
|
||||
layout.addWidget(self.maxBtn)
|
||||
layout.addWidget(self.closeBtn)
|
||||
return layout
|
||||
|
||||
def __clickInValidMoveWidget__(self, x=-1, y=-1) -> bool:
|
||||
if self.validMoveWidget is None:
|
||||
return True
|
||||
if x == -1 and y == -1:
|
||||
x = self.clickPos.x()
|
||||
y = self.clickPos.y()
|
||||
|
||||
pos = self.validMoveWidget.pos()
|
||||
if x < pos.x() or x > pos.x() + self.validMoveWidget.width():
|
||||
return False
|
||||
if y < pos.y() or y > pos.y() + self.validMoveWidget.height():
|
||||
return False
|
||||
return True
|
||||
|
||||
def mousePressEvent(self, e: QMouseEvent):
|
||||
if e.button() == Qt.LeftButton:
|
||||
self.clickPos = e.pos()
|
||||
|
||||
def mouseReleaseEvent(self, e: QMouseEvent):
|
||||
if e.button() == Qt.LeftButton:
|
||||
self.clickPos = QPoint(-1, -1)
|
||||
|
||||
def mouseMoveEvent(self, e: QMouseEvent):
|
||||
if not self.enableMove:
|
||||
return
|
||||
if Qt.LeftButton & e.buttons():
|
||||
if self.__clickInValidMoveWidget__() and self.clickPos:
|
||||
self.move(e.pos() + self.pos() - self.clickPos)
|
||||
|
||||
def mouseDoubleClickEvent(self, e: QMouseEvent):
|
||||
if self.maxBtn.isHidden():
|
||||
return
|
||||
if Qt.LeftButton & e.buttons():
|
||||
if self.__clickInValidMoveWidget__(e.x(), e.y()):
|
||||
self.__showMaxWindows__()
|
||||
|
||||
def getGrid(self):
|
||||
return self.contentGrid
|
||||
|
||||
def disableMove(self):
|
||||
self.enableMove = False
|
||||
|
||||
def setValidMoveWidget(self, widget):
|
||||
self.validMoveWidget = widget
|
||||
|
||||
def setWindowButton(self, showClose=True, showMin=True, showMax=True):
|
||||
if not showMax:
|
||||
self.maxBtn.hide()
|
||||
if not showMin:
|
||||
self.minBtn.hide()
|
||||
if not showClose:
|
||||
self.closeBtn.hide()
|
||||
self.grid.addLayout(self.windowBtnGrid, 0, 0, Qt.AlignTop | Qt.AlignRight)
|
||||
@@ -1,20 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- encoding: utf-8 -*-
|
||||
"""
|
||||
@File : label.py
|
||||
@Date : 2021/05/08
|
||||
@Author : Yaronzz
|
||||
@Version : 1.0
|
||||
@Contact : yaronhuang@foxmail.com
|
||||
@Desc :
|
||||
"""
|
||||
from PyQt5.QtWidgets import QLabel
|
||||
|
||||
from tidal_gui.style import LabelStyle
|
||||
|
||||
|
||||
class Label(QLabel):
|
||||
def __init__(self, text: str = "", style: LabelStyle = LabelStyle.Default):
|
||||
super(Label, self).__init__()
|
||||
self.setText(text)
|
||||
self.setObjectName(style.name + "Label")
|
||||
@@ -1,25 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- encoding: utf-8 -*-
|
||||
"""
|
||||
@File : layout.py
|
||||
@Date : 2021/8/13
|
||||
@Author : Yaronzz
|
||||
@Version : 1.0
|
||||
@Contact : yaronhuang@foxmail.com
|
||||
@Desc :
|
||||
"""
|
||||
from PyQt5.QtWidgets import QHBoxLayout, QVBoxLayout
|
||||
|
||||
|
||||
def createHBoxLayout(widgets):
|
||||
layout = QHBoxLayout()
|
||||
for item in widgets:
|
||||
layout.addWidget(item)
|
||||
return layout
|
||||
|
||||
|
||||
def createVBoxLayout(widgets):
|
||||
layout = QVBoxLayout()
|
||||
for item in widgets:
|
||||
layout.addWidget(item)
|
||||
return layout
|
||||
@@ -1,20 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- encoding: utf-8 -*-
|
||||
"""
|
||||
@File : line.py
|
||||
@Date : 2021/8/17
|
||||
@Author : Yaronzz
|
||||
@Version : 1.0
|
||||
@Contact : yaronhuang@foxmail.com
|
||||
@Desc :
|
||||
"""
|
||||
from PyQt5.QtWidgets import QFrame
|
||||
|
||||
|
||||
class Line(QFrame):
|
||||
def __init__(self, shape: str = 'V'):
|
||||
super(Line, self).__init__()
|
||||
self.setFrameShape(QFrame.VLine if shape == 'V' else QFrame.HLine)
|
||||
self.setFrameShadow(QFrame.Sunken)
|
||||
|
||||
self.setObjectName('VLineQFrame' if shape == 'V' else 'HLineQFrame')
|
||||
@@ -1,17 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- encoding: utf-8 -*-
|
||||
"""
|
||||
@File : lineEdit.py
|
||||
@Date : 2021/05/08
|
||||
@Author : Yaronzz
|
||||
@Version : 1.0
|
||||
@Contact : yaronhuang@foxmail.com
|
||||
@Desc :
|
||||
"""
|
||||
from PyQt5.QtWidgets import QLineEdit
|
||||
|
||||
|
||||
class LineEdit(QLineEdit):
|
||||
def __init__(self, placeholderText: str = ""):
|
||||
super(LineEdit, self).__init__()
|
||||
self.setPlaceholderText(placeholderText)
|
||||
@@ -1,25 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- encoding: utf-8 -*-
|
||||
"""
|
||||
@File : listWidget.py
|
||||
@Date : 2021/8/17
|
||||
@Author : Yaronzz
|
||||
@Version : 1.0
|
||||
@Contact : yaronhuang@foxmail.com
|
||||
@Desc :
|
||||
"""
|
||||
from PyQt5.QtCore import QSize
|
||||
from PyQt5.QtGui import QIcon
|
||||
from PyQt5.QtWidgets import QListWidget, QListWidgetItem
|
||||
|
||||
from tidal_gui.style import ListWidgetStyle
|
||||
|
||||
|
||||
class ListWidget(QListWidget):
|
||||
def __init__(self, style: ListWidgetStyle = ListWidgetStyle.Default):
|
||||
super(ListWidget, self).__init__()
|
||||
self.setObjectName(style.name + "ListWidget")
|
||||
|
||||
def addIConTextItem(self, iconUrl: str, text: str):
|
||||
self.addItem(QListWidgetItem(QIcon(iconUrl), text))
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- encoding: utf-8 -*-
|
||||
"""
|
||||
@File : pushButton.py
|
||||
@Date : 2021/05/08
|
||||
@Author : Yaronzz
|
||||
@Version : 1.0
|
||||
@Contact : yaronhuang@foxmail.com
|
||||
@Desc :
|
||||
"""
|
||||
from PyQt5.QtGui import QIcon
|
||||
from PyQt5.QtWidgets import QPushButton
|
||||
|
||||
from tidal_gui.style import ButtonStyle
|
||||
|
||||
|
||||
class PushButton(QPushButton):
|
||||
def __init__(self,
|
||||
text: str = '',
|
||||
style: ButtonStyle = ButtonStyle.Default,
|
||||
width=0,
|
||||
iconUrl=''):
|
||||
super(PushButton, self).__init__()
|
||||
self.setText(text)
|
||||
self.setObjectName(style.name + "PushButton")
|
||||
|
||||
if width > 0:
|
||||
self.setFixedWidth(width)
|
||||
|
||||
if iconUrl != '':
|
||||
self.setIcon(QIcon(iconUrl))
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- encoding: utf-8 -*-
|
||||
"""
|
||||
@File : tableView.py
|
||||
@Date : 2021/9/10
|
||||
@Author : Yaronzz
|
||||
@Version : 1.0
|
||||
@Contact : yaronhuang@foxmail.com
|
||||
@Desc :
|
||||
"""
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtGui import QStandardItemModel, QStandardItem
|
||||
from PyQt5.QtWidgets import QTableView, QTableWidgetItem, QAbstractItemView
|
||||
|
||||
|
||||
class TableView(QTableView):
|
||||
def __init__(self, columnNames: list, rowCount: int = 20):
|
||||
super(TableView, self).__init__()
|
||||
|
||||
self._model = QStandardItemModel()
|
||||
self._model.setColumnCount(len(columnNames))
|
||||
self._model.setRowCount(rowCount)
|
||||
|
||||
for index, name in enumerate(columnNames):
|
||||
self._model.setHeaderData(index, Qt.Horizontal, name)
|
||||
|
||||
self.setModel(self._model)
|
||||
# self.setHorizontalHeaderItem(index, QTableWidgetItem(name))
|
||||
# for index in range(0, rowCount):
|
||||
# self.setRowHeight(index, 50)
|
||||
|
||||
self.setShowGrid(False)
|
||||
self.verticalHeader().setVisible(False)
|
||||
self.setSelectionBehavior(QAbstractItemView.SelectRows)
|
||||
self.setSelectionMode(QAbstractItemView.SingleSelection)
|
||||
|
||||
self.horizontalHeader().setStretchLastSection(True)
|
||||
self.setEditTriggers(QAbstractItemView.NoEditTriggers)
|
||||
|
||||
self.setFocusPolicy(Qt.NoFocus)
|
||||
|
||||
def addItem(self, rowIdx: int, colIdx: int, text: str):
|
||||
item = QStandardItem(text)
|
||||
item.setTextAlignment(Qt.AlignCenter)
|
||||
self._model.setItem(rowIdx, colIdx, item)
|
||||
#
|
||||
# def addWidgetItem(self, rowIdx: int, colIdx: int, widget):
|
||||
# self.setCellWidget(rowIdx, colIdx, widget)
|
||||
@@ -1,56 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- encoding: utf-8 -*-
|
||||
"""
|
||||
@File : tableWidget.py
|
||||
@Date : 2021/8/18
|
||||
@Author : Yaronzz
|
||||
@Version : 1.0
|
||||
@Contact : yaronhuang@foxmail.com
|
||||
@Desc :
|
||||
"""
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtGui import QIcon
|
||||
from PyQt5.QtWidgets import QTableWidget, QTableWidgetItem, QAbstractItemView
|
||||
|
||||
|
||||
class TableWidget(QTableWidget):
|
||||
def __init__(self, columnNames: list, rowCount: int = 20):
|
||||
super(TableWidget, self).__init__()
|
||||
|
||||
self.setColumnCount(len(columnNames))
|
||||
self.setRowCount(rowCount)
|
||||
|
||||
for index, name in enumerate(columnNames):
|
||||
self.setHorizontalHeaderItem(index, QTableWidgetItem(name))
|
||||
for index in range(0, rowCount):
|
||||
self.setRowHeight(index, 50)
|
||||
|
||||
self.setShowGrid(False)
|
||||
self.verticalHeader().setVisible(False)
|
||||
self.setSelectionBehavior(QAbstractItemView.SelectRows)
|
||||
self.setSelectionMode(QAbstractItemView.SingleSelection)
|
||||
|
||||
self.horizontalHeader().setStretchLastSection(True)
|
||||
self.setEditTriggers(QAbstractItemView.NoEditTriggers)
|
||||
|
||||
self.setFocusPolicy(Qt.NoFocus)
|
||||
|
||||
def changeRowCount(self, rows: int):
|
||||
if rows != self.rowCount():
|
||||
self.setRowCount(rows)
|
||||
for index in range(0, rows):
|
||||
self.setRowHeight(index, 50)
|
||||
|
||||
def addItem(self, rowIdx: int, colIdx: int, text: str):
|
||||
item = QTableWidgetItem(text)
|
||||
item.setTextAlignment(Qt.AlignCenter)
|
||||
self.setItem(rowIdx, colIdx, item)
|
||||
|
||||
def addPicItem(self, rowIdx: int, colIdx: int, url: str):
|
||||
item = QTableWidgetItem()
|
||||
item.setTextAlignment(Qt.AlignCenter)
|
||||
item.setIcon(QIcon(url))
|
||||
self.setItem(rowIdx, colIdx, item)
|
||||
|
||||
def addWidgetItem(self, rowIdx: int, colIdx: int, widget):
|
||||
self.setCellWidget(rowIdx, colIdx, widget)
|
||||
@@ -1,16 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- encoding: utf-8 -*-
|
||||
"""
|
||||
@File : downloader.py
|
||||
@Date : 2021/09/15
|
||||
@Author : Yaronzz
|
||||
@Version : 1.0
|
||||
@Contact : yaronhuang@foxmail.com
|
||||
@Desc :
|
||||
"""
|
||||
class DownloaderImp():
|
||||
pass
|
||||
|
||||
|
||||
|
||||
downloadImp = DownloaderImp()
|
||||
@@ -1,4 +0,0 @@
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1629184159878" class="icon" viewBox="0 0 1092 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="23123" xmlns:xlink="http://www.w3.org/1999/xlink" width="136.5" height="128"><defs><style type="text/css"></style></defs><path d="M538.624 1017.344L0.580267 405.162667 212.445867 0h652.356266L1076.565333 405.162667z" fill="#46F256" p-id="23124"></path><path d="M538.624 748.6464l-317.44-351.607467 67.618133-61.098666 249.787734 276.718933 249.821866-276.6848 67.618134 61.064533z" fill="#000000" p-id="23125"></path></svg>
|
||||
|
Before Width: | Height: | Size: 673 B |
@@ -1,4 +0,0 @@
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<svg t="1629268466285" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="18338" width="128" height="128"><path d="M294.314667 0L242.432 119.424H165.418667v107.648h29.653333L225.152 418.133333H178.005333l62.293334 351.146667 40.021333-0.426667 40.192 255.146667h380.501333l2.645334-17.066667 37.546666-238.08 37.888 0.426667 62.293334-351.189333h-45.056l30.08-191.018667h32.256V119.466667h-81.834667L724.906667 0H294.314667z m22.528 34.346667h385.834666l32.896 75.946666H283.818667l33.024-75.946666z m-117.333334 119.338666H824.32v39.253334H199.509333v-39.253334z m19.328 298.581334h581.76l-50.176 282.453333-241.024-2.56-240.469333 2.56-50.090667-282.453333z" p-id="18339" fill="#ffffff"></path></svg>
|
||||
|
Before Width: | Height: | Size: 743 B |
@@ -1,5 +0,0 @@
|
||||
<svg fill="#ffffff" t="1606188206696" class="icon" viewBox="0 0 1024 1024" version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg" p-id="2750" width="16" height="16">
|
||||
<path d="M376.123077 836.923077L51.2 510.030769c-11.815385-11.815385-11.815385-31.507692 0-43.323077l43.323077-43.323077c11.815385-11.815385 31.507692-11.815385 43.323077 0L382.030769 669.538462c7.876923 7.876923 21.661538 7.876923 29.538462 0L890.092308 187.076923c11.815385-11.815385 31.507692-11.815385 43.323077 0l43.323077 43.323077c11.815385 11.815385 11.815385 31.507692 0 43.323077L419.446154 836.923077c-11.815385 13.784615-31.507692 13.784615-43.323077 0z"
|
||||
p-id="2751"></path>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 672 B |
@@ -1,6 +0,0 @@
|
||||
<!-- <svg t="1605685211717" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1511"
|
||||
width="150" height="150">
|
||||
<path d="M316.16 366.506667L512 561.92l195.84-195.413333L768 426.666667l-256 256-256-256z" fill="#cbcbcb"
|
||||
p-id="1512"></path>
|
||||
</svg> -->
|
||||
<svg t="1629251448482" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1609" width="128" height="128"><path d="M179.758545 374.008242a31.030303 31.030303 0 0 1 43.876849 0L512 662.372848l288.364606-288.364606a31.030303 31.030303 0 0 1 43.876849 43.876849l-310.303031 310.30303a31.030303 31.030303 0 0 1-43.876848 0l-310.303031-310.30303a31.030303 31.030303 0 0 1 0-43.876849z" p-id="1610" fill="#cbcbcb"></path></svg>
|
||||
|
Before Width: | Height: | Size: 769 B |
@@ -1,6 +0,0 @@
|
||||
<!-- <svg t="1605685211717" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1511"
|
||||
width="150" height="150">
|
||||
<path d="M316.16 366.506667L512 561.92l195.84-195.413333L768 426.666667l-256 256-256-256z" fill="#326cf3"
|
||||
p-id="1512"></path>
|
||||
</svg> -->
|
||||
<svg t="1629251448482" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1609" width="128" height="128"><path d="M179.758545 374.008242a31.030303 31.030303 0 0 1 43.876849 0L512 662.372848l288.364606-288.364606a31.030303 31.030303 0 0 1 43.876849 43.876849l-310.303031 310.30303a31.030303 31.030303 0 0 1-43.876848 0l-310.303031-310.30303a31.030303 31.030303 0 0 1 0-43.876849z" p-id="1610" fill="#326cf3"></path></svg>
|
||||
|
Before Width: | Height: | Size: 769 B |
@@ -1 +0,0 @@
|
||||
<svg t="1629268481541" class="icon" viewBox="0 0 1025 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="19187" width="128" height="128"><path d="M512.032 831.904c-19.168 0-38.304-9.92-58.144-29.76-7.808-7.808-7.808-20.48 0-28.288s20.48-7.808 28.288 0C494.368 786.08 504.16 792 512.032 792s17.664-5.92 29.856-18.144c7.808-7.808 20.48-7.808 28.288 0s7.808 20.48 0 28.288c-19.84 19.84-38.976 29.76-58.144 29.76z m-512-306.4c0 49.888 4.256 95.136 12.8 135.68s20.544 75.744 36 105.536 35.008 55.904 58.656 78.336 49.344 40.928 77.056 55.456c27.744 14.528 59.456 26.304 95.2 35.264S351.84 951.04 388.8 954.624 466.496 960 510.944 960c44.448 0 85.248-1.792 122.4-5.376s73.6-9.856 109.344-18.848c35.744-8.96 67.552-20.736 95.456-35.264s53.792-33.024 77.6-55.456c23.808-22.432 43.456-48.544 58.944-78.336s27.552-64.96 36.256-105.536c8.704-40.576 13.056-85.792 13.056-135.68 0-89.376-27.744-166.368-83.2-230.976 3.2-8.608 5.952-18.496 8.256-29.6s4.544-26.816 6.656-47.104c2.144-20.288 1.344-43.712-2.4-70.272S942.56 93.888 932.256 66.24l-8-1.632c-5.344-1.088-14.048-0.704-26.144 1.088s-26.208 5.024-42.4 9.696-37.056 13.92-62.656 27.744-52.608 31.328-81.056 52.512c-48.352-14.72-115.008-30.112-200-30.112s-151.808 15.392-200.544 30.112c-28.448-21.184-55.552-38.592-81.344-52.224s-46.4-22.976-61.856-28c-15.456-5.024-29.792-8.256-42.944-9.696s-21.6-1.888-25.344-1.344c-3.744 0.544-6.496 1.152-8.256 1.888-10.304 27.648-17.408 54.752-21.344 81.312s-4.8 49.888-2.656 69.984c2.144 20.096 4.448 35.904 6.944 47.392S80 286.304 83.2 294.56C27.744 358.816 0 435.808 0 525.536z m136.544 113.888c0-58.016 21.344-110.624 64-157.856 12.8-14.4 27.648-25.312 44.544-32.704s36.096-11.616 57.6-12.608 42.048-0.8 61.6 0.608 43.744 3.296 72.544 5.696 53.696 3.616 74.656 3.616c20.96 0 45.856-1.184 74.656-3.616s52.992-4.288 72.544-5.696c19.552-1.408 40.096-1.6 61.6-0.608s40.8 5.216 57.856 12.608c17.056 7.392 32 18.304 44.8 32.704 42.656 47.232 64 99.84 64 157.856 0 34.016-3.552 64.32-10.656 90.944s-16.096 48.928-26.944 66.912c-10.848 18.016-26.048 33.216-45.6 45.632s-38.496 22.016-56.8 28.8c-18.304 6.784-41.952 12.096-70.944 15.904s-54.944 6.112-77.856 6.912c-22.944 0.8-51.808 1.216-86.656 1.216s-63.648-0.416-86.4-1.216c-22.752-0.8-48.608-3.104-77.6-6.912s-52.608-9.12-70.944-15.904c-18.304-6.816-37.248-16.416-56.8-28.8s-34.752-27.616-45.6-45.632c-10.848-18.016-19.84-40.32-26.944-66.912s-10.656-56.928-10.656-90.944zM256.032 608c0-53.024 28.64-96 64-96s64 42.976 64 96-28.64 96-64 96-64-42.976-64-96z m384 0c0-53.024 28.64-96 64-96s64 42.976 64 96-28.64 96-64 96-64-42.976-64-96z" p-id="19188"></path></svg>
|
||||
|
Before Width: | Height: | Size: 2.5 KiB |
@@ -1 +0,0 @@
|
||||
<svg t="1629270772080" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1817" width="128" height="128"><path d="M658.059636 187.826424a31.030303 31.030303 0 0 1 0 43.876849l-288.364606 288.364606 288.364606 288.364606a31.030303 31.030303 0 0 1-43.876848 43.876848l-310.30303-310.30303a31.030303 31.030303 0 0 1 0-43.876848l310.30303-310.303031a31.030303 31.030303 0 0 1 43.876848 0z" p-id="1818"></path></svg>
|
||||
|
Before Width: | Height: | Size: 452 B |
@@ -1 +0,0 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1629182866847" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="22424" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M938.666667 682.666667v170.666666a85.333333 85.333333 0 0 1-85.333334 85.333334H170.666667a85.333333 85.333333 0 0 1-85.333334-85.333334v-170.666666h85.333334v170.666666h682.666666v-170.666666h85.333334z m-384-145.664l140.501333-140.501334 60.330667 60.330667L512 700.330667l-243.498667-243.498667 60.330667-60.330667L469.333333 537.002667V85.333333h85.333334v451.669334z" p-id="22425" fill="#ffffff"></path></svg>
|
||||
|
Before Width: | Height: | Size: 792 B |
@@ -1 +0,0 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1629183863957" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="22616" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M938.666667 682.666667v170.666666a85.333333 85.333333 0 0 1-85.333334 85.333334H170.666667a85.333333 85.333333 0 0 1-85.333334-85.333334v-170.666666h85.333334v170.666666h682.666666v-170.666666h85.333334z m-384-145.664l140.501333-140.501334 60.330667 60.330667L512 700.330667l-243.498667-243.498667 60.330667-60.330667L469.333333 537.002667V85.333333h85.333334v451.669334z" p-id="22617" fill="#e6e6e6"></path></svg>
|
||||
|
Before Width: | Height: | Size: 792 B |
@@ -1 +0,0 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1629182847499" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="22040" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M512 981.333333C252.8 981.333333 42.666667 771.2 42.666667 512S252.8 42.666667 512 42.666667s469.333333 210.133333 469.333333 469.333333-210.133333 469.333333-469.333333 469.333333z m0-85.333333a384 384 0 1 0 0-768 384 384 0 0 0 0 768z m42.837333-298.752h42.624v85.333333h-170.666666v-85.333333h42.666666v-85.333333h-42.666666v-85.333334h128v170.666667z m-42.837333-213.333333a42.666667 42.666667 0 1 1 0-85.333334 42.666667 42.666667 0 0 1 0 85.333334z" p-id="22041" fill="#ffffff"></path></svg>
|
||||
|
Before Width: | Height: | Size: 874 B |
@@ -1 +0,0 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1629181942259" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="21410" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M696.32 635.989333l229.845333 229.845334-60.330666 60.330666-229.845334-229.845333a341.333333 341.333333 0 1 1 60.330667-60.330667zM426.666667 682.666667a256 256 0 1 0 0-512 256 256 0 0 0 0 512z" p-id="21411" fill="#ffffff"></path></svg>
|
||||
|
Before Width: | Height: | Size: 615 B |
@@ -1 +0,0 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1629182857650" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="22232" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M890.581333 797.013333l-94.592 94.592-121.088-33.706666-34.602666 14.250666L578.133333 981.333333h-133.76l-61.824-109.525333-34.56-14.506667-121.088 33.322667-94.549333-94.549333 33.706667-121.088-14.250667-34.602667L42.666667 578.133333v-133.76l109.568-61.824 14.506666-34.56-33.322666-121.088 94.506666-94.506666 121.088 33.749333 34.56-14.250667L445.696 42.666667h133.802667l61.824 109.568 34.56 14.506666 121.045333-33.322666 94.72 94.506666-33.792 121.130667 14.293333 34.56L981.333333 445.738667v133.802666l-109.525333 61.781334-14.506667 34.688 33.28 121.045333z m-123.392-126.805333l37.205334-88.832L896 529.664v-34.304l-91.605333-52.053333-36.650667-88.874667 28.245333-101.333333-24.277333-24.234667-101.674667 27.946667-88.746666-37.205334L529.621333 128h-34.304l-52.053333 91.605333-88.874667 36.650667-101.376-28.288-24.149333 24.149333 27.946667 101.674667-37.205334 88.746667L128 494.208v34.346667l91.52 52.138666 36.650667 88.874667-28.245334 101.376 24.192 24.192 101.674667-27.946667 88.746667 37.205334 51.626666 91.562666h34.346667l52.138667-91.52 88.874666-36.650666 101.376 28.245333 24.234667-24.234667-27.946667-101.589333zM512 682.666667a170.666667 170.666667 0 1 1 0-341.333334 170.666667 170.666667 0 0 1 0 341.333334z m0-85.333334a85.333333 85.333333 0 1 0 0-170.666666 85.333333 85.333333 0 0 0 0 170.666666z" p-id="22233" fill="#ffffff"></path></svg>
|
||||
|
Before Width: | Height: | Size: 1.7 KiB |
@@ -1 +0,0 @@
|
||||
<svg t="1629268420515" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="16731" width="128" height="128"><path d="M350.8 591.8c-7 38.4-34.8 217.4-43 268-0.6 3.6-2 5-6 5H152.6c-15.2 0-26.2-13.2-24.2-27.8L245.6 93.2c3-19.2 20.2-33.8 40-33.8 304.6 0 330.2-7.4 408 22.8 120.2 46.6 131.2 159 88 280.6-43 125.2-145 179-280.2 180.6-86.8 1.4-139-14-150.6 48.4zM842.2 304c-3.6-2.6-5-3.6-6 2.6-4 22.8-10.2 45-17.6 67.2-79.8 227.6-301 207.8-409 207.8-12.2 0-20.2 6.6-21.8 18.8-45.2 280.8-54.2 339.4-54.2 339.4-2 14.2 7 25.8 21.2 25.8h127c17.2 0 31.4-12.6 34.8-29.8 1.4-10.8-2.2 12.2 28.8-182.6 9.2-44 28.6-39.4 58.6-39.4 142 0 252.8-57.6 285.8-224.6 13-69.6 9.2-142.8-47.6-185.2z" p-id="16732" fill="#ffffff"></path></svg>
|
||||
|
Before Width: | Height: | Size: 753 B |
@@ -1 +0,0 @@
|
||||
<svg t="1629270798317" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1968" width="128" height="128"><path d="M365.940364 187.826424a31.030303 31.030303 0 0 1 43.876848 0l310.30303 310.303031a31.030303 31.030303 0 0 1 0 43.876848l-310.30303 310.30303a31.030303 31.030303 0 0 1-43.876848-43.876848l288.364606-288.364606-288.364606-288.364606a31.030303 31.030303 0 0 1 0-43.876849z" p-id="1969"></path></svg>
|
||||
|
Before Width: | Height: | Size: 451 B |
@@ -1 +0,0 @@
|
||||
<svg t="1629269306451" class="icon" viewBox="0 0 1057 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="15526" width="128" height="128"><path d="M409.012356 811.965935c-108.676129 0.660645-213.058065-41.851871-289.924129-117.991225A401.242839 401.242839 0 0 1 0.006937 406.594065a401.242839 401.242839 0 0 1 119.015226-287.512775A408.344774 408.344774 0 0 1 409.012356 0.990968a408.344774 408.344774 0 0 1 289.924129 118.05729 401.275871 401.275871 0 0 1 119.08129 287.44671 401.275871 401.275871 0 0 1-119.048258 287.380645 408.344774 408.344774 0 0 1-289.891096 118.090322h-0.066065z m0-695.130838A290.617806 290.617806 0 0 0 201.63584 200.836129a285.563871 285.563871 0 0 0-84.69471 205.625806c0 162.221419 128.495484 289.626839 292.071226 289.626839 163.641806 0 292.13729-127.405419 292.13729-289.560774 0-162.221419-128.495484-289.725935-292.071225-289.725935h-0.066065zM957.942421 1005.799226l-173.980904-171.866839a55.130839 55.130839 0 0 1 0-80.235355c23.221677-22.990452 58.004645-22.990452 81.193291 0l173.947871 171.965936a55.130839 55.130839 0 0 1 0 80.235355 56.419097 56.419097 0 0 1-81.160258 0v-0.099097z" p-id="15527" fill="#ffffff"></path></svg>
|
||||
|
Before Width: | Height: | Size: 1.1 KiB |
@@ -1 +0,0 @@
|
||||
<svg t="1629255942168" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8597" width="128" height="128"><path d="M512 0C229.248 0 0 229.248 0 512s229.248 512 512 512 512-229.248 512-512S794.752 0 512 0zM432.64 748.256 197.056 512.64l90.496-90.496 145.056 145.12 307.744-307.744 90.496 90.496L432.64 748.256z" p-id="8598" fill="#2DB84D"></path></svg>
|
||||
|
Before Width: | Height: | Size: 391 B |
@@ -1 +0,0 @@
|
||||
<svg t="1629255998157" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8792" width="128" height="128"><path d="M512 0C229.248 0 0 229.248 0 512s229.248 512 512 512 512-229.248 512-512S794.752 0 512 0zM320 768 320 256l512.256 256L320 768z" p-id="8793" fill="#00BCD4"></path></svg>
|
||||
|
Before Width: | Height: | Size: 323 B |
@@ -1 +0,0 @@
|
||||
<svg t="1629256110134" class="icon" viewBox="0 0 1185 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3025" width="128" height="128"><path d="M700.365715 60.074208l468.319709 783.01037a118.307323 118.307323 0 0 1-45.345458 164.539234 127.444603 127.444603 0 0 1-62.324434 16.297089H124.376114A122.739586 122.739586 0 0 1 0 903.567918a117.557248 117.557248 0 0 1 16.706221-60.346963L485.02593 60.210586A126.694528 126.694528 0 0 1 655.020257 16.365278a122.739586 122.739586 0 0 1 45.345458 43.845308zM592.764011 916.046443a80.803561 80.803561 0 1 0-80.80356-80.803561 80.803561 80.803561 0 0 0 80.735372 80.803561z m0-673.567572a95.464122 95.464122 0 0 0-94.373104 106.988006l34.09433 270.640786a61.369793 61.369793 0 0 0 121.103058 0l34.094329-270.640786a95.464122 95.464122 0 0 0-94.373103-106.919818z" p-id="3026" fill="#DB3340"></path></svg>
|
||||
|
Before Width: | Height: | Size: 857 B |
@@ -1 +0,0 @@
|
||||
<svg t="1629251564375" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1864" width="128" height="128"><path d="M490.061576 311.947636a31.030303 31.030303 0 0 1 43.876848 0l310.303031 310.303031a31.030303 31.030303 0 0 1-43.876849 43.876848L512 377.762909l-288.364606 288.364606a31.030303 31.030303 0 0 1-43.876849-43.876848l310.303031-310.303031z" p-id="1865" fill="#326cf3"></path></svg>
|
||||
|
Before Width: | Height: | Size: 432 B |
@@ -1,5 +0,0 @@
|
||||
<svg fill="#cbcbcb" t="1605778065489" class="icon" viewBox="0 0 1024 1024" version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg" p-id="6682" width="16" height="16">
|
||||
<path d="M622.276923 508.061538l257.969231-257.96923c11.815385-11.815385 11.815385-29.538462 0-41.353846l-41.353846-41.353847c-11.815385-11.815385-29.538462-11.815385-41.353846 0L539.569231 425.353846c-7.876923 7.876923-19.692308 7.876923-27.569231 0L254.030769 165.415385c-11.815385-11.815385-29.538462-11.815385-41.353846 0l-41.353846 41.353846c-11.815385 11.815385-11.815385 29.538462 0 41.353846l257.969231 257.969231c7.876923 7.876923 7.876923 19.692308 0 27.56923L169.353846 793.6c-11.815385 11.815385-11.815385 29.538462 0 41.353846l41.353846 41.353846c11.815385 11.815385 29.538462 11.815385 41.353846 0L512 618.338462c7.876923-7.876923 19.692308-7.876923 27.569231 0l257.969231 257.96923c11.815385 11.815385 29.538462 11.815385 41.353846 0l41.353846-41.353846c11.815385-11.815385 11.815385-29.538462 0-41.353846L622.276923 535.630769c-5.907692-7.876923-5.907692-19.692308 0-27.569231z"
|
||||
p-id="6683"></path>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.1 KiB |
@@ -1,5 +0,0 @@
|
||||
<svg fill="#ffffff" t="1605778065489" class="icon" viewBox="0 0 1024 1024" version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg" p-id="6682" width="16" height="16">
|
||||
<path d="M622.276923 508.061538l257.969231-257.96923c11.815385-11.815385 11.815385-29.538462 0-41.353846l-41.353846-41.353847c-11.815385-11.815385-29.538462-11.815385-41.353846 0L539.569231 425.353846c-7.876923 7.876923-19.692308 7.876923-27.569231 0L254.030769 165.415385c-11.815385-11.815385-29.538462-11.815385-41.353846 0l-41.353846 41.353846c-11.815385 11.815385-11.815385 29.538462 0 41.353846l257.969231 257.969231c7.876923 7.876923 7.876923 19.692308 0 27.56923L169.353846 793.6c-11.815385 11.815385-11.815385 29.538462 0 41.353846l41.353846 41.353846c11.815385 11.815385 29.538462 11.815385 41.353846 0L512 618.338462c7.876923-7.876923 19.692308-7.876923 27.569231 0l257.969231 257.96923c11.815385 11.815385 29.538462 11.815385 41.353846 0l41.353846-41.353846c11.815385-11.815385 11.815385-29.538462 0-41.353846L622.276923 535.630769c-5.907692-7.876923-5.907692-19.692308 0-27.569231z"
|
||||
p-id="6683"></path>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.1 KiB |
@@ -1,5 +0,0 @@
|
||||
<svg fill="#cbcbcb" t="1605778299751" class="icon" viewBox="0 0 1024 1024" version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg" p-id="12048" width="16" height="16">
|
||||
<path d="M170.666667 85.333333h682.666666a85.333333 85.333333 0 0 1 85.333334 85.333334v682.666666a85.333333 85.333333 0 0 1-85.333334 85.333334H170.666667a85.333333 85.333333 0 0 1-85.333334-85.333334V170.666667a85.333333 85.333333 0 0 1 85.333334-85.333334z m0 85.333334v682.666666h682.666666V170.666667H170.666667z"
|
||||
p-id="12049"></path>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 526 B |
@@ -1,4 +0,0 @@
|
||||
<svg fill="#cbcbcb" t="1605777927585" class="icon" viewBox="0 0 1024 1024" version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg" p-id="5690" width="16" height="16">
|
||||
<path d="M938.666667 469.333333v85.333334H85.333333v-85.333334z" p-id="5691"></path>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 260 B |
@@ -1,633 +0,0 @@
|
||||
:root {
|
||||
--Font_Family: Microsoft YaHei UI;
|
||||
--Font_Size: 12px;
|
||||
--Font_Size_TableHeader: 15px;
|
||||
--Font_Size_PageTitle: 15px;
|
||||
--Font_Size_HugeTitle: 30px;
|
||||
--Font_Size_MsgLabel: 15px;
|
||||
|
||||
--Color_Default: #ffffff;
|
||||
--Color_DefaultHover: #f0f0f0;
|
||||
--Color_DefaultPressed: #ececec;
|
||||
--Color_DefaultText: #212121;
|
||||
|
||||
--Color_Primary: #326cf3;
|
||||
--Color_PrimaryHover: #477bf4;
|
||||
--Color_PrimaryPressed: #84a7f8;
|
||||
--Color_PrimaryText: #ffffff;
|
||||
|
||||
--Color_Success: #2db84d;
|
||||
--Color_SuccessHover: #42bf5f;
|
||||
--Color_SuccessPressed: #81d494;
|
||||
|
||||
--Color_Danger: #db3340;
|
||||
--Color_DangerHover: #df4853;
|
||||
--Color_DangerPressed: #e9858c;
|
||||
|
||||
--Color_Warning: #e9af20;
|
||||
--Color_WarningHover: #ebb737;
|
||||
--Color_WarningPressed: #f2cf79;
|
||||
|
||||
--Color_Info: #00bcd4;
|
||||
--Color_InfoHover: #1ac3d8;
|
||||
--Color_InfoPressed: #66d7e5;
|
||||
|
||||
--Color_Border: #cbcbcb;
|
||||
--Color_WindowsIcon: #cbcbcb;
|
||||
--Color_Background: #eeeeee;
|
||||
--Color_Shadow: #AA000000;
|
||||
|
||||
--Color_Transparent: transparent;
|
||||
|
||||
--Size_InputPaddingLR: 8px;
|
||||
--Size_InputPaddingTB: 6px;
|
||||
|
||||
--Size_HeaderHeight: 50px;
|
||||
--Size_ItemHeight: 18px;
|
||||
--Size_ProgressHeight: 26px;
|
||||
--Size_ControlHeight: 18px;
|
||||
|
||||
--Size_ControlPaddingLR: 8px;
|
||||
--Size_ControlPaddingTB: 6px;
|
||||
|
||||
--Size_IconSize: 24px;
|
||||
--Size_CornerRadius: 4px;
|
||||
|
||||
--Size_CalendarWidth: 287px;
|
||||
--Size_CalendarHeight: 300px;
|
||||
}
|
||||
|
||||
/* #QSS_START */
|
||||
|
||||
* {
|
||||
font-family: var(--Font_Family);
|
||||
font-size: var(--Font_Size);
|
||||
|
||||
background: var(--Color_Default);
|
||||
color: var(--Color_DefaultText);
|
||||
}
|
||||
|
||||
/* Widget */
|
||||
|
||||
QWidget#MainViewLeftWidget {
|
||||
background: #000000;
|
||||
}
|
||||
|
||||
QWidget#TestWidget {
|
||||
background: #000000;
|
||||
}
|
||||
|
||||
QWidget#AboutWidget {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* PushButton Style */
|
||||
|
||||
QPushButton {
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-color: var(--Color_DefaultPressed);
|
||||
padding-left: var(--Size_InputPaddingLR);
|
||||
padding-right: var(--Size_InputPaddingLR);
|
||||
padding-top: var(--Size_InputPaddingTB);
|
||||
padding-bottom: var(--Size_InputPaddingTB);
|
||||
border-radius: var(--Size_CornerRadius);
|
||||
color: var(--Color_DefaultText);
|
||||
background: var(--Color_Default);
|
||||
}
|
||||
|
||||
QPushButton::hover {
|
||||
color: var(--Color_DefaultText);
|
||||
background: var(--Color_DefaultHover);
|
||||
}
|
||||
|
||||
QPushButton::pressed {
|
||||
color: var(--Color_DefaultText);
|
||||
background: var(--Color_DefaultPressed);
|
||||
}
|
||||
|
||||
|
||||
QPushButton#PrimaryPushButton {
|
||||
border-color: var(--Color_PrimaryPressed);
|
||||
color: var(--Color_PrimaryText);
|
||||
background: var(--Color_Primary);
|
||||
}
|
||||
|
||||
QPushButton#PrimaryPushButton::hover {
|
||||
background: var(--Color_PrimaryHover);
|
||||
}
|
||||
|
||||
QPushButton#PrimaryPushButton::pressed {
|
||||
background: var(--Color_PrimaryPressed);
|
||||
}
|
||||
|
||||
QPushButton#SuccessPushButton {
|
||||
border-color: var(--Color_SuccessPressed);
|
||||
color: var(--Color_PrimaryText);
|
||||
background: var(--Color_Success);
|
||||
}
|
||||
|
||||
QPushButton#SuccessPushButton::hover {
|
||||
background: var(--Color_SuccessHover);
|
||||
}
|
||||
|
||||
QPushButton#SuccessPushButton::pressed {
|
||||
background: var(--Color_SuccessPressed);
|
||||
}
|
||||
|
||||
QPushButton#DangerPushButton {
|
||||
border-color: var(--Color_DangerPressed);
|
||||
color: var(--Color_PrimaryText);
|
||||
background: var(--Color_Danger);
|
||||
}
|
||||
|
||||
QPushButton#DangerPushButton::hover {
|
||||
background: var(--Color_DangerHover);
|
||||
}
|
||||
|
||||
QPushButton#DangerPushButton::pressed {
|
||||
background: var(--Color_DangerPressed);
|
||||
}
|
||||
|
||||
QPushButton#WarningPushButton {
|
||||
border-color: var(--Color_WarningPressed);
|
||||
color: var(--Color_PrimaryText);
|
||||
background: var(--Color_Warning);
|
||||
}
|
||||
|
||||
QPushButton#WarningPushButton::hover {
|
||||
background: var(--Color_WarningHover);
|
||||
}
|
||||
|
||||
QPushButton#WarningPushButton::pressed {
|
||||
background: var(--Color_WarningPressed);
|
||||
}
|
||||
|
||||
QPushButton#InfoPushButton {
|
||||
border-color: var(--Color_InfoPressed);
|
||||
color: var(--Color_PrimaryText);
|
||||
background: var(--Color_Info);
|
||||
}
|
||||
|
||||
QPushButton#InfoPushButton::hover {
|
||||
background: var(--Color_InfoHover);
|
||||
}
|
||||
|
||||
QPushButton#InfoPushButton::pressed {
|
||||
background: var(--Color_InfoPressed);
|
||||
}
|
||||
|
||||
/* Software Buton */
|
||||
|
||||
QPushButton#SoftwareIconPushButton {
|
||||
border-style: none;
|
||||
border-radius: 0px;
|
||||
height: 26;
|
||||
width: 26;
|
||||
background: var(--Color_Transparent);
|
||||
image: url($PACKAGE_PATH$/resource/svg/V.svg)
|
||||
}
|
||||
QPushButton#SoftwareIconPushButton::hover {
|
||||
image: url($PACKAGE_PATH$/resource/svg/V.svg)
|
||||
}
|
||||
QPushButton#SoftwareIconPushButton::pressed {
|
||||
image: url($PACKAGE_PATH$/resource/svg/V.svg)
|
||||
}
|
||||
|
||||
|
||||
/* Windows Buton */
|
||||
QPushButton#CloseWindowPushButton {
|
||||
border-style: none;
|
||||
border-radius: 0px;
|
||||
background: var(--Color_Transparent);
|
||||
image: url($PACKAGE_PATH$/resource/svg/windows/close.svg)
|
||||
}
|
||||
|
||||
QPushButton#CloseWindowPushButton::hover {
|
||||
background: #ff1a1a;
|
||||
image: url($PACKAGE_PATH$/resource/svg/windows/closeHover.svg)
|
||||
}
|
||||
|
||||
QPushButton#CloseWindowPushButton::pressed {
|
||||
background: #ff6666;
|
||||
image: url($PACKAGE_PATH$/resource/svg/windows/closeHover.svg)
|
||||
}
|
||||
|
||||
QPushButton#MaxWindowPushButton {
|
||||
border-style: none;
|
||||
border-radius: 0px;
|
||||
background: var(--Color_Transparent);
|
||||
image: url($PACKAGE_PATH$/resource/svg/windows/max.svg)
|
||||
}
|
||||
|
||||
QPushButton#MaxWindowPushButton::hover {
|
||||
background: var(--Color_DefaultHover);
|
||||
}
|
||||
|
||||
QPushButton#MaxWindowPushButton::pressed {
|
||||
background: var(var(--Color_DefaultPressed));
|
||||
}
|
||||
|
||||
QPushButton#MinWindowPushButton {
|
||||
border-style: none;
|
||||
border-radius: 0px;
|
||||
background: var(--Color_Transparent);
|
||||
image: url($PACKAGE_PATH$/resource/svg/windows/min.svg)
|
||||
}
|
||||
|
||||
QPushButton#MinWindowPushButton::hover {
|
||||
background: var(--Color_DefaultHover);
|
||||
}
|
||||
|
||||
QPushButton#MinWindowPushButton::pressed {
|
||||
background: var(var(--Color_DefaultPressed));
|
||||
}
|
||||
|
||||
|
||||
/* Icon Button */
|
||||
QPushButton#SearchIconPushButton {
|
||||
border-style: none;
|
||||
border-radius: 0px;
|
||||
height: 26;
|
||||
width: 26;
|
||||
background: var(--Color_Transparent);
|
||||
image: url($PACKAGE_PATH$/resource/svg/leftTab/search.svg)
|
||||
}
|
||||
QPushButton#SearchIconPushButton::hover {
|
||||
image: url($PACKAGE_PATH$/resource/svg/leftTab/search.svg)
|
||||
}
|
||||
QPushButton#SearchIconPushButton::pressed {
|
||||
image: url($PACKAGE_PATH$/resource/svg/leftTab/search.svg)
|
||||
}
|
||||
|
||||
QPushButton#TaskIconPushButton {
|
||||
border-style: none;
|
||||
border-radius: 0px;
|
||||
height: 26;
|
||||
width: 26;
|
||||
background: var(--Color_Transparent);
|
||||
image: url($PACKAGE_PATH$/resource/svg/leftTab/download.svg)
|
||||
}
|
||||
QPushButton#TaskIconPushButton::hover {
|
||||
image: url($PACKAGE_PATH$/resource/svg/leftTab/downloadHover.svg)
|
||||
}
|
||||
QPushButton#TaskIconPushButton::pressed {
|
||||
image: url($PACKAGE_PATH$/resource/svg/leftTab/downloadHover.svg)
|
||||
}
|
||||
|
||||
QPushButton#SettingsIconPushButton {
|
||||
border-style: none;
|
||||
border-radius: 0px;
|
||||
height: 26;
|
||||
width: 26;
|
||||
background: var(--Color_Transparent);
|
||||
image: url($PACKAGE_PATH$/resource/svg/leftTab/settings.svg)
|
||||
}
|
||||
QPushButton#SettingsIconPushButton::hover {
|
||||
image: url($PACKAGE_PATH$/resource/svg/leftTab/settings.svg)
|
||||
}
|
||||
QPushButton#SettingsIconPushButton::pressed {
|
||||
image: url($PACKAGE_PATH$/resource/svg/leftTab/settings.svg)
|
||||
}
|
||||
|
||||
QPushButton#AboutIconPushButton {
|
||||
border-style: none;
|
||||
border-radius: 0px;
|
||||
height: 26;
|
||||
width: 26;
|
||||
background: var(--Color_Transparent);
|
||||
image: url($PACKAGE_PATH$/resource/svg/leftTab/info.svg)
|
||||
}
|
||||
QPushButton#AboutIconPushButton::hover {
|
||||
image: url($PACKAGE_PATH$/resource/svg/leftTab/info.svg)
|
||||
}
|
||||
QPushButton#AboutIconPushButton::pressed {
|
||||
image: url($PACKAGE_PATH$/resource/svg/leftTab/info.svg)
|
||||
}
|
||||
|
||||
|
||||
QPushButton#PrePagePushButton {
|
||||
border-style: none;
|
||||
border-radius: 0px;
|
||||
height: 18;
|
||||
width: 18;
|
||||
background: var(--Color_DefaultHover);
|
||||
image: url($PACKAGE_PATH$/resource/svg/left.svg)
|
||||
}
|
||||
QPushButton#PrePagePushButton::hover {
|
||||
image: url($PACKAGE_PATH$/resource/svg/left.svg)
|
||||
}
|
||||
QPushButton#PrePagePushButton::pressed {
|
||||
image: url($PACKAGE_PATH$/resource/svg/left.svg)
|
||||
}
|
||||
|
||||
QPushButton#NextPagePushButton {
|
||||
border-style: none;
|
||||
border-radius: 0px;
|
||||
height: 18;
|
||||
width: 18;
|
||||
background: var(--Color_DefaultHover);
|
||||
image: url($PACKAGE_PATH$/resource/svg/right.svg)
|
||||
}
|
||||
QPushButton#NextPagePushButton::hover {
|
||||
image: url($PACKAGE_PATH$/resource/svg/right.svg)
|
||||
}
|
||||
QPushButton#NextPagePushButton::pressed {
|
||||
image: url($PACKAGE_PATH$/resource/svg/right.svg)
|
||||
}
|
||||
/* LineEdit Style */
|
||||
|
||||
QLineEdit {
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-color: var(--Color_Border);
|
||||
padding-left: var(--Size_InputPaddingLR);
|
||||
padding-right: var(--Size_InputPaddingLR);
|
||||
padding-top: var(--Size_InputPaddingTB);
|
||||
padding-bottom: var(--Size_InputPaddingTB);
|
||||
border-radius: var(--Size_CornerRadius);
|
||||
min-height: var(--Size_ControlHeight);
|
||||
color: var(--Color_DefaultText);
|
||||
background: var(--Color_Default);
|
||||
}
|
||||
|
||||
QLineEdit::hover {
|
||||
border-color: var(--Color_Primary);
|
||||
}
|
||||
|
||||
QLineEdit::focus {
|
||||
border-color: var(--Color_Primary);
|
||||
}
|
||||
|
||||
/* CheckBox Style */
|
||||
|
||||
QCheckBox::indicator {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
padding: 2px;
|
||||
|
||||
border: 1px solid var(--Color_Border);
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
QCheckBox::indicator::unchecked:hover {
|
||||
border: 1px solid var(--Color_PrimaryHover);
|
||||
}
|
||||
|
||||
QCheckBox::indicator::checked {
|
||||
background: var(--Color_Primary);
|
||||
image: url($PACKAGE_PATH$/resource/svg/check.svg);
|
||||
border: 1px solid var(--Color_Primary);
|
||||
}
|
||||
|
||||
/* TabWidget */
|
||||
|
||||
QTabWidget::pane {
|
||||
border:none;
|
||||
border-top: 1px solid var(--Color_Border);
|
||||
}
|
||||
QTabBar::tab {
|
||||
border:none;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
padding-bottom: 3px;
|
||||
font-size: var(--Font_Size_TableHeader);
|
||||
font-weight: bold;
|
||||
min-width: 70;
|
||||
}
|
||||
QTabBar::tab:selected {
|
||||
color: var(--Color_Primary);
|
||||
border-color: var(--Color_Primary);
|
||||
border-style: solid;
|
||||
border-bottom-width: 3px;
|
||||
}
|
||||
|
||||
/* Label */
|
||||
QLabel#PageTitleLabel {
|
||||
font-size: var(--Font_Size_PageTitle);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
QLabel#PageSubTitleLabel {
|
||||
font-size: var(--Font_Size_PageTitle);
|
||||
}
|
||||
|
||||
QLabel#HugeTitleLabel {
|
||||
font-size: var(--Font_Size_HugeTitle);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
QLabel#LogoBottomLabel {
|
||||
font-size: var(--Font_Size_MsgLabel);
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
/* QFrame */
|
||||
QFrame#VLineQFrame
|
||||
{
|
||||
border-top-style: none;
|
||||
border-bottom-style: none;
|
||||
border-right-style: none;
|
||||
border-left: 1px solid var(--Color_Border);
|
||||
}
|
||||
|
||||
QFrame#HLineQFrame
|
||||
{
|
||||
border-top: 1px solid var(--Color_Border);
|
||||
border-bottom-style: none;
|
||||
border-right-style: none;
|
||||
border-left-style: none;
|
||||
}
|
||||
|
||||
/* QComboBox */
|
||||
QComboBox {
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-color: var(--Color_Border);
|
||||
padding-left: var(--Size_InputPaddingLR);
|
||||
padding-right: var(--Size_InputPaddingLR);
|
||||
padding-top: var(--Size_InputPaddingTB);
|
||||
padding-bottom: var(--Size_InputPaddingTB);
|
||||
border-radius: var(--Size_CornerRadius);
|
||||
min-height: var(--Size_ControlHeight);
|
||||
color: var(--Color_DefaultText);
|
||||
background: var(--Color_Default);
|
||||
}
|
||||
|
||||
QComboBox::hover {
|
||||
border-color: var(--Color_Primary);
|
||||
}
|
||||
|
||||
QComboBox::focus {
|
||||
border-color: var(--Color_Primary);
|
||||
}
|
||||
|
||||
QComboBox::drop-down {
|
||||
subcontrol-position:center right;
|
||||
margin-right: 15px;
|
||||
border-left-style: none;
|
||||
}
|
||||
QComboBox::down-arrow {
|
||||
image: url($PACKAGE_PATH$/resource/svg/down.svg);
|
||||
width : 24px;
|
||||
height : 24px;
|
||||
}
|
||||
QComboBox::down-arrow:hover {
|
||||
image: url($PACKAGE_PATH$/resource/svg/downHover.svg);
|
||||
}
|
||||
|
||||
QComboBox::down-arrow:on {
|
||||
image: url($PACKAGE_PATH$/resource/svg/upHover.svg);
|
||||
}
|
||||
|
||||
QComboBox QAbstractItemView {
|
||||
margin-top:5px;
|
||||
border:1px solid var(--Color_Primary);
|
||||
outline:none;
|
||||
}
|
||||
|
||||
QComboBox QAbstractItemView::item {
|
||||
height: var(--Size_ItemHeight);
|
||||
|
||||
padding-top: var(--Size_InputPaddingTB);
|
||||
padding-bottom: var(--Size_InputPaddingTB);
|
||||
}
|
||||
|
||||
QComboBox QAbstractItemView::item:selected{
|
||||
color: var(--Color_PrimaryText);
|
||||
background: var(--Color_Primary);
|
||||
}
|
||||
|
||||
|
||||
/* QListWidget */
|
||||
QListWidget#TaskTabListWidget {
|
||||
border-style: none;
|
||||
background: var(--Color_Default);
|
||||
max-width: 150px;
|
||||
outline:none;
|
||||
}
|
||||
|
||||
QListWidget#TaskTabListWidget::item
|
||||
{
|
||||
height:32px;
|
||||
padding-left: var(--Size_ControlPaddingLR);
|
||||
border: none;
|
||||
border-radius: var(--Size_CornerRadius);
|
||||
margin-top:5px;
|
||||
}
|
||||
|
||||
QListWidget#TaskTabListWidget::item:hover
|
||||
{
|
||||
background: var(--Color_DefaultHover);
|
||||
color: var(--Color_DefaultText);
|
||||
}
|
||||
|
||||
QListWidget#TaskTabListWidget::item:selected
|
||||
{
|
||||
background: var(--Color_Primary);
|
||||
color: var(--Color_PrimaryText);
|
||||
}
|
||||
|
||||
|
||||
QListWidget#TaskContentListWidget {
|
||||
border-style: none;
|
||||
background: var(--Color_Default);
|
||||
}
|
||||
|
||||
/* QTableWidget */
|
||||
QTableWidget {
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
border-top: none;
|
||||
border-bottom: 1px solid var(--Color_Border);
|
||||
|
||||
text-align: center;
|
||||
color: var(--Color_DefaultText);
|
||||
background: var(--Color_DefaultHover);
|
||||
padding:5px;
|
||||
|
||||
}
|
||||
|
||||
QTableWidget::item{
|
||||
margin-top: 5px;
|
||||
background: var(--Color_Default);
|
||||
}
|
||||
QTableWidget::item:selected{
|
||||
color: var(--Color_PrimaryText);
|
||||
background: var(--Color_Primary);
|
||||
}
|
||||
|
||||
|
||||
QTableWidget QHeaderView::section {
|
||||
color: var(--Color_DefaultText);
|
||||
background: var(--Color_DefaultHover);
|
||||
text-align: center;
|
||||
height: var(--Size_HeaderHeight);
|
||||
border: none;
|
||||
font-size: var(--Font_Size_TableHeader);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
QTableWidget QScrollBar::vertical{
|
||||
background:transparent;
|
||||
width: 4px;
|
||||
border-radius:6px;
|
||||
}
|
||||
QTableWidget QScrollBar::handle{
|
||||
background: lightgray;
|
||||
border-radius:6px;
|
||||
}
|
||||
QTableWidget QScrollBar::handle:hover{background:gray;}
|
||||
QTableWidget QScrollBar::sub-line{background:transparent;}
|
||||
QTableWidget QScrollBar::add-line{background:transparent;}
|
||||
|
||||
|
||||
|
||||
/* QTableView */
|
||||
QTableView {
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
border-top: none;
|
||||
border-bottom: 1px solid var(--Color_Border);
|
||||
|
||||
text-align: center;
|
||||
color: var(--Color_DefaultText);
|
||||
background: var(--Color_DefaultHover);
|
||||
padding:5px;
|
||||
|
||||
}
|
||||
|
||||
QTableView::item{
|
||||
margin-top: 5px;
|
||||
background: var(--Color_Default);
|
||||
}
|
||||
QTableView::item:selected{
|
||||
color: var(--Color_PrimaryText);
|
||||
background: var(--Color_Primary);
|
||||
}
|
||||
|
||||
|
||||
QTableView QHeaderView::section {
|
||||
color: var(--Color_DefaultText);
|
||||
background: var(--Color_DefaultHover);
|
||||
text-align: center;
|
||||
height: var(--Size_HeaderHeight);
|
||||
border: none;
|
||||
font-size: var(--Font_Size_TableHeader);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
QTableView QScrollBar::vertical{
|
||||
background:transparent;
|
||||
width: 4px;
|
||||
border-radius:6px;
|
||||
}
|
||||
QTableView QScrollBar::handle{
|
||||
background: lightgray;
|
||||
border-radius:6px;
|
||||
}
|
||||
QTableView QScrollBar::handle:hover{background:gray;}
|
||||
QTableView QScrollBar::sub-line{background:transparent;}
|
||||
QTableView QScrollBar::add-line{background:transparent;}
|
||||
@@ -1,54 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- encoding: utf-8 -*-
|
||||
'''
|
||||
@File : enum.py
|
||||
@Date : 2021/05/08
|
||||
@Author : Yaronzz
|
||||
@Version : 1.0
|
||||
@Contact : yaronhuang@foxmail.com
|
||||
@Desc :
|
||||
'''
|
||||
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class ButtonStyle(Enum):
|
||||
Default = 0,
|
||||
Primary = 1,
|
||||
Success = 2,
|
||||
Danger = 3,
|
||||
Warning = 4,
|
||||
Info = 5,
|
||||
|
||||
CloseWindow = 6,
|
||||
MaxWindow = 7,
|
||||
MinWindow = 8,
|
||||
|
||||
SearchIcon = 9,
|
||||
TaskIcon = 10,
|
||||
SettingsIcon = 11,
|
||||
AboutIcon = 12,
|
||||
|
||||
SoftwareIcon = 13
|
||||
|
||||
PrePage = 14
|
||||
NextPage = 15
|
||||
|
||||
|
||||
class LabelStyle(Enum):
|
||||
Default = 0,
|
||||
PageTitle = 1,
|
||||
PageSubTitle = 2,
|
||||
HugeTitle = 3,
|
||||
LogoBottom = 4,
|
||||
|
||||
|
||||
class ThemeStyle(Enum):
|
||||
Default = 0,
|
||||
Dark = 1,
|
||||
|
||||
|
||||
class ListWidgetStyle(Enum):
|
||||
Default = 0,
|
||||
TaskTab = 1,
|
||||
TaskContent = 2,
|
||||
@@ -1,60 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- encoding: utf-8 -*-
|
||||
"""
|
||||
@File : qssParse.py
|
||||
@Date : 2021/05/08
|
||||
@Author : Yaronzz
|
||||
@Version : 1.0
|
||||
@Contact : yaronhuang@foxmail.com
|
||||
@Desc :
|
||||
"""
|
||||
|
||||
import aigpy
|
||||
|
||||
from tidal_gui.style import ThemeStyle
|
||||
|
||||
|
||||
def __getParam__(line: str):
|
||||
key = aigpy.string.getSub(line, "--", ":")
|
||||
value = aigpy.string.getSub(line, ":", ";")
|
||||
return key, value
|
||||
|
||||
|
||||
def __parseParamsList__(content: str) -> dict:
|
||||
globalStr = aigpy.string.getSub(content, ":root", "}")
|
||||
lines = globalStr.split("\n")
|
||||
|
||||
array = {}
|
||||
for line in lines:
|
||||
key, value = __getParam__(line)
|
||||
if key == "" or value == "":
|
||||
continue
|
||||
array[key] = value
|
||||
return array
|
||||
|
||||
|
||||
def __parseQss__(content: str, params: dict) -> str:
|
||||
content = aigpy.string.getSub(content, "/* #QSS_START */")
|
||||
for key in params:
|
||||
content = content.replace("var(--" + key + ")", params[key])
|
||||
|
||||
content = content.replace("$PACKAGE_PATH$", getPackagePath())
|
||||
return content
|
||||
|
||||
|
||||
def __getQss__(filePath: str) -> str:
|
||||
content = aigpy.file.getContent(filePath)
|
||||
params = __parseParamsList__(content)
|
||||
qss = __parseQss__(content, params)
|
||||
return qss
|
||||
|
||||
|
||||
def getPackagePath():
|
||||
path = __file__
|
||||
return aigpy.path.getDirName(path).replace('\\', '/')
|
||||
|
||||
|
||||
def getThemeQssContent(style: ThemeStyle = ThemeStyle.Default):
|
||||
name = "theme" + style.name + ".qss"
|
||||
path = getPackagePath() + "/resource/"
|
||||
return __getQss__(path + name)
|
||||
@@ -1,90 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- encoding: utf-8 -*-
|
||||
"""
|
||||
@File : tidalImp.py
|
||||
@Date : 2021/9/2
|
||||
@Author : Yaronzz
|
||||
@Version : 1.0
|
||||
@Contact : yaronhuang@foxmail.com
|
||||
@Desc :
|
||||
"""
|
||||
import time
|
||||
|
||||
import requests
|
||||
import tidal_dl.model
|
||||
from aigpy.stringHelper import isNull
|
||||
from tidal_dl import TokenSettings, TOKEN, TidalAPI
|
||||
|
||||
|
||||
class TidalImp(TidalAPI):
|
||||
def __init__(self):
|
||||
super(TidalImp, self).__init__()
|
||||
|
||||
def loginByConfig(self):
|
||||
if isNull(TOKEN.accessToken):
|
||||
return False
|
||||
|
||||
msg, check = self.verifyAccessToken(TOKEN.accessToken)
|
||||
if check:
|
||||
self.key.countryCode = TOKEN.countryCode
|
||||
self.key.userId = TOKEN.userid
|
||||
self.key.accessToken = TOKEN.accessToken
|
||||
return True
|
||||
|
||||
msg, check = self.refreshAccessToken(TOKEN.refreshToken)
|
||||
if check:
|
||||
TOKEN.userid = self.key.userId
|
||||
TOKEN.countryCode = self.key.countryCode
|
||||
TOKEN.accessToken = self.key.accessToken
|
||||
TOKEN.expiresAfter = time.time() + int(self.key.expiresIn)
|
||||
TokenSettings.save(TOKEN)
|
||||
return True
|
||||
else:
|
||||
tmp = TokenSettings() # clears saved tokens
|
||||
TokenSettings.save(tmp)
|
||||
return False
|
||||
|
||||
def loginByWeb(self):
|
||||
start = time.time()
|
||||
elapsed = 0
|
||||
while elapsed < self.key.authCheckTimeout:
|
||||
elapsed = time.time() - start
|
||||
msg, check = self.checkAuthStatus()
|
||||
if not check:
|
||||
if msg == "pending":
|
||||
time.sleep(self.key.authCheckInterval + 1)
|
||||
continue
|
||||
return False
|
||||
if check:
|
||||
TOKEN.userid = self.key.userId
|
||||
TOKEN.countryCode = self.key.countryCode
|
||||
TOKEN.accessToken = self.key.accessToken
|
||||
TOKEN.refreshToken = self.key.refreshToken
|
||||
TOKEN.expiresAfter = time.time() + int(self.key.expiresIn)
|
||||
TokenSettings.save(TOKEN)
|
||||
return True
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def getArtistsNames(self, artists: list[tidal_dl.model.Artist]):
|
||||
ret = []
|
||||
for item in artists:
|
||||
ret.append(item.name)
|
||||
return ','.join(ret)
|
||||
|
||||
@staticmethod
|
||||
def getDurationString(seconds: int):
|
||||
m, s = divmod(seconds, 60)
|
||||
h, m = divmod(m, 60)
|
||||
return "%02d:%02d:%02d" % (h, m, s)
|
||||
|
||||
def getCoverData(self, sid, width="320", height="320"):
|
||||
url = self.getCoverUrl(sid, width, height)
|
||||
try:
|
||||
respond = requests.get(url)
|
||||
return respond.content
|
||||
except:
|
||||
return ''
|
||||
|
||||
|
||||
tidalImp = TidalImp()
|
||||
@@ -1,10 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- encoding: utf-8 -*-
|
||||
"""
|
||||
@File : __init__.py
|
||||
@Date : 2021/05/11
|
||||
@Author : Yaronzz
|
||||
@Version : 1.0
|
||||
@Contact : yaronhuang@foxmail.com
|
||||
@Desc :
|
||||
"""
|
||||
@@ -1,74 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- encoding: utf-8 -*-
|
||||
"""
|
||||
@File : aboutView.py
|
||||
@Date : 2021/8/17
|
||||
@Author : Yaronzz
|
||||
@Version : 1.0
|
||||
@Contact : yaronhuang@foxmail.com
|
||||
@Desc :
|
||||
"""
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtGui import QPixmap
|
||||
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QGridLayout, QHBoxLayout, QLabel
|
||||
|
||||
from tidal_gui.control.label import Label
|
||||
from tidal_gui.control.pushButton import PushButton
|
||||
from tidal_gui.style import LabelStyle, ButtonStyle
|
||||
from tidal_gui.theme import getPackagePath
|
||||
|
||||
|
||||
class AboutView(QWidget):
|
||||
def __init__(self):
|
||||
super(AboutView, self).__init__()
|
||||
self.__initView__()
|
||||
|
||||
def __initView__(self):
|
||||
grid = QGridLayout(self)
|
||||
grid.addWidget(self.__initLogo__(), 0, 0, Qt.AlignLeft)
|
||||
grid.addLayout(self.__initContent__(), 0, 1)
|
||||
|
||||
def __initLogo__(self):
|
||||
path = getPackagePath() + "/resource/svg/V.svg"
|
||||
self._logo = QLabel()
|
||||
self._logo.setPixmap(QPixmap(path))
|
||||
return self._logo
|
||||
|
||||
def __initButton__(self):
|
||||
path = getPackagePath() + "/resource/svg/"
|
||||
|
||||
self._feedbackBtn = PushButton('Feedback', ButtonStyle.Default, iconUrl=path + 'github.svg')
|
||||
self._buymeacoffeeBtn = PushButton('Buymeacoffee', ButtonStyle.Info, iconUrl=path + 'buymeacoffee.svg')
|
||||
self._paypalBtn = PushButton('Paypal', ButtonStyle.Primary, iconUrl=path + 'paypal.svg')
|
||||
|
||||
layout = QHBoxLayout()
|
||||
layout.addWidget(self._feedbackBtn)
|
||||
layout.addWidget(self._buymeacoffeeBtn)
|
||||
layout.addWidget(self._paypalBtn)
|
||||
return layout
|
||||
|
||||
def __initContent__(self):
|
||||
self._titleLabel = Label('', LabelStyle.HugeTitle)
|
||||
self._authorLabel = Label('')
|
||||
self._versionLabel = Label('')
|
||||
self._lastVersionLabel = Label('')
|
||||
|
||||
layout = QVBoxLayout()
|
||||
layout.addWidget(self._titleLabel)
|
||||
layout.addWidget(self._authorLabel)
|
||||
layout.addWidget(self._versionLabel)
|
||||
layout.addWidget(self._lastVersionLabel)
|
||||
layout.addLayout(self.__initButton__())
|
||||
return layout
|
||||
|
||||
def setTitle(self, text: str):
|
||||
self._titleLabel.setText(text)
|
||||
|
||||
def setAuthor(self, text: str):
|
||||
self._authorLabel.setText('MADE WITH ♥ BY ' + text)
|
||||
|
||||
def setVersion(self, text: str):
|
||||
self._versionLabel.setText('VERSION ' + text)
|
||||
|
||||
def setLastVersion(self, text: str):
|
||||
self._lastVersionLabel.setText('LAST-VERSION ' + text)
|
||||
@@ -1,156 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- encoding: utf-8 -*-
|
||||
"""
|
||||
@File : loginView.py
|
||||
@Date : 2021/04/30
|
||||
@Author : Yaronzz
|
||||
@Version : 1.0
|
||||
@Contact : yaronhuang@foxmail.com
|
||||
@Desc :
|
||||
"""
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtGui import QPixmap
|
||||
from PyQt5.QtWidgets import *
|
||||
|
||||
from tidal_gui.control.checkBox import CheckBox
|
||||
from tidal_gui.control.framelessWidget import FramelessWidget
|
||||
from tidal_gui.control.label import Label
|
||||
from tidal_gui.control.layout import createHBoxLayout
|
||||
from tidal_gui.control.lineEdit import LineEdit
|
||||
from tidal_gui.control.pushButton import PushButton
|
||||
from tidal_gui.style import ButtonStyle, LabelStyle
|
||||
from tidal_gui.theme import getPackagePath
|
||||
|
||||
|
||||
class LoginView(FramelessWidget):
|
||||
viewWidth = 650
|
||||
viewHeight = 400
|
||||
logoWidth = 300
|
||||
|
||||
def __init__(self):
|
||||
super(LoginView, self).__init__()
|
||||
self.setFixedSize(self.viewWidth, self.viewHeight)
|
||||
self.__initView__()
|
||||
self.setWindowButton(True, False, False)
|
||||
|
||||
def __initAccountTab__(self):
|
||||
self._deviceCodeEdit = LineEdit()
|
||||
self._confirmBtn = PushButton("LOGIN", ButtonStyle.Primary)
|
||||
|
||||
grid = QGridLayout()
|
||||
grid.setSpacing(15)
|
||||
grid.setRowStretch(0, 1)
|
||||
|
||||
grid.addLayout(createHBoxLayout([Label("DeviceCode"), self._deviceCodeEdit]), 1, 0, 1, 2)
|
||||
grid.setRowStretch(3, 1)
|
||||
grid.addWidget(self._confirmBtn, 5, 0, 1, 2)
|
||||
grid.setRowStretch(6, 1)
|
||||
|
||||
widget = QWidget()
|
||||
widget.setLayout(grid)
|
||||
return widget
|
||||
|
||||
def __initProxyTab__(self):
|
||||
self._enableProxyCheck = CheckBox('')
|
||||
self._proxyHostEdit = LineEdit()
|
||||
self._proxyPortEdit = LineEdit()
|
||||
self._proxyUserEdit = LineEdit()
|
||||
self._proxyPwdEdit = LineEdit()
|
||||
|
||||
grid = QGridLayout()
|
||||
grid.setSpacing(8)
|
||||
grid.setRowStretch(0, 1)
|
||||
grid.addWidget(Label("HttpProxy"), 1, 0)
|
||||
grid.addWidget(self._enableProxyCheck, 1, 1)
|
||||
grid.addWidget(Label("Host"), 2, 0)
|
||||
grid.addWidget(self._proxyHostEdit, 2, 1)
|
||||
grid.addWidget(Label("Port"), 3, 0)
|
||||
grid.addWidget(self._proxyPortEdit, 3, 1)
|
||||
grid.addWidget(Label("UserName"), 4, 0)
|
||||
grid.addWidget(self._proxyUserEdit, 4, 1)
|
||||
grid.addWidget(Label("Password"), 5, 0)
|
||||
grid.addWidget(self._proxyPwdEdit, 5, 1)
|
||||
grid.setRowStretch(6, 1)
|
||||
|
||||
widget = QWidget()
|
||||
widget.setLayout(grid)
|
||||
return widget
|
||||
|
||||
def __initIconWidget__(self):
|
||||
self._icon = Label('')
|
||||
self._icon.setStyleSheet("QLabel{background-color:rgb(0,0,0);}")
|
||||
|
||||
self._icon.setPixmap(QPixmap(getPackagePath() + "/resource/svg/V.svg"))
|
||||
self._icon.setAlignment(Qt.AlignCenter)
|
||||
|
||||
self._iconLabel = Label('', LabelStyle.LogoBottom)
|
||||
self._iconLabel.setAlignment(Qt.AlignCenter)
|
||||
self._iconLabel.hide()
|
||||
|
||||
layout = QVBoxLayout()
|
||||
layout.setSpacing(15)
|
||||
layout.setContentsMargins(0, 0, 0, 0)
|
||||
layout.addStretch(1)
|
||||
layout.addWidget(self._icon)
|
||||
layout.addWidget(self._iconLabel)
|
||||
layout.addStretch(1)
|
||||
|
||||
widget = QWidget()
|
||||
widget.setStyleSheet("QWidget{background-color:rgb(0,0,0);}")
|
||||
widget.setLayout(layout)
|
||||
return widget
|
||||
|
||||
def __initView__(self):
|
||||
iconWidget = self.__initIconWidget__()
|
||||
|
||||
self._tab = QTabWidget(self)
|
||||
self._tab.addTab(self.__initAccountTab__(), "LOGIN")
|
||||
self._tab.addTab(self.__initProxyTab__(), "PROXY")
|
||||
self._tab.setFixedWidth(self.viewWidth - self.logoWidth - 60)
|
||||
self._tab.hide()
|
||||
|
||||
grid = self.getGrid()
|
||||
grid.setSpacing(15)
|
||||
grid.setContentsMargins(0, 0, 0, 0)
|
||||
grid.addWidget(iconWidget)
|
||||
grid.addWidget(self._tab, 0, 1, Qt.AlignCenter)
|
||||
|
||||
self.setValidMoveWidget(iconWidget)
|
||||
|
||||
def showEnterView(self):
|
||||
self._tab.show()
|
||||
|
||||
def hideEnterView(self):
|
||||
self._tab.hide()
|
||||
|
||||
def setDeviceCode(self, text):
|
||||
self._deviceCodeEdit.setText(text)
|
||||
|
||||
def enableHttpProxy(self) -> bool:
|
||||
return self._enableProxyCheck.isChecked()
|
||||
|
||||
def getProxyInfo(self) -> dict:
|
||||
infos = {'host': self._proxyHostEdit.text(), 'port': self._proxyPortEdit.text(),
|
||||
'username': self._proxyUserEdit.text(), 'password': self._proxyPwdEdit.text()}
|
||||
return infos
|
||||
|
||||
def connectConfirmButton(self, func):
|
||||
self._confirmBtn.clicked.connect(func)
|
||||
|
||||
def enableConfirmButton(self, enable):
|
||||
self._confirmBtn.setEnabled(enable)
|
||||
|
||||
def setMsg(self, text):
|
||||
if len(text) <= 0:
|
||||
self._iconLabel.hide()
|
||||
else:
|
||||
self._iconLabel.setText(text)
|
||||
self._iconLabel.show()
|
||||
|
||||
def showErrMessage(self, text: str):
|
||||
qmb = QMessageBox(self)
|
||||
qmb.setWindowTitle('Error')
|
||||
qmb.setIcon(QMessageBox.Warning)
|
||||
qmb.setText(text)
|
||||
qmb.addButton(QPushButton('OK', qmb), QMessageBox.YesRole)
|
||||
qmb.open()
|
||||
@@ -1,116 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- encoding: utf-8 -*-
|
||||
"""
|
||||
@File : main.py
|
||||
@Date : 2021/05/11
|
||||
@Author : Yaronzz
|
||||
@Version : 1.0
|
||||
@Contact : yaronhuang@foxmail.com
|
||||
@Desc :
|
||||
"""
|
||||
from enum import IntEnum
|
||||
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtWidgets import QVBoxLayout, QWidget, QGridLayout
|
||||
|
||||
from tidal_gui.control.framelessWidget import FramelessWidget
|
||||
from tidal_gui.control.pushButton import PushButton
|
||||
from tidal_gui.style import ButtonStyle
|
||||
|
||||
|
||||
class PageType(IntEnum):
|
||||
Search = 0,
|
||||
Task = 1,
|
||||
Settings = 2,
|
||||
About = 3,
|
||||
Max = 4,
|
||||
|
||||
|
||||
class MainView(FramelessWidget):
|
||||
viewWidth = 1200
|
||||
viewHeight = 700
|
||||
|
||||
def __init__(self):
|
||||
super(MainView, self).__init__()
|
||||
self.setMinimumHeight(self.viewHeight)
|
||||
self.setMinimumWidth(self.viewWidth)
|
||||
self.__initPages__()
|
||||
self.__initView__()
|
||||
self.setWindowButton(True, True, True)
|
||||
|
||||
def __initPages__(self):
|
||||
self._pages = []
|
||||
for index in range(0, PageType.Max):
|
||||
self._pages.append(None)
|
||||
|
||||
def __initView__(self):
|
||||
leftTab = self.__initLeftTab__()
|
||||
content = self.__initContent__()
|
||||
|
||||
grid = self.getGrid()
|
||||
grid.addWidget(leftTab, 0, 0, Qt.AlignLeft)
|
||||
grid.addLayout(content, 0, 1)
|
||||
|
||||
self.setValidMoveWidget(leftTab)
|
||||
|
||||
def __initLeftTab__(self):
|
||||
self._icon = PushButton("", ButtonStyle.SoftwareIcon)
|
||||
self._searchBtn = PushButton("", ButtonStyle.SearchIcon)
|
||||
self._taskBtn = PushButton("", ButtonStyle.TaskIcon)
|
||||
self._settingsBtn = PushButton("", ButtonStyle.SettingsIcon)
|
||||
self._aboutBtn = PushButton("", ButtonStyle.AboutIcon)
|
||||
|
||||
self._searchBtn.clicked.connect(lambda: self.showPage(PageType.Search))
|
||||
self._taskBtn.clicked.connect(lambda: self.showPage(PageType.Task))
|
||||
self._settingsBtn.clicked.connect(lambda: self.showPage(PageType.Settings))
|
||||
self._aboutBtn.clicked.connect(lambda: self.showPage(PageType.About))
|
||||
|
||||
layout = QVBoxLayout()
|
||||
layout.setSpacing(15)
|
||||
layout.setContentsMargins(15, 45, 15, 20)
|
||||
layout.addWidget(self._icon)
|
||||
layout.addWidget(self._searchBtn)
|
||||
layout.addWidget(self._taskBtn)
|
||||
layout.addStretch(1)
|
||||
layout.addWidget(self._settingsBtn)
|
||||
layout.addWidget(self._aboutBtn)
|
||||
|
||||
widget = QWidget()
|
||||
widget.setLayout(layout)
|
||||
widget.setObjectName("MainViewLeftWidget")
|
||||
return widget
|
||||
|
||||
def __initContent__(self) -> QGridLayout:
|
||||
self._searchView = None
|
||||
self._settingsView = None
|
||||
self._aboutView = None
|
||||
self._taskView = None
|
||||
self._contentLayout = QGridLayout()
|
||||
self._contentLayout.setContentsMargins(10, 30, 10, 10)
|
||||
return self._contentLayout
|
||||
|
||||
def showPage(self, pageType: PageType = PageType.Search):
|
||||
for index in range(0, PageType.Max):
|
||||
if index == pageType:
|
||||
self._pages[index].show()
|
||||
else:
|
||||
self._pages[index].hide()
|
||||
|
||||
def __setContentPage__(self, view, pageType: PageType):
|
||||
self._pages[pageType] = view
|
||||
self._pages[pageType].hide()
|
||||
self._contentLayout.addWidget(view, 0, 0)
|
||||
|
||||
def setSearchView(self, view):
|
||||
self.__setContentPage__(view, PageType.Search)
|
||||
|
||||
def setTaskView(self, view):
|
||||
self.__setContentPage__(view, PageType.Task)
|
||||
|
||||
def setSettingsView(self, view):
|
||||
self.__setContentPage__(view, PageType.Settings)
|
||||
|
||||
def setAboutView(self, view: QWidget):
|
||||
# self.__setContentPage__(view, PageType.About)
|
||||
self._pages[PageType.About] = view
|
||||
self._pages[PageType.About].hide()
|
||||
@@ -1,199 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- encoding: utf-8 -*-
|
||||
"""
|
||||
@File : searchView.py
|
||||
@Date : 2021/8/17
|
||||
@Author : Yaronzz
|
||||
@Version : 1.0
|
||||
@Contact : yaronhuang@foxmail.com
|
||||
@Desc :
|
||||
"""
|
||||
import tidal_dl.model
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QTabWidget
|
||||
from tidal_dl import Type
|
||||
|
||||
from tidal_gui.control.comboBox import ComboBox
|
||||
from tidal_gui.control.label import Label
|
||||
from tidal_gui.control.layout import createHBoxLayout
|
||||
from tidal_gui.control.lineEdit import LineEdit
|
||||
from tidal_gui.control.pushButton import PushButton
|
||||
from tidal_gui.control.tableView import TableView
|
||||
from tidal_gui.control.tableWidget import TableWidget
|
||||
from tidal_gui.style import ButtonStyle
|
||||
from tidal_gui.theme import getPackagePath
|
||||
from tidal_gui.tidalImp import tidalImp
|
||||
|
||||
|
||||
class SearchView(QWidget):
|
||||
def __init__(self):
|
||||
super(SearchView, self).__init__()
|
||||
self._rowCount = 20
|
||||
self._table = {}
|
||||
self.__initView__()
|
||||
self._searchEdit.setFocus()
|
||||
self._searchBtn.setDefault(True)
|
||||
|
||||
def __initView__(self):
|
||||
grid = QVBoxLayout(self)
|
||||
grid.addLayout(self.__initHead__(), Qt.AlignTop)
|
||||
grid.addLayout(self.__initContent__())
|
||||
grid.addLayout(self.__initTail__(), Qt.AlignBottom)
|
||||
|
||||
def __initHead__(self):
|
||||
self._searchEdit = LineEdit()
|
||||
self._searchBtn = PushButton('Search', ButtonStyle.Primary,
|
||||
iconUrl=getPackagePath() + "/resource/svg/search.svg")
|
||||
|
||||
layout = createHBoxLayout([self._searchEdit, self._searchBtn])
|
||||
return layout
|
||||
|
||||
def __initTail__(self):
|
||||
self._trackQualityComboBox = ComboBox([])
|
||||
self._videoQualityComboBox = ComboBox([])
|
||||
|
||||
self._prePageBtn = PushButton('', ButtonStyle.PrePage)
|
||||
self._nextPageBtn = PushButton('', ButtonStyle.NextPage)
|
||||
self._pageIndexEdit = LineEdit('')
|
||||
|
||||
self._downloadBtn = PushButton('Download', ButtonStyle.Primary)
|
||||
|
||||
layout = QHBoxLayout()
|
||||
layout.addWidget(Label('Track:'))
|
||||
layout.addWidget(self._trackQualityComboBox)
|
||||
layout.addWidget(Label('Video:'))
|
||||
layout.addWidget(self._videoQualityComboBox)
|
||||
layout.addStretch(1)
|
||||
layout.addWidget(self._prePageBtn)
|
||||
layout.addWidget(self._pageIndexEdit)
|
||||
layout.addWidget(self._nextPageBtn)
|
||||
layout.addWidget(self._downloadBtn)
|
||||
return layout
|
||||
|
||||
def __initContent__(self):
|
||||
self._tabWidget = QTabWidget(self)
|
||||
self._tabWidget.addTab(self.__initTable__(Type.Album), "ALBUM")
|
||||
self._tabWidget.addTab(self.__initTable__(Type.Track), "TRACK")
|
||||
self._tabWidget.addTab(self.__initTable__(Type.Video), "VIDEO")
|
||||
self._tabWidget.addTab(self.__initTable__(Type.Playlist), "PLAYLIST")
|
||||
|
||||
layout = QVBoxLayout()
|
||||
layout.addWidget(self._tabWidget)
|
||||
return layout
|
||||
|
||||
def __initTable__(self, stype: Type):
|
||||
if stype == Type.Album:
|
||||
columnHeads = ['#', ' ', 'Title', 'Artists', 'Release', 'Duration']
|
||||
self._table[stype] = TableWidget(columnHeads)
|
||||
self._table[stype].setColumnWidth(0, 50)
|
||||
self._table[stype].setColumnWidth(1, 60)
|
||||
self._table[stype].setColumnWidth(2, 400)
|
||||
self._table[stype].setColumnWidth(3, 200)
|
||||
elif stype == Type.Track:
|
||||
columnHeads = ['#', ' ', 'Title', 'Album', 'Artists', 'Duration']
|
||||
self._table[stype] = TableWidget(columnHeads)
|
||||
self._table[stype].setColumnWidth(0, 50)
|
||||
self._table[stype].setColumnWidth(1, 60)
|
||||
self._table[stype].setColumnWidth(2, 400)
|
||||
self._table[stype].setColumnWidth(3, 200)
|
||||
self._table[stype].setColumnWidth(4, 200)
|
||||
elif stype == Type.Video:
|
||||
columnHeads = ['#', ' ', 'Title', 'Artists', 'Duration']
|
||||
self._table[stype] = TableWidget(columnHeads)
|
||||
self._table[stype].setColumnWidth(0, 50)
|
||||
self._table[stype].setColumnWidth(1, 60)
|
||||
self._table[stype].setColumnWidth(2, 400)
|
||||
self._table[stype].setColumnWidth(3, 200)
|
||||
self._table[stype].setColumnWidth(4, 200)
|
||||
elif stype == Type.Playlist:
|
||||
columnHeads = ['#', 'Title', 'Artist', 'Duration']
|
||||
self._table[stype] = TableWidget(columnHeads)
|
||||
self._table[stype].setColumnWidth(0, 50)
|
||||
self._table[stype].setColumnWidth(1, 400)
|
||||
self._table[stype].setColumnWidth(2, 200)
|
||||
self._table[stype].setColumnWidth(3, 200)
|
||||
return self._table[stype]
|
||||
|
||||
def setTableItems(self, stype: Type, indexOffset: int, result: tidal_dl.model.SearchResult):
|
||||
if stype == Type.Album:
|
||||
items = result.albums.items
|
||||
self._table[stype].changeRowCount(len(items))
|
||||
for index, item in enumerate(items):
|
||||
self._table[stype].addItem(index, 0, str(index + 1 + indexOffset))
|
||||
self._table[stype].addItem(index, 1, tidalImp.getFlag(item, Type.Album, True))
|
||||
self._table[stype].addItem(index, 2, item.title)
|
||||
self._table[stype].addItem(index, 3, item.artists[0].name)
|
||||
self._table[stype].addItem(index, 4, str(item.releaseDate))
|
||||
self._table[stype].addItem(index, 5, tidalImp.getDurationString(item.duration))
|
||||
elif stype == Type.Track:
|
||||
items = result.tracks.items
|
||||
self._table[stype].changeRowCount(len(items))
|
||||
for index, item in enumerate(items):
|
||||
self._table[stype].addItem(index, 0, str(index + 1 + indexOffset))
|
||||
self._table[stype].addItem(index, 1, tidalImp.getFlag(item, Type.Track, True))
|
||||
self._table[stype].addItem(index, 2, item.title)
|
||||
self._table[stype].addItem(index, 3, item.album.title)
|
||||
self._table[stype].addItem(index, 4, item.artists[0].name)
|
||||
self._table[stype].addItem(index, 5, tidalImp.getDurationString(item.duration))
|
||||
elif stype == Type.Video:
|
||||
items = result.videos.items
|
||||
self._table[stype].changeRowCount(len(items))
|
||||
for index, item in enumerate(items):
|
||||
self._table[stype].addItem(index, 0, str(index + 1 + indexOffset))
|
||||
self._table[stype].addItem(index, 1, tidalImp.getFlag(item, Type.Video, True))
|
||||
self._table[stype].addItem(index, 2, item.title)
|
||||
self._table[stype].addItem(index, 3, item.artists[0].name)
|
||||
self._table[stype].addItem(index, 4, tidalImp.getDurationString(item.duration))
|
||||
elif stype == Type.Playlist:
|
||||
items = result.playlists.items
|
||||
self._table[stype].changeRowCount(len(items))
|
||||
for index, item in enumerate(items):
|
||||
self._table[stype].addItem(index, 0, str(index + 1 + indexOffset))
|
||||
self._table[stype].addItem(index, 1, item.title)
|
||||
self._table[stype].addItem(index, 2, '')
|
||||
self._table[stype].addItem(index, 3, tidalImp.getDurationString(item.duration))
|
||||
self._table[stype].viewport().update()
|
||||
|
||||
def getSearchText(self):
|
||||
return self._searchEdit.text()
|
||||
|
||||
def setPageIndex(self, index):
|
||||
self._pageIndexEdit.setText(str(index))
|
||||
|
||||
def getPageIndex(self):
|
||||
return int(self._pageIndexEdit.text())
|
||||
|
||||
def getSelectedTabIndex(self):
|
||||
return self._tabWidget.currentIndex()
|
||||
|
||||
def getSelectedTableIndex(self, stype: Type):
|
||||
array = self._table[stype].selectedIndexes()
|
||||
if len(array) <= 0:
|
||||
return -1
|
||||
return array[0].row()
|
||||
|
||||
def setTrackQualityItems(self, items: list):
|
||||
self._trackQualityComboBox.setItems(items)
|
||||
|
||||
def setVideoQualityItems(self, items: list):
|
||||
self._videoQualityComboBox.setItems(items)
|
||||
|
||||
def getTrackQualityText(self):
|
||||
return self._trackQualityComboBox.currentText()
|
||||
|
||||
def getVideoQualityText(self):
|
||||
return self._videoQualityComboBox.currentText()
|
||||
|
||||
def connectButton(self, name: str, func):
|
||||
if name == 'search':
|
||||
self._searchBtn.clicked.connect(func)
|
||||
self._searchEdit.returnPressed.connect(func)
|
||||
elif name == 'prePage':
|
||||
self._prePageBtn.clicked.connect(func)
|
||||
elif name == 'nextPage':
|
||||
self._nextPageBtn.clicked.connect(func)
|
||||
elif name == 'download':
|
||||
self._downloadBtn.clicked.connect(func)
|
||||
|
||||
def connectTab(self, func):
|
||||
self._tabWidget.currentChanged.connect(func)
|
||||
@@ -1,96 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- encoding: utf-8 -*-
|
||||
"""
|
||||
@File : settingsView.py
|
||||
@Date : 2021/05/11
|
||||
@Author : Yaronzz
|
||||
@Version : 1.0
|
||||
@Contact : yaronhuang@foxmail.com
|
||||
@Desc :
|
||||
"""
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QGridLayout
|
||||
|
||||
from tidal_gui.control.checkBox import CheckBox
|
||||
from tidal_gui.control.comboBox import ComboBox
|
||||
from tidal_gui.control.label import Label
|
||||
from tidal_gui.control.line import Line
|
||||
from tidal_gui.control.lineEdit import LineEdit
|
||||
from tidal_gui.control.pushButton import PushButton
|
||||
from tidal_gui.style import LabelStyle, ButtonStyle, ThemeStyle
|
||||
|
||||
|
||||
class SettingsView(QWidget):
|
||||
def __init__(self):
|
||||
super(SettingsView, self).__init__()
|
||||
self.__initView__()
|
||||
|
||||
def __initView__(self):
|
||||
grid = QVBoxLayout(self)
|
||||
grid.addLayout(self.__initHeader__())
|
||||
grid.addLayout(self.__initContent__())
|
||||
grid.addLayout(self.__initToolButton__())
|
||||
|
||||
def __initHeader__(self):
|
||||
self._header = Label("SETTINGS", LabelStyle.PageTitle)
|
||||
layout = QVBoxLayout()
|
||||
layout.addWidget(self._header)
|
||||
layout.addWidget(Line('H'))
|
||||
layout.setSpacing(10)
|
||||
layout.setContentsMargins(0, 0, 0, 10)
|
||||
return layout
|
||||
|
||||
def __initToolButton__(self) -> QHBoxLayout:
|
||||
self._logoutBtn = PushButton('Logout', ButtonStyle.Danger, 100)
|
||||
self._cancelBtn = PushButton('Cancel', ButtonStyle.Default, 100)
|
||||
self._confirmBtn = PushButton('OK', ButtonStyle.Primary, 100)
|
||||
|
||||
layout = QHBoxLayout()
|
||||
layout.addWidget(self._logoutBtn)
|
||||
layout.addStretch(1)
|
||||
layout.addWidget(self._cancelBtn)
|
||||
layout.addWidget(self._confirmBtn)
|
||||
return layout
|
||||
|
||||
def __addContent__(self, control, desc=''):
|
||||
rowIdx = self._contentLayout.rowCount()
|
||||
if desc != '':
|
||||
self._contentLayout.addWidget(Label(desc), rowIdx, 0, Qt.AlignRight)
|
||||
self._contentLayout.addWidget(control, rowIdx, 1)
|
||||
|
||||
def __initContent__(self):
|
||||
self._contentLayout = QGridLayout()
|
||||
self._contentLayout.setSpacing(15)
|
||||
|
||||
self._pathEdit = LineEdit()
|
||||
self._threadNumComboBox = ComboBox([1, 5, 10, 20])
|
||||
self._searchNumComboBox = ComboBox([10, 20, 30, 40, 50])
|
||||
self.__addContent__(self._pathEdit, 'Path:')
|
||||
self.__addContent__(self._threadNumComboBox, 'ThreadNum:')
|
||||
self.__addContent__(self._searchNumComboBox, 'SearchNum:')
|
||||
|
||||
self._contentLayout.setRowStretch(self._contentLayout.rowCount(), 1)
|
||||
|
||||
self._albumFolderFormatEdit = LineEdit()
|
||||
self._trackFileFormatEdit = LineEdit()
|
||||
self._videoFileFormatEdit = LineEdit()
|
||||
self.__addContent__(self._albumFolderFormatEdit, 'AlbumFolderFormat:')
|
||||
self.__addContent__(self._trackFileFormatEdit, 'TrackFileFormat:')
|
||||
self.__addContent__(self._videoFileFormatEdit, 'VideoFileFormat:')
|
||||
|
||||
self._saveCoverCheck = CheckBox('Download album cover')
|
||||
self._skipExistCheck = CheckBox('Skip exist file when downloading')
|
||||
self._convertMp4ToM4a = CheckBox('Convert mp4 to m4a')
|
||||
self.__addContent__(self._saveCoverCheck)
|
||||
self.__addContent__(self._skipExistCheck)
|
||||
self.__addContent__(self._convertMp4ToM4a)
|
||||
|
||||
self._contentLayout.setRowStretch(self._contentLayout.rowCount(), 1)
|
||||
|
||||
self._themeComboBox = ComboBox(list(map(lambda x: x.name, ThemeStyle)))
|
||||
self._languageComboBox = ComboBox(['Default'])
|
||||
self.__addContent__(self._themeComboBox, 'Theme:')
|
||||
self.__addContent__(self._languageComboBox, 'Language:')
|
||||
|
||||
self._contentLayout.setRowStretch(self._contentLayout.rowCount(), 10)
|
||||
return self._contentLayout
|
||||
@@ -1,68 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- encoding: utf-8 -*-
|
||||
"""
|
||||
@File : taskItemView.py
|
||||
@Date : 2021/9/14
|
||||
@Author : Yaronzz
|
||||
@Version : 1.0
|
||||
@Contact : yaronhuang@foxmail.com
|
||||
@Desc :
|
||||
"""
|
||||
from PyQt5.QtWidgets import QWidget, QHBoxLayout, QTableWidget, QVBoxLayout
|
||||
|
||||
from tidal_gui.control.label import Label
|
||||
from tidal_gui.control.layout import createHBoxLayout, createVBoxLayout
|
||||
from tidal_gui.control.pushButton import PushButton
|
||||
|
||||
|
||||
class TaskItemView(QWidget):
|
||||
def __init__(self):
|
||||
super(TaskItemView, self).__init__()
|
||||
self.__initView__()
|
||||
|
||||
def __initView__(self):
|
||||
grid = QVBoxLayout(self)
|
||||
grid.addLayout(self.__initHead__())
|
||||
grid.addWidget(self.__initList__())
|
||||
|
||||
def __initHead__(self):
|
||||
self._btnRetry = PushButton()
|
||||
self._btnCancel = PushButton()
|
||||
self._btnDelete = PushButton()
|
||||
self._btnOpen = PushButton()
|
||||
self._btnExpand = PushButton()
|
||||
btnLayout = createHBoxLayout([self._btnRetry, self._btnCancel,
|
||||
self._btnDelete, self._btnOpen,
|
||||
self._btnExpand])
|
||||
|
||||
self._titleLabel = Label()
|
||||
self._descLabel = Label()
|
||||
self._errLabel = Label()
|
||||
self._errLabel.hide()
|
||||
labelLayout = createVBoxLayout([self._titleLabel, self._descLabel, self._errLabel])
|
||||
|
||||
self._picLabel = Label()
|
||||
headLayout = QHBoxLayout()
|
||||
headLayout.addWidget(self._picLabel)
|
||||
headLayout.addLayout(labelLayout)
|
||||
headLayout.addStretch(1)
|
||||
headLayout.addLayout(btnLayout)
|
||||
|
||||
return headLayout
|
||||
|
||||
def __initList__(self):
|
||||
self._list = QTableWidget()
|
||||
return self._list
|
||||
|
||||
def setLabel(self, title, desc):
|
||||
self._titleLabel.setText(title)
|
||||
self._descLabel.setText(desc)
|
||||
|
||||
def setErrmsg(self, msg):
|
||||
self._errLabel.setText(msg)
|
||||
|
||||
def setPic(self, data):
|
||||
pass
|
||||
|
||||
def addList(self):
|
||||
pass
|
||||
@@ -1,73 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- encoding: utf-8 -*-
|
||||
"""
|
||||
@File : taskView.py
|
||||
@Date : 2021/8/17
|
||||
@Author : Yaronzz
|
||||
@Version : 1.0
|
||||
@Contact : yaronhuang@foxmail.com
|
||||
@Desc :
|
||||
"""
|
||||
from PyQt5.QtCore import Qt, QSize
|
||||
from PyQt5.QtWidgets import QWidget, QGridLayout, QListWidgetItem
|
||||
|
||||
from tidal_gui.control.label import Label
|
||||
from tidal_gui.control.line import Line
|
||||
from tidal_gui.control.listWidget import ListWidget
|
||||
from tidal_gui.style import LabelStyle, ListWidgetStyle
|
||||
from tidal_gui.theme import getPackagePath
|
||||
|
||||
|
||||
class TaskView(QWidget):
|
||||
def __init__(self):
|
||||
super(TaskView, self).__init__()
|
||||
self._listMap = {'Download': ListWidget(ListWidgetStyle.TaskContent),
|
||||
'Complete': ListWidget(ListWidgetStyle.TaskContent),
|
||||
'Error': ListWidget(ListWidgetStyle.TaskContent)}
|
||||
self._pageMap = {'Download': QWidget(),
|
||||
'Complete': QWidget(),
|
||||
'Error': QWidget()}
|
||||
self.__initView__()
|
||||
|
||||
def __initView__(self):
|
||||
grid = QGridLayout(self)
|
||||
grid.addLayout(self.__initLefTab__(), 0, 0, Qt.AlignLeft)
|
||||
grid.addWidget(self.__createContent__('Download'), 0, 1, Qt.AlignTop)
|
||||
grid.addWidget(self.__createContent__('Complete'), 0, 1, Qt.AlignTop)
|
||||
grid.addWidget(self.__createContent__('Error'), 0, 1, Qt.AlignTop)
|
||||
|
||||
def __initLefTab__(self):
|
||||
self._listTab = ListWidget(ListWidgetStyle.TaskTab)
|
||||
self._listTab.setIconSize(QSize(20, 20))
|
||||
|
||||
iconPath = getPackagePath() + "/resource/svg/taskTab/"
|
||||
self._listTab.addIConTextItem(iconPath + 'download.svg', 'Download')
|
||||
self._listTab.addIConTextItem(iconPath + 'complete.svg', 'Complete')
|
||||
self._listTab.addIConTextItem(iconPath + 'Error.svg', 'Error')
|
||||
|
||||
self._listTab.itemClicked.connect(self.__tabItemChanged__)
|
||||
|
||||
layout = QGridLayout()
|
||||
layout.addWidget(Label("TASK LIST", LabelStyle.PageTitle), 0, 0, Qt.AlignLeft)
|
||||
layout.addWidget(self._listTab, 1, 0, Qt.AlignLeft)
|
||||
layout.addWidget(Line('V'), 0, 1, 2, 1, Qt.AlignLeft)
|
||||
return layout
|
||||
|
||||
def __createContent__(self, typeStr: str):
|
||||
layout = QGridLayout()
|
||||
layout.setContentsMargins(0, 0, 10, 10)
|
||||
layout.setSpacing(10)
|
||||
layout.addWidget(Label(typeStr, LabelStyle.PageSubTitle), 0, 0, Qt.AlignTop)
|
||||
layout.addWidget(Line('H'), 1, 0, Qt.AlignTop)
|
||||
layout.addWidget(self._listMap[typeStr], 2, 0)
|
||||
|
||||
self._pageMap[typeStr].setLayout(layout)
|
||||
return self._pageMap[typeStr]
|
||||
|
||||
def __tabItemChanged__(self, item: QListWidgetItem):
|
||||
for name in self._listMap:
|
||||
if name == item.text():
|
||||
self._pageMap[name].show()
|
||||
else:
|
||||
self._pageMap[name].hide()
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- encoding: utf-8 -*-
|
||||
"""
|
||||
@File : __init__.py
|
||||
@Date : 2021/8/17
|
||||
@Author : Yaronzz
|
||||
@Version : 1.0
|
||||
@Contact : yaronhuang@foxmail.com
|
||||
@Desc :
|
||||
"""
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- encoding: utf-8 -*-
|
||||
"""
|
||||
@File : aboutModel.py
|
||||
@Date : 2021/8/17
|
||||
@Author : Yaronzz
|
||||
@Version : 1.0
|
||||
@Contact : yaronhuang@foxmail.com
|
||||
@Desc :
|
||||
"""
|
||||
from tidal_gui.view.aboutView import AboutView
|
||||
from tidal_gui.viewModel.viewModel import ViewModel
|
||||
|
||||
|
||||
class AboutModel(ViewModel):
|
||||
def __init__(self):
|
||||
super(AboutModel, self).__init__()
|
||||
self.view = AboutView()
|
||||
self.view.setTitle('TIDAL-GUI')
|
||||
self.view.setAuthor('Yaronzz')
|
||||
self.view.setVersion('1.0.0.1')
|
||||
self.view.setLastVersion('1.0.0.1')
|
||||
@@ -1,68 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- encoding: utf-8 -*-
|
||||
"""
|
||||
@File : loginModel.py
|
||||
@Date : 2021/8/17
|
||||
@Author : Yaronzz
|
||||
@Version : 1.0
|
||||
@Contact : yaronhuang@foxmail.com
|
||||
@Desc :
|
||||
"""
|
||||
import _thread
|
||||
import time
|
||||
import webbrowser
|
||||
|
||||
from PyQt5.QtCore import QTimer, pyqtSignal, QObject
|
||||
|
||||
from tidal_gui.tidalImp import tidalImp
|
||||
from tidal_gui.view.loginView import LoginView
|
||||
from tidal_gui.viewModel.viewModel import ViewModel
|
||||
|
||||
|
||||
class LoginModel(ViewModel):
|
||||
SIGNAL_LOGIN_SUCCESS = pyqtSignal()
|
||||
|
||||
def __init__(self):
|
||||
super(LoginModel, self).__init__()
|
||||
self.view = LoginView()
|
||||
self.view.connectConfirmButton(self.__openWebAndWait__)
|
||||
|
||||
def loginByConfig(self):
|
||||
self.view.hideEnterView()
|
||||
self.view.setMsg("LOGIN...")
|
||||
|
||||
def __thread_login__(model: LoginModel):
|
||||
if tidalImp.loginByConfig():
|
||||
model.SIGNAL_LOGIN_SUCCESS.emit()
|
||||
return
|
||||
model.getDeviceCode()
|
||||
|
||||
_thread.start_new_thread(__thread_login__, (self,))
|
||||
|
||||
def getDeviceCode(self):
|
||||
self.view.hideEnterView()
|
||||
self.view.setMsg("GET DEVICE-CODE...")
|
||||
|
||||
def __thread_getCode__(model: LoginModel):
|
||||
msg, check = tidalImp.getDeviceCode()
|
||||
if check:
|
||||
model.view.enableConfirmButton(True)
|
||||
model.view.setDeviceCode(tidalImp.key.userCode)
|
||||
model.view.setMsg(' ')
|
||||
model.view.showEnterView()
|
||||
else:
|
||||
model.view.setMsg(msg)
|
||||
|
||||
_thread.start_new_thread(__thread_getCode__, (self,))
|
||||
|
||||
def __openWebAndWait__(self):
|
||||
self.view.enableConfirmButton(False)
|
||||
webbrowser.open('link.tidal.com', new=0, autoraise=True)
|
||||
|
||||
def __thread_waitLogin__(model: LoginModel):
|
||||
if tidalImp.loginByWeb():
|
||||
model.SIGNAL_LOGIN_SUCCESS.emit()
|
||||
else:
|
||||
model.getDeviceCode()
|
||||
|
||||
_thread.start_new_thread(__thread_waitLogin__, (self,))
|
||||
@@ -1,47 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- encoding: utf-8 -*-
|
||||
"""
|
||||
@File : mainModel.py
|
||||
@Date : 2021/8/17
|
||||
@Author : Yaronzz
|
||||
@Version : 1.0
|
||||
@Contact : yaronhuang@foxmail.com
|
||||
@Desc :
|
||||
"""
|
||||
from tidal_gui.view.mainView import MainView
|
||||
from tidal_gui.viewModel.aboutModel import AboutModel
|
||||
from tidal_gui.viewModel.loginModel import LoginModel
|
||||
from tidal_gui.viewModel.searchModel import SearchModel
|
||||
from tidal_gui.viewModel.settingsModel import SettingsModel
|
||||
from tidal_gui.viewModel.taskModel import TaskModel
|
||||
from tidal_gui.viewModel.viewModel import ViewModel
|
||||
|
||||
|
||||
class MainModel(ViewModel):
|
||||
def __init__(self):
|
||||
super(MainModel, self).__init__()
|
||||
self.loginModel = LoginModel()
|
||||
self.searchModel = SearchModel()
|
||||
self.taskModel = TaskModel()
|
||||
self.settingsModel = SettingsModel()
|
||||
self.aboutModel = AboutModel()
|
||||
|
||||
self.loginModel.SIGNAL_LOGIN_SUCCESS.connect(self.__loginSuccess__)
|
||||
self.searchModel.SIGNAL_ADD_TASKITEM.connect(self.taskModel.addTaskItem)
|
||||
|
||||
self.view = MainView()
|
||||
self.view.setSearchView(self.searchModel.view)
|
||||
self.view.setTaskView(self.taskModel.view)
|
||||
self.view.setSettingsView(self.settingsModel.view)
|
||||
self.view.setAboutView(self.aboutModel.view)
|
||||
|
||||
self.view.showPage()
|
||||
|
||||
def show(self):
|
||||
self.view.hide()
|
||||
self.loginModel.loginByConfig()
|
||||
self.loginModel.show()
|
||||
|
||||
def __loginSuccess__(self):
|
||||
self.loginModel.hide()
|
||||
self.view.show()
|
||||
@@ -1,101 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- encoding: utf-8 -*-
|
||||
"""
|
||||
@File : searchModel.py
|
||||
@Date : 2021/8/17
|
||||
@Author : Yaronzz
|
||||
@Version : 1.0
|
||||
@Contact : yaronhuang@foxmail.com
|
||||
@Desc :
|
||||
"""
|
||||
import _thread
|
||||
import threading
|
||||
|
||||
import aigpy.stringHelper
|
||||
import tidal_dl
|
||||
from PyQt5.QtCore import pyqtSignal
|
||||
from aigpy.modelHelper import ModelBase
|
||||
from tidal_dl import Type
|
||||
from tidal_dl.model import Album, SearchResult
|
||||
|
||||
from tidal_gui.tidalImp import tidalImp
|
||||
from tidal_gui.view.searchView import SearchView
|
||||
from tidal_gui.viewModel.viewModel import ViewModel
|
||||
|
||||
|
||||
class SearchModel(ViewModel):
|
||||
SIGNAL_ADD_TASKITEM = pyqtSignal(ModelBase)
|
||||
|
||||
def __init__(self):
|
||||
super(SearchModel, self).__init__()
|
||||
self._lock = threading.Lock()
|
||||
self._resultData = SearchResult()
|
||||
self.view = SearchView()
|
||||
self.view.setPageIndex(1)
|
||||
self.view.connectButton('search', self.__search__)
|
||||
self.view.connectButton('prePage', self.__searchPrePage__)
|
||||
self.view.connectButton('nextPage', self.__searchNextPage__)
|
||||
self.view.connectButton('download', self.__download__)
|
||||
self.view.connectTab(self.__search__)
|
||||
|
||||
def __startThread__(self):
|
||||
def __thread_search__(model: SearchModel):
|
||||
typeIndex = model.view.getSelectedTabIndex()
|
||||
pageIndex = model.view.getPageIndex()
|
||||
searchText = model.view.getSearchText()
|
||||
|
||||
limit = 20
|
||||
offset = (pageIndex - 1) * limit
|
||||
stype = tidal_dl.Type(typeIndex)
|
||||
msg, model._resultData = tidalImp.search(searchText, stype, offset, limit)
|
||||
|
||||
if not aigpy.stringHelper.isNull(msg):
|
||||
# errmessage
|
||||
model._lock.release()
|
||||
return
|
||||
|
||||
model.view.setTableItems(stype, offset, model._resultData)
|
||||
model._lock.release()
|
||||
|
||||
_thread.start_new_thread(__thread_search__, (self,))
|
||||
|
||||
def __search__(self):
|
||||
if not self._lock.acquire(False):
|
||||
return
|
||||
self.view.setPageIndex(1)
|
||||
self.__startThread__()
|
||||
|
||||
def __searchNextPage__(self):
|
||||
if not self._lock.acquire(False):
|
||||
return
|
||||
self.view.setPageIndex(self.view.getPageIndex() + 1)
|
||||
self.__startThread__()
|
||||
|
||||
def __searchPrePage__(self):
|
||||
if not self._lock.acquire(False):
|
||||
return
|
||||
index = self.view.getPageIndex() - 1
|
||||
if index < 1:
|
||||
index = 1
|
||||
self.view.setPageIndex(index)
|
||||
self.__startThread__()
|
||||
|
||||
def __download__(self):
|
||||
typeIndex = self.view.getSelectedTabIndex()
|
||||
stype = tidal_dl.Type(typeIndex)
|
||||
index = self.view.getSelectedTableIndex(stype)
|
||||
if index <= 0:
|
||||
pass
|
||||
|
||||
data = None
|
||||
if stype == Type.Album:
|
||||
data = self._resultData.albums.items[index]
|
||||
elif stype == Type.Track:
|
||||
data = self._resultData.tracks.items[index]
|
||||
elif stype == Type.Video:
|
||||
data = self._resultData.videos.items[index]
|
||||
elif stype == Type.Playlist:
|
||||
data = self._resultData.playlists.items[index]
|
||||
|
||||
if data is not None:
|
||||
self.SIGNAL_ADD_TASKITEM.emit(data)
|
||||
@@ -1,18 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- encoding: utf-8 -*-
|
||||
"""
|
||||
@File : settingsModel.py
|
||||
@Date : 2021/8/17
|
||||
@Author : Yaronzz
|
||||
@Version : 1.0
|
||||
@Contact : yaronhuang@foxmail.com
|
||||
@Desc :
|
||||
"""
|
||||
from tidal_gui.view.settingsView import SettingsView
|
||||
from tidal_gui.viewModel.viewModel import ViewModel
|
||||
|
||||
|
||||
class SettingsModel(ViewModel):
|
||||
def __init__(self):
|
||||
super(SettingsModel, self).__init__()
|
||||
self.view = SettingsView()
|
||||
@@ -1,66 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- encoding: utf-8 -*-
|
||||
"""
|
||||
@File : taskItemModel.py
|
||||
@Date : 2021/9/14
|
||||
@Author : Yaronzz
|
||||
@Version : 1.0
|
||||
@Contact : yaronhuang@foxmail.com
|
||||
@Desc :
|
||||
"""
|
||||
import _thread
|
||||
|
||||
import aigpy.stringHelper
|
||||
from tidal_dl import Type
|
||||
from tidal_dl.model import Album, Track, Video, Playlist
|
||||
|
||||
from tidal_gui.tidalImp import tidalImp
|
||||
from tidal_gui.view.taskItemView import TaskItemView
|
||||
from tidal_gui.viewModel.viewModel import ViewModel
|
||||
|
||||
|
||||
class TaskItemModel(ViewModel):
|
||||
def __init__(self, data):
|
||||
super(TaskItemModel, self).__init__()
|
||||
self.view = TaskItemView()
|
||||
if isinstance(data, Album):
|
||||
self.__initAlbum__(data)
|
||||
elif isinstance(data, Track):
|
||||
self.__initTrack__(data)
|
||||
elif isinstance(data, Video):
|
||||
self.__initVideo__(data)
|
||||
elif isinstance(data, Playlist):
|
||||
self.__initPlaylist__(data)
|
||||
|
||||
def __initAlbum__(self, data: Album):
|
||||
title = data.title
|
||||
desc = f"by {data.artist.name} " \
|
||||
f"{tidalImp.getDurationString(data.duration)} " \
|
||||
f"Track-{data.numberOfTracks} " \
|
||||
f"Video-{data.numberOfVideos}"
|
||||
self.view.setLabel(title, desc)
|
||||
|
||||
def __thread_func__(model: TaskItemModel, album: Album):
|
||||
cover = tidalImp.getCoverData(album.cover, '1280', '1280')
|
||||
self.view.setPic(cover)
|
||||
|
||||
msg, tracks, videos = tidalImp.getItems(album.id, Type.Album)
|
||||
if not aigpy.stringHelper.isNull(msg):
|
||||
model.view.setErrmsg(msg)
|
||||
return
|
||||
# TODO
|
||||
for item in tracks:
|
||||
pass
|
||||
for item in videos:
|
||||
pass
|
||||
|
||||
_thread.start_new_thread(__thread_func__, (self, data))
|
||||
|
||||
def __initTrack__(self, data: Track):
|
||||
pass
|
||||
|
||||
def __initVideo__(self, data: Video):
|
||||
pass
|
||||
|
||||
def __initPlaylist__(self, data: Playlist):
|
||||
pass
|
||||
@@ -1,25 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- encoding: utf-8 -*-
|
||||
"""
|
||||
@File : taskModel.py
|
||||
@Date : 2021/8/17
|
||||
@Author : Yaronzz
|
||||
@Version : 1.0
|
||||
@Contact : yaronhuang@foxmail.com
|
||||
@Desc :
|
||||
"""
|
||||
from tidal_dl import Type
|
||||
|
||||
from tidal_gui.view.taskView import TaskView
|
||||
from tidal_gui.viewModel.taskItemModel import TaskItemModel
|
||||
from tidal_gui.viewModel.viewModel import ViewModel
|
||||
|
||||
|
||||
class TaskModel(ViewModel):
|
||||
def __init__(self):
|
||||
super(TaskModel, self).__init__()
|
||||
self.view = TaskView()
|
||||
|
||||
def addTaskItem(self, data):
|
||||
item = TaskItemModel(data)
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- encoding: utf-8 -*-
|
||||
"""
|
||||
@File : viewModel.py
|
||||
@Date : 2021/8/17
|
||||
@Author : Yaronzz
|
||||
@Version : 1.0
|
||||
@Contact : yaronhuang@foxmail.com
|
||||
@Desc :
|
||||
"""
|
||||
from PyQt5.QtCore import QObject
|
||||
|
||||
|
||||
class ViewModel(QObject):
|
||||
def __init__(self):
|
||||
super(ViewModel, self).__init__()
|
||||
self.view = None
|
||||
|
||||
def show(self):
|
||||
self.view.show()
|
||||
|
||||
def hide(self):
|
||||
self.view.hide()
|
||||
@@ -1,56 +0,0 @@
|
||||
cd TIDALDL-PY
|
||||
rm -rf dist
|
||||
rm -rf build
|
||||
rm -rf exe
|
||||
rm -rf tidal_gui.egg-info
|
||||
mkdir exe
|
||||
|
||||
# pack
|
||||
python setup.py sdist bdist_wheel
|
||||
# creat exe file
|
||||
pyinstaller -F tidal_gui/__init__.py
|
||||
# rename exe name
|
||||
mv dist/__init__.exe exe/tidal-gui.exe
|
||||
|
||||
pip uninstall -y tidal-gui
|
||||
|
||||
# creat requirements.txt
|
||||
# pipreqs ./ --force --encoding=utf8
|
||||
|
||||
# python setup.py install
|
||||
|
||||
# upload
|
||||
twine upload dist/*
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# powershell·
|
||||
cd TIDALDL-PY
|
||||
Remove-Item dist -recurse -Force
|
||||
Remove-Item build -recurse -Force
|
||||
Remove-Item exe -recurse -Force
|
||||
Remove-Item tidal_dl.egg-info -recurse -Force
|
||||
md exe
|
||||
|
||||
# pack
|
||||
python setup.py sdist bdist_wheel
|
||||
# creat exe file
|
||||
pyinstaller -F tidal_dl/__init__.py
|
||||
#pyinstaller -F -i ../logo.ico tidal_dl/__init__.py
|
||||
# rename exe name
|
||||
cp dist/__init__.exe exe/tidal-dl.exe
|
||||
rm dist/__init__.exe
|
||||
|
||||
pip uninstall -y tidal-dl
|
||||
|
||||
# creat requirements.txt
|
||||
# pipreqs ./ --force
|
||||
|
||||
# python setup.py install
|
||||
|
||||
# upload
|
||||
twine upload dist/*
|
||||
@@ -0,0 +1,3 @@
|
||||
include tidal_gui/resource/themeDefault.qss
|
||||
include tidal_gui/resource/svg/*.svg
|
||||
include tidal_gui/resource/svg/*/*.svg
|
||||
@@ -1,8 +1,12 @@
|
||||
requests==2.22.0
|
||||
colorama==0.4.3
|
||||
prettytable==0.7.2
|
||||
mutagen==1.45.1
|
||||
psutil==5.7.3
|
||||
pycryptodome==3.9.9
|
||||
aigpy==2021.9.10.3
|
||||
lyricsgenius==3.0.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
|
||||
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
from setuptools import setup, find_packages
|
||||
setup(
|
||||
name = 'tidal-gui',
|
||||
version = '1.0.0.1',
|
||||
version = '2022.01.18.3',
|
||||
license = "Apache2",
|
||||
description = "Tidal Music Downloader.",
|
||||
description = "Tidal Music Downloader-GUI.",
|
||||
|
||||
author = 'YaronH',
|
||||
author_email = "yaronhuang@foxmail.com",
|
||||
|
||||
packages = find_packages(),
|
||||
packages=find_packages(exclude=['tidal_dl*']),
|
||||
include_package_data = True,
|
||||
platforms = "any",
|
||||
install_requires=["aigpy", "PyQt5", "requests>=2.22.0", "pycryptodome", "pydub", "prettytable", "lyricsgenius"],
|
||||
install_requires=["tidal-dl"],
|
||||
entry_points={'console_scripts': [ 'tidal-gui = tidal_gui:main', ]}
|
||||
)
|
||||
@@ -10,9 +10,14 @@ setup(
|
||||
author='YaronH',
|
||||
author_email="yaronhuang@foxmail.com",
|
||||
|
||||
packages=find_packages(),
|
||||
include_package_data=True,
|
||||
packages=find_packages(exclude=['tidal_gui*']),
|
||||
include_package_data=False,
|
||||
platforms="any",
|
||||
install_requires=["aigpy>=2021.9.10.3", "requests>=2.22.0", "pycryptodome", "pydub", "prettytable", "lyricsgenius"],
|
||||
install_requires=["aigpy>=2022.7.8.1",
|
||||
"requests>=2.22.0",
|
||||
"pycryptodome",
|
||||
"pydub",
|
||||
"prettytable",
|
||||
"lxml"],
|
||||
entry_points={'console_scripts': ['tidal-dl = tidal_dl:main', ]}
|
||||
)
|
||||
|
||||
@@ -1,295 +1,162 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- encoding: utf-8 -*-
|
||||
'''
|
||||
@File : __init__.py
|
||||
@Time : 2020/11/08
|
||||
@Author : Yaronzz
|
||||
@Version : 2.1
|
||||
@Contact : yaronhuang@foxmail.com
|
||||
@Desc :
|
||||
'''
|
||||
import getopt
|
||||
import logging
|
||||
import ssl
|
||||
import sys
|
||||
import time
|
||||
|
||||
from aigpy.cmdHelper import green, yellow
|
||||
from aigpy.pathHelper import mkdirs
|
||||
from aigpy.pipHelper import getLastVersion
|
||||
from aigpy.stringHelper import isNull
|
||||
from aigpy.systemHelper import cmpVersion
|
||||
|
||||
from tidal_dl.download import start
|
||||
from tidal_dl.enums import AudioQuality, VideoQuality, Type
|
||||
from tidal_dl.lang.language import setLang, initLang, getLangChoicePrint
|
||||
from tidal_dl.printf import Printf, VERSION
|
||||
from tidal_dl.settings import Settings, TokenSettings, getLogPath
|
||||
from tidal_dl.tidal import TidalAPI
|
||||
from tidal_dl.util import API
|
||||
|
||||
ssl._create_default_https_context = ssl._create_unverified_context
|
||||
|
||||
TOKEN = TokenSettings.read()
|
||||
CONF = Settings.read()
|
||||
LANG = initLang(CONF.language)
|
||||
|
||||
logging.basicConfig(filename=getLogPath(),
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(levelname)s: %(message)s')
|
||||
|
||||
|
||||
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 login():
|
||||
print(LANG.AUTH_START_LOGIN)
|
||||
msg, check = API.getDeviceCode()
|
||||
if not check:
|
||||
Printf.err(msg)
|
||||
return
|
||||
|
||||
print(LANG.AUTH_LOGIN_CODE.format(green(API.key.userCode)))
|
||||
print(LANG.AUTH_NEXT_STEP.format(green(API.key.verificationUrl), yellow(displayTime(API.key.authCheckTimeout))))
|
||||
print(LANG.AUTH_WAITING)
|
||||
start = time.time()
|
||||
elapsed = 0
|
||||
while elapsed < API.key.authCheckTimeout:
|
||||
elapsed = time.time() - start
|
||||
# print("Check auth status...")
|
||||
msg, check = API.checkAuthStatus()
|
||||
if not check:
|
||||
if msg == "pending":
|
||||
time.sleep(API.key.authCheckInterval + 1)
|
||||
continue
|
||||
Printf.err(msg)
|
||||
break
|
||||
if check:
|
||||
Printf.success(LANG.MSG_VALID_ACCESSTOKEN.format(displayTime(int(API.key.expiresIn))))
|
||||
TOKEN.userid = API.key.userId
|
||||
TOKEN.countryCode = API.key.countryCode
|
||||
TOKEN.accessToken = API.key.accessToken
|
||||
TOKEN.refreshToken = API.key.refreshToken
|
||||
TOKEN.expiresAfter = time.time() + int(API.key.expiresIn)
|
||||
TokenSettings.save(TOKEN)
|
||||
break
|
||||
if elapsed >= API.key.authCheckTimeout:
|
||||
Printf.err(LANG.AUTH_TIMEOUT)
|
||||
return
|
||||
|
||||
|
||||
def setAccessToken():
|
||||
while True:
|
||||
print("-------------AccessToken---------------")
|
||||
token = Printf.enter("accessToken('0' go back):")
|
||||
if token == '0':
|
||||
return
|
||||
msg, check = API.loginByAccessToken(token, TOKEN.userid)
|
||||
if not check:
|
||||
Printf.err(msg)
|
||||
continue
|
||||
break
|
||||
|
||||
print("-------------RefreshToken---------------")
|
||||
refreshToken = Printf.enter("refreshToken('0' to skip):")
|
||||
if refreshToken == '0':
|
||||
refreshToken = TOKEN.refreshToken
|
||||
|
||||
TOKEN.assesstoken = token
|
||||
TOKEN.refreshToken = refreshToken
|
||||
TOKEN.expiresAfter = 0
|
||||
TokenSettings.save(TOKEN)
|
||||
|
||||
|
||||
def checkLogin():
|
||||
if not isNull(TOKEN.accessToken):
|
||||
# print('Checking Access Token...') #add to translations
|
||||
msg, check = API.verifyAccessToken(TOKEN.accessToken)
|
||||
if check:
|
||||
Printf.info(LANG.MSG_VALID_ACCESSTOKEN.format(displayTime(int(TOKEN.expiresAfter - time.time()))))
|
||||
return
|
||||
else:
|
||||
Printf.info(LANG.MSG_INVAILD_ACCESSTOKEN)
|
||||
msg, check = API.refreshAccessToken(TOKEN.refreshToken)
|
||||
if check:
|
||||
Printf.success(LANG.MSG_VALID_ACCESSTOKEN.format(displayTime(int(API.key.expiresIn))))
|
||||
TOKEN.userid = API.key.userId
|
||||
TOKEN.countryCode = API.key.countryCode
|
||||
TOKEN.accessToken = API.key.accessToken
|
||||
TOKEN.expiresAfter = time.time() + int(API.key.expiresIn)
|
||||
TokenSettings.save(TOKEN)
|
||||
return
|
||||
else:
|
||||
Printf.err(msg)
|
||||
tmp = TokenSettings() # clears saved tokens
|
||||
TokenSettings.save(tmp)
|
||||
login()
|
||||
return
|
||||
|
||||
|
||||
def checkLogout():
|
||||
global LANG
|
||||
login()
|
||||
return
|
||||
|
||||
|
||||
def changeSettings():
|
||||
global LANG
|
||||
Printf.settings(CONF)
|
||||
choice = Printf.enter(LANG.CHANGE_START_SETTINGS)
|
||||
if choice == '0':
|
||||
return
|
||||
|
||||
CONF.downloadPath = Printf.enterPath(LANG.CHANGE_DOWNLOAD_PATH, LANG.MSG_PATH_ERR, '0', CONF.downloadPath)
|
||||
CONF.audioQuality = AudioQuality(int(Printf.enterLimit(
|
||||
LANG.CHANGE_AUDIO_QUALITY, LANG.MSG_INPUT_ERR, ['0', '1', '2', '3'])))
|
||||
CONF.videoQuality = VideoQuality(int(Printf.enterLimit(
|
||||
LANG.CHANGE_VIDEO_QUALITY, LANG.MSG_INPUT_ERR, ['1080', '720', '480', '360'])))
|
||||
CONF.onlyM4a = Printf.enter(LANG.CHANGE_ONLYM4A) == '1'
|
||||
CONF.checkExist = Printf.enter(LANG.CHANGE_CHECK_EXIST) == '1'
|
||||
CONF.includeEP = Printf.enter(LANG.CHANGE_INCLUDE_EP) == '1'
|
||||
CONF.saveCovers = Printf.enter(LANG.CHANGE_SAVE_COVERS) == '1'
|
||||
CONF.showProgress = Printf.enter(LANG.CHANGE_SHOW_PROGRESS) == '1'
|
||||
CONF.saveAlbumInfo = Printf.enter(LANG.CHANGE_SAVE_ALBUM_INFO) == '1'
|
||||
CONF.showTrackInfo = Printf.enter(LANG.CHANGE_SHOW_TRACKINFO) == '1'
|
||||
CONF.usePlaylistFolder = Printf.enter(LANG.SETTING_USE_PLAYLIST_FOLDER + "('0'-No,'1'-Yes):") == '1'
|
||||
CONF.language = Printf.enter(LANG.CHANGE_LANGUAGE + "(" + getLangChoicePrint() + "):")
|
||||
CONF.albumFolderFormat = Printf.enterFormat(
|
||||
LANG.CHANGE_ALBUM_FOLDER_FORMAT, CONF.albumFolderFormat, Settings.getDefaultAlbumFolderFormat())
|
||||
CONF.trackFileFormat = Printf.enterFormat(LANG.CHANGE_TRACK_FILE_FORMAT,
|
||||
CONF.trackFileFormat, Settings.getDefaultTrackFileFormat())
|
||||
CONF.addLyrics = Printf.enter(LANG.CHANGE_ADD_LYRICS) == '1'
|
||||
CONF.lyricsServerProxy = Printf.enterFormat(
|
||||
LANG.CHANGE_LYRICS_SERVER_PROXY, CONF.lyricsServerProxy, CONF.lyricsServerProxy)
|
||||
CONF.lyricFile = Printf.enter(LANG.CHANGE_ADD_LRC_FILE) == '1'
|
||||
|
||||
LANG = setLang(CONF.language)
|
||||
Settings.save(CONF)
|
||||
|
||||
|
||||
def mainCommand():
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], "hvl:o:q:r:", ["help", "version",
|
||||
"link=", "output=", "quality", "resolution"])
|
||||
except getopt.GetoptError as errmsg:
|
||||
Printf.err(vars(errmsg)['msg'] + ". Use 'tidal-dl -h' for useage.")
|
||||
return
|
||||
|
||||
link = None
|
||||
for opt, val in opts:
|
||||
if opt in ('-h', '--help'):
|
||||
Printf.usage()
|
||||
continue
|
||||
if opt in ('-v', '--version'):
|
||||
Printf.logo()
|
||||
continue
|
||||
if opt in ('-l', '--link'):
|
||||
checkLogin()
|
||||
link = val
|
||||
continue
|
||||
if opt in ('-o', '--output'):
|
||||
CONF.downloadPath = val
|
||||
Settings.save(CONF)
|
||||
continue
|
||||
if opt in ('-q', '--quality'):
|
||||
CONF.audioQuality = Settings.getAudioQuality(val)
|
||||
Settings.save(CONF)
|
||||
continue
|
||||
if opt in ('-r', '--resolution'):
|
||||
CONF.videoQuality = Settings.getVideoQuality(val)
|
||||
Settings.save(CONF)
|
||||
continue
|
||||
|
||||
if not mkdirs(CONF.downloadPath):
|
||||
Printf.err(LANG.MSG_PATH_ERR + CONF.downloadPath)
|
||||
return
|
||||
|
||||
if link is not None:
|
||||
Printf.info(LANG.SETTING_DOWNLOAD_PATH + ':' + CONF.downloadPath)
|
||||
start(TOKEN, CONF, link)
|
||||
|
||||
|
||||
def debug():
|
||||
checkLogin()
|
||||
API.key.accessToken = TOKEN.accessToken
|
||||
API.key.userId = TOKEN.userid
|
||||
API.key.countryCode = TOKEN.countryCode
|
||||
# https://api.tidal.com/v1/mixes/{01453963b7dbd41c8b82ccb678d127/items?countryCode={country}
|
||||
API.getMix("01453963b7dbd41c8b82ccb678d127")
|
||||
# msg, result = API.search('Mojito', Type.Null, 0, 10)
|
||||
msg, lyric = API.getLyrics('144909909')
|
||||
pass
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) > 1:
|
||||
mainCommand()
|
||||
return
|
||||
|
||||
Printf.logo()
|
||||
Printf.settings(CONF)
|
||||
|
||||
checkLogin()
|
||||
|
||||
onlineVer = getLastVersion('tidal-dl')
|
||||
if not isNull(onlineVer):
|
||||
icmp = cmpVersion(onlineVer, VERSION)
|
||||
if icmp > 0:
|
||||
Printf.info(LANG.PRINT_LATEST_VERSION + ' ' + onlineVer)
|
||||
|
||||
while True:
|
||||
Printf.choices()
|
||||
choice = Printf.enter(LANG.PRINT_ENTER_CHOICE)
|
||||
if choice == "0":
|
||||
return
|
||||
elif choice == "1":
|
||||
checkLogin()
|
||||
elif choice == "2":
|
||||
changeSettings()
|
||||
elif choice == "3":
|
||||
checkLogout()
|
||||
elif choice == "4":
|
||||
setAccessToken()
|
||||
elif choice == "10": # test track
|
||||
start(TOKEN, CONF, '70973230')
|
||||
elif choice == "11": # test video
|
||||
start(TOKEN, CONF, '188932980')
|
||||
elif choice == "12": # test album
|
||||
start(TOKEN, CONF, '58138532')
|
||||
elif choice == "13": # test playlist
|
||||
start(TOKEN, CONF, '98235845-13e8-43b4-94e2-d9f8e603cee7')
|
||||
elif choice == "14": # test playlist
|
||||
start(TOKEN, CONF, '01453963b7dbd41c8b82ccb678d127')
|
||||
else:
|
||||
start(TOKEN, CONF, choice)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# debug()
|
||||
main()
|
||||
# test example
|
||||
# track 70973230 77798028 212657
|
||||
# video 155608351 188932980
|
||||
# album 58138532 77803199 21993753 79151897 56288918
|
||||
# playlist 98235845-13e8-43b4-94e2-d9f8e603cee7
|
||||
#!/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 getopt
|
||||
import aigpy
|
||||
|
||||
from events import *
|
||||
from settings import *
|
||||
from gui import startGui
|
||||
from printf import Printf
|
||||
|
||||
|
||||
def mainCommand():
|
||||
try:
|
||||
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
|
||||
|
||||
link = None
|
||||
showGui = False
|
||||
|
||||
for opt, val in opts:
|
||||
if opt in ('-h', '--help'):
|
||||
Printf.usage()
|
||||
return
|
||||
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:
|
||||
start(choice)
|
||||
|
||||
|
||||
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
|
||||
# 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
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# test()
|
||||
main()
|
||||
|
||||
@@ -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
|
||||
@@ -6,550 +6,217 @@
|
||||
@Author : Yaronzz
|
||||
@Version : 1.0
|
||||
@Contact : yaronhuang@foxmail.com
|
||||
@Desc :
|
||||
@Desc :
|
||||
'''
|
||||
import logging
|
||||
import os
|
||||
import datetime
|
||||
|
||||
import aigpy
|
||||
import lyricsgenius
|
||||
from tidal_dl.decryption import decrypt_file
|
||||
from tidal_dl.decryption import decrypt_security_token
|
||||
from tidal_dl.enums import Type, AudioQuality
|
||||
from tidal_dl.model import Track, Video, Lyrics, Mix
|
||||
from tidal_dl.printf import Printf
|
||||
from tidal_dl.settings import Settings
|
||||
from tidal_dl.tidal import TidalAPI
|
||||
from tidal_dl.util import getVideoPath, getTrackPath, getAlbumPath, getArtistsName, convertToM4a, setMetaData, \
|
||||
isNeedDownload, API, getLyricsFromGemius
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
|
||||
from decryption import *
|
||||
from printf import *
|
||||
from tidal import *
|
||||
|
||||
|
||||
def __loadAPI__(user):
|
||||
API.key.accessToken = user.accessToken
|
||||
API.key.userId = user.userid
|
||||
API.key.countryCode = user.countryCode
|
||||
# API.key.sessionId = user.sessionid1
|
||||
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 __loadVideoAPI__(user):
|
||||
API.key.accessToken = user.accessToken
|
||||
API.key.userId = user.userid
|
||||
API.key.countryCode = user.countryCode
|
||||
# API.key.sessionId = user.sessionid2 if not aigpy.string.isNull(user.sessionid2) else user.sessionid1
|
||||
|
||||
|
||||
# def __getIndexStr__(index):
|
||||
# pre = "0"
|
||||
# if index < 10:
|
||||
# return pre + str(index)
|
||||
# if index < 99:
|
||||
# return str(index)
|
||||
# return str(index)
|
||||
|
||||
|
||||
# def __getExtension__(url):
|
||||
# if '.flac' in url:
|
||||
# return '.flac'
|
||||
# if '.mp4' in url:
|
||||
# return '.mp4'
|
||||
# return '.m4a'
|
||||
|
||||
|
||||
# def __getArtists__(array):
|
||||
# ret = []
|
||||
# for item in array:
|
||||
# ret.append(item.name)
|
||||
# return ret
|
||||
|
||||
|
||||
# def __getArtistsString__(artists):
|
||||
# return ", ".join(map(lambda artist: artist.name, artists))
|
||||
|
||||
|
||||
# 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
|
||||
|
||||
|
||||
# GEMIUS = lyricsgenius.Genius('vNKbAWAE3rVY_48nRaiOrDcWNLvsxS-Z8qyG5XfEzTOtZvkTfg6P3pxOVlA2BjaW')
|
||||
#
|
||||
#
|
||||
# def __getLyrics__(trackName, artistName, proxy):
|
||||
# try:
|
||||
# if not aigpy.string.isNull(proxy):
|
||||
# GEMIUS._session.proxies = {
|
||||
# 'http': f'http://{proxy}',
|
||||
# 'https': f'http://{proxy}',
|
||||
# }
|
||||
#
|
||||
# song = GEMIUS.search_song(trackName, artistName)
|
||||
# return song.lyrics
|
||||
# except:
|
||||
# return ""
|
||||
|
||||
#
|
||||
# def __setMetaData__(track, 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 = map(lambda artist: artist.name, track.artists) # __getArtists__(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 = map(lambda artist: artist.name, album.artists) #__getArtists__(album.artists)
|
||||
# obj.date = album.releaseDate
|
||||
# obj.totaldisc = album.numberOfVolumes
|
||||
# obj.lyrics = lyrics
|
||||
# if obj.totaldisc <= 1:
|
||||
# obj.totaltrack = album.numberOfTracks
|
||||
# coverpath = API.getCoverUrl(album.cover, "1280", "1280")
|
||||
# obj.save(coverpath)
|
||||
# return
|
||||
|
||||
|
||||
# def __convertToM4a__(filepath, codec):
|
||||
# if 'ac4' in codec or 'mha1' in codec:
|
||||
# return filepath
|
||||
# if '.mp4' not in filepath:
|
||||
# return filepath
|
||||
# newpath = filepath.replace('.mp4', '.m4a')
|
||||
# aigpy.path.remove(newpath)
|
||||
# os.rename(filepath, newpath)
|
||||
# return newpath
|
||||
|
||||
|
||||
# def __stripPathParts__(stripped_path, separator):
|
||||
# result = ""
|
||||
# stripped_path = stripped_path.split(separator)
|
||||
# for stripped_path_part in stripped_path:
|
||||
# result += stripped_path_part.strip()
|
||||
# if not stripped_path.index(stripped_path_part) == len(stripped_path) - 1:
|
||||
# result += separator
|
||||
# return result.strip()
|
||||
#
|
||||
#
|
||||
# def __stripPath__(path):
|
||||
# result = __stripPathParts__(path, "/")
|
||||
# result = __stripPathParts__(result, "\\")
|
||||
# return result.strip()
|
||||
|
||||
# "{ArtistName}/{Flag} [{AlbumID}] [{AlbumYear}] {AlbumTitle}"
|
||||
# def getAlbumPath(conf: Settings, album):
|
||||
# base = conf.downloadPath + '/Album/'
|
||||
# artist = aigpy.path.replaceLimitChar(__getArtistsString__(album.artists), '-')
|
||||
# # album folder pre: [ME][ID]
|
||||
# flag = API.getFlag(album, Type.Album, True, "")
|
||||
# if conf.audioQuality != AudioQuality.Master:
|
||||
# flag = flag.replace("M", "")
|
||||
# if not conf.addExplicitTag:
|
||||
# flag = flag.replace("E", "")
|
||||
# if not aigpy.string.isNull(flag):
|
||||
# flag = "[" + flag + "] "
|
||||
#
|
||||
# sid = str(album.id)
|
||||
# # album and addyear
|
||||
# albumname = aigpy.path.replaceLimitChar(album.title, '-')
|
||||
# year = ""
|
||||
# if album.releaseDate is not None:
|
||||
# year = aigpy.string.getSubOnlyEnd(album.releaseDate, '-')
|
||||
# # retpath
|
||||
# retpath = conf.albumFolderFormat
|
||||
# if retpath is None or len(retpath) <= 0:
|
||||
# retpath = Settings.getDefaultAlbumFolderFormat()
|
||||
# retpath = retpath.replace(R"{ArtistName}", artist.strip())
|
||||
# retpath = retpath.replace(R"{Flag}", flag)
|
||||
# retpath = retpath.replace(R"{AlbumID}", sid)
|
||||
# retpath = retpath.replace(R"{AlbumYear}", year)
|
||||
# retpath = retpath.replace(R"{AlbumTitle}", albumname.strip())
|
||||
# retpath = __stripPath__(retpath.strip())
|
||||
# return base + retpath
|
||||
#
|
||||
#
|
||||
# def __getAlbumPath2__(conf, album):
|
||||
# # outputdir/Album/artist/
|
||||
# artist = aigpy.path.replaceLimitChar(__getArtistsString__(album.artists), '-').strip()
|
||||
# base = conf.downloadPath + '/Album/' + artist + '/'
|
||||
#
|
||||
# # album folder pre: [ME][ID]
|
||||
# flag = API.getFlag(album, Type.Album, True, "")
|
||||
# if conf.audioQuality != AudioQuality.Master:
|
||||
# flag = flag.replace("M", "")
|
||||
# if not conf.addExplicitTag:
|
||||
# flag = flag.replace("E", "")
|
||||
# if not aigpy.string.isNull(flag):
|
||||
# flag = "[" + flag + "] "
|
||||
#
|
||||
# sid = "[" + str(album.id) + "] " if conf.addAlbumIDBeforeFolder else ""
|
||||
#
|
||||
# # album and addyear
|
||||
# albumname = aigpy.path.replaceLimitChar(album.title, '-').strip()
|
||||
# year = ""
|
||||
# if conf.addYear and album.releaseDate is not None:
|
||||
# year = "[" + aigpy.string.getSubOnlyEnd(album.releaseDate, '-') + "] "
|
||||
# return base + flag + sid + year + albumname + '/'
|
||||
#
|
||||
#
|
||||
# def getPlaylistPath(conf, playlist):
|
||||
# # outputdir/Playlist/
|
||||
# base = conf.downloadPath + '/Playlist/'
|
||||
# # name
|
||||
# name = aigpy.path.replaceLimitChar(playlist.title, '-')
|
||||
# return base + name + '/'
|
||||
#
|
||||
#
|
||||
# # "{TrackNumber} - {ArtistName} - {TrackTitle}{ExplicitFlag}"
|
||||
#
|
||||
#
|
||||
# def getTrackPath(conf: Settings, track, stream, album=None, playlist=None):
|
||||
# if album is not None:
|
||||
# base = getAlbumPath(conf, album) + '/'
|
||||
# if album.numberOfVolumes > 1:
|
||||
# base += 'CD' + str(track.volumeNumber) + '/'
|
||||
# if playlist is not None and conf.usePlaylistFolder:
|
||||
# base = getPlaylistPath(conf, playlist)
|
||||
# # number
|
||||
# number = __getIndexStr__(track.trackNumber)
|
||||
# if playlist is not None and conf.usePlaylistFolder:
|
||||
# number = __getIndexStr__(track.trackNumberOnPlaylist)
|
||||
# # artist
|
||||
# artist = aigpy.path.replaceLimitChar(__getArtistsString__(track.artists), '-')
|
||||
# # title
|
||||
# title = track.title
|
||||
# if not aigpy.string.isNull(track.version):
|
||||
# title += ' (' + track.version + ')'
|
||||
# title = aigpy.path.replaceLimitChar(title, '-')
|
||||
# # get explicit
|
||||
# explicit = "(Explicit)" if conf.addExplicitTag and track.explicit else ''
|
||||
# # album and addyear
|
||||
# albumname = aigpy.path.replaceLimitChar(album.title, '-')
|
||||
# year = ""
|
||||
# if album.releaseDate is not None:
|
||||
# year = aigpy.string.getSubOnlyEnd(album.releaseDate, '-')
|
||||
# # extension
|
||||
# extension = __getExtension__(stream.url)
|
||||
# retpath = conf.trackFileFormat
|
||||
# if retpath is None or len(retpath) <= 0:
|
||||
# retpath = Settings.getDefaultTrackFileFormat()
|
||||
# retpath = retpath.replace(R"{TrackNumber}", number)
|
||||
# retpath = retpath.replace(R"{ArtistName}", artist.strip())
|
||||
# retpath = retpath.replace(R"{TrackTitle}", title)
|
||||
# retpath = retpath.replace(R"{ExplicitFlag}", explicit)
|
||||
# retpath = retpath.replace(R"{AlbumYear}", year)
|
||||
# retpath = retpath.replace(R"{AlbumTitle}", albumname.strip())
|
||||
# retpath = retpath.strip()
|
||||
# return base + retpath + extension
|
||||
#
|
||||
#
|
||||
# def __getTrackPath2__(conf, track, stream, album=None, playlist=None):
|
||||
# if album is not None:
|
||||
# base = getAlbumPath(conf, album)
|
||||
# if album.numberOfVolumes > 1:
|
||||
# base += 'CD' + str(track.volumeNumber) + '/'
|
||||
# if playlist is not None and conf.usePlaylistFolder:
|
||||
# base = getPlaylistPath(conf, playlist)
|
||||
#
|
||||
# # hyphen
|
||||
# hyphen = ' - ' if conf.addHyphen else ' '
|
||||
# # get number
|
||||
# number = ''
|
||||
# if conf.useTrackNumber:
|
||||
# number = __getIndexStr__(track.trackNumber) + hyphen
|
||||
# if playlist is not None:
|
||||
# number = __getIndexStr__(track.trackNumberOnPlaylist) + hyphen
|
||||
# # get artist
|
||||
# artist = ''
|
||||
# if conf.artistBeforeTitle:
|
||||
# artist = aigpy.path.replaceLimitChar(__getArtistsString__(track.artists), '-') + hyphen
|
||||
# # get explicit
|
||||
# explicit = "(Explicit)" if conf.addExplicitTag and track.explicit else ''
|
||||
# # title
|
||||
# title = track.title
|
||||
# if not aigpy.string.isNull(track.version):
|
||||
# title += ' - ' + track.version
|
||||
# title = aigpy.path.replaceLimitChar(title, '-')
|
||||
# # extension
|
||||
# extension = __getExtension__(stream.url)
|
||||
# return base + number + artist.strip() + title + explicit + extension
|
||||
#
|
||||
#
|
||||
# def getVideoPath(conf, video, album=None, playlist=None):
|
||||
# if album is not None and album.title is not None:
|
||||
# base = getAlbumPath(conf, album)
|
||||
# elif playlist is not None and conf.usePlaylistFolder:
|
||||
# base = getPlaylistPath(conf, playlist)
|
||||
# else:
|
||||
# base = conf.downloadPath + '/Video/'
|
||||
#
|
||||
# # hyphen
|
||||
# hyphen = ' - ' if conf.addHyphen else ' '
|
||||
# # get number
|
||||
# number = ''
|
||||
# if conf.useTrackNumber:
|
||||
# number = __getIndexStr__(video.trackNumber) + hyphen
|
||||
# # get artist
|
||||
# artist = ''
|
||||
# if conf.artistBeforeTitle:
|
||||
# artist = aigpy.path.replaceLimitChar(__getArtistsString__(video.artists), '-') + hyphen
|
||||
# # get explicit
|
||||
# explicit = "(Explicit)" if conf.addExplicitTag and video.explicit else ''
|
||||
# # title
|
||||
# title = aigpy.path.replaceLimitChar(video.title, '-')
|
||||
# # extension
|
||||
# extension = ".mp4"
|
||||
# return base + number + artist.strip() + title + explicit + extension
|
||||
|
||||
|
||||
# def __isNeedDownload__(path, url):
|
||||
# curSize = aigpy.file.getSize(path)
|
||||
# if curSize <= 0:
|
||||
# return True
|
||||
# netSize = aigpy.net.getSize(url)
|
||||
# if curSize >= netSize:
|
||||
# return False
|
||||
# return True
|
||||
|
||||
|
||||
|
||||
def __downloadVideo__(conf, video: Video, album=None, playlist=None):
|
||||
if video.allowStreaming is False:
|
||||
Printf.err("Download failed! " + video.title + ' not allow streaming.')
|
||||
return
|
||||
|
||||
msg, stream = API.getVideoStreamUrl(video.id, conf.videoQuality)
|
||||
Printf.video(video, stream)
|
||||
if not aigpy.string.isNull(msg):
|
||||
Printf.err(video.title + "." + msg)
|
||||
return
|
||||
path = getVideoPath(conf, video, album, playlist)
|
||||
|
||||
logging.info("[DL Video] name=" + aigpy.path.getFileName(path) + "\nurl=" + stream.m3u8Url)
|
||||
check, msg = aigpy.m3u8.download(stream.m3u8Url, path)
|
||||
if check is True:
|
||||
Printf.success(aigpy.path.getFileName(path))
|
||||
def __encrypted__(stream, srcPath, descPath):
|
||||
if aigpy.string.isNull(stream.encryptionKey):
|
||||
os.replace(srcPath, descPath)
|
||||
else:
|
||||
Printf.err("\nDownload failed!" + msg + '(' + aigpy.path.getFileName(path) + ')')
|
||||
key, nonce = decrypt_security_token(stream.encryptionKey)
|
||||
decrypt_file(srcPath, descPath, key, nonce)
|
||||
os.remove(srcPath)
|
||||
|
||||
|
||||
def __downloadTrack__(conf: Settings, track: Track, album=None, playlist=None):
|
||||
def __parseContributors__(roleType, Contributors):
|
||||
if Contributors is None:
|
||||
return None
|
||||
try:
|
||||
# if track.allowStreaming is False:
|
||||
# Printf.err("Download failed! " + track.title + ' not allow streaming.')
|
||||
# return
|
||||
|
||||
msg, stream = API.getStreamUrl(track.id, conf.audioQuality)
|
||||
if conf.showTrackInfo:
|
||||
Printf.track(track, stream)
|
||||
if not aigpy.string.isNull(msg) or stream is None:
|
||||
Printf.err(track.title + "." + msg)
|
||||
return
|
||||
path = getTrackPath(conf, track, stream, album, playlist)
|
||||
|
||||
# check exist
|
||||
if conf.checkExist and isNeedDownload(path, stream.url) == False:
|
||||
Printf.success(aigpy.path.getFileName(path) + " (skip:already exists!)")
|
||||
return
|
||||
logging.info("[DL Track] name=" + aigpy.path.getFileName(path) + "\nurl=" + stream.url)
|
||||
tool = aigpy.download.DownloadTool(path + '.part', [stream.url])
|
||||
check, err = tool.start(conf.showProgress)
|
||||
|
||||
if not check:
|
||||
Printf.err("Download failed! " + aigpy.path.getFileName(path) + ' (' + str(err) + ')')
|
||||
return
|
||||
# encrypted -> decrypt and remove encrypted file
|
||||
if aigpy.string.isNull(stream.encryptionKey):
|
||||
os.replace(path + '.part', path)
|
||||
else:
|
||||
key, nonce = decrypt_security_token(stream.encryptionKey)
|
||||
decrypt_file(path + '.part', path, key, nonce)
|
||||
os.remove(path + '.part')
|
||||
|
||||
path = convertToM4a(path, stream.codec)
|
||||
|
||||
# contributors
|
||||
msg, contributors = API.getTrackContributors(track.id)
|
||||
msg, tidalLyrics = API.getLyrics(track.id)
|
||||
|
||||
lyrics = '' if tidalLyrics is None else tidalLyrics.subtitles
|
||||
if conf.addLyrics and lyrics == '':
|
||||
lyrics = getLyricsFromGemius(track.title, getArtistsName(track.artists), conf.lyricsServerProxy)
|
||||
|
||||
if conf.lyricFile:
|
||||
if tidalLyrics is None:
|
||||
Printf.info(f'Failed to get lyrics from tidal!"{track.title}"')
|
||||
else:
|
||||
lrcPath = path.rsplit(".", 1)[0] + '.lrc'
|
||||
aigpy.fileHelper.write(lrcPath, tidalLyrics.subtitles, 'w')
|
||||
|
||||
setMetaData(track, album, path, contributors, lyrics)
|
||||
Printf.success(aigpy.path.getFileName(path))
|
||||
except Exception as e:
|
||||
Printf.err("Download failed! " + track.title + ' (' + str(e) + ')')
|
||||
ret = []
|
||||
for item in Contributors['items']:
|
||||
if item['role'] == roleType:
|
||||
ret.append(item['name'])
|
||||
return ret
|
||||
except:
|
||||
return None
|
||||
|
||||
|
||||
def __downloadCover__(conf, album):
|
||||
if album == 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(conf, album) + '/cover.jpg'
|
||||
url = API.getCoverUrl(album.cover, "1280", "1280")
|
||||
if url is not None:
|
||||
aigpy.net.downloadFile(url, path)
|
||||
path = getAlbumPath(album) + '/cover.jpg'
|
||||
url = TIDAL_API.getCoverUrl(album.cover, "1280", "1280")
|
||||
aigpy.net.downloadFile(url, path)
|
||||
|
||||
|
||||
def __saveAlbumInfo__(conf, album, tracks):
|
||||
if album == None:
|
||||
def downloadAlbumInfo(album, tracks):
|
||||
if album is None:
|
||||
return
|
||||
path = getAlbumPath(conf, album) + '/AlbumInfo.txt'
|
||||
|
||||
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" % (str(album.artist.name))
|
||||
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'
|
||||
|
||||
i = 0
|
||||
while True:
|
||||
if i >= int(album.numberOfVolumes):
|
||||
break
|
||||
i = i + 1
|
||||
infos += "===========CD %d=============\n" % i
|
||||
for index in range(0, album.numberOfVolumes):
|
||||
volumeNumber = index + 1
|
||||
infos += f"===========CD {volumeNumber}=============\n"
|
||||
for item in tracks:
|
||||
if item.volumeNumber != i:
|
||||
if item.volumeNumber != volumeNumber:
|
||||
continue
|
||||
infos += '{:<8}'.format("[%d]" % item.trackNumber)
|
||||
infos += "%s\n" % item.title
|
||||
aigpy.file.write(path, infos, "w+")
|
||||
|
||||
|
||||
def __album__(conf, obj):
|
||||
Printf.album(obj)
|
||||
msg, tracks, videos = API.getItems(obj.id, Type.Album)
|
||||
if not aigpy.string.isNull(msg):
|
||||
Printf.err(msg)
|
||||
return
|
||||
if conf.saveAlbumInfo:
|
||||
__saveAlbumInfo__(conf, obj, tracks)
|
||||
if conf.saveCovers:
|
||||
__downloadCover__(conf, obj)
|
||||
for item in tracks:
|
||||
__downloadTrack__(conf, item, obj)
|
||||
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__(conf, item, obj)
|
||||
|
||||
|
||||
def __track__(conf, obj):
|
||||
msg, album = API.getAlbum(obj.album.id)
|
||||
if conf.saveCovers:
|
||||
__downloadCover__(conf, album)
|
||||
__downloadTrack__(conf, obj, album)
|
||||
|
||||
|
||||
def __video__(conf, obj):
|
||||
# Printf.video(obj)
|
||||
__downloadVideo__(conf, obj, obj.album)
|
||||
|
||||
|
||||
def __artist__(conf, obj):
|
||||
msg, albums = API.getArtistAlbums(obj.id, conf.includeEP)
|
||||
Printf.artist(obj, len(albums))
|
||||
if not aigpy.string.isNull(msg):
|
||||
Printf.err(msg)
|
||||
return
|
||||
for item in albums:
|
||||
__album__(conf, item)
|
||||
|
||||
|
||||
def __playlist__(conf, obj):
|
||||
Printf.playlist(obj)
|
||||
msg, tracks, videos = API.getItems(obj.uuid, Type.Playlist)
|
||||
if not aigpy.string.isNull(msg):
|
||||
Printf.err(msg)
|
||||
return
|
||||
|
||||
for index, item in enumerate(tracks):
|
||||
mag, album = API.getAlbum(item.album.id)
|
||||
item.trackNumberOnPlaylist = index + 1
|
||||
__downloadTrack__(conf, item, album, obj)
|
||||
if conf.saveCovers and not conf.usePlaylistFolder:
|
||||
__downloadCover__(conf, album)
|
||||
for item in videos:
|
||||
__downloadVideo__(conf, item, None)
|
||||
|
||||
|
||||
def __mix__(conf, obj: Mix):
|
||||
Printf.mix(obj)
|
||||
for index, item in enumerate(obj.tracks):
|
||||
mag, album = API.getAlbum(item.album.id)
|
||||
item.trackNumberOnPlaylist = index + 1
|
||||
__downloadTrack__(conf, item, album)
|
||||
if conf.saveCovers and not conf.usePlaylistFolder:
|
||||
__downloadCover__(conf, album)
|
||||
for item in obj.videos:
|
||||
__downloadVideo__(conf, item, None)
|
||||
|
||||
|
||||
def file(user, conf, 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(user, conf, item)
|
||||
|
||||
|
||||
def start(user, conf, string):
|
||||
__loadAPI__(user)
|
||||
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):
|
||||
file(user, conf, item)
|
||||
return
|
||||
|
||||
msg, etype, obj = API.getByString(item)
|
||||
if etype == Type.Null or not aigpy.string.isNull(msg):
|
||||
Printf.err(msg + " [" + item + "]")
|
||||
return
|
||||
|
||||
if etype == Type.Album:
|
||||
__album__(conf, obj)
|
||||
if etype == Type.Track:
|
||||
__track__(conf, obj)
|
||||
if etype == Type.Video:
|
||||
__loadVideoAPI__(user)
|
||||
__video__(conf, obj)
|
||||
if etype == Type.Artist:
|
||||
__artist__(conf, obj)
|
||||
if etype == Type.Playlist:
|
||||
__playlist__(conf, obj)
|
||||
if etype == Type.Mix:
|
||||
__mix__(conf, obj)
|
||||
downloadVideo(item, album, playlist)
|
||||
|
||||
@@ -1,36 +1,37 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- encoding: utf-8 -*-
|
||||
'''
|
||||
@File : enums.py
|
||||
@Time : 2020/08/08
|
||||
@Author : Yaronzz
|
||||
@Version : 2.0
|
||||
@Contact : yaronhuang@foxmail.com
|
||||
@Desc :
|
||||
'''
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class AudioQuality(Enum):
|
||||
Normal = 0
|
||||
High = 1
|
||||
HiFi = 2
|
||||
Master = 3
|
||||
|
||||
|
||||
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
|
||||
#!/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
|
||||
|
||||
@@ -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()
|
||||
@@ -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()
|
||||
@@ -30,14 +30,20 @@ class LangArabic(object):
|
||||
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_TRACKIFNO = "Show Track Info"
|
||||
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"
|
||||
SETTINGS_ADD_LRC_FILE = "Save timed lyrics (.lrc file)"
|
||||
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 = "وظيفة"
|
||||
@@ -49,6 +55,7 @@ class LangArabic(object):
|
||||
CHOICE_SET_ACCESS_TOKEN = "اعداد AccessToken"
|
||||
CHOICE_DOWNLOAD_BY_URL = "التحميل عبر الرابط او رقم التتبع"
|
||||
CHOICE_LOGOUT = "Logout"
|
||||
CHOICE_APIKEY = "Select APIKey"
|
||||
|
||||
PRINT_ERR = "[خطأ]"
|
||||
PRINT_INFO = "[معلومة]"
|
||||
@@ -61,7 +68,7 @@ class LangArabic(object):
|
||||
|
||||
CHANGE_START_SETTINGS = "بدء الاعدادات('0'-Return,'1'-Yes):"
|
||||
CHANGE_DOWNLOAD_PATH = "مجلد التنزيل('0' not modify):"
|
||||
CHANGE_AUDIO_QUALITY = "دقة الصوت('0'-Normal,'1'-High,'2'-HiFi,'3'-Master):"
|
||||
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):"
|
||||
@@ -74,14 +81,20 @@ class LangArabic(object):
|
||||
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):"
|
||||
CHANGE_TRACK_FILE_FORMAT = "Track file format('0' not modify):"
|
||||
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_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..."
|
||||
@@ -91,7 +104,7 @@ class LangArabic(object):
|
||||
AUTH_TIMEOUT = "Operation timed out."
|
||||
|
||||
MSG_VALID_ACCESSTOKEN = "AccessToken good for {}."
|
||||
MSG_INVAILD_ACCESSTOKEN = "Expired AccessToken. Attempting to refresh it."
|
||||
MSG_INVALID_ACCESSTOKEN = "Expired AccessToken. Attempting to refresh it."
|
||||
MSG_PATH_ERR = "!مجلد التنزيل خاطئ"
|
||||
MSG_INPUT_ERR = "!ادخال خاطئ"
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ class LangChinese(object):
|
||||
VALUE = "值"
|
||||
SETTING_DOWNLOAD_PATH = "下载目录"
|
||||
SETTING_ONLY_M4A = "转换mp4为m4a"
|
||||
SETTING_ADD_EXPLICIT_TAG = "文件名添加脏话标签Explicit"
|
||||
SETTING_ADD_EXPLICIT_TAG = "文件名添加脏标Explicit"
|
||||
SETTING_ADD_HYPHEN = "文件名用'-'代替空格"
|
||||
SETTING_ADD_YEAR = "专辑文件夹添加年代标签"
|
||||
SETTING_USE_TRACK_NUM = "歌曲名称添加序号"
|
||||
@@ -30,25 +30,32 @@ class LangChinese(object):
|
||||
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_TRACKIFNO = "显示歌曲信息"
|
||||
SETTING_SHOW_TRACKINFO = "显示歌曲信息"
|
||||
SETTING_SAVE_ALBUMINFO = "保存AlbumInfo.txt"
|
||||
SETTING_DOWNLOAD_VIDEOS = "Download videos"
|
||||
SETTING_ADD_LYRICS = "添加歌词"
|
||||
SETTING_LYRICS_SERVER_PROXY = "歌词服务器代理"
|
||||
SETTING_PATH = "Settings path"
|
||||
SETTINGS_ADD_LRC_FILE = "Save timed lyrics (.lrc file)"
|
||||
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 = "Check AccessToken"
|
||||
CHOICE_LOGIN = "检查AccessToken"
|
||||
CHOICE_SETTINGS = "配置"
|
||||
CHOICE_SET_ACCESS_TOKEN = "设置AccessToken"
|
||||
CHOICE_DOWNLOAD_BY_URL = "通过链接或ID下载"
|
||||
CHOICE_LOGOUT = "注销"
|
||||
CHOICE_APIKEY = "选择APIKey"
|
||||
|
||||
PRINT_ERR = "[错误]"
|
||||
PRINT_INFO = "[提示]"
|
||||
@@ -61,7 +68,7 @@ class LangChinese(object):
|
||||
|
||||
CHANGE_START_SETTINGS = "开始设置('0'-返回,'1'-是):"
|
||||
CHANGE_DOWNLOAD_PATH = "下载路径('0' 不修改):"
|
||||
CHANGE_AUDIO_QUALITY = "音频质量('0'-Normal,'1'-High,'2'-HiFi,'3'-Master):"
|
||||
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'-是):"
|
||||
@@ -75,13 +82,19 @@ class LangChinese(object):
|
||||
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 = "Save timed lyrics .lrc file ('0'-否,'1'-是):"
|
||||
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 = "开始启动登录..."
|
||||
@@ -90,8 +103,8 @@ class LangChinese(object):
|
||||
AUTH_WAITING = "等待登录验证..."
|
||||
AUTH_TIMEOUT = "操作超时."
|
||||
|
||||
MSG_VALID_ACCESSTOKEN = "AccessToken保质期为 {}."
|
||||
MSG_INVAILD_ACCESSTOKEN = "AccessToken失效. 正在尝试更新它."
|
||||
MSG_VALID_ACCESSTOKEN = "AccessToken有效期为 {}."
|
||||
MSG_INVALID_ACCESSTOKEN = "AccessToken失效. 正在尝试更新它."
|
||||
MSG_PATH_ERR = "路径错误!"
|
||||
MSG_INPUT_ERR = "输入错误!"
|
||||
|
||||
@@ -106,7 +119,7 @@ class LangChinese(object):
|
||||
MODEL_VIDEO_NUMBER = '视频数量'
|
||||
MODEL_RELEASE_DATE = '发布时间'
|
||||
MODEL_VERSION = '版本'
|
||||
MODEL_EXPLICIT = '脏话标志'
|
||||
MODEL_EXPLICIT = '脏标'
|
||||
MODEL_ALBUM = '专辑'
|
||||
MODEL_ID = 'ID'
|
||||
MODEL_NAME = '名称'
|
||||
|
||||
@@ -30,14 +30,20 @@ class LangCroatian(object):
|
||||
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_TRACKIFNO = "Show Track Info"
|
||||
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"
|
||||
SETTINGS_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 = "ODABIR"
|
||||
FUNCTION = "FUNKCIJA"
|
||||
@@ -49,6 +55,7 @@ class LangCroatian(object):
|
||||
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]"
|
||||
@@ -61,7 +68,7 @@ class LangCroatian(object):
|
||||
|
||||
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):"
|
||||
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):"
|
||||
@@ -74,14 +81,20 @@ class LangCroatian(object):
|
||||
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):"
|
||||
CHANGE_TRACK_FILE_FORMAT = "Track file format('0' not modify):"
|
||||
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_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..."
|
||||
@@ -91,7 +104,7 @@ class LangCroatian(object):
|
||||
AUTH_TIMEOUT = "Operation timed out."
|
||||
|
||||
MSG_VALID_ACCESSTOKEN = "AccessToken good for {}."
|
||||
MSG_INVAILD_ACCESSTOKEN = "Expired AccessToken. Attempting to refresh it."
|
||||
MSG_INVALID_ACCESSTOKEN = "Expired AccessToken. Attempting to refresh it."
|
||||
MSG_PATH_ERR = "Pogreska putanje!"
|
||||
MSG_INPUT_ERR = "Pogreska unosa!"
|
||||
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
'''
|
||||
@File : czech.py
|
||||
@Time : 2020/08/20
|
||||
@Author : Tomikk
|
||||
@Version : 1.0
|
||||
@Contact : justtomikk@gmail.com
|
||||
@Time : 2022/11/13
|
||||
@Author : Tomikk & Sweder
|
||||
@Version : 1.2
|
||||
@Contact : justtomikk@gmail.com & djsweder@gmail.com
|
||||
@Desc :
|
||||
'''
|
||||
|
||||
@@ -15,42 +15,49 @@ class LangCzech(object):
|
||||
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 explicitní značku"
|
||||
SETTING_ADD_HYPHEN = "Používat pomlčky místo mezer"
|
||||
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 jestli soubor již existuje"
|
||||
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 single&ep"
|
||||
SETTING_INCLUDE_EP = "Zahrnout singly & EP"
|
||||
SETTING_SAVE_COVERS = "Uložit obal alba"
|
||||
SETTING_LANGUAGE = "Změna jazyka"
|
||||
SETTING_USE_PLAYLIST_FOLDER = "Use playlist folder"
|
||||
SETTING_MULITHREAD_DOWNLOAD = "Multi thread download"
|
||||
SETTING_ALBUM_FOLDER_FORMAT = "Album folder format"
|
||||
SETTING_TRACK_FILE_FORMAT = "Track file format"
|
||||
SETTING_SHOW_PROGRESS = "Show progress"
|
||||
SETTING_SHOW_TRACKIFNO = "Show Track Info"
|
||||
SETTING_SAVE_ALBUMINFO = "Save AlbumInfo.txt"
|
||||
SETTING_ADD_LYRICS = "Add lyrics"
|
||||
SETTING_LYRICS_SERVER_PROXY = "Lyrics server proxy"
|
||||
SETTINGS_ADD_LRC_FILE = "Save timed lyrics (.lrc file)"
|
||||
SETTING_PATH = "Settings path"
|
||||
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 = "Enter"
|
||||
CHOICE_ENTER = "Zvolit"
|
||||
CHOICE_ENTER_URLID = "Vložit 'Url/ID':"
|
||||
CHOICE_EXIT = "Ukončit"
|
||||
CHOICE_LOGIN = "Check AccessToken"
|
||||
CHOICE_LOGIN = "Zkontrolovat přístupový token"
|
||||
CHOICE_SETTINGS = "Nastavení"
|
||||
CHOICE_SET_ACCESS_TOKEN = "Nastavit přístupový token"
|
||||
CHOICE_DOWNLOAD_BY_URL = "Stáhnout buď url nebo id"
|
||||
CHOICE_LOGOUT = "Logout"
|
||||
CHOICE_DOWNLOAD_BY_URL = "Stáhnout buď dle URL nebo ID"
|
||||
CHOICE_LOGOUT = "Odhlásit"
|
||||
CHOICE_APIKEY = "Vybrat APIKey"
|
||||
|
||||
PRINT_ERR = "[Error]"
|
||||
PRINT_ERR = "[Chyba]"
|
||||
PRINT_INFO = "[Info]"
|
||||
PRINT_SUCCESS = "[Staženo]"
|
||||
|
||||
@@ -59,54 +66,60 @@ class LangCzech(object):
|
||||
# PRINT_USERNAME = "přihlašovací jméno:"
|
||||
# PRINT_PASSWORD = "heslo"
|
||||
|
||||
CHANGE_START_SETTINGS = "Start settings('0'-Zpět,'1'-Ano):"
|
||||
CHANGE_DOWNLOAD_PATH = "Cesta stažení('0' not modify):"
|
||||
CHANGE_AUDIO_QUALITY = "Kvalita hudby('0'-Normal,'1'-High,'2'-HiFi,'3'-Master):"
|
||||
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 explicitní značku 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 existujicí soubor před stažením('0'-Ne,'1'-Ano):"
|
||||
CHANGE_ARTIST_BEFORE_TITLE = "Přidat jméno interpreta před názvem skladby('0'-Ne,'1'-Ano):"
|
||||
CHANGE_INCLUDE_EP = "Při stahování alba interpreta zahrnout singly a EP('0'-Ne,'1'-Ano):"
|
||||
CHANGE_ALBUMID_BEFORE_FOLDER = "Přidat ID před složku do alba('0'-Ne,'1'-Ano):"
|
||||
CHANGE_SAVE_COVERS = "Uložit obaly alb('0'-Ne,'1'-Ano):"
|
||||
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 = "Album folder format('0' not modify):"
|
||||
CHANGE_TRACK_FILE_FORMAT = "Track file format('0' not modify):"
|
||||
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_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_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 = "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."
|
||||
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 = "AccessToken good for {}."
|
||||
MSG_INVAILD_ACCESSTOKEN = "Expired AccessToken. Attempting to refresh it."
|
||||
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 vstupu!"
|
||||
MSG_INPUT_ERR = "Chyba zadání!"
|
||||
|
||||
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_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 = 'Explicit'
|
||||
MODEL_EXPLICIT = 'Explicitní'
|
||||
MODEL_ALBUM = 'Album'
|
||||
MODEL_ID = 'ID'
|
||||
MODEL_NAME = 'Jméno'
|
||||
|
||||
@@ -1,113 +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_TRACK_FILE_FORMAT = "Musiknummerets filformat"
|
||||
SETTING_SHOW_PROGRESS = "Vis fremskridt"
|
||||
SETTING_SHOW_TRACKIFNO = "Show Track Info"
|
||||
SETTING_SAVE_ALBUMINFO = "Save AlbumInfo.txt"
|
||||
SETTING_ADD_LYRICS = "Add lyrics"
|
||||
SETTING_LYRICS_SERVER_PROXY = "Lyrics server proxy"
|
||||
SETTING_PATH = "Settings path"
|
||||
SETTINGS_ADD_LRC_FILE = "Save timed lyrics (.lrc file)"
|
||||
|
||||
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"
|
||||
|
||||
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):"
|
||||
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_TRACK_FILE_FORMAT = "Musiknummerets filformat('0' Ændrer ikke, 'default' for at indstille som standard):"
|
||||
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_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):"
|
||||
|
||||
# {} 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_INVAILD_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'
|
||||
#!/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'
|
||||
|
||||
@@ -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'
|
||||
@@ -2,9 +2,9 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
'''
|
||||
@File : english.py
|
||||
@Time : 2021/11/11
|
||||
@Time : 2021/11/24
|
||||
@Author : Yaronzz & jee019
|
||||
@Version : 1.1
|
||||
@Version : 1.2
|
||||
@Contact : yaronhuang@foxmail.com
|
||||
@Desc :
|
||||
'''
|
||||
@@ -30,14 +30,20 @@ class LangEnglish(object):
|
||||
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_TRACKIFNO = "Show Track Info"
|
||||
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"
|
||||
SETTINGS_ADD_LRC_FILE = "Save timed lyrics (.lrc file)"
|
||||
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"
|
||||
@@ -47,8 +53,9 @@ class LangEnglish(object):
|
||||
CHOICE_LOGIN = "Check AccessToken"
|
||||
CHOICE_SETTINGS = "Settings"
|
||||
CHOICE_SET_ACCESS_TOKEN = "Set AccessToken"
|
||||
CHOICE_DOWNLOAD_BY_URL = "Download by url or id"
|
||||
CHOICE_DOWNLOAD_BY_URL = "Download by url or ID"
|
||||
CHOICE_LOGOUT = "Logout"
|
||||
CHOICE_APIKEY = "Select APIKey"
|
||||
|
||||
PRINT_ERR = "[ERR]"
|
||||
PRINT_INFO = "[INFO]"
|
||||
@@ -60,8 +67,8 @@ class LangEnglish(object):
|
||||
# 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):"
|
||||
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):"
|
||||
@@ -74,14 +81,20 @@ class LangEnglish(object):
|
||||
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_TRACK_FILE_FORMAT = "Track file format('0' not modify,'default' to set default):"
|
||||
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_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..."
|
||||
@@ -91,7 +104,7 @@ class LangEnglish(object):
|
||||
AUTH_TIMEOUT = "Operation timed out."
|
||||
|
||||
MSG_VALID_ACCESSTOKEN = "AccessToken good for {}."
|
||||
MSG_INVAILD_ACCESSTOKEN = "Expired AccessToken. Attempting to refresh it."
|
||||
MSG_INVALID_ACCESSTOKEN = "Expired AccessToken. Attempting to refresh it."
|
||||
MSG_PATH_ERR = "Path is error!"
|
||||
MSG_INPUT_ERR = "Input error!"
|
||||
|
||||
@@ -110,4 +123,4 @@ class LangEnglish(object):
|
||||
MODEL_ALBUM = 'Album'
|
||||
MODEL_ID = 'ID'
|
||||
MODEL_NAME = 'Name'
|
||||
MODEL_TYPE = 'Type'
|
||||
MODEL_TYPE = 'Type'
|
||||
|
||||
@@ -30,14 +30,20 @@ class LangFilipino(object):
|
||||
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_TRACKIFNO = "Show Track Info"
|
||||
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"
|
||||
SETTINGS_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 = "PAGPIPILIAN"
|
||||
FUNCTION = "SILBI"
|
||||
@@ -49,6 +55,7 @@ class LangFilipino(object):
|
||||
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]"
|
||||
@@ -61,7 +68,7 @@ class LangFilipino(object):
|
||||
|
||||
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):"
|
||||
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):"
|
||||
@@ -74,14 +81,20 @@ class LangFilipino(object):
|
||||
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):"
|
||||
CHANGE_TRACK_FILE_FORMAT = "Track file format('0' not modify):"
|
||||
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_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..."
|
||||
@@ -91,7 +104,7 @@ class LangFilipino(object):
|
||||
AUTH_TIMEOUT = "Operation timed out."
|
||||
|
||||
MSG_VALID_ACCESSTOKEN = "AccessToken good for {}."
|
||||
MSG_INVAILD_ACCESSTOKEN = "Expired AccessToken. Attempting to refresh it."
|
||||
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!"
|
||||
|
||||
|
||||
@@ -1,113 +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_TRACK_FILE_FORMAT = "Format du fichier de tracklist"
|
||||
SETTING_SHOW_PROGRESS = "Afficher la Progression"
|
||||
SETTING_SHOW_TRACKIFNO = "Show Track Info"
|
||||
SETTING_SAVE_ALBUMINFO = "Save AlbumInfo.txt"
|
||||
SETTING_ADD_LYRICS = "Add lyrics"
|
||||
SETTING_LYRICS_SERVER_PROXY = "Lyrics server proxy"
|
||||
SETTING_PATH = "Settings path"
|
||||
SETTINGS_ADD_LRC_FILE = "Save timed lyrics (.lrc file)"
|
||||
|
||||
CHOICE = "CHOIX"
|
||||
FUNCTION = "FONCTION"
|
||||
CHOICE_ENTER = "Saisir"
|
||||
CHOICE_ENTER_URLID = "Saisir 'Url/ID':"
|
||||
CHOICE_EXIT = "Quitter"
|
||||
CHOICE_LOGIN = "Check AccessToken"
|
||||
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 = "Logout"
|
||||
|
||||
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):"
|
||||
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_TRACK_FILE_FORMAT = "Format du fichier de tracklist('0' ne pas modifier):"
|
||||
CHANGE_SHOW_PROGRESS = "Afficher la progression('0'-Non,'1'-Oui):"
|
||||
CHANGE_SHOW_TRACKINFO = "Show track info('0'-No,'1'-Yes):"
|
||||
CHANGE_SAVE_ALBUM_INFO = "Save AlbumInfo.txt('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):"
|
||||
|
||||
# {} 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_INVAILD_ACCESSTOKEN = "Expired AccessToken. Attempting to refresh it."
|
||||
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'
|
||||
#!/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'
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
'''
|
||||
@File : german.py
|
||||
@Time : 2021/01/04
|
||||
@Authors : Sematre, MineClashTV
|
||||
@Version : 1.0
|
||||
@Time : 2022/11/8
|
||||
@Authors : Sematre, MineClashTV, Click1701
|
||||
@Version : 1.1
|
||||
@Contact :
|
||||
@Desc :
|
||||
'''
|
||||
@@ -24,20 +24,26 @@ class LangGerman(object):
|
||||
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 = "Einschließlich single&ep"
|
||||
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_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_TRACKIFNO = "Show Track Info"
|
||||
SETTING_SAVE_ALBUMINFO = "Save AlbumInfo.txt"
|
||||
SETTING_ADD_LYRICS = "Add lyrics"
|
||||
SETTING_LYRICS_SERVER_PROXY = "Lyrics server proxy"
|
||||
SETTING_PATH = "Settings path"
|
||||
SETTINGS_ADD_LRC_FILE = "Save timed lyrics (.lrc file)"
|
||||
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"
|
||||
@@ -47,8 +53,9 @@ class LangGerman(object):
|
||||
CHOICE_LOGIN = "AccessToken überprüfen"
|
||||
CHOICE_SETTINGS = "Einstellungen"
|
||||
CHOICE_SET_ACCESS_TOKEN = "AccessToken setzen"
|
||||
CHOICE_DOWNLOAD_BY_URL = "Herunterladen per URL oder ID"
|
||||
CHOICE_LOGOUT = "Logout"
|
||||
CHOICE_DOWNLOAD_BY_URL = "Download per URL oder ID"
|
||||
CHOICE_LOGOUT = "Ausloggen"
|
||||
CHOICE_APIKEY = "APIKey Auswahl"
|
||||
|
||||
PRINT_ERR = "[FEHLER]"
|
||||
PRINT_INFO = "[INFO]"
|
||||
@@ -59,39 +66,45 @@ class LangGerman(object):
|
||||
# PRINT_USERNAME = "Benutzername:"
|
||||
# PRINT_PASSWORD = "Passwort:"
|
||||
|
||||
CHANGE_START_SETTINGS = "Einstellungen starten ('0'-Zurück,'1'-Ja):"
|
||||
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):"
|
||||
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 = "Verwende Bindestriche statt Leerzeichen im Dateinamen ('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_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_TRACK_FILE_FORMAT = "Track-Dateiformat('0' überspringen):"
|
||||
CHANGE_SHOW_PROGRESS = "Fortschritt anzeigen('0'-Nein,'1'-Ja):"
|
||||
CHANGE_SHOW_TRACKINFO = "Show track info('0'-No,'1'-Yes):"
|
||||
CHANGE_SAVE_ALBUM_INFO = "Save AlbumInfo.txt('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_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 = "Auf Autorisierung warten..."
|
||||
AUTH_WAITING = "Warte auf Autorisierung..."
|
||||
AUTH_TIMEOUT = "Zeitüberschreitung der Operation."
|
||||
|
||||
MSG_VALID_ACCESSTOKEN = "AccessToken gültig für {}."
|
||||
MSG_INVAILD_ACCESSTOKEN = "AccessToken abgelaufen. Versuche zu erneuern."
|
||||
MSG_INVALID_ACCESSTOKEN = "AccessToken abgelaufen. Er muss erneuert werden."
|
||||
MSG_PATH_ERR = "Ungültiger Pfad!"
|
||||
MSG_INPUT_ERR = "Eingabefehler!"
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
'''
|
||||
@File : hungarian.py
|
||||
@Time : 2021/06/20
|
||||
@Time : 2022/08/01
|
||||
@Author : Shanahan
|
||||
@Version : 1.0
|
||||
@Version : 1.2
|
||||
@Contact :
|
||||
@Desc :
|
||||
'''
|
||||
@@ -25,19 +25,25 @@ class LangHungarian(object):
|
||||
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ó mentése"
|
||||
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_TRACKIFNO = "Show Track Info"
|
||||
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_PATH = "Beállítások elérési útvonala"
|
||||
SETTINGS_ADD_LRC_FILE = "Save timed lyrics (.lrc file)"
|
||||
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Ó"
|
||||
@@ -49,6 +55,7 @@ class LangHungarian(object):
|
||||
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Ó]"
|
||||
@@ -57,11 +64,11 @@ class LangHungarian(object):
|
||||
PRINT_ENTER_CHOICE = "Válasszon:"
|
||||
PRINT_LATEST_VERSION = "Legújabb verzió:"
|
||||
# PRINT_USERNAME = "felhasználónév:"
|
||||
# PRINT_PASSWORD = "jelszó
|
||||
# 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):"
|
||||
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):"
|
||||
@@ -70,18 +77,24 @@ class LangHungarian(object):
|
||||
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_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_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_SHOW_PROGRESS = "Haladás megjelenítése('0'-nem, '1'-igen):"
|
||||
CHANGE_SHOW_TRACKINFO = "Show track info('0'-No,'1'-Yes):"
|
||||
CHANGE_SAVE_ALBUM_INFO = "AlbumInfo.txt mentése('0'-nem, '1'-igen):"
|
||||
CHANGE_ADD_LYRICS = "Dalszöveg hozzáadása('0'-nem,'1'-igen):"
|
||||
CHANGE_LYRICS_SERVER_PROXY = "Dalszöveg kiszolgáló prox('0' nincs módosítás):"
|
||||
CHANGE_ADD_LRC_FILE = "Save timed lyrics .lrc file ('0'-No,'1'-Yes):"
|
||||
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..."
|
||||
@@ -91,15 +104,15 @@ class LangHungarian(object):
|
||||
AUTH_TIMEOUT = "A művelet leállt."
|
||||
|
||||
MSG_VALID_ACCESSTOKEN = "AccessToken érvényessége {}."
|
||||
MSG_INVAILD_ACCESSTOKEN = "Lejárt AccessToken. Megpróbálom frissíteni."
|
||||
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-TULAJDONSÁGOK"
|
||||
MODEL_TRACK_PROPERTY = "TRACK-TULAJDONSÁGOK"
|
||||
MODEL_VIDEO_PROPERTY = "VIDEO-TULAJDONSÁGOK"
|
||||
MODEL_ARTIST_PROPERTY = "ELŐADÓ-TULAJDONSÁGOK"
|
||||
MODEL_PLAYLIST_PROPERTY = "LEJÁTSZÁSI LISTA-TULAJDONSÁGOK"
|
||||
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'
|
||||
|
||||
@@ -30,14 +30,20 @@ class LangItalian(object):
|
||||
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_TRACKIFNO = "Show Track Info"
|
||||
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"
|
||||
SETTINGS_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 = "SCELTA"
|
||||
FUNCTION = "FUNZIONE"
|
||||
@@ -49,6 +55,7 @@ class LangItalian(object):
|
||||
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]"
|
||||
@@ -61,7 +68,7 @@ class LangItalian(object):
|
||||
|
||||
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):"
|
||||
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ì):"
|
||||
@@ -74,14 +81,20 @@ class LangItalian(object):
|
||||
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):"
|
||||
CHANGE_TRACK_FILE_FORMAT = "Track file format('0' not modify):"
|
||||
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_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..."
|
||||
@@ -91,7 +104,7 @@ class LangItalian(object):
|
||||
AUTH_TIMEOUT = "Operation timed out."
|
||||
|
||||
MSG_VALID_ACCESSTOKEN = "AccessToken good for {}."
|
||||
MSG_INVAILD_ACCESSTOKEN = "Expired AccessToken. Attempting to refresh it."
|
||||
MSG_INVALID_ACCESSTOKEN = "Expired AccessToken. Attempting to refresh it."
|
||||
MSG_PATH_ERR = "Percorso errato!"
|
||||
MSG_INPUT_ERR = "Inserimento errato!"
|
||||
|
||||
|
||||
@@ -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 = 'タイプ'
|
||||
@@ -2,9 +2,9 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
'''
|
||||
@File : korean.py
|
||||
@Time : 2021/11/11
|
||||
@Time : 2021/11/24
|
||||
@Author : jee019
|
||||
@Version : 1.0
|
||||
@Version : 1.1
|
||||
@Contact : qwer010910@gmail.com
|
||||
@Desc :
|
||||
'''
|
||||
@@ -30,14 +30,20 @@ class LangKorean(object):
|
||||
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_TRACKIFNO = "트랙 정보 표시"
|
||||
SETTING_SHOW_TRACKINFO = "트랙 정보 표시"
|
||||
SETTING_SAVE_ALBUMINFO = "AlbumInfo.txt 저장"
|
||||
SETTING_DOWNLOAD_VIDEOS = "Download videos"
|
||||
SETTING_ADD_LYRICS = "가사 추가"
|
||||
SETTING_LYRICS_SERVER_PROXY = "가사 서버 프록시"
|
||||
SETTINGS_ADD_LRC_FILE = "맞춤 가사 저장 (.lrc 파일)"
|
||||
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 = "기능"
|
||||
@@ -47,8 +53,9 @@ class LangKorean(object):
|
||||
CHOICE_LOGIN = "액세스 토큰 확인"
|
||||
CHOICE_SETTINGS = "설정"
|
||||
CHOICE_SET_ACCESS_TOKEN = "액세스 토큰 설정"
|
||||
CHOICE_DOWNLOAD_BY_URL = "url 또는 id로 다운로드"
|
||||
CHOICE_DOWNLOAD_BY_URL = "Url 또는 id로 다운로드"
|
||||
CHOICE_LOGOUT = "로그아웃"
|
||||
CHOICE_APIKEY = "Select APIKey"
|
||||
|
||||
PRINT_ERR = "[에러]"
|
||||
PRINT_INFO = "[정보]"
|
||||
@@ -60,8 +67,8 @@ class LangKorean(object):
|
||||
# PRINT_PASSWORD = "비밀번호:"
|
||||
|
||||
CHANGE_START_SETTINGS = "설정 시작('0'-뒤로가기,'1'-예):"
|
||||
CHANGE_DOWNLOAD_PATH = "다운로드 경로('0' 변경 안 함):"
|
||||
CHANGE_AUDIO_QUALITY = "음질('0'-보통,'1'-높음,'2'-HiFi,'3'-Master):"
|
||||
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'-예):"
|
||||
@@ -74,14 +81,20 @@ class LangKorean(object):
|
||||
CHANGE_ALBUMID_BEFORE_FOLDER = "앨범 폴더 앞에 ID 추가('0'-아니요,'1'-예):"
|
||||
CHANGE_SAVE_COVERS = "커버 저장('0'-아니요,'1'-예):"
|
||||
CHANGE_LANGUAGE = "언어 선택"
|
||||
CHANGE_ALBUM_FOLDER_FORMAT = "앨범 폴더 형식('0' 변경 안 함,'default' 기본 설정):"
|
||||
CHANGE_TRACK_FILE_FORMAT = "트랙 파일 형식('0' 변경 안 함,'default' 기본 설정):"
|
||||
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 = "맞춤 가사 .lrc 파일 저장 ('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 = "로그인 중..."
|
||||
@@ -90,8 +103,8 @@ class LangKorean(object):
|
||||
AUTH_WAITING = "승인 대기 중..."
|
||||
AUTH_TIMEOUT = "작업 시간 초과"
|
||||
|
||||
MSG_VALID_ACCESSTOKEN = "{}에 대해 액세스토큰이 유효합니다."
|
||||
MSG_INVAILD_ACCESSTOKEN = "만료된 액세스 토큰입니다. 새로 고침 중입니다."
|
||||
MSG_VALID_ACCESSTOKEN = "{}에 대해 액세스 토큰이 유효합니다."
|
||||
MSG_INVALID_ACCESSTOKEN = "만료된 액세스 토큰입니다. 새로 고침 중입니다."
|
||||
MSG_PATH_ERR = "경로 오류!"
|
||||
MSG_INPUT_ERR = "입력 오류!"
|
||||
|
||||
|
||||
@@ -6,131 +6,90 @@
|
||||
@Author : Yaronzz
|
||||
@Version : 1.0
|
||||
@Contact : yaronhuang@foxmail.com
|
||||
@Desc :
|
||||
@Desc :
|
||||
'''
|
||||
|
||||
from tidal_dl.lang.arabic import LangArabic
|
||||
from tidal_dl.lang.chinese import LangChinese
|
||||
from tidal_dl.lang.croatian import LangCroatian
|
||||
from tidal_dl.lang.czech import LangCzech
|
||||
from tidal_dl.lang.danish import LangDanish
|
||||
from tidal_dl.lang.english import LangEnglish
|
||||
from tidal_dl.lang.filipino import LangFilipino
|
||||
from tidal_dl.lang.french import LangFrench
|
||||
from tidal_dl.lang.german import LangGerman
|
||||
from tidal_dl.lang.hungarian import LangHungarian
|
||||
from tidal_dl.lang.italian import LangItalian
|
||||
from tidal_dl.lang.portuguese import LangPortuguese
|
||||
from tidal_dl.lang.russian import LangRussian
|
||||
from tidal_dl.lang.spanish import LangSpanish
|
||||
from tidal_dl.lang.turkish import LangTurkish
|
||||
from tidal_dl.lang.ukrainian import LangUkrainian
|
||||
from tidal_dl.lang.vietnamese import LangVietnamese
|
||||
from tidal_dl.lang.korean import LangKorean
|
||||
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
|
||||
|
||||
LANG = None
|
||||
_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)
|
||||
|
||||
|
||||
def initLang(index): # 初始化
|
||||
global LANG
|
||||
return setLang(index)
|
||||
|
||||
|
||||
def setLang(index):
|
||||
global LANG
|
||||
if str(index) == '0':
|
||||
LANG = LangEnglish()
|
||||
elif str(index) == '1':
|
||||
LANG = LangChinese()
|
||||
elif str(index) == '2':
|
||||
LANG = LangTurkish()
|
||||
elif str(index) == '3':
|
||||
LANG = LangItalian()
|
||||
elif str(index) == '4':
|
||||
LANG = LangCzech()
|
||||
elif str(index) == '5':
|
||||
LANG = LangArabic()
|
||||
elif str(index) == '6':
|
||||
LANG = LangRussian()
|
||||
elif str(index) == '7':
|
||||
LANG = LangFilipino()
|
||||
elif str(index) == '8':
|
||||
LANG = LangCroatian()
|
||||
elif str(index) == '9':
|
||||
LANG = LangSpanish()
|
||||
elif str(index) == '10':
|
||||
LANG = LangPortuguese()
|
||||
elif str(index) == '11':
|
||||
LANG = LangUkrainian()
|
||||
elif str(index) == '12':
|
||||
LANG = LangVietnamese()
|
||||
elif str(index) == '13':
|
||||
LANG = LangFrench()
|
||||
elif str(index) == '14':
|
||||
LANG = LangGerman()
|
||||
elif str(index) == '15':
|
||||
LANG = LangDanish()
|
||||
elif str(index) == '16':
|
||||
LANG = LangHungarian()
|
||||
elif str(index) == '17':
|
||||
LANG = LangKorean()
|
||||
else:
|
||||
LANG = LangEnglish()
|
||||
return LANG
|
||||
|
||||
|
||||
def getLang():
|
||||
global LANG
|
||||
return LANG
|
||||
|
||||
|
||||
def getLangName(index):
|
||||
if str(index) == '0':
|
||||
return "English"
|
||||
if str(index) == '1':
|
||||
return "中文"
|
||||
if str(index) == '2':
|
||||
return "Turkish"
|
||||
if str(index) == '3':
|
||||
return "Italian"
|
||||
if str(index) == '4':
|
||||
return "Czech"
|
||||
if str(index) == '5':
|
||||
return "Arabic"
|
||||
if str(index) == '6':
|
||||
return "Russian"
|
||||
if str(index) == '7':
|
||||
return "Filipino"
|
||||
if str(index) == '8':
|
||||
return "Croatian"
|
||||
if str(index) == '9':
|
||||
return "Spanish"
|
||||
if str(index) == '10':
|
||||
return "Portuguese"
|
||||
if str(index) == '11':
|
||||
return "Ukrainian"
|
||||
if str(index) == '12':
|
||||
return "Vietnamese"
|
||||
if str(index) == '13':
|
||||
return "French"
|
||||
if str(index) == '14':
|
||||
return "German"
|
||||
if str(index) == '15':
|
||||
return "Danish"
|
||||
if str(index) == '16':
|
||||
return "Hungarian"
|
||||
if str(index) == '17':
|
||||
return "Korean"
|
||||
return ""
|
||||
|
||||
|
||||
def getLangChoicePrint():
|
||||
array = []
|
||||
index = 0
|
||||
while True:
|
||||
name = getLangName(index)
|
||||
if name == "":
|
||||
break
|
||||
array.append('\'' + str(index) + '\'-' + name)
|
||||
index += 1
|
||||
return ','.join(array)
|
||||
LANG = Language()
|
||||
|
||||