Started reworking the library
This commit is contained in:
parent
a991ad04ec
commit
8afdfc7042
|
@ -4,6 +4,12 @@ import click
|
|||
import deemix.app.cli as app
|
||||
from deemix.app.settings import initSettings
|
||||
from os.path import isfile
|
||||
import random
|
||||
import string
|
||||
|
||||
def randomString(stringLength=8):
|
||||
letters = string.ascii_lowercase
|
||||
return ''.join(random.choice(letters) for i in range(stringLength))
|
||||
|
||||
|
||||
@click.command()
|
||||
|
@ -26,8 +32,5 @@ def download(bitrate, local, url):
|
|||
if local:
|
||||
click.echo(settings['downloadLocation']) #folder name output
|
||||
|
||||
def main():
|
||||
download()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
download()
|
||||
|
|
|
@ -0,0 +1,168 @@
|
|||
#!/usr/bin/env python3
|
||||
import json
|
||||
import os.path as path
|
||||
from os import makedirs, listdir, remove
|
||||
from deemix import __version__ as deemixVersion
|
||||
import logging
|
||||
import datetime
|
||||
import platform
|
||||
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger('deemix')
|
||||
|
||||
import deemix.utils.localpaths as localpaths
|
||||
|
||||
class Settings:
|
||||
def __init__(self, configFolder=None):
|
||||
self.settings = {}
|
||||
self.configFolder = configFolder
|
||||
if not self.configFolder:
|
||||
self.configFolder = localpaths.getConfigFolder()
|
||||
self.defaultSettings = {
|
||||
"downloadLocation": path.join(localpaths.getHomeFolder(), 'deemix Music'),
|
||||
"tracknameTemplate": "%artist% - %title%",
|
||||
"albumTracknameTemplate": "%tracknumber% - %title%",
|
||||
"playlistTracknameTemplate": "%position% - %artist% - %title%",
|
||||
"createPlaylistFolder": True,
|
||||
"playlistNameTemplate": "%playlist%",
|
||||
"createArtistFolder": False,
|
||||
"artistNameTemplate": "%artist%",
|
||||
"createAlbumFolder": True,
|
||||
"albumNameTemplate": "%artist% - %album%",
|
||||
"createCDFolder": True,
|
||||
"createStructurePlaylist": False,
|
||||
"createSingleFolder": False,
|
||||
"padTracks": True,
|
||||
"paddingSize": "0",
|
||||
"illegalCharacterReplacer": "_",
|
||||
"queueConcurrency": 3,
|
||||
"maxBitrate": "3",
|
||||
"fallbackBitrate": True,
|
||||
"fallbackSearch": False,
|
||||
"logErrors": True,
|
||||
"logSearched": False,
|
||||
"saveDownloadQueue": False,
|
||||
"overwriteFile": "n",
|
||||
"createM3U8File": False,
|
||||
"playlistFilenameTemplate": "playlist",
|
||||
"syncedLyrics": False,
|
||||
"embeddedArtworkSize": 800,
|
||||
"localArtworkSize": 1400,
|
||||
"localArtworkFormat": "jpg",
|
||||
"saveArtwork": True,
|
||||
"coverImageTemplate": "cover",
|
||||
"saveArtworkArtist": False,
|
||||
"artistImageTemplate": "folder",
|
||||
"jpegImageQuality": 80,
|
||||
"dateFormat": "Y-M-D",
|
||||
"albumVariousArtists": True,
|
||||
"removeAlbumVersion": False,
|
||||
"removeDuplicateArtists": False,
|
||||
"featuredToTitle": "0",
|
||||
"titleCasing": "nothing",
|
||||
"artistCasing": "nothing",
|
||||
"executeCommand": "",
|
||||
"tags": {
|
||||
"title": True,
|
||||
"artist": True,
|
||||
"album": True,
|
||||
"cover": True,
|
||||
"trackNumber": True,
|
||||
"trackTotal": False,
|
||||
"discNumber": True,
|
||||
"discTotal": False,
|
||||
"albumArtist": True,
|
||||
"genre": True,
|
||||
"year": True,
|
||||
"date": True,
|
||||
"explicit": False,
|
||||
"isrc": True,
|
||||
"length": True,
|
||||
"barcode": True,
|
||||
"bpm": True,
|
||||
"replayGain": False,
|
||||
"label": True,
|
||||
"lyrics": False,
|
||||
"copyright": False,
|
||||
"composer": False,
|
||||
"involvedPeople": False,
|
||||
"savePlaylistAsCompilation": False,
|
||||
"useNullSeparator": False,
|
||||
"saveID3v1": True,
|
||||
"multiArtistSeparator": "default",
|
||||
"singleAlbumArtist": False
|
||||
}
|
||||
}
|
||||
|
||||
# Create config folder if it doesn't exsist
|
||||
makedirs(self.configFolder, exist_ok=True)
|
||||
|
||||
# Create config file if it doesn't exsist
|
||||
if not path.isfile(path.join(self.configFolder, 'config.json')):
|
||||
with open(path.join(self.configFolder, 'config.json'), 'w') as f:
|
||||
json.dump(self.defaultSettings, f, indent=2)
|
||||
|
||||
# Read config file
|
||||
with open(path.join(self.configFolder, 'config.json'), 'r') as configFile:
|
||||
self.settings = json.load(configFile)
|
||||
|
||||
self.settingsCheck()
|
||||
|
||||
# Make sure the download path exsits
|
||||
makedirs(self.settings['downloadLocation'], exist_ok=True)
|
||||
|
||||
# LOGFILES
|
||||
|
||||
# Create logfile name and path
|
||||
logspath = path.join(self.configFolder, 'logs')
|
||||
now = datetime.datetime.now()
|
||||
logfile = now.strftime("%Y-%m-%d_%H%M%S")+".log"
|
||||
makedirs(logspath, exist_ok=True)
|
||||
|
||||
# Add handler for logging
|
||||
fh = logging.FileHandler(path.join(logspath, logfile))
|
||||
fh.setLevel(logging.DEBUG)
|
||||
fh.setFormatter(logging.Formatter('%(asctime)s - [%(levelname)s] %(message)s'))
|
||||
logger.addHandler(fh)
|
||||
logger.info(f"{platform.platform(True, True)} - Python {platform.python_version()}, deemix {deemixVersion}")
|
||||
|
||||
# Only keep last 5 logfiles (to preserve disk space)
|
||||
logslist = listdir(logspath)
|
||||
logslist.sort()
|
||||
if len(logslist)>5:
|
||||
for i in range(len(logslist)-5):
|
||||
remove(path.join(logspath, logslist[i]))
|
||||
|
||||
def getSettings(self):
|
||||
return self.settings
|
||||
|
||||
def getDefaultSettings(self):
|
||||
return self.defaultSettings
|
||||
|
||||
# Saves the settings
|
||||
def saveSettings(self, newSettings=None):
|
||||
if newSettings:
|
||||
self.settings = newSettings
|
||||
with open(path.join(self.configFolder, 'config.json'), 'w') as configFile:
|
||||
json.dump(self.settings, configFile, indent=2)
|
||||
|
||||
# Checks if the default settings have changed
|
||||
def settingsCheck(self):
|
||||
changes = 0
|
||||
for x in self.defaultSettings:
|
||||
if not x in self.settings or type(self.settings[x]) != type(self.defaultSettings[x]):
|
||||
self.settings[x] = self.defaultSettings[x]
|
||||
changes += 1
|
||||
for x in self.defaultSettings['tags']:
|
||||
if not x in self.settings['tags'] or type(self.settings['tags'][x]) != type(self.defaultSettings['tags'][x]):
|
||||
self.settings['tags'][x] = self.defaultSettings['tags'][x]
|
||||
changes += 1
|
||||
if self.settings['downloadLocation'] == "":
|
||||
self.settings['downloadLocation'] = path.join(localpaths.getHomeFolder(), 'deemix Music')
|
||||
changes += 1
|
||||
for template in ['tracknameTemplate', 'albumTracknameTemplate', 'playlistTracknameTemplate', 'playlistNameTemplate', 'artistNameTemplate', 'albumNameTemplate', 'playlistFilenameTemplate', 'coverImageTemplate', 'artistImageTemplate']:
|
||||
if self.settings[template] == "":
|
||||
self.settings[template] = self.defaultSettings[template]
|
||||
changes += 1
|
||||
if changes > 0:
|
||||
saveSettings()
|
|
@ -1,2 +1,6 @@
|
|||
#!/usr/bin/env python3
|
||||
# Empty File
|
||||
|
||||
class deemix:
|
||||
def __init__(self):
|
||||
|
||||
|
|
|
@ -1,75 +0,0 @@
|
|||
{
|
||||
"downloadLocation": "",
|
||||
"tracknameTemplate": "%artist% - %title%",
|
||||
"albumTracknameTemplate": "%tracknumber% - %title%",
|
||||
"playlistTracknameTemplate": "%position% - %artist% - %title%",
|
||||
"createPlaylistFolder": true,
|
||||
"playlistNameTemplate": "%playlist%",
|
||||
"createArtistFolder": false,
|
||||
"artistNameTemplate": "%artist%",
|
||||
"createAlbumFolder": true,
|
||||
"albumNameTemplate": "%artist% - %album%",
|
||||
"createCDFolder": true,
|
||||
"createStructurePlaylist": false,
|
||||
"createSingleFolder": false,
|
||||
"padTracks": true,
|
||||
"paddingSize": "0",
|
||||
"illegalCharacterReplacer": "_",
|
||||
"queueConcurrency": 3,
|
||||
"maxBitrate": "3",
|
||||
"fallbackBitrate": true,
|
||||
"fallbackSearch": false,
|
||||
"logErrors": true,
|
||||
"logSearched": false,
|
||||
"saveDownloadQueue": false,
|
||||
"overwriteFile": "n",
|
||||
"createM3U8File": false,
|
||||
"playlistFilenameTemplate": "playlist",
|
||||
"syncedLyrics": false,
|
||||
"embeddedArtworkSize": 800,
|
||||
"localArtworkSize": 1400,
|
||||
"localArtworkFormat": "jpg",
|
||||
"saveArtwork": true,
|
||||
"coverImageTemplate": "cover",
|
||||
"saveArtworkArtist": false,
|
||||
"artistImageTemplate": "folder",
|
||||
"jpegImageQuality": 80,
|
||||
"dateFormat": "Y-M-D",
|
||||
"albumVariousArtists": true,
|
||||
"removeAlbumVersion": false,
|
||||
"removeDuplicateArtists": false,
|
||||
"featuredToTitle": "0",
|
||||
"titleCasing": "nothing",
|
||||
"artistCasing": "nothing",
|
||||
"executeCommand": "",
|
||||
"tags": {
|
||||
"title": true,
|
||||
"artist": true,
|
||||
"album": true,
|
||||
"cover": true,
|
||||
"trackNumber": true,
|
||||
"trackTotal": false,
|
||||
"discNumber": true,
|
||||
"discTotal": false,
|
||||
"albumArtist": true,
|
||||
"genre": true,
|
||||
"year": true,
|
||||
"date": true,
|
||||
"explicit": false,
|
||||
"isrc": true,
|
||||
"length": true,
|
||||
"barcode": true,
|
||||
"bpm": true,
|
||||
"replayGain": false,
|
||||
"label": true,
|
||||
"lyrics": false,
|
||||
"copyright": false,
|
||||
"composer": false,
|
||||
"involvedPeople": false,
|
||||
"savePlaylistAsCompilation": false,
|
||||
"useNullSeparator": false,
|
||||
"saveID3v1": true,
|
||||
"multiArtistSeparator": "default",
|
||||
"singleAlbumArtist": false
|
||||
}
|
||||
}
|
|
@ -1,103 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
import json
|
||||
import os.path as path
|
||||
from os import makedirs, listdir, remove
|
||||
from deemix import __version__ as deemixVersion
|
||||
import random
|
||||
import string
|
||||
import logging
|
||||
import datetime
|
||||
import platform
|
||||
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger('deemix')
|
||||
|
||||
import deemix.utils.localpaths as localpaths
|
||||
|
||||
settings = {}
|
||||
defaultSettings = {}
|
||||
configDir = ""
|
||||
|
||||
def initSettings(configFolder = None):
|
||||
global settings
|
||||
global defaultSettings
|
||||
global configDir
|
||||
currentFolder = path.abspath(path.dirname(__file__))
|
||||
if not configFolder:
|
||||
configFolder = localpaths.getConfigFolder()
|
||||
configDir = configFolder
|
||||
makedirs(configFolder, exist_ok=True)
|
||||
with open(path.join(currentFolder, 'default.json'), 'r') as d:
|
||||
defaultSettings = json.load(d)
|
||||
defaultSettings['downloadLocation'] = path.join(localpaths.getHomeFolder(), 'deemix Music')
|
||||
if not path.isfile(path.join(configFolder, 'config.json')):
|
||||
with open(path.join(configFolder, 'config.json'), 'w') as f:
|
||||
json.dump(defaultSettings, f, indent=2)
|
||||
with open(path.join(configFolder, 'config.json'), 'r') as configFile:
|
||||
settings = json.load(configFile)
|
||||
settingsCheck()
|
||||
|
||||
if settings['downloadLocation'] == "":
|
||||
settings['downloadLocation'] = path.join(localpaths.getHomeFolder(), 'deemix Music')
|
||||
saveSettings(settings)
|
||||
makedirs(settings['downloadLocation'], exist_ok=True)
|
||||
|
||||
# logfiles
|
||||
# logfile name
|
||||
logspath = path.join(configFolder, 'logs')
|
||||
now = datetime.datetime.now()
|
||||
logfile = now.strftime("%Y-%m-%d_%H%M%S")+".log"
|
||||
makedirs(logspath, exist_ok=True)
|
||||
# add handler for logfile
|
||||
fh = logging.FileHandler(path.join(logspath, logfile))
|
||||
fh.setLevel(logging.DEBUG)
|
||||
fh.setFormatter(logging.Formatter('%(asctime)s - [%(levelname)s] %(message)s'))
|
||||
logger.addHandler(fh)
|
||||
logger.info(f"{platform.platform(True, True)} - Python {platform.python_version()}, deemix {deemixVersion}")
|
||||
#delete old logfiles
|
||||
logslist = listdir(logspath)
|
||||
logslist.sort()
|
||||
if len(logslist)>5:
|
||||
for i in range(len(logslist)-5):
|
||||
remove(path.join(logspath, logslist[i]))
|
||||
|
||||
return settings
|
||||
|
||||
|
||||
def getSettings():
|
||||
global settings
|
||||
return settings
|
||||
|
||||
|
||||
def getDefaultSettings():
|
||||
global defaultSettings
|
||||
return defaultSettings
|
||||
|
||||
|
||||
def saveSettings(newSettings):
|
||||
global settings
|
||||
settings = newSettings
|
||||
with open(path.join(configDir, 'config.json'), 'w') as configFile:
|
||||
json.dump(settings, configFile, indent=2)
|
||||
return True
|
||||
|
||||
|
||||
def settingsCheck():
|
||||
global settings
|
||||
global defaultSettings
|
||||
changes = 0
|
||||
for x in defaultSettings:
|
||||
if not x in settings or type(settings[x]) != type(defaultSettings[x]):
|
||||
settings[x] = defaultSettings[x]
|
||||
changes += 1
|
||||
for x in defaultSettings['tags']:
|
||||
if not x in settings['tags'] or type(settings['tags'][x]) != type(defaultSettings['tags'][x]):
|
||||
settings['tags'][x] = defaultSettings['tags'][x]
|
||||
changes += 1
|
||||
if changes > 0:
|
||||
saveSettings(settings)
|
||||
|
||||
|
||||
def randomString(stringLength=8):
|
||||
letters = string.ascii_lowercase
|
||||
return ''.join(random.choice(letters) for i in range(stringLength))
|
|
@ -11,14 +11,12 @@ if getenv("APPDATA"):
|
|||
elif sys.platform.startswith('darwin'):
|
||||
userdata = homedata + '/Library/Application Support/deemix/'
|
||||
elif getenv("XDG_CONFIG_HOME"):
|
||||
userdata = getenv("XDG_CONFIG_HOME") + '/deemix/';
|
||||
userdata = getenv("XDG_CONFIG_HOME") + '/deemix/'
|
||||
else:
|
||||
userdata = homedata + '/.config/deemix/';
|
||||
|
||||
userdata = homedata + '/.config/deemix/'
|
||||
|
||||
def getHomeFolder():
|
||||
return homedata
|
||||
|
||||
|
||||
def getConfigFolder():
|
||||
return userdata
|
||||
|
|
|
@ -94,12 +94,3 @@ def uniqueArray(arr):
|
|||
if iPrinc!=iRest and namePrinc.lower() in nRest.lower():
|
||||
del arr[iRest]
|
||||
return arr
|
||||
|
||||
|
||||
def isValidLink(text):
|
||||
if text.lower().startswith("http"):
|
||||
if "deezer.com" in text.lower() or "open.spotify.com" in text.lower():
|
||||
return True
|
||||
elif text.lower().startswith("spotify:"):
|
||||
return True
|
||||
return False
|
||||
|
|
|
@ -3,8 +3,9 @@ from mutagen.flac import FLAC, Picture
|
|||
from mutagen.id3 import ID3, ID3NoHeaderError, TXXX, TIT2, TPE1, TALB, TPE2, TRCK, TPOS, TCON, TYER, TDAT, TLEN, TBPM, \
|
||||
TPUB, TSRC, USLT, APIC, IPLS, TCOM, TCOP, TCMP
|
||||
|
||||
|
||||
# Adds tags to a MP3 file
|
||||
def tagID3(stream, track, save):
|
||||
# Delete exsisting tags
|
||||
try:
|
||||
tag = ID3(stream)
|
||||
tag.delete()
|
||||
|
@ -13,6 +14,7 @@ def tagID3(stream, track, save):
|
|||
|
||||
if save['title']:
|
||||
tag.add(TIT2(text=track['title']))
|
||||
|
||||
if save['artist'] and len(track['artists']):
|
||||
if save['multiArtistSeparator'] != "default":
|
||||
if save['multiArtistSeparator'] == "nothing":
|
||||
|
@ -22,13 +24,16 @@ def tagID3(stream, track, save):
|
|||
tag.add(TXXX(desc="ARTISTS", text=track['artists']))
|
||||
else:
|
||||
tag.add(TPE1(text=track['artists']))
|
||||
|
||||
if save['album']:
|
||||
tag.add(TALB(text=track['album']['title']))
|
||||
|
||||
if save['albumArtist'] and len(track['album']['artists']):
|
||||
if save['singleAlbumArtist'] and track['album']['mainArtist']['save']:
|
||||
tag.add(TPE2(text=track['album']['mainArtist']['name']))
|
||||
else:
|
||||
tag.add(TPE2(text=track['album']['artists']))
|
||||
|
||||
if save['trackNumber']:
|
||||
tag.add(TRCK(
|
||||
text=str(track['trackNumber']) + ("/" + str(track['album']['trackTotal']) if save['trackTotal'] else "")))
|
||||
|
@ -57,6 +62,7 @@ def tagID3(stream, track, save):
|
|||
tag.add(TXXX(desc="REPLAYGAIN_TRACK_GAIN", text=track['replayGain']))
|
||||
if 'unsync' in track['lyrics'] and save['lyrics']:
|
||||
tag.add(USLT(text=track['lyrics']['unsync']))
|
||||
|
||||
involved_people = []
|
||||
for role in track['contributors']:
|
||||
if role in ['author', 'engineer', 'mixer', 'producer', 'writer']:
|
||||
|
@ -66,10 +72,12 @@ def tagID3(stream, track, save):
|
|||
tag.add(TCOM(text=track['contributors']['composer']))
|
||||
if len(involved_people) > 0 and save['involvedPeople']:
|
||||
tag.add(IPLS(people=involved_people))
|
||||
|
||||
if save['copyright']:
|
||||
tag.add(TCOP(text=track['copyright']))
|
||||
if save['savePlaylistAsCompilation'] and "playlist" in track:
|
||||
tag.add(TCMP(text="1"))
|
||||
|
||||
if save['cover'] and track['album']['picPath']:
|
||||
with open(track['album']['picPath'], 'rb') as f:
|
||||
tag.add(
|
||||
|
@ -78,13 +86,16 @@ def tagID3(stream, track, save):
|
|||
tag.save(stream, v1=2 if save['saveID3v1'] else 0, v2_version=3,
|
||||
v23_sep=None if save['useNullSeparator'] else '/')
|
||||
|
||||
|
||||
# Adds tags to a FLAC file
|
||||
def tagFLAC(stream, track, save):
|
||||
# Delete exsisting tags
|
||||
tag = FLAC(stream)
|
||||
tag.delete()
|
||||
tag.clear_pictures()
|
||||
|
||||
if save['title']:
|
||||
tag["TITLE"] = track['title']
|
||||
|
||||
if save['artist'] and len(track['artists']):
|
||||
if save['multiArtistSeparator'] != "default":
|
||||
if save['multiArtistSeparator'] == "nothing":
|
||||
|
@ -94,13 +105,16 @@ def tagFLAC(stream, track, save):
|
|||
tag["ARTISTS"] = track['artists']
|
||||
else:
|
||||
tag["ARTIST"] = track['artists']
|
||||
|
||||
if save['album']:
|
||||
tag["ALBUM"] = track['album']['title']
|
||||
|
||||
if save['albumArtist'] and len(track['album']['artists']):
|
||||
if save['singleAlbumArtist']:
|
||||
tag["ALBUMARTIST"] = track['album']['mainArtist']['name']
|
||||
else:
|
||||
tag["ALBUMARTIST"] = track['album']['artists']
|
||||
|
||||
if save['trackNumber']:
|
||||
tag["TRACKNUMBER"] = str(track['trackNumber'])
|
||||
if save['trackTotal']:
|
||||
|
@ -131,12 +145,14 @@ def tagFLAC(stream, track, save):
|
|||
tag["REPLAYGAIN_TRACK_GAIN"] = track['replayGain']
|
||||
if 'unsync' in track['lyrics'] and save['lyrics']:
|
||||
tag["LYRICS"] = track['lyrics']['unsync']
|
||||
|
||||
for role in track['contributors']:
|
||||
if role in ['author', 'engineer', 'mixer', 'producer', 'writer', 'composer']:
|
||||
if save['involvedPeople'] and role != 'composer' or role == 'composer' and save['composer']:
|
||||
tag[role] = track['contributors'][role]
|
||||
elif role == 'musicpublisher' and save['involvedPeople']:
|
||||
tag["ORGANIZATION"] = track['contributors']['musicpublisher']
|
||||
|
||||
if save['copyright']:
|
||||
tag["COPYRIGHT"] = track['copyright']
|
||||
if save['savePlaylistAsCompilation'] and "playlist" in track:
|
||||
|
|
Loading…
Reference in New Issue