Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import os, sys, re, json, urllib.request, urllib.parse, urllib.error, threading
- from functools import partial
- from PyQt4 import QtCore, QtGui
- from win32api import GetSystemMetrics
- Dimensions = [512, 512]
- XY = [GetSystemMetrics (i)/2-(Dimensions[i]/2) for i in range(2)] #create window in center of screen
- XY += Dimensions
- class Window(QtGui.QWidget):
- def __init__(self):
- super(Window, self).__init__()
- self.initUI()
- def initUI(self):
- self.setGeometry(*XY)
- self.setFixedSize(*Dimensions)
- self.setWindowTitle("Bandcamp Ripper")
- self.show()
- urlInput = QtGui.QLineEdit(self)
- urlInput.show()
- scanInitialize = QtGui.QPushButton(self)
- scanInitialize.setText("Fetch")
- scanInitialize.show()
- songListDisplay = QtGui.QTreeWidget(self)
- songListDisplay.setHeaderLabels(["Name", "Url", "Download status"])
- songListDisplay.show()
- urlInput.setPlaceholderText("Enter bandcamp album URL")
- toplayout = QtGui.QGridLayout(self)
- toplayout.addWidget(scanInitialize, 0, 0)
- toplayout.addWidget(urlInput, 0, 1)
- mainGroup = QtGui.QGroupBox(self)
- mainGroup.setTitle("URL")
- #mainGroup.setMinimumWidth(512)
- mainGroup.setMinimumHeight(30)
- mainGroup.setLayout(toplayout)
- mainGroup.show()
- ArtistLabel = QtGui.QLabel(self)
- ArtistLabel.setText("Artist")
- FoundArtistLabel = QtGui.QLabel(self)
- FoundArtistLabel.setText("...")
- AlbumLabel = QtGui.QLabel(self)
- AlbumLabel.setText("Album Art")
- FoundAlbumLabel = QtGui.QLabel(self)
- FoundAlbumLabel.setText("...")
- NameLabel = QtGui.QLabel(self)
- NameLabel.setText("Album Name")
- FoundNameLabel = QtGui.QLabel(self)
- FoundNameLabel.setText("...")
- SongLabel = QtGui.QLabel(self)
- SongLabel.setText("Songs")
- FoundSongLabel = QtGui.QLabel(self)
- FoundSongLabel.setText("...")
- objectsFound = QtGui.QGridLayout(self)
- objectsFound.addWidget(ArtistLabel, 0, 0)
- objectsFound.addWidget(FoundArtistLabel, 0, 1)
- objectsFound.addWidget(AlbumLabel, 1, 0)
- objectsFound.addWidget(FoundAlbumLabel, 1, 1)
- objectsFound.addWidget(NameLabel, 2, 0)
- objectsFound.addWidget(FoundNameLabel, 2, 1)
- objectsFound.addWidget(SongLabel, 3, 0)
- objectsFound.addWidget(FoundSongLabel, 3, 1)
- statusBox = QtGui.QGroupBox(self)
- statusBox.setTitle("Album scan status")
- #statusBox.setMinimumWidth(512)
- statusBox.setMinimumHeight(30)
- statusBox.setLayout(objectsFound)
- statusBox.show()
- downloadInitialize = QtGui.QPushButton(self)
- downloadInitialize.setText("Begin Download")
- downloadInitialize.setDisabled(True)
- MAINlayout = QtGui.QGridLayout(self)
- MAINlayout.addWidget(mainGroup, 0, 0)
- MAINlayout.addWidget(statusBox, 1, 0)
- MAINlayout.addWidget(downloadInitialize, 2, 0)
- MAINlayout.addWidget(songListDisplay, 3, 0)
- self.setLayout(MAINlayout)
- def confirm():
- if not re.match("^https?:\/{2}.+\.?[bandcamp]?\.com\/album\/.+$", urlInput.text()): #Test if iput is valid URL
- QtGui.QMessageBox.warning(self, "Error", "Invalid Url\nValid example: http://artist.bandcamp.com/album/albumname")
- else:
- url = str(urlInput.text())
- data = urllib.request.urlopen(url).read()
- toFind = {
- "Artist": {
- "Found": False,
- "Collected": None,
- "Pattern": 'BandData.+?{.+?name: "(.+?)".+?};',
- "Namespace": "artistName",
- "iPath": FoundArtistLabel
- },
- "Art": {
- "Found": False,
- "Collected": None,
- "Pattern": 'TralbumData.+?{.+?artFullsizeUrl: "(.+?)".+?};',
- "Namespace": "artData",
- "iPath": FoundAlbumLabel
- },
- "Album": {
- "Found": False,
- "Collected": None,
- "Pattern": 'EmbedData.+?{.+?album_title: "(.+?)".+?};',
- "Namespace": "albumName",
- "iPath": FoundNameLabel
- },
- "Songs": {
- "Found": False,
- "Collected": None,
- "Pattern": 'trackinfo.+?(\[.+?\])',
- "Namespace": "songsData",
- "iPath": FoundSongLabel
- }
- }
- # I probably shouldn't put this here, but...
- def downloadInit():
- directory = toFind["Album"]["Collected"]+"/"
- if not os.path.exists(directory):
- os.mkdir(directory)
- urllib.request.urlretrieve(toFind["Art"]["Collected"], directory+"Album"+os.path.splitext(toFind["Art"]["Collected"])[1])
- # ^^ download cover art
- def threadedDL():
- root = songListDisplay.invisibleRootItem()
- def subThread(child_):
- rc = root.child(child_)
- rc.setText(2, "Downloading...")
- fileName = "{0} - {1}.mp3".format(toFind["Artist"]["Collected"], rc.text(0))
- urllib.request.urlretrieve("http:"+str(rc.text(1)), directory+fileName)
- rc.setText(2, "Done!")
- for i in range(root.childCount()):
- sub = threading.Thread(target=partial(subThread, i))
- #sub.daemon = True
- sub.start()
- t = threading.Thread(target=threadedDL)
- t.daemon = True
- t.start()
- for subject in toFind:
- try:
- regex_data = re.findall(toFind[subject]["Pattern"], str(data), re.DOTALL)
- if len(regex_data) == 1:
- toFind[subject]["Collected"] = regex_data[0]
- else:
- toFind[subject]["Collected"] = list(reversed(sorted(regex_data,key=len)))[0]
- toFind[subject]["Found"] = True
- toFind[subject]["iPath"].setText("Found!")
- except Exception as e:
- QtGui.QMessageBox.warning(self, "Error", e)
- try:
- toFind["Songs"]["Collected"]=[(str(i["title"]), str(i["file"]['mp3-128'])) for i in json.loads(toFind["Songs"]["Collected"])]
- except Exception as e:
- QtGui.QMessageBox.warning(self, "Error", e)
- # ^^^^ Turn "songs" list into tuples formatted like (name, url)
- #scanInitializees into tree widget below...
- for i in toFind["Songs"]["Collected"]:
- sitem = QtGui.QTreeWidgetItem(list(i) + ["Pending"])
- songListDisplay.addTopLevelItem(sitem)
- downloadInitialize.setDisabled(False)
- downloadInitialize.clicked.connect(downloadInit)
- scanInitialize.clicked.connect(confirm)
- def main():
- ab = QtGui.QApplication(sys.argv)
- ex = Window()
- sys.exit(ab.exec_())
- if __name__ == '__main__':
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement