Restructure and fixed issues

This commit is contained in:
RemixDev 2020-02-17 16:46:18 +01:00
parent e29bf188b2
commit f8d8f08417
9 changed files with 701 additions and 0 deletions

2
deemix/__init__.py Normal file
View File

@ -0,0 +1,2 @@
#!/usr/bin/env python3
#Empty File

8
deemix/__main__.py Normal file
View File

@ -0,0 +1,8 @@
#!/usr/bin/env python3
import wx
from deemix.ui.MainFrame import MainFrame
if __name__ == '__main__':
app = wx.App()
frame = MainFrame()
app.MainLoop()

2
deemix/api/__init__.py Normal file
View File

@ -0,0 +1,2 @@
#!/usr/bin/env python3
#Empty File

309
deemix/api/deezer.py Executable file
View File

@ -0,0 +1,309 @@
#!/usr/bin/env python3
from urllib.request import urlopen
import requests
import json
import re
import hashlib
import pyaes
import binascii
import blowfish
class Deezer:
def __init__(self):
self.api_url = "http://www.deezer.com/ajax/gw-light.php"
self.legacy_api_url = "https://api.deezer.com/"
self.http_headers = {
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36"
}
self.album_pictures_host = "https://e-cdns-images.dzcdn.net/images/cover/"
self.artist_pictures_host = "https://e-cdns-images.dzcdn.net/images/artist/"
self.user = {}
self.session = requests.Session()
self.logged_in = False
self.session.post("http://www.deezer.com/", headers=self.http_headers)
self.sid = self.session.cookies.get_dict()['sid']
def get_token(self):
tokenData = self.gw_api_call('deezer.getUserData')
return tokenData["results"]["checkForm"]
def get_track_MD5(self, id):
site = self.session.post("https://api.deezer.com/1.0/gateway.php",
params = {
'api_key' : "4VCYIJUCDLOUELGD1V8WBVYBNVDYOXEWSLLZDONGBBDFVXTZJRXPR29JRLQFO6ZE",
'sid' : self.sid,
'input' : '3',
'output': '3',
'method' : 'song_getData'
},
data = json.dumps({'sng_id': id}),
headers = self.http_headers
)
response = json.loads(site.text)
return response['results']['PUID']
def gw_api_call(self, method, args={}):
result = self.session.post(
self.api_url,
params = {
'api_version' : "1.0",
'api_token' : 'null' if method == 'deezer.getUserData' else self.get_token(),
'input' : '3',
'method' : method
},
data = json.dumps(args),
headers = self.http_headers
)
result = json.loads(result.text)
return result
def api_call(self, method, args={}):
result = self.session.get(
self.legacy_api_url+method,
params = args,
headers = self.http_headers
)
result_json = json.loads(result.text)
if 'error' in result_json.keys():
raise APIError()
return result_json
def login(self, email, password, reCaptchaToken):
checkFormLogin = self.gw_api_call("deezer.getUserData")
login = self.session.post(
"https://www.deezer.com/ajax/action.php",
data={
'type':'login',
'mail':email,
'password':password,
'checkFormLogin':checkFormLogin['results']['checkFormLogin'],
'reCaptchaToken': reCaptchaToken
},
headers = {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}.update(self.http_headers)
)
if not 'success' in login.text:
self.logged_in = False
return False
userData = self.gw_api_call("deezer.getUserData")
self.user = {
'email': email,
'id': userData["results"]["USER"]["USER_ID"],
'name': userData["results"]["USER"]["BLOG_NAME"],
'picture': userData["results"]["USER"]["USER_PICTURE"] if "USER_PICTURE" in userData["results"]["USER"] else ""
}
self.logged_in = True
return True
def login_via_arl(self, arl):
cookie_obj = requests.cookies.create_cookie(
domain='deezer.com',
name='arl',
value=arl,
path="/",
rest={'HttpOnly': True}
)
self.session.cookies.set_cookie(cookie_obj)
userData = self.gw_api_call("deezer.getUserData")
if (userData["results"]["USER"]["USER_ID"] == 0):
self.logged_in = False
return False
self.user = {
'id': userData["results"]["USER"]["USER_ID"],
'name': userData["results"]["USER"]["BLOG_NAME"],
'picture': userData["results"]["USER"]["USER_PICTURE"] if "USER_PICTURE" in userData["results"]["USER"] else ""
}
self.logged_in = True
return True
def get_track_gw(self, id):
if (int(id)<0):
body = self.gw_api_call('song.getData', {'sng_id': id})
else:
body = self.gw_api_call('deezer.pageTrack', {'sng_id': id})
if 'LYRICS' in body['results']:
body['results']['DATA']['LYRICS'] = body['results']['LYRICS']
body['results'] = body['results']['DATA']
return body['results']
def get_tracks_gw(self, ids):
tracksArray = []
body = self.gw_api_call('song.getListData', {'sng_ids': ids})
errors = 0
for i in range(len(ids)):
if ids[i] != 0:
tracksArray.append(body['results']['data'][i-errors])
else:
errors += 1
tracksArray.append({
'SNG_ID': 0,
'SNG_TITLE': '',
'DURATION': 0,
'MD5_ORIGIN': 0,
'MEDIA_VERSION': 0,
'FILESIZE': 0,
'ALB_TITLE': "",
'ALB_PICTURE': "",
'ART_ID': 0,
'ART_NAME': ""
})
return tracksArray
def get_album_gw(self, id):
body = self.gw_api_call('album.getData', {'alb_id': id})
return body['results']
def get_album_tracks_gw(self, id):
tracksArray = []
body = self.gw_api_call('song.getListByAlbum', {'alb_id': id, 'nb': -1})
for track in body['results']['data']:
_track = track
_track['position'] = body['results']['data'].index(track)
tracksArray.append(_track)
return tracksArray
def get_artist_gw(self, id):
body = self.gw_api_call('deezer.pageArtist', {'art_id': id})
return body
def get_playlist_gw(self, id):
body = self.gw_api_call('deezer.pagePlaylist', {'playlist_id': id})
return body
def get_playlist_tracks_gw(self, id):
tracksArray = []
body = self.gw_api_call('playlist.getSongs', {'playlist_id': id, 'nb': -1})
for track in body['results']['data']:
_track = track
_track['position'] = body['results']['data'].index(track)
tracksArray.append(_track)
return tracksArray
def get_artist_toptracks_gw(self, id):
tracksArray = []
body = self.gw_api_call('artist.getTopTrack', {'art_id': id, 'nb': 100})
for track in body['results']['data']:
_track = track
_track['position'] = body['results']['data'].index(track)
tracksArray.append(_track)
return tracksArray
def get_lyrics_gw(self, id):
body = self.gw_api_call('song.getLyrics', {'sng_id': id})
lyr = {}
lyr['unsyncLyrics'] = {
'description': "",
'lyrics': body["results"]["LYRICS_TEXT"]
}
lyr['syncLyrics'] = ""
for i in range(len(body["results"]["LYRICS_SYNC_JSON"])):
if "lrc_timestamp" in body["results"]["LYRICS_SYNC_JSON"][i]:
lyr['syncLyrics'] += body["results"]["LYRICS_SYNC_JSON"][i]["lrc_timestamp"] + body["results"]["LYRICS_SYNC_JSON"][i]["line"]+"\r\n"
elif i+1 < len(body["results"]["LYRICS_SYNC_JSON"]):
lyr['syncLyrics'] += body["results"]["LYRICS_SYNC_JSON"][i+1]["lrc_timestamp"] + body["results"]["LYRICS_SYNC_JSON"][i]["line"]+"\r\n"
return lyr
def get_user_playlist(self, id):
body = self.api_call('user/'+str(id)+'/playlists', {'limit': -1})
return body
def get_track(self, id):
body = self.api_call('track/'+str(id))
return body
def get_track_by_ISRC(self, isrc):
body = self.api_call('track/isrc:'+isrc)
return body
def get_charts_top_country(self):
return self.get_user_playlist('637006841')
def get_playlist(self, id):
body = self.api_call('playlist/'+str(id))
return body
def get_playlist_tracks(self, id):
body = self.api_call('playlist/'+str(id)+'/tracks', {'limit': -1})
return body
def get_album(self, id):
body = self.api_call('album/'+str(id))
return body
def get_album_by_UPC(self, upc):
body = self.api_call('album/upc:'+str(upc))
def get_album_tracks(self, id):
body = self.api_call('album/'+str(id)+'/tracks', {'limit': -1})
return body
def get_artist(self, id):
body = self.api_call('artist/'+str(id))
return body
def get_artist_albums(self, id):
body = self.api_call('artist/'+str(id)+'/albums', {'limit': -1})
return body
def search(self, term, type, limit = 30):
body = self.api_call('search/'+type, {'q': term, 'limit': limit})
return body
def decrypt_track(self, trackId, input, output):
response = open(input, 'rb')
outfile = open(output, 'wb')
cipher = blowfish.Cipher(str.encode(self._get_blowfish_key(str(trackId))))
i=0
while True:
chunk = response.read(2048)
if not chunk:
break
if (i % 3)==0 and len(chunk)==2048:
chunk = b"".join(cipher.decrypt_cbc(chunk,b"\x00\x01\x02\x03\x04\x05\x06\x07"))
outfile.write(chunk)
i += 1
def stream_track(self, trackId, url, stream):
response = urlopen(url)
cipher = blowfish.Cipher(str.encode(self._get_blowfish_key(str(trackId))))
i=0
while True:
chunk = response.read(2048)
if not chunk:
break
if (i % 3)==0 and len(chunk)==2048:
chunk = b"".join(cipher.decrypt_cbc(chunk,b"\x00\x01\x02\x03\x04\x05\x06\x07"))
stream.write(chunk)
i += 1
def _md5(self, data):
h=hashlib.new("md5")
h.update(str.encode(data) if isinstance(data, str) else data)
return h.hexdigest()
def _ecb_crypt(self, key, data):
res = b''
for x in range(int(len(data)/16)):
res += binascii.hexlify(pyaes.AESModeOfOperationECB(key).encrypt(data[:16]))
data = data[16:]
return res
def _get_blowfish_key(self, trackId):
SECRET = 'g4el58wc'+'0zvf9na1'
idMd5 = self._md5(trackId)
bfKey = ""
for i in range(16):
bfKey += chr(ord(idMd5[i]) ^ ord(idMd5[i+16]) ^ ord(SECRET[i]))
return bfKey
def get_track_stream_url(self, sng_id, md5, media_version, format):
urlPart = b'\xa4'.join([str.encode(md5), str.encode(str(format)), str.encode(str(sng_id)), str.encode(str(media_version))])
md5val = self._md5(urlPart)
step2 = str.encode(md5val)+b'\xa4'+urlPart+b'\xa4'
while len(step2)%16 > 0:
step2 += b'.'
urlPart = self._ecb_crypt(b'jo6aey6haid2Teih', step2)
return "https://e-cdns-proxy-" + md5[0] + ".dzcdn.net/mobile/1/" + urlPart.decode("utf-8")
class APIError(Exception):
pass

