File size: 6,042 Bytes
f3f431f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220

# THIS FILE IS RESPONSABLE FOR MANY CLASS DECLARATIONS

import json
import math
from base64 import b64encode
from urllib.request import urlretrieve
from . import constructor
from . import calls


# AUTHENTICATION AND TOKENS
class Authenticator:

    def __init__(self, client_id:str, client_secret:str):
        self.credentials = self.encode_credentials(client_id, client_secret)
    

    def encode_credentials(self, client_id, client_secret):
        credentials = f'{client_id}:{client_secret}'
        encoded_credentials = b64encode(credentials.encode('utf-8'))
        return str(encoded_credentials, 'utf-8')


    def get_acess_token(self):
        response = calls.call_acess_token(self.credentials)
        return response.json()['access_token']


# OBJECTS

# Base class for all classes
class Base: 
    
    def __init__(self, data, type, name, url, id):
        self.data = data
        self.type = type
        self.name = name
        self.url = url
        self.id = id
    

    def export_json(self, path:str):
        file = open(path, 'w')
        json.dump(self.data, file, indent=4)
        file.close()


# Base class for track-like objects
class TrackBase(Base): 
    
    def __init__(self, data, type, name, url, id, explicit, duration_ms):
        super().__init__(data, type, name, url, id)
        self.explicit = explicit
        self.duration_ms = duration_ms
    

    def get_formatted_duration(self) -> dict:
        
        duration_in_seconds = self.duration_ms / 1000
        hours = 0
        mins = math.floor(duration_in_seconds // 60)

        if mins >= 60:
            hours = math.floor(mins // 60)
            mins = math.floor(mins % 60)
        
        secs = math.floor(duration_in_seconds % 60)

        return {'hours':hours, 'minutes':mins, 'seconds':secs}
    

    def get_string_duration(self) -> str:
     
        duration = self.get_formatted_duration()
        format = self.__format_duration
        
        hours = format(str(duration['hours']))
        mins = format(str(duration['minutes']))
        secs = format(str(duration['seconds']))       
        
        if int(hours):
            return f'{hours}:{mins}:{secs}'
        else:
            return f'{mins}:{secs}'


    def __format_duration(self, value:str):
        if len(value) < 2:
            return ('0' + value)
        else: return value


class Artist(Base):

    def __init__(self, data:dict, type:str, name:str, url:str, id:str):
        super().__init__(data, type, name, url, id)


class AlbumCover:

    def __init__(self, width, height, url):
        self.width = width
        self.height = height
        self.url = url
    

    def export_image(self, path):
        urlretrieve(self.url, path)


class Album(Base):

    def __init__(self, data:dict, type:str, name:str, url:str, id:str, 

    images:list, artists:list, available_markets:list, release_date:str, total_tracks:int):
        
        super().__init__(data, type, name, url, id)
        self.images = images
        self.artists = artists
        self.available_markets = available_markets
        self.release_date = release_date
        self.total_tracks = total_tracks
        

class TrackPreview:

    def __init__(self, url):
        self.url = url
    

    def export_audio(self, path):
        urlretrieve(self.url, path)


class Track(TrackBase):

    def __init__(self, data:dict, type:str, name:str, url:str, id:str, explicit:bool,

    duration_ms:int, preview:TrackPreview, artists:list, album:Album, available_markets:list, 

    disc_number:int, popularity:int):
        
        super().__init__(data, type, name, url, id, explicit, duration_ms)
        self.preview = preview
        self.artists = artists
        self.album = album
        self.available_markets = available_markets
        self.disc_number = disc_number
        self.popularity = popularity


class Episode(TrackBase):

    def __init__(self, data:dict, type:str, name:str, url:str, id:str, 

    explicit:bool,  duration_ms:int, preview:str, description:str, html_description:str,

    images:list, language:str, languages:list, release_date:str):
        
        super().__init__(data, type, name, url, id, explicit, duration_ms)
        self.preview = preview
        self.description = description
        self.html_description = html_description
        self.images = images
        self.language = language
        self.languages = languages
        self.release_date = release_date


# CLIENT OBJECTS
class Results(Base):

    def __init__(self, data):
        self.data = data
    

    def __get_items(self, type):     
        
        if type == 'artist':
            try:
                data = self.data['artists']['items']
                func = constructor.artist
            except KeyError:
                return []
        
        elif type == 'track':
            try:
                data = self.data['tracks']['items']
                func = constructor.track
            except KeyError:
                return []
        
        elif type == 'album':
            try:
                data = self.data['albums']['items']
                func = constructor.album
            except KeyError:
                return []
        
        elif type == 'episode':
            try:
                data = self.data['episodes']['items']
                func = constructor.episode
            except KeyError:
                return [] 
        
        return [func(item) for item in data]


    def get_tracks(self) -> list:
        return self.__get_items('track')
    

    def get_artists(self) -> list:
        return self.__get_items('artist')
    

    def get_albums(self) -> list:
        return self.__get_items('album')


    def get_episodes(self) -> list:
        return self.__get_items('episode')