Skip to content
This repository has been archived by the owner on Jun 4, 2022. It is now read-only.

This should work #13

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Auto detect text files and perform LF normalization
* text=auto

# Custom for Visual Studio
*.cs diff=csharp
*.sln merge=union
*.csproj merge=union
*.vbproj merge=union
*.fsproj merge=union
*.dbproj merge=union

# Standard to msysgit
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain
169 changes: 169 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
#################
## Eclipse
#################

.pydevproject
.project
.metadata
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.classpath
.settings/
.loadpath

# External tool builders
.externalToolBuilders/

# Locally stored "Eclipse launch configurations"
*.launch

# CDT-specific
.cproject

# PDT-specific
.buildpath


#################
## Visual Studio
#################

## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.

# User-specific files
*.suo
*.user
*.sln.docstates

# Build results
[Dd]ebug/
[Rr]elease/
*_i.c
*_p.c
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.vspscc
.builds
*.dotCover

## TODO: If you have NuGet Package Restore enabled, uncomment this
#packages/

# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf

# Visual Studio profiler
*.psess
*.vsp

# ReSharper is a .NET coding add-in
_ReSharper*

# Installshield output folder
[Ee]xpress

# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html

# Click-Once directory
publish

# Others
[Bb]in
[Oo]bj
sql
TestResults
*.Cache
ClientBin
stylecop.*
~$*
*.dbmdl
Generated_Code #added for RIA/Silverlight projects

# Backup & report files from converting an old project file to a newer
# Visual Studio version. Backup files are not needed, because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML



############
## Windows
############

# Windows image file caches
Thumbs.db

# Folder config file
Desktop.ini


#############
## Python
#############

*.py[co]

# Packages
*.egg
*.egg-info
dist
build
eggs
parts
bin
var
sdist
develop-eggs
.installed.cfg

# Installer logs
pip-log.txt

# Unit test / coverage reports
.coverage
.tox

#Translations
*.mo

#Mr Developer
.mr.developer.cfg

# Mac crap
.DS_Store

#Cookies
*.cookie

#Music
*.mp3
60 changes: 30 additions & 30 deletions dist/compile.py
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
#!/usr/bin/env python
import os
import sys
import shutil
if len(sys.argv) < 2: print "Argument missing."; exit()
dir = sys.argv[1]
sys.argv[1] = "py2exe"
from distutils.core import setup
import py2exe
setup(
windows=[{
"script":"groove.py",
"icon_resources": [(1, "../misc/groove.ico")]
}],
zipfile="modules\library.zip",
options={
"py2exe":{
"dist_dir":dir,
"optimize": 2,
"dll_excludes":["w9xpopen.exe", "win32clipboard.pyd", "MPR.dll"],
"excludes":["email", "doctest", "pdb", "unittest", "difflib", "inspect"],
"compressed":False,
"ignores":["ExampleImages", "ExampleModel", "_scproxy"],
"ascii":False
}
}
)
#!/usr/bin/env python
import os
import sys
import shutil

if len(sys.argv) < 2: print "Argument missing."; exit()
dir = sys.argv[1]
sys.argv[1] = "py2exe"

from distutils.core import setup
import py2exe

setup(
windows=[{
"script":"groove.py",
"icon_resources": [(1, "../misc/groove.ico")]
}],
zipfile="modules\library.zip",
options={
"py2exe":{
"dist_dir":dir,
"optimize": 2,
"dll_excludes":["w9xpopen.exe", "win32clipboard.pyd", "MPR.dll"],
"excludes":["email", "doctest", "pdb", "unittest", "difflib", "inspect"],
"compressed":False,
"ignores":["ExampleImages", "ExampleModel", "_scproxy"],
"ascii":False
}
}
)
94 changes: 47 additions & 47 deletions dist/debian/assist.py
Original file line number Diff line number Diff line change
@@ -1,48 +1,48 @@
import sys
import math
def roundup(x):
return int(math.ceil(x / 512.0)) * 512
def zero(x):
for i in x:
if i != '\0': return False
return True
def checksum(x):
c = 0
for i in x: c += ord(i)
return list(('%06o\0 ' % c))
def tar(f):
uid = ['0']*7 + ['\0']
f = open(f, 'rb+')
c = 0
while (True):
data = list(f.read(512))
if len(data) == 0: break
elif len(data) != 512: print "ERROR"
elif zero(data):
if c == 1: break
c+=1
continue
c = 0
data[108:116] = uid
data[116:124] = uid
data[148:156] = [' ']*8
data[148:156] = checksum(data)
size = roundup(int(''.join(data[124:135]), 8))
f.seek(-512, 1)
f.write(''.join(data))
d = f.seek(size, 1)
f.close()
if sys.argv[1][-3:] == 'tar':
tar(sys.argv[1])
elif sys.argv[1] == 'version':
exec(open("../../python/gui.py", "r").read().split('\n')[1])
f = open('control/control', 'r').read().split('\n')
f[1] = 'Version: %s-1' % version
open('control/control', 'w').write('\n'.join(f))
import sys
import math

