diff --git a/TIDALDL-PY/requirements.txt b/TIDALDL-PY/requirements.txt index 624a9f9..80711bb 100644 --- a/TIDALDL-PY/requirements.txt +++ b/TIDALDL-PY/requirements.txt @@ -9,4 +9,5 @@ lyricsgenius==3.0.1 pydub==0.25.1 PyQt5==5.15.7 qt-material==2.12 -lxml==4.7.1 \ No newline at end of file +lxml==4.7.1 +tidalapi==0.7.3 diff --git a/TIDALDL-PY/tidal_dl/__init__.py b/TIDALDL-PY/tidal_dl/__init__.py index bc7ad07..c873f6a 100644 --- a/TIDALDL-PY/tidal_dl/__init__.py +++ b/TIDALDL-PY/tidal_dl/__init__.py @@ -22,11 +22,12 @@ def mainCommand(): "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 useage.") + 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() diff --git a/TIDALDL-PY/tidal_dl/gui.py b/TIDALDL-PY/tidal_dl/gui.py index be6fb2f..ddb10dc 100644 --- a/TIDALDL-PY/tidal_dl/gui.py +++ b/TIDALDL-PY/tidal_dl/gui.py @@ -67,7 +67,7 @@ else: def __init__(self, ) -> None: super().__init__() self.initView() - self.setMinimumSize(600, 620) + self.setMinimumSize(800, 620) self.setWindowTitle("Tidal-dl") def __info__(self, msg): @@ -120,6 +120,16 @@ else: 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.resize(200, 400) + self.tree_playlists.setColumnCount(2) + self.tree_playlists.setHeaderLabels(("Name", "# Tracks")) + self.tree_playlists.setColumnWidth(0, 250) + # print self.c_printTextEdit = QtWidgets.QTextEdit() self.c_printTextEdit.setReadOnly(True) @@ -148,7 +158,8 @@ else: self.funcGrid.addWidget(self.c_printTextEdit) self.mainGrid = QtWidgets.QGridLayout(self) - self.mainGrid.addLayout(self.funcGrid, 0, 0) + self.mainGrid.addWidget(self.tree_playlists, 0, 0) + self.mainGrid.addLayout(self.funcGrid, 0, 1) self.mainGrid.addWidget(self.c_widgetSetting, 0, 0) # connect @@ -166,9 +177,9 @@ else: 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: @@ -269,6 +280,14 @@ else: def showSettings(self): self.c_widgetSetting.show() + def tree_items_playlists(self): + playlists = TIDAL_API.get_playlists() + + for playlist in playlists: + item = QtWidgets.QTreeWidgetItem(self.tree_playlists) + item.setText(0, playlist.name) + item.setText(1, str(playlist.num_tracks)) + def startGui(): aigpy.cmd.enableColor(False) @@ -278,6 +297,7 @@ else: window = MainView() window.show() window.checkLogin() + window.tree_items_playlists() app.exec_() diff --git a/TIDALDL-PY/tidal_dl/tidal.py b/TIDALDL-PY/tidal_dl/tidal.py index 2cfa0b7..1e5c137 100644 --- a/TIDALDL-PY/tidal_dl/tidal.py +++ b/TIDALDL-PY/tidal_dl/tidal.py @@ -12,6 +12,8 @@ import json import random import re import time +from typing import Union, List + import aigpy import base64 import requests @@ -21,6 +23,8 @@ from model import * from enums import * from settings import * +import tidalapi + # SSL Warnings | retry number requests.packages.urllib3.disable_warnings() requests.adapters.DEFAULT_RETRIES = 5 @@ -157,8 +161,14 @@ class TidalAPI(object): def verifyAccessToken(self, accessToken) -> bool: header = {'authorization': 'Bearer {}'.format(accessToken)} result = requests.get('https://api.tidal.com/v1/sessions', headers=header).json() + if 'status' in result and result['status'] != 200: return False + + # Set tidalapi session. + self.session = tidalapi.session.Session() + self.session.load_oauth_session("Bearer", accessToken) + return True def refreshAccessToken(self, refreshToken) -> bool: @@ -193,6 +203,7 @@ class TidalAPI(object): self.key.userId = result['userId'] self.key.countryCode = result['countryCode'] self.key.accessToken = accessToken + return def getAlbum(self, id) -> Album: @@ -233,6 +244,7 @@ class TidalAPI(object): def search(self, text: str, type: Type, offset: int = 0, limit: int = 10) -> SearchResult: typeStr = type.name.upper() + "S" + if type == Type.Null: typeStr = "ARTISTS,ALBUMS,TRACKS,VIDEOS,PLAYLISTS" @@ -474,6 +486,15 @@ class TidalAPI(object): raise Exception("No result.") + def get_playlists(self) -> List[Union["Playlist", "UserPlaylist"]]: + playlists = self.session.user.playlists() + + return playlists + + def get_playlist_items(self, playlist_id: int) -> Union[tidalapi.Playlist, tidalapi.UserPlaylist]: + tracks = self.session.playlist(playlist_id).items() + + return tracks # Singleton TIDAL_API = TidalAPI()