Added downloading from spotify.

TODO: Two playing options - old stream and new download
This commit is contained in:
BarsTiger
2022-12-12 23:04:17 +02:00
parent 9d2bc0aeb6
commit 9dae35a537
15 changed files with 351 additions and 78 deletions

View File

@@ -1,30 +0,0 @@
import pydub
import validators
from urllib.request import urlopen
from io import BytesIO
from rich import print
import pafy
import hashlib
import os
def get_silenced_media(original: str) -> str | None:
if not os.path.isdir('temp'):
os.mkdir('temp')
try:
name = original
namehash = 'temp\\' + hashlib.md5(name.encode('utf-8')).hexdigest()
if not os.path.isfile(namehash):
if validators.url(original):
if 'youtu' in original:
original = pafy.new(original).getbestaudio().url
original = BytesIO(urlopen(original).read())
(pydub.AudioSegment.from_file(original) + pydub.AudioSegment.silent(1500))\
.export(namehash, format='mp3')
return namehash
except Exception as e:
print(e)
return None

42
modules/player/convert.py Normal file
View File

@@ -0,0 +1,42 @@
import pydub
import validators
from io import BytesIO
from rich import print
import pafy
import hashlib
import os
from modules.spotify.spotify_dl import Spotify
from gui.modules.core.popup import popup
import requests
def get_raw_link(url):
if validators.url(url):
if 'spotify' in url:
url = Spotify().get_youtube_url(url)
if 'youtu' in url:
url = pafy.new(url).audiostreams[0].url
else:
url = None
return url
def get_silenced_media(original: str) -> str | None:
if not os.path.isdir('temp'):
os.mkdir('temp')
try:
namehash = 'temp\\' + hashlib.md5(original.encode('utf-8')).hexdigest()
if not os.path.isfile(original):
if validators.url(original):
original = BytesIO(requests.get(get_raw_link(original)).content)
(pydub.AudioSegment.from_file(original) + pydub.AudioSegment.silent(1500))\
.export(namehash, format='mp3')
return namehash
except Exception as e:
raise e
print(e)
return None

View File

@@ -1,7 +1,7 @@
import vlc
from gui.gui import Ui_MainWindow
from gui.modules.core import popup
from modules.player.add_second import get_silenced_media
from modules.player.convert import get_silenced_media
def get_instance() -> vlc.Instance:
@@ -24,14 +24,16 @@ def get_devices(mediaplayer: vlc.MediaPlayer) -> dict:
class Player(object):
def __init__(self):
def __init__(self, ui: Ui_MainWindow):
self.instance_preview = get_instance()
self.instance_out = get_instance()
self.mediaplayer_preview = get_player(self.instance_preview)
self.mediaplayer_preview.audio_output_device_set(None, get_devices(self.mediaplayer_preview)['Default'])
self.mediaplayer_preview.audio_output_device_set(None, get_devices(self.mediaplayer_preview)[
ui.preview_device_play_box.currentText()
])
self.mediaplayer_out = get_player(self.instance_out)
self.mediaplayer_out.audio_output_device_set(None, get_devices(
self.mediaplayer_out)['CABLE Input (VB-Audio Virtual Cable)'])
self.mediaplayer_out)[ui.output_device_play_box.currentText()])
def set_media(self, media: str) -> None:
if get_silenced_media(media):
@@ -77,5 +79,10 @@ class Player(object):
self.mediaplayer_preview.set_position(pos)
self.mediaplayer_out.set_position(pos)
def update_devices(self):
pass
def update_devices(self, ui: Ui_MainWindow):
self.mediaplayer_preview.audio_output_device_set(None, get_devices(self.mediaplayer_preview)[
ui.preview_device_play_box.currentText()
])
self.mediaplayer_out.audio_output_device_set(None, get_devices(self.mediaplayer_out)[
ui.output_device_play_box.currentText()
])

View File

51
modules/spotify/config.py Normal file
View File

@@ -0,0 +1,51 @@
import json
import os
from dataclasses import dataclass
from dataclasses_json import dataclass_json
@dataclass_json
@dataclass(frozen=True)
class SpotConfig:
client_id: str
client_secret: str
class SpotifyConfig:
@staticmethod
def default():
return {
"client_id": "5f573c9620494bae87890c0f08a60293",
"client_secret": "212476d9b0f3472eaa762d90b19b0ba8"
}
@staticmethod
def fix() -> None:
try:
with open("data/config.spotify", "w") as file:
json.dump(SpotifyConfig.default(), file)
except FileNotFoundError:
if not os.path.exists('data'):
os.mkdir('data')
SpotifyConfig.fix()
@staticmethod
def get() -> SpotConfig:
try:
with open("data/config.spotify", "r") as file:
return SpotConfig.from_dict(json.load(file))
except:
SpotifyConfig.fix()
return SpotifyConfig.get()
@staticmethod
def update(key: str, value: str | None) -> dict:
with open("data/config.spotify", "r") as file:
settings = json.load(file)
settings[key] = value
with open("data/config.spotify", "w") as file:
json.dump(settings, file)
return settings

View File

@@ -0,0 +1,57 @@
import requests
from urllib.parse import urlencode
from urllib.request import urlopen
from urllib.error import HTTPError
import re
from base64 import b64encode
from modules.spotify.config import SpotifyConfig
def reencode(text: str):
return b64encode(text.encode()).decode()
class Spotify(object):
def __init__(self):
try:
headers = {
'Authorization': f'Basic '
f'{reencode(f"{SpotifyConfig.get().client_id}:{SpotifyConfig.get().client_secret}")}',
}
data = {
'grant_type': 'client_credentials'
}
r = requests.post('https://accounts.spotify.com/api/token', headers=headers, data=data)
self.token = r.json()['access_token']
except Exception as e:
print(e)
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)
try:
query_string = urlencode({'search_query': artist_name + ' ' + song_name})
htm_content = urlopen('http://www.youtube.com/results?' + query_string)
search_results = re.findall(r'/watch\?v=(.{11})', htm_content.read().decode())
return f'http://www.youtube.com/watch?v={search_results[0]}'
except HTTPError:
return None