def roundup(x):
return int(math.ceil(x / 512.0)) * 512

def zero(x):
for i in x:
if i != '\0': return False
return True

def checksum(x):
c = 0
for i in x: c += ord(i)
return list(('%06o\0 ' % c))

def tar(f):
uid = ['0']*7 + ['\0']
f = open(f, 'rb+')
c = 0
while (True):
data = list(f.read(512))
if len(data) == 0: break
elif len(data) != 512: print "ERROR"
elif zero(data):
if c == 1: break
c+=1
continue
c = 0
data[108:116] = uid
data[116:124] = uid
data[148:156] = [' ']*8
data[148:156] = checksum(data)
size = roundup(int(''.join(data[124:135]), 8))
f.seek(-512, 1)
f.write(''.join(data))
d = f.seek(size, 1)
f.close()


if sys.argv[1][-3:] == 'tar':
tar(sys.argv[1])
elif sys.argv[1] == 'version':
exec(open("../../python/gui.py", "r").read().split('\n')[1])
f = open('control/control', 'r').read().split('\n')
f[1] = 'Version: %s-1' % version
open('control/control', 'w').write('\n'.join(f))

18 changes: 9 additions & 9 deletions dist/debian/control/control
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
Package: groove-dl
Version: 0.97.2-1
Section: python
Priority: optional
Architecture: all
Depends: python (>=2.5), unzip, wget, python-wxgtk2.8
Installed-Size: 124
Maintainer: George Stephanos <gaf.stephanos@gmail.com>
Description: A downloader to Grooveshark's library of music.
Package: groove-dl
Version: 0.97.2-1
Section: python
Priority: optional
Architecture: all
Depends: python (>=2.5), unzip, wget, python-wxgtk2.8
Installed-Size: 124
Maintainer: George Stephanos <gaf.stephanos@gmail.com>
Description: A downloader to Grooveshark's library of music.
18 changes: 9 additions & 9 deletions dist/debian/data/usr/share/applications/groove-dl.desktop
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
[Desktop Entry]
Version=1.0
Name=JTR's Grooveshark Downloader
Comment=Download music from Grooveshark
Exec=groove-dl
Icon=groove-dl
Terminal=false
Type=Application
Categories=Network;
[Desktop Entry]
Version=1.0
Name=JTR's Grooveshark Downloader
Comment=Download music from Grooveshark
Exec=groove-dl
Icon=groove-dl
Terminal=false
Type=Application
Categories=Network;
28 changes: 14 additions & 14 deletions misc/readme.txt
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
Welcome to JTR's Grooveshark downloader!
Follow these instructions to download your favorite songs in no time:
1) Click on groove.
2) Type the name of the song that you want and hit Enter.
3) Double click the song you want, wait till it gets to you.
4) Double click it in the downloads table and your default player will open to play the song.
You will find the downloaded songs in My Music.
If you want to change the destination directory, click "Choose Destination".
Enjoy :)
Downloaded from https://github.com/jacktheripper51/groove-dl
Welcome to JTR's Grooveshark downloader!

Follow these instructions to download your favorite songs in no time:
1) Click on groove.
2) Type the name of the song that you want and hit Enter.
3) Double click the song you want, wait till it gets to you.
4) Double click it in the downloads table and your default player will open to play the song.

You will find the downloaded songs in My Music.
If you want to change the destination directory, click "Choose Destination".

Enjoy :)

