def _generate_temp_spectral(self, track, filenames): assert len(filenames) == 2 track_path = os.path.join(self.temp_dir, track.temp_filename) logger.info('Generating spectrals for {0}'.format(track.temp_filename)) full_title = '{0} Full'.format(os.path.splitext(track.filename)[0]) zoom_title = '{0} Zoom'.format(os.path.splitext(track.filename)[0]) ensure_file_dir_exists(filenames[0]) ensure_file_dir_exists(filenames[0]) args = [ 'sox', track_path, '-n', 'remix', '1', 'spectrogram', '-x', '3000', '-y', '513', '-w', 'Kaiser', '-t', full_title, '-o', filenames[0] ] if self.high_color: args.append('-h') if call([q_enc(a) for a in args]) != 0: raise Exception('sox returned non-zero') assert track.duration >= 4, 'Track is shorter than 4 seconds' zoom_start = time_text(min(40, track.duration - 4)) args = [ 'sox', track_path, '-n', 'remix', '1', 'spectrogram', '-x', '3000', '-y', '513', '-w', 'Kaiser', '-S', zoom_start, '-d', '0:04', '-t', zoom_title, '-o', filenames[1] ] if self.high_color: args.append('-h') if call([q_enc(a) for a in args]) != 0: raise Exception('sox returned non-zero')
def remove_bad_files(temp_dir): for f in os.listdir(q_enc(temp_dir)): f = q_dec(f) if f.lower() in BAD_FILES: os.remove(q_enc(os.path.join(temp_dir, f))) logger.info('{0} file found. Removing.'.format(f)) os.remove(q_enc(os.path.join(temp_dir, f)))
def _merge_spectrals(paths, dest_path): images = map(Image.open, [q_enc(p) for p in paths]) try: result_width = max(i.size[0] for i in images) result_height = sum(i.size[1] for i in images) result = Image.new('P', (result_width, result_height)) result.putpalette(images[0].getpalette()) current_y = 0 for image in images: result.paste(image, (0, current_y, image.size[0], current_y + image.size[1])) current_y += image.size[1] result.save(q_enc(dest_path), 'PNG') finally: for image in images: image.close()
def stream_reconstruct_download(destination, url): session = requests.Session() session.headers.update({ 'Accept': '*/*', 'Origin': 'http://listen.tidalhifi.com', 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.104 Safari/537.36', }) response = session.options(url) assert response.status_code == 200, 'OPTIONS did not return 200' offset = 0 length = 4 * 2**32 # 4MB chunks with open(q_enc(destination), 'wb') as f: while offset < length: with closing( session.get(url, stream=True, headers={ 'Range': 'bytes={0}-{1}'.format( offset, offset + 2**20 - 1), })) as response: assert response.status_code == 206, 'GET piece did not return 206' length = int(response.headers['Content-Range'].split('/')[1]) offset += int(response.headers['Content-Length']) for chunk in response.iter_content(4096): f.write(chunk)
def _merge_spectrals(paths, dest_path): images = map(Image.open, [q_enc(p) for p in paths]) try: result_width = max(i.size[0] for i in images) result_height = sum(i.size[1] for i in images) result = Image.new('P', (result_width, result_height)) result.putpalette(images[0].getpalette()) current_y = 0 for image in images: result.paste( image, (0, current_y, image.size[0], current_y + image.size[1])) current_y += image.size[1] result.save(q_enc(dest_path), 'PNG') finally: for image in images: image.close()
def load_from_qobuz(self, qobuz_api, temp_dir, album_id): try: qobuz_album = qobuz_api.call('album/get', album_id=album_id) except HTTPError: raise Exception('Couldn\'t fetch Qobuz album.') self.metadata = UploadMetadata() self.metadata.load_from_qobuz(qobuz_api, qobuz_album) self.state = self.STATE_INITIALIZED os.mkdir(q_enc(temp_dir))
def upload_cover(self, temp_dir, username, password, album_id): if hasattr(self.metadata, 'image_url'): raise Exception('Image already uploaded to {0}'.format(self.metadata.image_url)) for image in self.metadata.images: if image.name == 'large': with open(q_enc(os.path.join(temp_dir, image.filename)), 'rb') as f: url = whatimg.upload_image_from_memory(username, password, album_id, f.read()) self.metadata.image_url = url return raise Exception('Qobuz large image not found for uploading')
def make_torrent(self, metadata): try: self.stash_func() remove_bad_files(self.temp_dir) torrent_path = os.path.join(self.temp_dir, metadata.torrent_name + '.torrent') args = [ 'mktorrent', '-a', self.announce, '-p', '-n', metadata.torrent_name, '-o', torrent_path, self.temp_dir ] logger.debug('Executing mktorrent: {0}'.format(args)) if call([q_enc(a) for a in args]) != 0: raise Exception('mktorrent returned non-zero') with open(q_enc(torrent_path), 'rb') as f: torrent_data = f.read() torrent_data = pthify_torrent(torrent_data) with open(q_enc(torrent_path), 'wb') as f: f.write(torrent_data) finally: self.unstash_func()
def load_from_tidal(self, tidal_api, temp_dir, album_id): self.concurrency = 4 try: tidal_album = tidal_api.call('albums', album_id) tidal_tracks = tidal_api.call('albums', album_id, 'tracks') except HTTPError: raise Exception('Couldn\'t fetch Qobuz album.') self.metadata = UploadMetadata() self.metadata.load_from_tidal(tidal_api, tidal_album, tidal_tracks) self.state = self.STATE_INITIALIZED os.mkdir(q_enc(temp_dir))
def upload_new_group(self, release_type_id, tags, title=None, force_artists=False, remaster=False, original_year=None): if not force_artists: self.check_artists() if title is None: title = self.metadata.title if not tags: raise Exception('No tags present') if not hasattr(self.metadata, 'image_url'): raise MissingImageException( 'Image URL not found. Upload the cover.') if remaster: assert original_year, 'You need to specify original year with remaster' payload_files = dict() payload_files['file_input'] = ('torrent.torrent', open(q_enc(self.torrent_file_path), 'rb')) payload = dict() payload['submit'] = 'true' payload['auth'] = self.what_api.authkey payload['type'] = 'Music' payload['artists[]'] = tuple(i.name for i in self.metadata.artists) payload['importance[]'] = tuple(i.artist_type for i in self.metadata.artists) payload['title'] = title if remaster: payload['year'] = original_year payload['record_label'] = '' payload['remaster'] = 'on' payload['remaster_year'] = str(self.metadata.year) payload['remaster_title'] = '' payload['remaster_record_label'] = self.metadata.label payload['remaster_catalogue_number'] = '' else: payload['year'] = str(self.metadata.year) payload['record_label'] = self.metadata.label payload['releasetype'] = str(release_type_id) payload['format'] = 'FLAC' payload['bitrate'] = 'Lossless' payload['media'] = 'WEB' payload['tags'] = tags payload['image'] = self.metadata.image_url payload['album_desc'] = self.metadata.gen_description() payload['release_desc'] = self.get_release_desc() self._perform_upload(payload, payload_files)
def prepare_track(self, album, track): temp_path = os.path.join(self.temp_dir, track.temp_filename) track_path = os.path.join(self.temp_dir, track.filename) meta_file = FLAC(q_enc(temp_path)) meta_file.clear() meta_file['album'] = album.title meta_file['albumartist'] = album.joined_artists meta_file['artist'] = track.joined_artists meta_file['title'] = track.title meta_file['date'] = str(album.year) meta_file['genre'] = album.genre meta_file['tracknumber'] = str(track.track_number) meta_file['totaltracks'] = str(track.track_total) meta_file['discnumber'] = str(track.media_number) meta_file['totaldiscs'] = str(album.media_total) meta_file.save() conditional_rename(temp_path, track_path)
def make_torrent(self, metadata): try: self.stash_func() remove_bad_files(self.temp_dir) torrent_path = os.path.join(self.temp_dir, metadata.torrent_name + '.torrent') args = [ 'mktorrent', '-a', self.announce, '-p', '-n', metadata.torrent_name, '-o', torrent_path, self.temp_dir ] logger.debug('Executing mktorrent: {0}'.format(args)) if call([q_enc(a) for a in args]) != 0: raise Exception('mktorrent returned non-zero') finally: self.unstash_func()
def upload_new_group(self, release_type_id, tags, title=None, force_artists=False, remaster=False, original_year=None): if not force_artists: self.check_artists() if title is None: title = self.metadata.title if not tags: raise Exception('No tags present') if not hasattr(self.metadata, 'image_url'): raise MissingImageException('Image URL not found. Upload the cover.') if remaster: assert original_year, 'You need to specify original year with remaster' payload_files = dict() payload_files['file_input'] = ('torrent.torrent', open(q_enc(self.torrent_file_path), 'rb')) payload = dict() payload['submit'] = 'true' payload['auth'] = self.what_api.authkey payload['type'] = 'Music' payload['artists[]'] = tuple(i.name for i in self.metadata.artists) payload['importance[]'] = tuple(i.artist_type for i in self.metadata.artists) payload['title'] = title if remaster: payload['year'] = original_year payload['record_label'] = '' payload['remaster'] = 'on' payload['remaster_year'] = str(self.metadata.year) payload['remaster_title'] = '' payload['remaster_record_label'] = self.metadata.label payload['remaster_catalogue_number'] = '' else: payload['year'] = str(self.metadata.year) payload['record_label'] = self.metadata.label payload['releasetype'] = str(release_type_id) payload['format'] = 'FLAC' payload['bitrate'] = 'Lossless' payload['media'] = 'WEB' payload['tags'] = tags payload['image'] = self.metadata.image_url payload['album_desc'] = self.metadata.gen_description() payload['release_desc'] = self.get_release_desc() self._perform_upload(payload, payload_files)
def _upload_in_group(self, group_id, remaster): payload_files = dict() payload_files['file_input'] = ('torrent.torrent', open(q_enc(self.torrent_file_path), 'rb')) payload = dict() payload['submit'] = 'true' payload['auth'] = self.what_api.authkey payload['type'] = 'Music' payload['groupid'] = str(group_id) payload['format'] = 'FLAC' payload['bitrate'] = 'Lossless' payload['media'] = 'WEB' payload['release_desc'] = self.get_release_desc() if remaster: payload['remaster'] = 'on' payload['remaster_year'] = remaster['year'] payload['remaster_title'] = remaster['title'] payload['remaster_record_label'] = remaster['record_label'] payload['remaster_catalogue_number'] = remaster['catalogue_number'] self._perform_upload(payload, payload_files)
def stream_reconstruct_download(destination, url): session = requests.Session() session.headers.update({ 'Accept': '*/*', 'Origin': 'http://listen.tidalhifi.com', 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.104 Safari/537.36', }) response = session.options(url) assert response.status_code == 200, 'OPTIONS did not return 200' offset = 0 length = 4 * 2 ** 32 # 4MB chunks with open(q_enc(destination), 'wb') as f: while offset < length: with closing(session.get(url, stream=True, headers={ 'Range': 'bytes={0}-{1}'.format(offset, offset + 2 ** 20 - 1), })) as response: assert response.status_code == 206, 'GET piece did not return 206' length = int(response.headers['Content-Range'].split('/')[1]) offset += int(response.headers['Content-Length']) for chunk in response.iter_content(4096): f.write(chunk)
def conditional_rename(src, dst): if src != dst: logger.debug('Renaming {0} to {1}'.format(src, dst)) shutil.move(q_enc(src), q_enc(dst))
def generate_spectral(self, track): filenames = self.get_filenames(track) self._generate_temp_spectral(track, filenames[0]) self._merge_spectrals(filenames[0], filenames[1]) for temp_spectral in filenames[0]: os.remove(q_enc(temp_spectral))
def __init__(self, temp_dir): if not os.path.exists(q_enc(temp_dir)): raise Exception('Destination directory does not exist.') self.temp_dir = temp_dir
def unstash(self): shutil.move(q_enc(self.stash_dir), q_enc(self.spectrals_dir))
def __init__(self, temp_dir): if os.path.exists(q_enc(temp_dir)): raise Exception('Destination directory already exists. Run clean.') self.concurrency = self.DEFAULT_CONCURRENCY self.metadata = None self.state = None
def do_upload(): resp.append(self.imgur_client.upload_from_path(q_enc(spectral_path)))
def stream_download(destination, response): ensure_file_dir_exists(destination) with open(q_enc(destination), 'wb') as f: for chunk in response.iter_content(4096): f.write(chunk)
def do_upload(): resp.append( self.imgur_client.upload_from_path(q_enc(spectral_path)))
def clean(self, temp_dir): if os.path.exists(q_enc(temp_dir)): shutil.rmtree(q_enc(temp_dir)) self.state = self.STATE_INITIALIZED