Downloading tracks
This commit is contained in:
39
gui/gui.py
39
gui/gui.py
@@ -176,7 +176,7 @@ class Ui_MainWindow(object):
|
||||
self.edit_second_pads_collection_lay.addWidget(self.edit_second_pads_collection_label)
|
||||
self.edit_second_pads_collection_list = QtWidgets.QListWidget(self.edit_second_pads_collection_widget)
|
||||
self.edit_second_pads_collection_list.setStyleSheet("font: 15pt \"Segoe UI\";")
|
||||
self.edit_second_pads_collection_list.setEditTriggers(QtWidgets.QAbstractItemView.DoubleClicked|QtWidgets.QAbstractItemView.EditKeyPressed|QtWidgets.QAbstractItemView.SelectedClicked)
|
||||
self.edit_second_pads_collection_list.setEditTriggers(QtWidgets.QAbstractItemView.AllEditTriggers)
|
||||
self.edit_second_pads_collection_list.setDragEnabled(True)
|
||||
self.edit_second_pads_collection_list.setObjectName("edit_second_pads_collection_list")
|
||||
self.edit_second_pads_collection_lay.addWidget(self.edit_second_pads_collection_list)
|
||||
@@ -327,6 +327,39 @@ class Ui_MainWindow(object):
|
||||
self.content.addWidget(self.collab_page)
|
||||
self.download_page = QtWidgets.QWidget()
|
||||
self.download_page.setObjectName("download_page")
|
||||
self.download_page_lay = QtWidgets.QVBoxLayout(self.download_page)
|
||||
self.download_page_lay.setContentsMargins(0, 0, 0, 0)
|
||||
self.download_page_lay.setObjectName("download_page_lay")
|
||||
self.download_url_box = QtWidgets.QLineEdit(self.download_page)
|
||||
self.download_url_box.setMinimumSize(QtCore.QSize(0, 35))
|
||||
self.download_url_box.setObjectName("download_url_box")
|
||||
self.download_page_lay.addWidget(self.download_url_box)
|
||||
self.download_path_widget = QtWidgets.QWidget(self.download_page)
|
||||
self.download_path_widget.setObjectName("download_path_widget")
|
||||
self.download_path_widget_lay = QtWidgets.QHBoxLayout(self.download_path_widget)
|
||||
self.download_path_widget_lay.setContentsMargins(0, 0, 0, 0)
|
||||
self.download_path_widget_lay.setObjectName("download_path_widget_lay")
|
||||
self.download_to_path_box = QtWidgets.QLineEdit(self.download_path_widget)
|
||||
self.download_to_path_box.setMinimumSize(QtCore.QSize(0, 35))
|
||||
self.download_to_path_box.setObjectName("download_to_path_box")
|
||||
self.download_path_widget_lay.addWidget(self.download_to_path_box)
|
||||
self.choose_download_path_button = QtWidgets.QPushButton(self.download_path_widget)
|
||||
self.choose_download_path_button.setMinimumSize(QtCore.QSize(100, 35))
|
||||
self.choose_download_path_button.setObjectName("choose_download_path_button")
|
||||
self.download_path_widget_lay.addWidget(self.choose_download_path_button)
|
||||
self.download_page_lay.addWidget(self.download_path_widget)
|
||||
self.download_track_button = QtWidgets.QPushButton(self.download_page)
|
||||
self.download_track_button.setMinimumSize(QtCore.QSize(0, 35))
|
||||
self.download_track_button.setObjectName("download_track_button")
|
||||
self.download_page_lay.addWidget(self.download_track_button)
|
||||
self.download_track_logs = QtWidgets.QTextBrowser(self.download_page)
|
||||
self.download_track_logs.setObjectName("download_track_logs")
|
||||
self.download_page_lay.addWidget(self.download_track_logs)
|
||||
self.download_track_progress = QtWidgets.QProgressBar(self.download_page)
|
||||
self.download_track_progress.setProperty("value", 0)
|
||||
self.download_track_progress.setTextVisible(False)
|
||||
self.download_track_progress.setObjectName("download_track_progress")
|
||||
self.download_page_lay.addWidget(self.download_track_progress)
|
||||
self.content.addWidget(self.download_page)
|
||||
self.settings_page = QtWidgets.QWidget()
|
||||
self.settings_page.setObjectName("settings_page")
|
||||
@@ -578,6 +611,10 @@ class Ui_MainWindow(object):
|
||||
self.collections_page_tabs.setTabText(self.collections_page_tabs.indexOf(self.edit_collections_tabs), _translate("MainWindow", "Edit collections"))
|
||||
self.to_stream_url_box.setPlaceholderText(_translate("MainWindow", "URL (direct web file, YouTube or spotify link) or path to file"))
|
||||
self.play_stream_button.setText(_translate("MainWindow", "Play"))
|
||||
self.download_url_box.setPlaceholderText(_translate("MainWindow", "URL (direct web file, YouTube or spotify link) or path to file"))
|
||||
self.download_to_path_box.setPlaceholderText(_translate("MainWindow", "File download folder"))
|
||||
self.choose_download_path_button.setText(_translate("MainWindow", "Choose path"))
|
||||
self.download_track_button.setText(_translate("MainWindow", "Download"))
|
||||
self.play_options_group.setTitle(_translate("MainWindow", "Play options"))
|
||||
self.output_device_play_label.setText(_translate("MainWindow", "Output device (or virtual mic input)"))
|
||||
self.preview_device_play_label.setText(_translate("MainWindow", "Preview device (your headphones)"))
|
||||
|
||||
116
gui/gui.ui
116
gui/gui.ui
@@ -301,6 +301,20 @@ QSlider::handle:horizontal:hover {
|
||||
QSlider::handle:horizontal:pressed {
|
||||
background-color: #bfbfbf;
|
||||
}
|
||||
|
||||
QProgressBar {
|
||||
text-align: center;
|
||||
color: white;
|
||||
border-width: 1px;
|
||||
border-radius: 10px;
|
||||
border-color: #3a3a3a;
|
||||
border-style: inset;
|
||||
background-color:#202020;
|
||||
}
|
||||
QProgressBar::chunk {
|
||||
background-color: #848484;
|
||||
border-radius: 5px;
|
||||
}
|
||||
</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
@@ -690,7 +704,7 @@ QListWidget:item:selected {
|
||||
<string notr="true">font: 15pt "Segoe UI";</string>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed|QAbstractItemView::SelectedClicked</set>
|
||||
<set>QAbstractItemView::AllEditTriggers</set>
|
||||
</property>
|
||||
<property name="dragEnabled">
|
||||
<bool>true</bool>
|
||||
@@ -1059,7 +1073,105 @@ QListWidget:item:selected {
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="collab_page"/>
|
||||
<widget class="QWidget" name="download_page"/>
|
||||
<widget class="QWidget" name="download_page">
|
||||
<layout class="QVBoxLayout" name="download_page_lay">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="download_url_box">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>URL (direct web file, YouTube or spotify link) or path to file</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="download_path_widget" native="true">
|
||||
<layout class="QHBoxLayout" name="download_path_widget_lay">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="download_to_path_box">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>File download folder</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="choose_download_path_button">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Choose path</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="download_track_button">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Download</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTextBrowser" name="download_track_logs"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QProgressBar" name="download_track_progress">
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="textVisible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="settings_page">
|
||||
<layout class="QVBoxLayout" name="settings_page_lay">
|
||||
<property name="leftMargin">
|
||||
|
||||
1
gui/modules/download/__init__.py
Normal file
1
gui/modules/download/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from .handlers import *
|
||||
42
gui/modules/download/downloader.py
Normal file
42
gui/modules/download/downloader.py
Normal file
@@ -0,0 +1,42 @@
|
||||
import time
|
||||
|
||||
import validators
|
||||
from ezzthread import threaded
|
||||
from gui.modules.core.qt_updater import call
|
||||
from gui.gui import Ui_MainWindow
|
||||
from modules.player import convert
|
||||
from modules.spotify.spotify_dl import Spotify
|
||||
from urllib.request import urlopen
|
||||
from functools import partial
|
||||
import os
|
||||
|
||||
|
||||
@threaded
|
||||
def download_track(ui: Ui_MainWindow):
|
||||
url = ui.download_url_box.text()
|
||||
|
||||
if not validators.url(url):
|
||||
call(ui.download_track_logs.append, f"{url} is not valid URL, skipping")
|
||||
return
|
||||
|
||||
call(ui.download_track_logs.append, f"Downloading {url}")
|
||||
|
||||
name = (lambda song: song.artist + " - " + song.name + ".mp3")(Spotify().get_song(url)) \
|
||||
if "spotify" in url or "youtu" in url else url.split('/')[-1]
|
||||
|
||||
url = convert.get_raw_link(url)
|
||||
|
||||
call(ui.download_track_button.setEnabled, False)
|
||||
|
||||
response = urlopen(url)
|
||||
call(ui.download_track_progress.setValue, 0)
|
||||
size = int(response.info()["Content-length"])
|
||||
downloaded = 0
|
||||
with open(os.path.join(ui.download_to_path_box.text(), name), "wb") as dest_file:
|
||||
for data in iter(partial(response.read, 4096), b""):
|
||||
downloaded += len(data)
|
||||
dest_file.write(data)
|
||||
call(ui.download_track_progress.setValue, int(downloaded / size * 100))
|
||||
|
||||
call(ui.download_track_button.setEnabled, True)
|
||||
call(ui.download_track_logs.append, f"Downloaded to {os.path.join(ui.download_to_path_box.text(), name)}")
|
||||
13
gui/modules/download/handlers.py
Normal file
13
gui/modules/download/handlers.py
Normal file
@@ -0,0 +1,13 @@
|
||||
from gui.gui import Ui_MainWindow
|
||||
from PyQt5.QtWidgets import QFileDialog
|
||||
from gui.modules.download import downloader
|
||||
|
||||
|
||||
def register_handlers(ui: Ui_MainWindow):
|
||||
ui.choose_download_path_button.clicked.connect(
|
||||
lambda: ui.download_to_path_box.setText(
|
||||
QFileDialog.getExistingDirectory(caption="Select where to download file")
|
||||
)
|
||||
)
|
||||
|
||||
ui.download_track_button.clicked.connect(lambda: downloader.download_track(ui))
|
||||
@@ -8,6 +8,7 @@ from gui.modules import restreammic
|
||||
from gui.modules import explorer
|
||||
from gui.modules import collections
|
||||
from gui.modules import stream
|
||||
from gui.modules import download
|
||||
from modules.player.player import Player
|
||||
from modules.restream.restream import Restreamer
|
||||
|
||||
@@ -21,3 +22,4 @@ def register_handlers(ui: Ui_MainWindow, MainWindow: QMainWindow, p: Player, rs:
|
||||
explorer.register_handlers(ui, p)
|
||||
collections.register_handlers(ui, p)
|
||||
stream.register_handlers(ui, p)
|
||||
download.register_handlers(ui)
|
||||
|
||||
@@ -5,12 +5,19 @@ from urllib.error import HTTPError
|
||||
import re
|
||||
from base64 import b64encode
|
||||
from modules.spotify.config import SpotifyConfig
|
||||
import pafy
|
||||
|
||||
|
||||
def reencode(text: str):
|
||||
return b64encode(text.encode()).decode()
|
||||
|
||||
|
||||
class Song(object):
|
||||
def __init__(self, artist: str, name: str):
|
||||
self.artist = artist
|
||||
self.name = name
|
||||
|
||||
|
||||
class Spotify(object):
|
||||
def __init__(self):
|
||||
try:
|
||||
@@ -29,25 +36,34 @@ class Spotify(object):
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
def get_song(self, url) -> Song | None:
|
||||
if "spotify" in url:
|
||||
track_id = url.split('/')[-1].split('?')[0]
|
||||
r = requests.get(f"https://api.spotify.com/v1/tracks/{track_id}",
|
||||
headers={'Authorization': f'Bearer {self.token}'})
|
||||
|
||||
if r.status_code == 400 or r.status_code == 401:
|
||||
return None
|
||||
|
||||
track = r.json()
|
||||
|
||||
song_name = track['name']
|
||||
artists = []
|
||||
|
||||
for artist in track['artists']:
|
||||
artists.append(artist['name'])
|
||||
artist_name = ' '.join(artists)
|
||||
|
||||
return Song(artist_name, song_name)
|
||||
else:
|
||||
video = pafy.new(url)
|
||||
return Song(video.author, video.title)
|
||||
|
||||
def get_youtube_url(self, url) -> str | None:
|
||||
track_id = url.split('/')[-1].split('?')[0]
|
||||
r = requests.get(f"https://api.spotify.com/v1/tracks/{track_id}",
|
||||
headers={'Authorization': f'Bearer {self.token}'})
|
||||
|
||||
if r.status_code == 400 or r.status_code == 401:
|
||||
return None
|
||||
|
||||
track = r.json()
|
||||
|
||||
song_name = track['name']
|
||||
artists = []
|
||||
|
||||
for artist in track['artists']:
|
||||
artists.append(artist['name'])
|
||||
artist_name = ' '.join(artists)
|
||||
song = self.get_song(url)
|
||||
|
||||
try:
|
||||
query_string = urlencode({'search_query': artist_name + ' ' + song_name})
|
||||
query_string = urlencode({'search_query': song.artist + ' ' + song.name})
|
||||
htm_content = urlopen('http://www.youtube.com/results?' + query_string)
|
||||
search_results = re.findall(r'/watch\?v=(.{11})', htm_content.read().decode())
|
||||
|
||||
|
||||
Reference in New Issue
Block a user