Downloaded from https://github.com/jacktheripper51/groove-dl
By George Stephanos <gaf.stephanos@gmail.com>
26 changes: 13 additions & 13 deletions misc/sfxconfig.txt
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
;!@Install@!UTF-8!
Title="JTR's Grooveshark Downloader Installation"
BeginPrompt="Welcome to JTR's Grooveshark Downloader installer."
ExtractDialogText="Please wait..."
ExtractPathText="Please choose the installation path:\nNote: Updates will not work if you change the path to C:\\Program Files"
ExtractTitle="Installing..."
FinishMessage="Installation has completed. An icon is now placed in Start Menu -> All Programs."
GUIFlags="8+32+64+256+2048+4096"
GUIMode="1"
InstallPath="%appdata%\\groove-dl"
AutoInstall="\"%%T\\groove.exe\""
OverwriteMode="0"
Shortcut="Pu, {%%T\\groove.exe}, {}, {}, {A downloader to Grooveshark's music library}, {JTR's Grooveshark Downloader}, {%%T}, {%%T\\groove.exe}, {0}"
;!@Install@!UTF-8!
Title="JTR's Grooveshark Downloader Installation"
BeginPrompt="Welcome to JTR's Grooveshark Downloader installer."
ExtractDialogText="Please wait..."
ExtractPathText="Please choose the installation path:\nNote: Updates will not work if you change the path to C:\\Program Files"
ExtractTitle="Installing..."
FinishMessage="Installation has completed. An icon is now placed in Start Menu -> All Programs."
GUIFlags="8+32+64+256+2048+4096"
GUIMode="1"
InstallPath="%appdata%\\groove-dl"
AutoInstall="\"%%T\\groove.exe\""
OverwriteMode="0"
Shortcut="Pu, {%%T\\groove.exe}, {}, {}, {A downloader to Grooveshark's music library}, {JTR's Grooveshark Downloader}, {%%T}, {%%T\\groove.exe}, {0}"
;!@InstallEnd@!
68 changes: 38 additions & 30 deletions python/groove.py
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@
if sys.version_info[1] >= 6: import json
else: import simplejson as json

_useragent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.56 Safari/536.5"
_useragent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20100101 Firefox/12.0"
_token = None

URL = "grooveshark.com" #The base URL of Grooveshark
@@ -173,7 +173,7 @@ def markStreamKeyOver30Seconds(songID, songQueueID, streamServer, streamKey):
return json.JSONDecoder().decode(gzip.GzipFile(fileobj=(StringIO.StringIO(conn.getresponse().read()))).read())["result"]

#Mark the song as downloaded, hopefully stopping us from getting banned.
def markSongDownloadedEx(streamServer, songID, streamKey):
def markSongDownloadedEx(self, streamServer, songID, streamKey):
p = {}
p["parameters"] = {}
p["parameters"]["streamServerID"] = streamServer
@@ -188,50 +188,58 @@ def markSongDownloadedEx(streamServer, songID, streamKey):
conn.request("POST", "/more.php?" + p["method"], json.JSONEncoder().encode(p), jsqueue[3])
return json.JSONDecoder().decode(gzip.GzipFile(fileobj=(StringIO.StringIO(conn.getresponse().read()))).read())["result"]

if __name__ == "__main__":
if len(sys.argv) < 2: #Check if we were passed more than 1 parameters
import gui
gui.main() #Open the gui
exit() #Close the command line
print entrystring #Print the welcome message
def init():
print entrystring
print "Initializing..."
getToken() #Get a static token
i = ' '.join(sys.argv[1:]) #Get the search parameter
#i = raw_input("Search: ") #Same as above, if you uncomment this, and comment the first 4 lines this can be run entirely from the command line.
print "Searching for '%s'..." % i
m = 0
s = getResultsFromSearch(i) #Get the result from the search
l = [('%s: "%s" by "%s" (%s)' % (str(m+1), l["SongName"], l["ArtistName"], l["AlbumName"])) for m,l in enumerate(s[:10])] #Iterate over the 10 first returned items, and add a tring to a list.
if l == []: #If the result was empty print a message and exit
print "No results found"
exit()
else:
print '\n'.join(l) #Print the results
songid = raw_input("Enter the Song ID you wish to download or (q) to exit: ") #Ask for input as to what we shoudl download

def search(string):
print "Searching for '%s'..." % string
s = getResultsFromSearch(string) #Get the result from the search
return s