264
deemix/app/functions.py Normal file
View File

@ -0,0 +1,264 @@
#!/usr/bin/env python3
from deemix.api.deezer import Deezer, APIError
from deemix.utils.taggers import tagID3, tagFLAC
import json
import re
extensions = {
9: '.flac',
3: '.mp3',
1: '.mp3',
8: '.mp3',
15: '.mp4',
14: '.mp4',
13: '.mp4'
}
dz = Deezer()
def getIDFromLink(link, type):
if '?' in link:
link = link[:link.find('?')]
if link.startswith("http") and 'open.spotify.com/' in link:
if type == "spotifyplaylist":
return link[link.find("/playlist/")+10]
if type == "spotifytrack":
return link[link.find("/track/")+7]
if type == "spotifyalbum":
return link[link.find("/album/")+7]
elif link.startswith("spotify:"):
if type == "spotifyplaylist":
return link[link.find("playlist:")+9]
if type == "spotifytrack":
return link[link.find("track:")+6]
if type == "spotifyalbum":
return link[link.find("album:")+6]
elif type == "artisttop":
return re.search("\/artist\/(\d+)\/top_track",link)[1]
else:
return link[link.rfind("/")+1:]
def getTypeFromLink(link):
type = ''
if 'spotify' in link:
type = 'spotify'
if 'playlist' in link:
type += 'playlist'
elif 'track' in link:
type += 'track'
elif 'album' in link:
type += 'album'
elif 'deezer' in link:
if '/track' in link:
type = 'track'
elif '/playlist' in link:
type = 'playlist'
elif '/album' in link:
type = 'album'
elif re.search("\/artist\/(\d+)\/top_track",link):
type = 'artisttop'
elif '/artist' in link:
type = 'artist'
return type
def getTrackData(id):
if not id:
return None
trackAPI = dz.get_track_gw(id)
if not 'MD5_ORIGIN' in trackAPI:
trackAPI['MD5_ORIGIN'] = dz.get_track_MD5(id)
track = {}
track['id'] = trackAPI['SNG_ID']
track['title'] = trackAPI['SNG_TITLE']
if trackAPI['VERSION']:
track['title'] += " "+trackAPI['VERSION']
track['duration'] = trackAPI['DURATION']
track['MD5'] = trackAPI['MD5_ORIGIN']
track['mediaVersion'] = trackAPI['MEDIA_VERSION']
if int(track['id'])<0:
track['filesize'] = trackAPI['FILESIZE']
track['album'] = {}
track['album']['id'] = 0
track['album']['title'] = trackAPI['ALB_TITLE']
if 'ALB_PICTURE' in trackAPI:
track['album']['pic'] = trackAPI['ALB_PICTURE']
track['mainArtist'] = {}
track['mainArtist']['id'] = 0
track['mainArtist']['name'] = trackAPI['ART_NAME']
track['artistArray'] = [trackAPI['ART_NAME']]
track['date'] = {
'day': 0,
'month': 0,
'year': 0
}
track['localTrack'] = True
return track
track['filesize'] = {}
track['filesize']['default'] = int(trackAPI['FILESIZE']) if 'FILESIZE' in trackAPI else None
track['filesize']['mp3_128'] = int(trackAPI['FILESIZE_MP3_128']) if 'FILESIZE_MP3_128' in trackAPI else None
track['filesize']['mp3_320'] = int(trackAPI['FILESIZE_MP3_320']) if 'FILESIZE_MP3_320' in trackAPI else None
track['filesize']['flac'] = int(trackAPI['FILESIZE_FLAC']) if 'FILESIZE_FLAC' in trackAPI else None
track['filesize']['mp4_ra1'] = int(trackAPI['FILESIZE_MP4_RA1']) if 'FILESIZE_MP4_RA1' in trackAPI else None
track['filesize']['mp4_ra2'] = int(trackAPI['FILESIZE_MP4_RA2']) if 'FILESIZE_MP4_RA2' in trackAPI else None
track['filesize']['mp4_ra3'] = int(trackAPI['FILESIZE_MP4_RA3']) if 'FILESIZE_MP4_RA3' in trackAPI else None
if 'DISK_NUMBER' in trackAPI:
track['discNumber'] = trackAPI['DISK_NUMBER']
if 'EXPLICIT_LYRICS' in trackAPI:
track['explicit'] = trackAPI['EXPLICIT_LYRICS'] != "0"
if 'COPYRIGHT' in trackAPI:
track['copyright'] = trackAPI['COPYRIGHT']
track['replayGain'] = "{0:.2f} dB".format((float(trackAPI['GAIN']) + 18.4) * -1)
track['ISRC'] = trackAPI['ISRC']
track['trackNumber'] = trackAPI['TRACK_NUMBER']
if 'FALLBACK' in trackAPI:
track['fallbackId'] = trackAPI['FALLBACK']['SNG_ID']
else:
track['fallbackId'] = 0
track['contributors'] = trackAPI['SNG_CONTRIBUTORS']
track['lyrics'] = {}
if 'LYRICS_ID' in trackAPI:
track['lyrics']['id'] = trackAPI['LYRICS_ID']
if "LYRICS" in trackAPI:
if "LYRICS_TEXT" in trackAPI["LYRICS"]:
track['lyrics']['unsync'] = trackAPI["LYRICS"]["LYRICS_TEXT"]
if "LYRICS_SYNC_JSON" in trackAPI["LYRICS"]:
track['lyrics']['sync'] = ""
for i in range(len(trackAPI["LYRICS"]["LYRICS_SYNC_JSON"])):
if "lrc_timestamp" in trackAPI["LYRICS"]["LYRICS_SYNC_JSON"][i]:
track['lyrics']['sync'] += trackAPI["LYRICS"]["LYRICS_SYNC_JSON"][i]["lrc_timestamp"] + trackAPI["LYRICS"]["LYRICS_SYNC_JSON"][i]["line"]+"\r\n"
elif i+1 < len(trackAPI["LYRICS"]["LYRICS_SYNC_JSON"]):
track['lyrics']['sync'] += trackAPI["LYRICS"]["LYRICS_SYNC_JSON"][i+1]["lrc_timestamp"] + trackAPI["LYRICS"]["LYRICS_SYNC_JSON"][i]["line"]+"\r\n"
track['mainArtist'] = {}
track['mainArtist']['id'] = trackAPI['ART_ID']
track['mainArtist']['name'] = trackAPI['ART_NAME']
if 'ART_PICTURE' in trackAPI:
track['mainArtist']['pic'] = trackAPI['ART_PICTURE']
if 'PHYSICAL_RELEASE_DATE' in trackAPI:
track['date'] = {
'day': trackAPI["PHYSICAL_RELEASE_DATE"][8:10],
'month': trackAPI["PHYSICAL_RELEASE_DATE"][5:7],
'year': trackAPI["PHYSICAL_RELEASE_DATE"][0:4]
}
track['album'] = {}
track['album']['id'] = trackAPI['ALB_ID']
track['album']['title'] = trackAPI['ALB_TITLE']
if 'ALB_PICTURE' in trackAPI:
track['album']['pic'] = trackAPI['ALB_PICTURE']
try:
albumAPI = dz.get_album(track['album']['id'])
track['album']['artist'] = {
'id': albumAPI['artist']['id'],
'name': albumAPI['artist']['name'],
'pic': albumAPI['artist']['picture_small'][46:-24]
}
track['album']['trackTotal'] = albumAPI['nb_tracks']
track['album']['recordType'] = albumAPI['record_type']
track['album']['barcode'] = albumAPI['upc'] if 'upc' in albumAPI else None
track['album']['label'] = albumAPI['label'] if 'label' in albumAPI else None
if not 'pic' in track['album']:
track['album']['pic'] = albumAPI['cover_small'][43:-24]
if 'release_date' in albumAPI:
track['date'] = {
'day': albumAPI["release_date"][8:10],
'month': albumAPI["release_date"][5:7],
'year': albumAPI["release_date"][0:4]
}
track['album']['genre'] = []
if 'genres' in albumAPI and 'data' in albumAPI['genres'] and len(albumAPI['genres']['data'])>0:
for genre in albumAPI['genres']['data']:
track['album']['genre'].append(genre['name'])
except APIError:
albumAPI = dz.get_album_gw(track['album']['id'])
track['album']['artist'] = {
'id': albumAPI['ART_ID'],
'name': albumAPI['ART_NAME']
}
track['album']['trackTotal'] = albumAPI['NUMBER_TRACK']
track['album']['discTotal'] = albumAPI['NUMBER_DISK']
track['album']['recordType'] = trackAPI['TYPE']
track['album']['barcode'] = None
track['album']['label'] = albumAPI['LABEL_NAME'] if 'LABEL_NAME' in albumAPI else None
if not 'pic' in track['album']:
track['album']['pic'] = albumAPI['ALB_PICTURE']
if 'PHYSICAL_RELEASE_DATE' in albumAPI:
track['date'] = {
'day': albumAPI["PHYSICAL_RELEASE_DATE"][8:10],
'month': albumAPI["PHYSICAL_RELEASE_DATE"][5:7],
'year': albumAPI["PHYSICAL_RELEASE_DATE"][0:4]
}
track['album']['genre'] = []
trackAPI2 = dz.get_track(track['id'])
track['bpm'] = trackAPI2['bpm']
if not 'replayGain' in track:
track['replayGain'] = "{0:.2f} dB".format((float(trackAPI2['gain']) + 18.4) * -1)
if not 'explicit' in track:
track['explicit'] = trackAPI2['explicit_lyrics']
track['artist'] = {}
track['artists'] = []
for artist in trackAPI2['contributors']:
track['artists'].append(artist['name'])
if not artist['role'] in track['artist']:
track['artist'][artist['role']] = []
track['artist'][artist['role']].append(artist['name'])
if not 'discTotal' in track['album']:
albumAPI2 = dz.get_album_gw(track['album']['id'])
track['album']['discTotal'] = albumAPI2['NUMBER_DISK']
return track
def downloadTrack(id, bitrate):
# Get the metadata
track = getTrackData(id)
# Get the selected bitrate
bitrateFound = False;
if int(bitrate) == 9:
track['selectedFormat'] = 9
track['selectedFilesize'] = track['filesize']['flac']
if track['filesize']['flac'] > 0:
bitrateFound = True
else:
bitrateFound = False
bitrate = 3
if int(bitrate) == 3:
track['selectedFormat'] = 3
track['selectedFilesize'] = track['filesize']['mp3_320']
if track['filesize']['mp3_320'] > 0:
bitrateFound = True
else:
bitrateFound = False
bitrate = 1
if int(bitrate) == 1:
track['selectedFormat'] = 3
track['selectedFilesize'] = track['filesize']['mp3_320']
if track['filesize']['mp3_320'] > 0:
bitrateFound = True
else:
bitrateFound = False
if not bitrateFound:
track['selectedFormat'] = 8
track['selectedFilesize'] = track['filesize']['default']
track['album']['bitrate'] = track['selectedFormat']
# Create the filename
filename = "{artist} - {title}".format(title=track['title'], artist=track['mainArtist']['name'])+extensions[track['selectedFormat']]
print(filename)
track['downloadUrl'] = dz.get_track_stream_url(track['id'], track['MD5'], track['mediaVersion'], track['selectedFormat'])
with open(filename, 'wb') as stream:
dz.stream_track(track['id'], track['downloadUrl'], stream)
if track['selectedFormat'] in [3,1,8]:
tagID3(filename, track)
elif track['selectedFormat'] == 9:
tagFLAC(filename, track)

