Downloading tracks

This commit is contained in:
BarsTiger
2022-12-25 12:02:59 +02:00
parent 762fc89c5a
commit 2848cb76be
7 changed files with 242 additions and 19 deletions

View File

@@ -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_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 = 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.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.setDragEnabled(True)
self.edit_second_pads_collection_list.setObjectName("edit_second_pads_collection_list") 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) 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.content.addWidget(self.collab_page)
self.download_page = QtWidgets.QWidget() self.download_page = QtWidgets.QWidget()
self.download_page.setObjectName("download_page") 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.content.addWidget(self.download_page)
self.settings_page = QtWidgets.QWidget() self.settings_page = QtWidgets.QWidget()
self.settings_page.setObjectName("settings_page") 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.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.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.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.play_options_group.setTitle(_translate("MainWindow", "Play options"))
self.output_device_play_label.setText(_translate("MainWindow", "Output device (or virtual mic input)")) 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)")) self.preview_device_play_label.setText(_translate("MainWindow", "Preview device (your headphones)"))

View File

@@ -301,6 +301,20 @@ QSlider::handle:horizontal:hover {
QSlider::handle:horizontal:pressed { QSlider::handle:horizontal:pressed {
background-color: #bfbfbf; 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> </string>
</property> </property>
<widget class="QWidget" name="centralwidget"> <widget class="QWidget" name="centralwidget">
@@ -690,7 +704,7 @@ QListWidget:item:selected {
<string notr="true">font: 15pt &quot;Segoe UI&quot;;</string> <string notr="true">font: 15pt &quot;Segoe UI&quot;;</string>
</property> </property>
<property name="editTriggers"> <property name="editTriggers">
<set>QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed|QAbstractItemView::SelectedClicked</set> <set>QAbstractItemView::AllEditTriggers</set>
</property> </property>
<property name="dragEnabled"> <property name="dragEnabled">
<bool>true</bool> <bool>true</bool>
@@ -1059,7 +1073,105 @@ QListWidget:item:selected {
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="collab_page"/> <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"> <widget class="QWidget" name="settings_page">
<layout class="QVBoxLayout" name="settings_page_lay"> <layout class="QVBoxLayout" name="settings_page_lay">
<property name="leftMargin"> <property name="leftMargin">

View File

@@ -0,0 +1 @@
from .handlers import *

View 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)}")

View 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))

View File

@@ -8,6 +8,7 @@ from gui.modules import restreammic
from gui.modules import explorer from gui.modules import explorer
from gui.modules import collections from gui.modules import collections
from gui.modules import stream from gui.modules import stream
from gui.modules import download
from modules.player.player import Player from modules.player.player import Player
from modules.restream.restream import Restreamer 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) explorer.register_handlers(ui, p)
collections.register_handlers(ui, p) collections.register_handlers(ui, p)
stream.register_handlers(ui, p) stream.register_handlers(ui, p)
download.register_handlers(ui)

View File

@@ -5,12 +5,19 @@ from urllib.error import HTTPError
import re import re
from base64 import b64encode from base64 import b64encode
from modules.spotify.config import SpotifyConfig from modules.spotify.config import SpotifyConfig
import pafy
def reencode(text: str): def reencode(text: str):
return b64encode(text.encode()).decode() return b64encode(text.encode()).decode()
class Song(object):
def __init__(self, artist: str, name: str):
self.artist = artist
self.name = name
class Spotify(object): class Spotify(object):
def __init__(self): def __init__(self):
try: try:
@@ -29,25 +36,34 @@ class Spotify(object):
except Exception as e: except Exception as e:
print(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: def get_youtube_url(self, url) -> str | None:
track_id = url.split('/')[-1].split('?')[0] song = self.get_song(url)
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)
try: 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) htm_content = urlopen('http://www.youtube.com/results?' + query_string)
search_results = re.findall(r'/watch\?v=(.{11})', htm_content.read().decode()) search_results = re.findall(r'/watch\?v=(.{11})', htm_content.read().decode())