def download(search, songid):
if songid == "" or songid == "q": exit() #Exit if choice is empty or q
songid = eval(songid)-1 #Turn it into an int ans subtract one to fit it to the list index
songid = int(songid) #Turn it into an int ans subtract one to fit it to the list index
queueID = getQueueID() #Get the queue ID
print "Adding song to player Queue"
addSongsToQueue(s[songid], queueID) #Add the song to the queue
addSongsToQueue(search[songid], queueID) #Add the song to the queue
print "Retrieving stream key.."
stream = getStreamKeyFromSongIDs(s[songid]["SongID"]) #Get the StreamKey for the selected song
stream = getStreamKeyFromSongIDs(search[songid]["SongID"]) #Get the StreamKey for the selected song
for k,v in stream.iteritems():
stream=v
stream=v
if stream == []:
print "Failed"
exit()
print "Starting timer" #Probably not needed, but i if the download takes over 30 seconds, why not? starts a timer that report the song as being played 30 seconds though if the download takes more than 30-35 seconds
markTimer = threading.Timer(30 + random.randint(0,5), markStreamKeyOver30Seconds, [s[songid]["SongID"], str(queueID), stream["ip"], stream["streamKey"]])
markTimer = threading.Timer(30 + random.randint(0,5), markStreamKeyOver30Seconds, [search[songid]["SongID"], str(queueID), stream["ip"], stream["streamKey"]])
markTimer.start()
cmd = 'wget --post-data=streamKey=%s -O "%s - %s.mp3" "http://%s/stream.php"' % (stream["streamKey"], s[songid]["ArtistName"], s[songid]["SongName"], stream["ip"]) #Run wget to download the song
cmd = 'wget --post-data=streamKey=%s -O "%s - %s.mp3" "http://%s/stream.php"' % (stream["streamKey"], search[songid]["ArtistName"], search[songid]["SongName"], stream["ip"]) #Run wget to download the song
p = subprocess.Popen(cmd, shell=True)
try:
p.wait()#Wait for wget to finish
print "Marking download as complete"
markSongDownloadedEx(stream["ip"], s[songid]["SongID"], stream["streamKey"]) #This is the important part, hopefully this will stop grooveshark from banning us (and take the load off their server) Mark the song as being downloaded
markSongDownloadedEx(stream["ip"], search[songid]["SongID"], stream["streamKey"]) #This is the important part, hopefully this will stop grooveshark from banning us (and take the load off their server) Mark the song as being downloaded
except KeyboardInterrupt: #If we are interrupted by the user
os.remove('%s - %s.mp3' % (s[songid]["ArtistName"], s[songid]["SongName"])) #Delete the song
os.remove('%s - %s.mp3' % (search[songid]["ArtistName"], search[songid]["SongName"])) #Delete the song
print "Marking download as complete"
markSongDownloadedEx(stream["ip"], s[songid]["SongID"], stream["streamKey"]) #We do it here to be sure
markSongDownloadedEx(stream["ip"], search[songid]["SongID"], stream["streamKey"]) #We do it here to be sure

print "\nDownload cancelled. File deleted."
#Natural Exit

if __name__ == "__main__":
#if len(sys.argv) < 2: #Check if we were passed more than 1 parameters
# import gui
# gui.main() #Open the gui
# exit() #Close the command line
init()
#i = ' '.join(sys.argv[1:]) #Get the search parameter
i = raw_input("Search: ")
s = search(i)
l = [('%s: "%s" by "%s" (%s)' % (str(m+1), l["SongName"], l["ArtistName"], l["AlbumName"])) for m,l in enumerate(s[:10])]
if l == []:
print "No results found"
exit()
else:
print '\n'.join(l)
download(s, raw_input("Select a song, q to exit: "))
291 changes: 291 additions & 0 deletions python/groovylib/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,291 @@
import urllib2
import json
import string
import hashlib
import uuid
import os
import cookielib
import gzip
import StringIO
import random
import re
import math
import time
import downloadHandler
from urlgrabber.keepalive import HTTPHandler

class grooveshark:
'''Handles all the network stuff'''

downloader = downloadHandler.downloadHandler()

URL = "https://grooveshark.com"
USERAGENT = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20100101 Firefox/12.0"
COOKIEFILE = "groovy.cookie"

jsQueue = {}
jsQueue["client"] = "jsqueue"
jsQueue["clientRevision"] = "20120312.08"
jsQueue["secret"] = "circlesAndSquares"
jsQueue["headers"] = {
"User-Agent":USERAGENT,
"Host":"grooveshark.com",
"Accept-Encoding":"gzip, deflate",
"Content-Type":"application/json",
"Accept-Language":"da,en-us;q=0.7,en;q=0.3"
}

