Added downloading from spotify.
TODO: Two playing options - old stream and new download
This commit is contained in:
@@ -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
42
modules/player/convert.py
Normal 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
|
||||
@@ -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()
|
||||
])
|
||||
|
||||
0
modules/spotify/__init__.py
Normal file
0
modules/spotify/__init__.py
Normal file
51
modules/spotify/config.py
Normal file
51
modules/spotify/config.py
Normal 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
|
||||
57
modules/spotify/spotify_dl.py
Normal file
57
modules/spotify/spotify_dl.py
Normal 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
|
||||
Reference in New Issue
Block a user