123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- import pickle, os, shutil, pathlib, music_tag
- from protolib import remove_empty_folders, correct_path
- from data import database, config
- class TemplateData(dict):
- def __getitem__(self, key):
- if key in self:
- return super().__getitem__(key)
- else:
- return key
- def get_sync_db_template():
- return {
- 'type': 'sync',
- 'music': {
- 'tracks': {},
- 'blacklist': [],
- 'overwrite': {
- 'metadata': True,
- 'path': True
- }
- },
- 'templates': {
- 'path': '%(album)s by %(albumArtist)s/%(title)s by %(artists)s.%(ext)s',
- 'artist': {
- 'seperator': {
- 'filename': ', ',
- 'metadata': ';'
- }
- }
- }
- }
- def sync(path, callback=None, force_meta_write=False, write_changed_meta=False, update_path=True):
- print('Preparing to sync music library')
- os.makedirs(path, exist_ok=True)
- if os.path.exists(os.path.join(path, 'sync.pkl')):
- print('Loading sync database')
- with open(os.path.join(path, 'sync.pkl'), 'rb') as f:
- db = pickle.load(f)
- else:
- db = get_sync_db_template()
- print('Syncing music library')
- added_files = 0
- updated_meta = 0
- moved_files = 0
- removed_files = 0
- running = True
- for uuid in database['music']:
- print('Preparing to proccess %s' % uuid)
- if callable(callback):
- running = callback(uuid)
- track = database['music'][uuid]
- if uuid in db['music']['blacklist']:
- if uuid in db['music']['tracks']:
- if os.path.exists(os.path.join(path, db['music']['tracks'][uuid]['path'])):
- print('Removing %s' % uuid)
- os.remove(os.path.join(path, db['music']['tracks'][uuid]['path']))
- del db['music']['tracks'][uuid]
- removed_files += 1
- continue
- if uuid not in db['music']['tracks']:
- db['music']['tracks'][uuid] = {
- 'path': track['path']
- }
- if not os.path.exists(os.path.join(path, db['music']['tracks'][uuid]['path'])):
- print('Adding file')
- os.makedirs(os.path.join(path, pathlib.Path(track['path']).parent), exist_ok=True)
- shutil.copyfile(
- os.path.join(
- config['files']['audio']['path'],
- track['path']),
- os.path.join(path, track['path']))
- added_files += 1
- if database['music'][uuid]['artists']:
- file_artists_strs = [database['artists'][artist]['name'] + db['templates']['artist']['seperator']['filename'] for artist in database['music'][uuid]['artists']]
- file_artists_str = ''.join(file_artists_strs)
- file_artists_str = file_artists_str.strip(db['templates']['artist']['seperator']['filename'])
- meta_artists_strs = [database['artists'][artist]['name'] + db['templates']['artist']['seperator']['metadata'] for artist in database['music'][uuid]['artists']]
- meta_artists_str = ''.join(meta_artists_strs)
- meta_artists_str = meta_artists_str.strip(db['templates']['artist']['seperator']['metadata'])
- else:
- file_artists_str = 'Unknown'
- meta_artists_str = None
- if db['music']['overwrite']['metadata'] and (force_meta_write or write_changed_meta):
- print('Updating the metadata')
- file = music_tag.load_file(os.path.join(path, db['music']['tracks'][uuid]['path']))
- overwrote_meta = False
- if database['music'][uuid]['title']:
- if force_meta_write or (write_changed_meta and file['title'] != database['music'][uuid]['title']):
- file['title'] = database['music'][uuid]['title']
- overwrote_meta = True
- if database['music'][uuid]['artists']:
- if force_meta_write or (write_changed_meta and file['artist'] != meta_artists_str):
- file['artist'] = meta_artists_str
- overwrote_meta = True
- if database['music'][uuid]['album']:
- if force_meta_write or (write_changed_meta and file['album'] != database['albums'][database['music'][uuid]['album']]['name']):
- file['album'] = database['albums'][database['music'][uuid]['album']]['name']
- overwrote_meta = True
- if force_meta_write or (write_changed_meta and file['albumartist'] != database['artists'][database['albums'][database['music'][uuid]['album']]['artist']]['name']):
- if database['albums'][database['music'][uuid]['album']]['artist']:
- file['albumartist'] = database['artists'][database['albums'][database['music'][uuid]['album']]['artist']]['name']
- if database['music'][uuid]['genre']:
- if force_meta_write or (write_changed_meta and file['genre'] != database['genres'][database['music'][uuid]['genre']]['name']):
- file['genre'] = database['genres'][database['music'][uuid]['genre']]['name']
- overwrote_meta = True
- if file['artwork']:
- if force_meta_write or not file['artwork'].value:
- cover = (database['music'][uuid]['album'] and database['albums'][database['music'][uuid]['album']]['cover']) or database['music'][uuid]['cover']
- if cover:
- cover_path = os.path.join(config['files']['images']['path'] if config['files']['images']['path'] else config['files']['audio']['path'], database['covers'][cover]['path'])
- with open(cover_path, 'rb') as f:
- file['artwork'] = f.read()
- overwrote_meta = True
- if overwrote_meta:
- print('Writing changes to metadata...')
- file.save()
- updated_meta += 1
- if db['music']['overwrite']['path'] and update_path:
- print('Preparing to move the file')
- data = TemplateData()
- data['title'] = database['music'][uuid]['title'] if database['music'][uuid]['title'] else 'Unknown'
- data['artists'] = file_artists_str
- data['album'] = database['albums'][database['music'][uuid]['album']]['name'] if database['music'][uuid]['album'] else 'Unknown'
- data['albumArtist'] = database['artists'][database['albums'][database['music'][uuid]['album']]['artist']]['name'] if database['music'][uuid]['album'] and database['albums'][database['music'][uuid]['album']]['artist'] else 'Unknown'
- data['ext'] = db['music']['tracks'][uuid]['path'].split('.')[-1]
- new_path: str = db['templates']['path'] % data
- new_path = correct_path(new_path)
- new_path = os.path.relpath(new_path, os.getcwd())
- if db['music']['tracks'][uuid]['path'] == new_path:
- print('Skipped moving file')
- continue
- print('Moving file...')
- os.makedirs(pathlib.Path(path, new_path).parent, exist_ok=True)
- shutil.move(os.path.join(path, db['music']['tracks'][uuid]['path']), os.path.join(path, new_path))
- db['music']['tracks'][uuid]['path'] = new_path
- moved_files += 1
- if not running:
- break
- print('Removing empty folders')
- remove_empty_folders(path)
- print('Added %s tracks' % added_files)
- print('Updated the metadata of %s tracks' % updated_meta)
- print('Moved %s files' % moved_files)
- print('Removed %s files' % removed_files)
- print('Dumping sync database')
- with open(os.path.join(path, 'sync.pkl'), 'wb') as f:
- pickle.dump(db, f)
|