30
deemix/ui/MainFrame.py Normal file
View File

@ -0,0 +1,30 @@
#!/usr/bin/env python3
import wx
from deemix.app.functions import downloadTrack, getIDFromLink, getTypeFromLink
class MainFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None, title='deemix')
panel = wx.Panel(self)
main_sizer = wx.BoxSizer(wx.VERTICAL)
search_sizer = wx.BoxSizer(wx.HORIZONTAL)
main_sizer.Add(search_sizer, 0, wx.EXPAND, 5)
self.text_ctrl = wx.TextCtrl(panel)
search_sizer.Add(self.text_ctrl, 1, wx.ALL, 5)
my_btn = wx.Button(panel, label='Download')
my_btn.Bind(wx.EVT_BUTTON, self.downloadTrack)
search_sizer.Add(my_btn, 0, wx.ALL, 5)
panel.SetSizer(main_sizer)
self.Show()
def downloadTrack(self, event):
value = self.text_ctrl.GetValue()
if not value:
print("You didn't enter anything!")
return None
type = getTypeFromLink(value)
id = getIDFromLink(value,type)
print(type, id)
if type == "track":
downloadTrack(id,9)
self.text_ctrl.SetValue("")

2
deemix/ui/__init__.py Normal file
View File

@ -0,0 +1,2 @@
#!/usr/bin/env python3
#Empty File