htmlshark = {}
htmlshark["client"] = "htmlshark"
htmlshark["clientRevision"] = "20120312"
htmlshark["secret"] = "reallyHotSauce"
htmlshark["headers"] = {
"User-Agent":USERAGENT,
"Host":"grooveshark.com",
"Accept-Encoding":"gzip, deflate",
"Content-Type":"application/json",
"Accept-Language":"da,en-us;q=0.7,en;q=0.3"
}

#Setting the static header (Country, session and uuid)
h = {}
h["country"] = {}
h["country"]["CC1"] = 72057594037927940
h["country"]["CC2"] = 0
h["country"]["CC3"] = 0
h["country"]["CC4"] = 0
h["country"]["ID"] = 57
h["country"]["IPR"] = 0
h["privacy"] = 0
h["uuid"] = str.upper(str(uuid.uuid4()))

token = None
session = None
userTrackingID = None
queueID = None
cj = None
tokenExpires = None

def __init__(self):
self.installHandlers()
self.getSession()
self.doCrossdomainRequest()
self.getToken()
self.getCountry()
self.generateQueueID()

def installHandlers(self):
global cj
#Install support for KeepAlive and HTTP/1.1, via urlgrabber (older versions)
keepalive_handler = HTTPHandler()
opener = urllib2.build_opener(keepalive_handler)
urllib2.install_opener(opener)

#Install cookielib for easy cookie management
self.cj = cookielib.LWPCookieJar()
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(self.cj))
urllib2.install_opener(opener)

#Proxy stuff, used for testing, might be added at a later date
#proxy = urllib2.ProxyHandler({"https":"119.252.160.34:8000"})
#opener = urllib2.build_opener(proxy)
#urllib2.install_opener(opener)

def parseMainPage(self, html):
global userTrackingID
matchObj = re.search(r'"userTrackingID":[^}]*', html, re.I|re.M)
if matchObj:
matchObj = re.search(r"[0123456789]+", matchObj.group(), re.I|re.M)
if matchObj:
self.userTrackingID = matchObj.group()
return
raise SyntaxError("TrackingID not found")

def readSession(self):
for cookie in self.cj:
if cookie.name == "PHPSESSID":
session = cookie.value
return session
return

def doCrossdomainRequest(self):
req = urllib2.Request(self.URL + "/crossdomain.xml?20120312.08")
page = urllib2.urlopen(req)
page.read()

def getSession(self):
global session

if os.path.isfile(self.COOKIEFILE):
self.cj.load(self.COOKIEFILE)
req = urllib2.Request(self.URL)
page = urllib2.urlopen(req)
self.parseMainPage(page.read())
self.session = self.readSession()
self.cj.save(self.COOKIEFILE)

def getCountry(self):
p = {}
p["header"] = {}
p["header"]["session"] = self.session
p["header"]["client"] = self.jsQueue["client"]
p["header"]["clientRevision"] = self.jsQueue["clientRevision"]
p["header"]["token"] = self.generateToken("getCountry", self.jsQueue["secret"])
p["header"]["privacy"] = self.h["privacy"]
p["header"]["uuid"] = self.h["uuid"]
p["method"] = "getCountry"
p["parameters"] = {}
page = urllib2.urlopen(self.createRequest(p, self.jsQueue))
self.h["country"] = json.JSONDecoder().decode(gzip.GzipFile(fileobj=(StringIO.StringIO(page.read()))).read())["result"]


def createHeader(self, data, client, method = None):
data["header"] = self.h
data["header"]["session"] = self.session
data["header"]["client"] = client["client"]
data["header"]["clientRevision"] = client["clientRevision"]
if method:
data["header"]["token"] = self.generateToken(method, client["secret"])
data["method"] = method
return data

def createRequest(self, data, client):
return urllib2.Request(self.URL + "/more.php?" + data["method"], json.JSONEncoder().encode(data), client["headers"])

def generateQueueID(self):
global queueID
part1 = self.userTrackingID + str(math.floor(time.time()))
part2 = str(math.floor(random.random() * 500))
while len(part2)<3:
part2 = "0" + part2
self.queueID = part1 + part2

