Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python
- try:
- # python3
- from urllib.request import urlopen, urlretrieve
- from urllib.parse import urlparse, urlencode, urlunparse
- except ImportError:
- # python2
- from urllib import urlencode, urlretrieve
- from urllib2 import urlopen
- from urlparse import urlparse, urlunparse
- import argparse
- import json
- import sys
- import os
- import re
- from PySide.QtCore import *
- from PySide.QtGui import *
- BASEDIR = os.path.dirname(os.path.realpath(__file__))
- CONFIG_NAME = 'config'
- class Logger(object):
- """ Logging information to console or other sources (TODO) """
- def __init__(self, console=True):
- super(Logger, self).__init__()
- self.console = console
- def notify(self, message, end='\n'):
- if self.console:
- # sys.stdout.flush()
- sys.stdout.write('%s%s' % (message, end))
- else:
- pass
- class StereoSong(object):
- """ Song implementation """
- def __init__(self, song):
- super(StereoSong, self).__init__()
- self.uuid = song['uuid']
- self.artist = song["artist"]
- self.title = song["songtitle"]
- self.name = self.__get_name()
- self.__percent = 0.0
- def __get_name(self):
- """ Building name for song """
- return re.sub(r'[/]', r'|', "{} - {}".format(self.artist, self.title))
- def get_url(self, client_id):
- """ Building url for song """
- return 'https://api.soundcloud.com/tracks/{}/stream?client_id={}'.format(self.uuid, client_id)
- @property
- def percent(self):
- return self.__percent
- @percent.setter
- def percent(self, value):
- self.__percent = min(100, max(0, value))
- class Config(object):
- """ Config model for StereodoseHandler """
- def __init__(self, logger):
- super(Config, self).__init__()
- self.__logger = logger
- self.__dict__.update(self.get_config())
- def get_client_id(self):
- """ Getting client_id from site for downloading songs """
- with urlopen('https://www.stereodose.com') as data:
- match = re.search(r'var\s+sc_client_id\s*=\s*"(\w+)";',
- data.read().decode(sys.getdefaultencoding()))
- return match.group(1) if match else str()
- def generate_config(self):
- """ Generating default config """
- self.__logger.notify('Generating config')
- songs_dir = os.path.join(BASEDIR, 'songs')
- # Creating songs directory if dont exists
- if not os.path.exists(songs_dir):
- self.__logger.notify('Creating songs directory')
- os.makedirs(songs_dir)
- default = dict(
- songs_directory=songs_dir,
- client_id=get_client_id()
- )
- # Writing default key = value to config file
- with open(os.path.join(BASEDIR, CONFIG_NAME), 'w') as config:
- for key, value in default.items():
- config.write('{key} = {value}\n'.format(key=key, value=value))
- def get_config(self):
- """ Reading and build config from file """
- config_path = os.path.join(BASEDIR, CONFIG_NAME)
- # Creating config file
- if not os.path.exists(config_path):
- generate_config()
- # Reading config file, then building dict from list of tuple (key,
- # value)
- with open(config_path) as config_file:
- config = config_file.read()
- match = re.findall(r'(\S+)\s*=\s*(\S+)', config, re.M)
- return dict(match)
- class StereodoseHandler(object):
- """ Simple API for stereodose """
- def __init__(self, url, logger):
- super(StereodoseHandler, self).__init__()
- self.url = url
- self.__config = Config(logger)
- self.__logger = logger
- self.songs = self.generate_songs()
- def generate_songs(self):
- self.__logger.notify('Building songs list')
- with urlopen(self.url) as data:
- result = data.read().decode(sys.getdefaultencoding())
- def get_song_array():
- match = re.search(r'var\s+songarray\s*=\s*(.+?);', result)
- return json.loads(match.group(1)) if match else list()
- songs = [StereoSong(song) for song in get_song_array()]
- return songs
- def download_songs(self):
- songs_dir = self.__config.songs_directory
- for song in self.songs:
- self.__logger.notify('Downloading: {}'.format(song.name))
- songs_path = os.path.join(songs_dir, song.name)
- if os.path.isfile(songs_path):
- self.__logger.notify('Here already'.format(song.name))
- continue
- try:
- self.download_song(song)
- except ValueError:
- os.remove(songs_path)
- def download_song(self, song):
- songs_path = os.path.join(self.__config.songs_directory, song.name)
- data = urlopen(song.get_url(self.__config.client_id))
- with open(songs_path, 'wb') as file:
- meta = data.info()
- file_size = int(meta.get("Content-Length"))
- file_size_dl, block_sz = 0, 8192
- while True:
- buffer = data.read(block_sz)
- if not buffer:
- break
- file_size_dl += len(buffer)
- file.write(buffer)
- status = file_size_dl * 100.0 / file_size
- song.percent = status
- class StereodoseGui(QWidget):
- """ GUI class for StereodoseHandler """
- def __init__(self, app):
- super(StereodoseGui, self).__init__()
- self.qt_app = app
- self.setMinimumSize(400, 185)
- self.setWindowTitle('Stereodose Downloader')
- def run(self):
- """ Show application window and start the main event loop """
- self.show()
- self.qt_app.exec_()
- def main():
- arg_parser = argparse.ArgumentParser()
- arg_parser.add_argument('-p', '--playlist', action='store')
- args = arg_parser.parse_args()
- if args.playlist:
- logger = Logger()
- sd = StereodoseHandler(args.playlist, logger)
- sd.download_songs()
- else:
- qt_app = QApplication(sys.argv)
- StereodoseGui(qt_app).run()
- if __name__ == '__main__':
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement