spoti-stream 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- spoti_fly/__init__.py +8 -0
- spoti_fly/converter.py +15 -0
- spoti_fly/downloader.py +85 -0
- spoti_fly/install_dependencies.py +40 -0
- spoti_fly/main.py +86 -0
- spoti_fly/spotify_utils.py +72 -0
- spoti_stream-0.1.0.dist-info/LICENSE.txt +22 -0
- spoti_stream-0.1.0.dist-info/METADATA +42 -0
- spoti_stream-0.1.0.dist-info/RECORD +12 -0
- spoti_stream-0.1.0.dist-info/WHEEL +5 -0
- spoti_stream-0.1.0.dist-info/entry_points.txt +2 -0
- spoti_stream-0.1.0.dist-info/top_level.txt +1 -0
spoti_fly/__init__.py
ADDED
spoti_fly/converter.py
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# spoti_fly/converter.py
|
|
2
|
+
import os
|
|
3
|
+
import subprocess
|
|
4
|
+
|
|
5
|
+
def convert_webm_to_mp3(webm_file_path, mp3_file_name, download_dir='songs'):
|
|
6
|
+
mp3_file_path = os.path.join(download_dir, mp3_file_name)
|
|
7
|
+
try:
|
|
8
|
+
# Suppressing FFmpeg logs by redirecting stdout and stderr
|
|
9
|
+
subprocess.run(['ffmpeg', '-i', webm_file_path, mp3_file_path],
|
|
10
|
+
check=True, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
|
|
11
|
+
print(f"Converted to MP3: {mp3_file_name}")
|
|
12
|
+
except subprocess.CalledProcessError as e:
|
|
13
|
+
print(f"Error converting {webm_file_path} to MP3: {e}")
|
|
14
|
+
|
|
15
|
+
|
spoti_fly/downloader.py
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# spoti_fly/downloader.py
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import yt_dlp
|
|
5
|
+
from .converter import convert_webm_to_mp3
|
|
6
|
+
import re
|
|
7
|
+
|
|
8
|
+
def sanitize_filename(filename):
|
|
9
|
+
return re.sub(r'[\\/*?:"<>|]', '_', filename) # Replaces problematic characters with underscore
|
|
10
|
+
|
|
11
|
+
def download_song(song_name, artist_name, download_dir='songs'):
|
|
12
|
+
query = f"{song_name} {artist_name} audio"
|
|
13
|
+
sanitized_song_name = sanitize_filename(f"{song_name} by {artist_name}")
|
|
14
|
+
mp3_file_name = f"{sanitized_song_name}.mp3"
|
|
15
|
+
mp3_file_path = os.path.join(download_dir, mp3_file_name)
|
|
16
|
+
|
|
17
|
+
if os.path.exists(mp3_file_path):
|
|
18
|
+
print(f"'{song_name} by {artist_name}' is already downloaded as MP3. Skipping...")
|
|
19
|
+
return
|
|
20
|
+
|
|
21
|
+
ydl_opts = {
|
|
22
|
+
'format': 'bestaudio[ext=webm]/bestaudio',
|
|
23
|
+
'outtmpl': os.path.join(download_dir, f"{sanitized_song_name}.webm"),
|
|
24
|
+
'noplaylist': True,
|
|
25
|
+
'quiet': True # Suppress yt-dlp logging
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
|
|
29
|
+
try:
|
|
30
|
+
print(f"Searching and downloading: {query}")
|
|
31
|
+
ydl.download([f"ytsearch1:{query}"])
|
|
32
|
+
print(f"Downloaded: {mp3_file_name}")
|
|
33
|
+
|
|
34
|
+
# Convert downloaded .webm to .mp3
|
|
35
|
+
convert_webm_to_mp3(os.path.join(download_dir, f"{sanitized_song_name}.webm"), mp3_file_name, download_dir)
|
|
36
|
+
|
|
37
|
+
# Remove the .webm file after conversion
|
|
38
|
+
webm_file_path = os.path.join(download_dir, f"{sanitized_song_name}.webm")
|
|
39
|
+
if os.path.exists(webm_file_path):
|
|
40
|
+
os.remove(webm_file_path)
|
|
41
|
+
|
|
42
|
+
except yt_dlp.utils.DownloadError as e:
|
|
43
|
+
print(f"Download error for {song_name} by {artist_name}: {e}")
|
|
44
|
+
except Exception as e:
|
|
45
|
+
print(f"An error occurred while downloading {song_name} by {artist_name}: {e}")
|
|
46
|
+
|
|
47
|
+
def download_songs_from_playlist(sp, playlist_id, playlist_name, download_dir='songs'):
|
|
48
|
+
from .spotify_utils import fetch_songs_from_playlist, save_songs_to_csv
|
|
49
|
+
songs = fetch_songs_from_playlist(sp, playlist_id)
|
|
50
|
+
if songs:
|
|
51
|
+
save_songs_to_csv(songs, playlist_name)
|
|
52
|
+
for song_name, artist_name in songs:
|
|
53
|
+
download_song(song_name, artist_name, download_dir)
|
|
54
|
+
else:
|
|
55
|
+
print(f"No songs found in playlist: {playlist_name}")
|
|
56
|
+
|
|
57
|
+
def download_songs_from_csv(csv_file_path, download_dir='songs'):
|
|
58
|
+
import csv
|
|
59
|
+
try:
|
|
60
|
+
with open(csv_file_path, newline='', encoding='utf-8') as csvfile:
|
|
61
|
+
reader = csv.DictReader(csvfile)
|
|
62
|
+
for row in reader:
|
|
63
|
+
song_name = row.get('Song Name')
|
|
64
|
+
artist_name = row.get('Artist Name')
|
|
65
|
+
if song_name and artist_name:
|
|
66
|
+
download_song(song_name, artist_name, download_dir)
|
|
67
|
+
except FileNotFoundError:
|
|
68
|
+
print(f"File not found: {csv_file_path}")
|
|
69
|
+
except Exception as e:
|
|
70
|
+
print(f"An error occurred while reading the CSV file: {e}")
|
|
71
|
+
|
|
72
|
+
def download_songs_from_txt(txt_file_path, download_dir='songs'):
|
|
73
|
+
try:
|
|
74
|
+
with open(txt_file_path, 'r', encoding='utf-8') as txtfile:
|
|
75
|
+
for line in txtfile:
|
|
76
|
+
song_info = line.strip().split('-')
|
|
77
|
+
if len(song_info) == 2:
|
|
78
|
+
song_name, artist_name = song_info
|
|
79
|
+
download_song(song_name.strip(), artist_name.strip(), download_dir)
|
|
80
|
+
else:
|
|
81
|
+
print(f"Invalid format in TXT file: {line}")
|
|
82
|
+
except FileNotFoundError:
|
|
83
|
+
print(f"File not found: {txt_file_path}")
|
|
84
|
+
except Exception as e:
|
|
85
|
+
print(f"An error occurred while reading the TXT file: {e}")
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import subprocess
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
def is_installed(command):
|
|
5
|
+
"""Check if a command exists on the system."""
|
|
6
|
+
try:
|
|
7
|
+
subprocess.run(command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, shell=True)
|
|
8
|
+
return True
|
|
9
|
+
except Exception:
|
|
10
|
+
return False
|
|
11
|
+
|
|
12
|
+
def install_scoop():
|
|
13
|
+
"""Install Scoop if it's not already installed."""
|
|
14
|
+
if is_installed('scoop'):
|
|
15
|
+
#print("Scoop is already installed.")
|
|
16
|
+
return
|
|
17
|
+
try:
|
|
18
|
+
# Suppress output and errors using DEVNULL
|
|
19
|
+
subprocess.run(
|
|
20
|
+
'powershell -Command "Set-ExecutionPolicy RemoteSigned -scope CurrentUser; iwr -useb get.scoop.sh | iex"',
|
|
21
|
+
shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL
|
|
22
|
+
)
|
|
23
|
+
print("Scoop installed successfully.")
|
|
24
|
+
except subprocess.CalledProcessError:
|
|
25
|
+
print("Failed to install Scoop.")
|
|
26
|
+
|
|
27
|
+
def install_ffmpeg():
|
|
28
|
+
"""Install FFmpeg using Scoop if it's not already installed."""
|
|
29
|
+
if is_installed('ffmpeg'):
|
|
30
|
+
#print("FFmpeg is already installed.")
|
|
31
|
+
return
|
|
32
|
+
try:
|
|
33
|
+
# Suppress output and errors using DEVNULL
|
|
34
|
+
subprocess.run(
|
|
35
|
+
'powershell -Command "scoop install ffmpeg"',
|
|
36
|
+
shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL
|
|
37
|
+
)
|
|
38
|
+
print("FFmpeg installed successfully.")
|
|
39
|
+
except subprocess.CalledProcessError:
|
|
40
|
+
print("Failed to install FFmpeg.")
|
spoti_fly/main.py
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# spoti_fly/main.py
|
|
2
|
+
import os
|
|
3
|
+
from .spotify_utils import authenticate_spotify, get_user_playlists, fetch_songs_from_playlist
|
|
4
|
+
from .downloader import download_songs_from_playlist, download_songs_from_csv, download_songs_from_txt, download_song
|
|
5
|
+
|
|
6
|
+
def main():
|
|
7
|
+
print("\n[INFO] Welcome to SpotiFly! ")
|
|
8
|
+
print("Download and listen to non-stop Spotify music with our tool.")
|
|
9
|
+
print("Music is an art which reach your soul to pacify it..... :)")
|
|
10
|
+
print("For more information visit: https://github.com/mehmoodulhaq570")
|
|
11
|
+
print(" =---------------------------------= ")
|
|
12
|
+
|
|
13
|
+
# Check for existing Spotify credentials
|
|
14
|
+
sp = authenticate_spotify()
|
|
15
|
+
|
|
16
|
+
while True:
|
|
17
|
+
print("\nWhat would you like to do?")
|
|
18
|
+
print("1. Use a Spotify playlist")
|
|
19
|
+
print("2. Provide your own CSV or TXT file")
|
|
20
|
+
print("3. Manually type in song names")
|
|
21
|
+
print("4. Exit from SpotiFly")
|
|
22
|
+
|
|
23
|
+
choice = input("Please enter 1, 2, 3 or 4: ").strip()
|
|
24
|
+
|
|
25
|
+
if choice == '1':
|
|
26
|
+
playlists = get_user_playlists(sp)
|
|
27
|
+
|
|
28
|
+
if playlists:
|
|
29
|
+
print("Your Playlists:")
|
|
30
|
+
for i, playlist in enumerate(playlists):
|
|
31
|
+
print(f"{i + 1}. {playlist['name']} (ID: {playlist['id']})")
|
|
32
|
+
else:
|
|
33
|
+
print("No playlists found or an error occurred.")
|
|
34
|
+
|
|
35
|
+
try:
|
|
36
|
+
selected_index = int(input("Select a playlist by number: ")) - 1
|
|
37
|
+
if selected_index < 0 or selected_index >= len(playlists):
|
|
38
|
+
print("Invalid selection. Please enter a valid playlist number.")
|
|
39
|
+
continue
|
|
40
|
+
|
|
41
|
+
selected_playlist = playlists[selected_index]
|
|
42
|
+
selected_playlist_id = selected_playlist['id']
|
|
43
|
+
selected_playlist_name = selected_playlist['name']
|
|
44
|
+
|
|
45
|
+
download_songs_from_playlist(sp, selected_playlist_id, selected_playlist_name)
|
|
46
|
+
|
|
47
|
+
except ValueError:
|
|
48
|
+
print("Invalid input. Please enter a valid number.")
|
|
49
|
+
except Exception as e:
|
|
50
|
+
print(f"An error occurred: {e}")
|
|
51
|
+
|
|
52
|
+
elif choice == '2':
|
|
53
|
+
file_path = input("Enter the full path to your CSV or TXT file: ").strip()
|
|
54
|
+
|
|
55
|
+
if file_path.lower().endswith('.csv'):
|
|
56
|
+
download_songs_from_csv(file_path)
|
|
57
|
+
elif file_path.lower().endswith('.txt'):
|
|
58
|
+
download_songs_from_txt(file_path)
|
|
59
|
+
else:
|
|
60
|
+
print("Invalid file format. Please provide a .csv or .txt file.")
|
|
61
|
+
|
|
62
|
+
elif choice == '3':
|
|
63
|
+
while True:
|
|
64
|
+
song_name = input("Enter the song name (or 'q' to stop): ").strip()
|
|
65
|
+
if song_name.lower() == 'q':
|
|
66
|
+
break
|
|
67
|
+
artist_name = input(f"Enter the artist name for '{song_name}': ").strip()
|
|
68
|
+
download_song(song_name, artist_name)
|
|
69
|
+
|
|
70
|
+
elif choice == '4':
|
|
71
|
+
print("\n *-------------------------------* ")
|
|
72
|
+
print("Thank you for using SpotiFly Music! Goodbye!")
|
|
73
|
+
print(" *-------------------------------* ")
|
|
74
|
+
break
|
|
75
|
+
|
|
76
|
+
else:
|
|
77
|
+
print("Invalid choice. Please enter 1, 2, 3 or 4.")
|
|
78
|
+
|
|
79
|
+
if input("Do you want to continue? (y/n): ").strip().lower() != 'y':
|
|
80
|
+
print("\n *-------------------------------* ")
|
|
81
|
+
print("Thank you for using SpotiFly Music! Goodbye!")
|
|
82
|
+
print(" *-------------------------------* ")
|
|
83
|
+
break
|
|
84
|
+
|
|
85
|
+
if __name__ == '__main__':
|
|
86
|
+
main()
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# spoti_fly/spotify_utils.py
|
|
2
|
+
import spotipy
|
|
3
|
+
from spotipy.oauth2 import SpotifyOAuth
|
|
4
|
+
|
|
5
|
+
def save_credentials_to_file(client_id, client_secret, file_path='spotify_credentials.txt'):
|
|
6
|
+
try:
|
|
7
|
+
with open(file_path, 'w') as f:
|
|
8
|
+
f.write(f"{client_id}\n{client_secret}\n")
|
|
9
|
+
print(f"Spotify credentials saved to {file_path}")
|
|
10
|
+
except Exception as e:
|
|
11
|
+
print(f"An error occurred while saving credentials: {e}")
|
|
12
|
+
|
|
13
|
+
def read_credentials_from_file(file_path='spotify_credentials.txt'):
|
|
14
|
+
try:
|
|
15
|
+
with open(file_path, 'r') as f:
|
|
16
|
+
lines = f.readlines()
|
|
17
|
+
client_id = lines[0].strip()
|
|
18
|
+
client_secret = lines[1].strip()
|
|
19
|
+
return client_id, client_secret
|
|
20
|
+
except Exception as e:
|
|
21
|
+
print(f"An error occurred while reading credentials: {e}")
|
|
22
|
+
return None, None
|
|
23
|
+
|
|
24
|
+
def authenticate_spotify():
|
|
25
|
+
client_id, client_secret = read_credentials_from_file()
|
|
26
|
+
|
|
27
|
+
if client_id is None or client_secret is None:
|
|
28
|
+
client_id = input("Enter your Spotify Client ID: ")
|
|
29
|
+
client_secret = input("Enter your Spotify Client Secret: ")
|
|
30
|
+
save_credentials_to_file(client_id, client_secret)
|
|
31
|
+
|
|
32
|
+
REDIRECT_URI = 'http://localhost:8888/callback'
|
|
33
|
+
scope = 'playlist-read-private user-library-read'
|
|
34
|
+
sp = spotipy.Spotify(auth_manager=SpotifyOAuth(client_id=client_id,
|
|
35
|
+
client_secret=client_secret,
|
|
36
|
+
redirect_uri=REDIRECT_URI,
|
|
37
|
+
scope=scope))
|
|
38
|
+
return sp
|
|
39
|
+
|
|
40
|
+
def get_user_playlists(sp):
|
|
41
|
+
try:
|
|
42
|
+
playlists = sp.current_user_playlists()
|
|
43
|
+
return playlists['items']
|
|
44
|
+
except Exception as e:
|
|
45
|
+
print(f"An error occurred while fetching playlists: {e}")
|
|
46
|
+
return []
|
|
47
|
+
|
|
48
|
+
def fetch_songs_from_playlist(sp, playlist_id):
|
|
49
|
+
tracks = []
|
|
50
|
+
try:
|
|
51
|
+
results = sp.playlist_items(playlist_id, limit=100)
|
|
52
|
+
while results:
|
|
53
|
+
for item in results['items']:
|
|
54
|
+
track = item['track']
|
|
55
|
+
tracks.append([track['name'], track['artists'][0]['name']])
|
|
56
|
+
if results['next'] is not None:
|
|
57
|
+
results = sp.next(results)
|
|
58
|
+
else:
|
|
59
|
+
break
|
|
60
|
+
except Exception as e:
|
|
61
|
+
print(f"An error occurred while fetching songs from the playlist: {e}")
|
|
62
|
+
return tracks
|
|
63
|
+
|
|
64
|
+
def save_songs_to_csv(songs, playlist_name):
|
|
65
|
+
import csv
|
|
66
|
+
from .downloader import sanitize_filename
|
|
67
|
+
filename = sanitize_filename(f"{playlist_name}.csv")
|
|
68
|
+
with open(filename, mode='w', newline='', encoding='utf-8') as file:
|
|
69
|
+
writer = csv.writer(file)
|
|
70
|
+
writer.writerow(['Song Name', 'Artist Name'])
|
|
71
|
+
writer.writerows(songs)
|
|
72
|
+
print(f"Playlist saved to: {filename}")
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Mehmood Ul Haq
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: spoti_stream
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A tool to download Spotify playlist songs using YouTube
|
|
5
|
+
Home-page: https://github.com/mehmoodulhaq570/SpotiStream
|
|
6
|
+
Author: Mehmood Ul Haq
|
|
7
|
+
Author-email: mehmoodulhaq1040@gmail.com
|
|
8
|
+
License: MIT
|
|
9
|
+
Project-URL: Documentation, https://github.com/mehmoodulhaq570/SpotiStream#readme
|
|
10
|
+
Project-URL: Source, https://github.com/mehmoodulhaq570/SpotiStream
|
|
11
|
+
Project-URL: Bug Tracker, https://github.com/mehmoodulhaq570/SpotiStream/issues
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Requires-Python: >=3.6
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
License-File: LICENSE.txt
|
|
18
|
+
Requires-Dist: spotipy >=2.19.0
|
|
19
|
+
Requires-Dist: yt-dlp >=2021.12.1
|
|
20
|
+
Requires-Dist: moviepy >=1.0.3
|
|
21
|
+
Requires-Dist: pydub >=0.25.1
|
|
22
|
+
|
|
23
|
+
# SpotiStream
|
|
24
|
+
|
|
25
|
+
**SpotiStream** is a Python package that allows you to download songs from Spotify playlists by fetching song information and downloading the corresponding audio from YouTube. The songs are saved in MP3 format.
|
|
26
|
+
|
|
27
|
+
## Features
|
|
28
|
+
|
|
29
|
+
- Authenticate with Spotify using OAuth to access playlists.
|
|
30
|
+
- Fetch and download songs from Spotify playlists.
|
|
31
|
+
- Save song information in a CSV file for easy access.
|
|
32
|
+
- Convert downloaded YouTube audio from WebM to MP3 format.
|
|
33
|
+
- Download songs directly from a user-provided CSV file.
|
|
34
|
+
- Handles credential storage and reuse.
|
|
35
|
+
|
|
36
|
+
## Installation
|
|
37
|
+
|
|
38
|
+
1. Clone the repository or install the package:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
git clone https://github.com/your-repo/spoti_stream.git
|
|
42
|
+
cd spoti_stream
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
spoti_fly/__init__.py,sha256=ejDT6N39W9DrhRRaqYOdQpIuhSsxxsTkHUMyfkjQp-M,190
|
|
2
|
+
spoti_fly/converter.py,sha256=FnMPU6IF-_cKLWoVGwwD5965rkwMTi_3OTmeONalgSw,595
|
|
3
|
+
spoti_fly/downloader.py,sha256=Olc6Na6_ncV3VmTCTHFcQUh4OlGCC4z5siB-mGhITpw,3548
|
|
4
|
+
spoti_fly/install_dependencies.py,sha256=yzwsbX6L7Pta-os5o9N8dQqesVnNjArAz3uCoWqcBbw,1452
|
|
5
|
+
spoti_fly/main.py,sha256=OrbDICoW486kYoSU9idEpZnNTV6wemxW66Tx8kzN_24,3520
|
|
6
|
+
spoti_fly/spotify_utils.py,sha256=9ehwUiepM2ZCK7VG6E-QwBL1_cHTagaJdG1ASqGakWY,2778
|
|
7
|
+
spoti_stream-0.1.0.dist-info/LICENSE.txt,sha256=qIVZzvyU9EhEIU_vKRQ9RCDb7L7FcDmNCXDZR1s3uV0,1072
|
|
8
|
+
spoti_stream-0.1.0.dist-info/METADATA,sha256=Eh1KZT00ku4SWMLs1n8712TAx-YAlWn21JXpOv-j0WU,1602
|
|
9
|
+
spoti_stream-0.1.0.dist-info/WHEEL,sha256=Z4pYXqR_rTB7OWNDYFOm1qRk0RX6GFP2o8LgvP453Hk,91
|
|
10
|
+
spoti_stream-0.1.0.dist-info/entry_points.txt,sha256=0muJlf-Id2OFknCd_zwoBvnfvhtRaUjrPZKsi5DqW5w,53
|
|
11
|
+
spoti_stream-0.1.0.dist-info/top_level.txt,sha256=dPL64yciCl8S94MbMkcnD-NLlUvkYLRWZwvuY9j8iVc,10
|
|
12
|
+
spoti_stream-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
spoti_fly
|