def generateToken(self, methodName, secret):
if (self.tokenExpires and self.tokenExpires > time.time()):
rnd = (''.join(random.choice(string.hexdigits) for x in range(6))).lower()
return rnd + hashlib.sha1('%s:%s:%s:%s' % (methodName, self.token, secret, rnd)).hexdigest()
else:
self.getToken()
return self.generateToken(methodName, secret)

def getToken(self):
global token, tokenExpires
p = {}
p["parameters"] = {}
p["parameters"]["secretKey"] = hashlib.md5(self.session).hexdigest()
p["method"] = "getCommunicationToken"
p = self.createHeader(p, self.htmlshark)
page = urllib2.urlopen(self.createRequest(p, self.htmlshark))
result = json.JSONDecoder().decode(gzip.GzipFile(fileobj=(StringIO.StringIO(page.read()))).read())["result"]
if result:
self.tokenExpires = time.time() + (60 * 25)
self.token = result
else:
raise KeyError("Couldn't get token")

def getResultsFromSearch(self, query, what="Songs"):
p = {}
p["parameters"] = {}
p["parameters"]["type"] = what
p["parameters"]["query"] = query
p = self.createHeader(p, self.htmlshark, "getResultsFromSearch")
page = urllib2.urlopen(self.createRequest(p, self.htmlshark))
j = json.JSONDecoder().decode(gzip.GzipFile(fileobj=(StringIO.StringIO(page.read()))).read())
try:
return j["result"]["result"]["Songs"]
except:
return j["result"]["result"]

def getStreamKeyFromSongIDEx(self, id):
p = {}
p["parameters"] = {}
p["parameters"]["type"] = 0
p["parameters"]["mobile"] = False
p["parameters"]["prefetch"] = False
p["parameters"]["songID"] = id
p["parameters"]["country"] = self.h["country"]
p = self.createHeader(p, self.jsQueue, "getStreamKeyFromSongIDEx")
page = urllib2.urlopen(self.createRequest(p, self.jsQueue))
return json.JSONDecoder().decode(gzip.GzipFile(fileobj=(StringIO.StringIO(page.read()))).read())["result"]

def addSongsToQueue(self, songObj, source = "user"):
queueObj = {}
queueObj["songID"] = songObj["SongID"]
queueObj["artistID"] = songObj["ArtistID"]
queueObj["source"] = source
queueObj["songQueueSongID"] = 1

p = {}
p["parameters"] = {}
p["parameters"]["songIDsArtistIDs"] = []
p["parameters"]["songIDsArtistIDs"].append(queueObj)
p["parameters"]["songQueueID"] = self.queueID
p = self.createHeader(p, self.jsQueue, "addSongsToQueue")
page = urllib2.urlopen(self.createRequest(p, self.jsQueue))
return json.JSONDecoder().decode(gzip.GzipFile(fileobj=(StringIO.StringIO(page.read()))).read())["result"]

def removeSongsFromQueue(self, userRemoved = True):
p = {}
p["parameters"] = {}
p["parameters"]["songQueueID"] = self.queueID
p["parameters"]["userRemoved"] = True
p["parameters"]["songQueueSongIDs"]=[1]
p = self.createHeader(p, self.jsQueue, "removeSongsFromQueue")
page = urllib2.urlopen(self.createRequest(p, self.jsQueue))
return json.JSONDecoder().decode(gzip.GzipFile(fileobj=(StringIO.StringIO(page.read()))).read())["result"]

def markSongDownloadedEx(self, streamServer, songID, streamKey):
p = {}
p["parameters"] = {}
p["parameters"]["streamServerID"] = streamServer
p["parameters"]["songID"] = songID
p["parameters"]["streamKey"] = streamKey
p = self.createHeader(p, self.jsQueue, "markSongDownloadedEx")
page = urllib2.urlopen(self.createRequest(p, self.jsQueue))
return json.JSONDecoder().decode(gzip.GzipFile(fileobj=(StringIO.StringIO(page.read()))).read())["result"]

def markSongQueueSongPlayed(self, streamServerID, streamKey, songID):
p = {}
p["parameters"] = {}
p["parameters"]["streamServerID"] = streamServerID
p["parameters"]["streamKey"] = streamKey
p["parameters"]["songQueueSongID"] = 1
p["parameters"]["songQueueID"] = self.queueID
p["parameters"]["songID"] = songID
p = self.createHeader(p, self.jsQueue, "markSongQueueSongPlayed")
page = urllib2.urlopen(self.createRequest(p, self.jsQueue))
return json.JSONDecoder().decode(gzip.GzipFile(fileobj=(StringIO.StringIO(page.read()))).read())["result"]

