Source

gSharkDown / lib / Cli.py

import os
import sys
import urllib
import subprocess
from progressbar import Bar, ETA, Percentage, FileTransferSpeed, RotatingMarker, ProgressBar
from termcolor import colored
import groove
import termios
import fcntl

class Cli(object):


    def __init__(self, *args, **kwargs):
        self.args = kwargs
        self.pbar = None

    def start(self):
        # Interactive search for a song
        if self.args.get('search'):
            search = ""
            if self.args.get('<term>'):
                search = self.args.get('<term>', False)
                print "Searching for %s" % (search)
                try:
                    groove.init()
                    results = groove.getSearchResultsEx(search.encode('utf-8'))
                    count = 0
                    for song in results:
                        print colored("[%d]" % count, 'white', attrs=['underline']), \
                                colored("::", 'blue'), \
                                colored(song['SongID'], 'blue', attrs=['bold']), \
                            "\t:", colored(song['ArtistName'], 'white', attrs=['bold']), \
                            "-", colored(song['SongName'])
                        count += 1
                        if count % 20 == 0:
                            print colored('More results = c | Stop results = q | Download = d', 'green')
                            key = self.getch()
                            # Continue printing results
                            if key in ['c', 'C']:
                                continue
                            elif key in ['d', 'D']:
                                try:
                                    sid = int(raw_input(colored("Enter Song Number: ", 'white', attrs=['bold'])))
                                    song_selected = results[sid]
                                    filename = song_selected['ArtistName']+'-'+song_selected['SongName']+".mp3"
                                    path = os.path.join(os.getcwd(), filename)
                                    response = groove.getStreamKeyFromSongIDEx(song_selected['SongID'])
                                    playurls = "http://%s/stream.php?streamKey=%s"
                                    songurl = playurls % (response["result"]["%s" % song_selected['SongID']]["ip"],
                                            response["result"]["%s" % song_selected['SongID']]["streamKey"])
                                    self._dlFile(songurl, path)
                                    continue
                                except:
                                    self.return_warning('You must enter an integer')
                                    break
                            else:
                                break
                    print colored("\t\tThis are all %d results" % (count), 'green', attrs=['bold'])
                except:
                    self.return_error("Grooveshark couldn't be initalized")

            else:
                self.return_warning("Nothing to search for")

        # Play a song by songid
        elif self.args.get('play', False):
            songid = None
            player = None
            if self.args.get("<songid>"):
                songid = self.args.get("<songid>", False)
            else:
                self.return_error('No songid specified.')

            if self.args.get("--player", False):
                player = self.args.get('<executable>')
            else:
                self.return_error("No player specified.")

            if songid is not None:
                try:
                    groove.init()
                    response = groove.getStreamKeyFromSongIDEx(songid)
                    playurls = "http://%s/stream.php?streamKey=%s"
                    songurl = playurls % (response['result']['%s' % songid]['ip'],
                            response['result']['%s' % songid]['streamKey'])
                    subprocess.call([player, songurl])
                except Exception:
                    self.return_error("Song with this ID was not found")
                    sys.exit()


        # Download a song by id
        elif self.args.get('download', False):
            songid = ""
            songurl = None
            outfile = ""
            if self.args.get("<songid>"):
                songid = self.args.get("<songid>", False)
                outfile = "%s.mp3" % (str(songid))
                try:
                    groove.init()
                    response = groove.getStreamKeyFromSongIDEx(songid)
                    playurls = "http://%s/stream.php?streamKey=%s"
                    songurl = playurls % (response["result"]["%s" % songid]["ip"],
                               response["result"]["%s" % songid]["streamKey"])
                except Exception:
                    self.return_error("Song with this ID was not found")
                    sys.exit()
            else:
                self.return_warning("You must specify a SongID of the song")
                sys.exit()

            if self.args.get('-o'):
                if self.args.get('<file>'):
                    outfile = self.args.get('<file>', False)

            if songurl is not None:
                self._dlFile(songurl, outfile)


    def _dlFile(self, songurl, path):
        widgets = [colored('Downloading: ', 'blue', attrs=['bold']),
                Percentage(), ' ', Bar(marker=RotatingMarker()), ' ',
                ETA(), ' ', FileTransferSpeed()]
        self.pbar = ProgressBar(widgets=widgets)
        urllib.urlretrieve(songurl, path, reporthook=self._dlProgress)
        self.pbar.finish()



    def _dlProgress(self, count, blockSize, totalSize):
        if self.pbar.maxval is None:
            self.pbar.maxval = totalSize
            self.pbar.start()
        self.pbar.update(min(count*blockSize, totalSize))

    def return_error(self, message):
        print colored("[ERROR] ", 'red', attrs=['bold']) + message + "\n"

    def return_warning(self, message):
        print colored("[WARNING] ", 'yellow', attrs=['bold']) + message + "\n"

    def getch(self):
        fd = sys.stdin.fileno()

        oldterm = termios.tcgetattr(fd)
        newattr = termios.tcgetattr(fd)
        newattr[3] = newattr[3] & ~termios.ICANON & ~termios.ECHO
        termios.tcsetattr(fd, termios.TCSANOW, newattr)

        oldflags = fcntl.fcntl(fd, fcntl.F_GETFL)
        fcntl.fcntl(fd, fcntl.F_SETFL, oldflags | os.O_NONBLOCK)

        try:
            while 1:
                try:
                    c = sys.stdin.read(1)
                    break
                except IOError: pass
        finally:
            termios.tcsetattr(fd, termios.TCSAFLUSH, oldterm)
            fcntl.fcntl(fd, fcntl.F_SETFL, oldflags)
        return c