2
deemix/utils/__init__.py Normal file
View File

@ -0,0 +1,2 @@
#!/usr/bin/env python3
#Empty File

82
deemix/utils/taggers.py Normal file
View File

@ -0,0 +1,82 @@
#!/usr/bin/env python3
from mutagen.id3 import ID3, ID3NoHeaderError
from mutagen.id3 import TXXX, TIT2, TPE1, TALB, TPE2, TRCK, TPOS, TCON, TYER, TDAT, TLEN, TBPM, TPUB, TSRC, USLT, APIC, IPLS, TCOM, TCOP, TCMP
from mutagen.flac import FLAC, Picture
from urllib.request import urlopen
def tagID3(stream, track):
try:
tag = ID3(stream)
except ID3NoHeaderError:
tag = ID3()
tag.add(TIT2(text=track['title']))
tag.add(TPE1(text=track['artists']))
tag.add(TALB(text=track['album']['title']))
tag.add(TPE2(text=track['album']['artist']['name']))
tag.add(TRCK(text=str(track['trackNumber'])))
tag.add(TPOS(text=str(track['discNumber'])))
tag.add(TCON(text=track['album']['genre']))
tag.add(TYER(text=str(track['date']['year'])))
tag.add(TDAT(text=str(track['date']['month'])+str(track['date']['day'])))
tag.add(TLEN(text=str(track['duration'])))
tag.add(TBPM(text=str(track['bpm'])))
tag.add(TPUB(text=track['album']['label']))
tag.add(TSRC(text=track['ISRC']))
tag.add(TXXX(desc="BARCODE", text=track['album']['barcode']))
tag.add(TXXX(desc="ITUNESADVISORY", text="1" if track['explicit'] else "0"))
tag.add(TXXX(desc="REPLAYGAIN_TRACK_GAIN", text=track['replayGain']))
if 'unsync' in track['lyrics']:
tag.add(USLT(text=track['lyrics']['unsync']))
involvedPeople = []
for role in track['contributors']:
if role in ['author', 'engineer', 'mixer', 'producer', 'writer']:
for person in track['contributors'][role]:
involvedPeople.append([role,person])
elif role == 'composer':
tag.add(TCOM(text=track['contributors']['composer']))
if len(involvedPeople) > 0:
tag.add(IPLS(people=involvedPeople))
tag.add(TCOP(text=track['copyright']))
tag.add(APIC(3, 'image/jpeg', 3, data=urlopen("http://e-cdn-images.deezer.com/images/cover/"+track["album"]['pic']+"/800x800.jpg").read()))
tag.save(stream, v1=2, v2_version=3, v23_sep=None)
def tagFLAC(stream, track):
tag = FLAC(stream)
tag["TITLE"] = track['title']
tag["ARTIST"] = track['artists']
tag["ALBUM"] = track['album']['title']
tag["ALBUMARTIST"] = track['album']['artist']['name']
tag["TRACKNUMBER"] = str(track['trackNumber'])
tag["TRACKTOTAL"] = str(track['album']['trackTotal'])
tag["DISCNUMBER"] = str(track['discNumber'])
tag["DISCTOTAL"] = str(track['album']['discTotal'])
tag["GENRE"] = track['album']['genre']
tag["YEAR"] = str(track['date']['year'])
tag["DATE"] = "{}-{}-{}".format(str(track['date']['year']), str(track['date']['month']), str(track['date']['day']))
tag["LENGTH"] = str(track['duration'])
tag["BPM"] = str(track['bpm'])
tag["PUBLISHER"] = track['album']['label']
tag["ISRC"] = track['ISRC']
tag["BARCODE"] = track['album']['barcode']
tag["ITUNESADVISORY"] = "1" if track['explicit'] else "0"
tag["REPLAYGAIN_TRACK_GAIN"] = track['replayGain']
if 'unsync' in track['lyrics']:
tag["LYRICS"] = track['lyrics']['unsync']
for role in track['contributors']:
if role in ['author', 'engineer', 'mixer', 'producer', 'writer', 'composer']:
tag[role.upper()] = track['contributors'][role]
elif role == 'musicpublisher':
tag["ORGANIZATION"] = track['contributors']['musicpublisher']
tag["COPYRIGHT"] = track['copyright']
image = Picture()
image.type = 3
image.mime = 'image/jpeg'
image.data = urlopen("http://e-cdn-images.deezer.com/images/cover/"+track["album"]['pic']+"/800x800.jpg").read()
tag.add_picture(image)
tag.save(deleteid3=True)