def download(self, search, choice, callBack = None):
try:
songid = int(choice)
except:
raise SyntaxError("Failed to convert choice to int")


self.addSongsToQueue(search[songid]) #Add the song to the queue

stream = self.getStreamKeyFromSongIDEx(search[songid]["SongID"]) #Get the StreamKey for the selected song
if stream == None:
raise Exception("StreamKey not found")

#markTimer = threading.Timer(30 + random.randint(0,5), self.markStreamKeyOver30Seconds, [search[choice]["SongID"], str(self.queueID), stream["ip"], stream["streamKey"]])
#markTimer.start()
data = {"streamKey":stream["streamKey"]}
headers = {"Accept-Encoding":"gzip, deflate", "Host":stream["ip"], "User-Agent":self.USERAGENT}
try:


self.markSongDownloadedEx(stream["ip"], search[songid]["SongID"], stream["streamKey"])

self.downloader.download(("http://%s/stream.php" % (stream["ip"])), ("%s - %s.mp3" % (search[songid]["ArtistName"], search[songid]["SongName"])), data, headers, callBack)

self.markSongQueueSongPlayed(stream["ip"], stream["streamKey"], search[songid]["SongID"])

self.removeSongsFromQueue()

except KeyboardInterrupt:

os.remove('%s - %s.mp3' % (search[songid]["ArtistName"], search[songid]["SongName"]))

self.markSongDownloadedEx(stream["ip"], search[songid]["SongID"], stream["streamKey"])
28 changes: 28 additions & 0 deletions python/groovylib/downloadHandler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import urllib2, urllib
class downloadHandler():
"""downloading files"""

def __init__(self):
pass

def download(self, url, outFile, data = {}, headers = {}, callBack = None):
data = urllib.urlencode(data)
req = urllib2.Request(url, data, headers)
u = urllib2.urlopen(req)
f = open(outFile, 'wb')
meta = u.info()
file_size = int(meta.getheaders("Content-Length")[0])
print "Downloading: %s Bytes: %s" % (outFile, file_size)

file_size_dl = 0
block_sz = 8192
while True:
buffer = u.read(block_sz)
if not buffer:
break

file_size_dl += len(buffer)
f.write(buffer)
if callBack:
callBack(file_size_dl, file_size)
f.close()
18 changes: 18 additions & 0 deletions python/groovylib/example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import groovylib

nh = groovylib.grooveshark()

s = nh.getResultsFromSearch(raw_input("Search Term: "))
i = 0
for item in s:
i = i + 1
print str(i) + ": " + item["ArtistName"] + " - " + item["SongName"]
if i == 10:
break

def reporter(downloaded, size):
status = r"%10d [%3.2f%%]" % (downloaded, downloaded * 100. / size)
status = status + chr(8)*(len(status)+1)
print status

nh.download(s, int(raw_input("Please Select: ")) - 1, reporter)
30 changes: 30 additions & 0 deletions python/groovylib/groovylib.pyproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{0543ac44-e5fe-4af0-adb1-40d1957bba69}</ProjectGuid>
<ProjectHome>.</ProjectHome>
<StartupFile>example.py</StartupFile>
<SearchPath>
</SearchPath>
<WorkingDirectory>.</WorkingDirectory>
<OutputPath>.</OutputPath>
<Name>groovylib</Name>
<RootNamespace>groovylib</RootNamespace>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DebugSymbols>true</DebugSymbols>
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DebugSymbols>true</DebugSymbols>
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
</PropertyGroup>
<ItemGroup>
<Compile Include="downloadHandler.py" />
<Compile Include="example.py" />
<Compile Include="groovylib.py" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.Common.targets" />
</Project>
18 changes: 18 additions & 0 deletions python/groovylib/groovylib.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{888888A0-9F3D-457C-B088-3A5042F75D52}") = "groovylib", "groovylib.pyproj", "{0543AC44-E5FE-4AF0-ADB1-40D1957BBA69}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{0543AC44-E5FE-4AF0-ADB1-40D1957BBA69}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0543AC44-E5FE-4AF0-ADB1-40D1957BBA69}.Release|Any CPU.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
1,022 changes: 511 additions & 511 deletions python/gui.py

Large diffs are not rendered by default.