mirror of
https://github.com/cooperhammond/irs.git
synced 2024-11-08 18:38:33 +00:00
Post-Processors are reimplemented. Call them with -o and -l flags.
This commit is contained in:
parent
fb09be845d
commit
5f1068e645
|
@ -15,4 +15,5 @@ install:
|
|||
script:
|
||||
- python tests/song.py
|
||||
- python tests/album.py
|
||||
- python tests/playlist.py
|
||||
- python tests/playlist.py
|
||||
- python tests/post_processors.py
|
|
@ -1,4 +1,6 @@
|
|||
<div style="text-align:center"><img src ="http://i.imgur.com/VbsyTe7.png" /></div>
|
||||
<div align="center">
|
||||
<img src ="http://i.imgur.com/VbsyTe7.png" />
|
||||
</div>
|
||||
Ironic Redistribution System
|
||||
===
|
||||
[![License: GNU](https://img.shields.io/badge/License-GNU-yellow.svg)](http://www.gnu.org/licenses/gpl.html)
|
||||
|
@ -32,6 +34,9 @@ optional arguments:
|
|||
Specify username. Must be used with -p/--playlist
|
||||
-p PLAYLIST, --playlist PLAYLIST
|
||||
Specify playlist name. Must be used with -u/--username
|
||||
-l LOCATION, --location LOCATION
|
||||
Specify a directory to place files in.
|
||||
-o, --organize Organize downloaded files.
|
||||
```
|
||||
So all of these are valid commands:
|
||||
```
|
||||
|
|
26
irs/cli.py
26
irs/cli.py
|
@ -7,26 +7,44 @@ import os
|
|||
|
||||
# Powered by:
|
||||
from .ripper import Ripper
|
||||
from .utils import console
|
||||
from .utils import console, remove_none_values
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
|
||||
# Single Song
|
||||
parser.add_argument("-a", "--artist", dest="artist", help="Specify artist name. Must be used with -s/--song")
|
||||
parser.add_argument("-s", "--song", dest="song", help="Specify song name. Must be used with -a/--artist")
|
||||
|
||||
# Album
|
||||
parser.add_argument("-A", "--album", dest="album", help="Specify album name")
|
||||
|
||||
# Playlist
|
||||
parser.add_argument("-u", "--username", dest="username", help="Specify username. Must be used with -p/--playlist")
|
||||
parser.add_argument("-p", "--playlist", dest="playlist", help="Specify playlist name. Must be used with -u/--username")
|
||||
|
||||
# Post-Processors
|
||||
parser.add_argument("-l", "--location", dest="location", help="Specify a directory to place files in.")
|
||||
parser.add_argument("-o", "--organize", dest="organize", action="store_true", help="Organize downloaded files.")
|
||||
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
ripper_args = {
|
||||
"post_processors": {
|
||||
"location": args.location,
|
||||
"organize": args.organize,
|
||||
}
|
||||
}
|
||||
|
||||
ripper = Ripper(ripper_args)
|
||||
|
||||
if args.artist and args.song:
|
||||
Ripper().song(args.song, args.artist)
|
||||
ripper.song(args.song, args.artist)
|
||||
elif args.album:
|
||||
Ripper().spotify_list("album", args.album)
|
||||
ripper.spotify_list("album", args.album)
|
||||
elif args.username and args.playlist:
|
||||
Ripper().spotify_list("playlist", args.playlist, args.username)
|
||||
ripper.spotify_list("playlist", args.playlist, args.username)
|
||||
else:
|
||||
console(Ripper())
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# MP3 Metadata editing
|
||||
from mutagen.mp3 import MP3, EasyMP3
|
||||
from mutagen.easyid3 import EasyID3
|
||||
from mutagen.easyid3 import EasyID3, EasyID3KeyError
|
||||
from mutagen.id3 import * # There's A LOT of stuff to import, forgive me.
|
||||
from mutagen.id3 import APIC
|
||||
|
||||
|
@ -37,7 +37,13 @@ class Metadata:
|
|||
def add_tag(self, tag, data):
|
||||
# For valid tags: `EasyID3.valid_keys.keys()`
|
||||
self.mp3[tag] = data
|
||||
self.mp3.save()
|
||||
self.mp3.save()
|
||||
|
||||
def read_tag(self, tag):
|
||||
try:
|
||||
return self.mp3[tag]
|
||||
except EasyID3KeyError:
|
||||
return []
|
||||
|
||||
def add_album_art(self, image_url):
|
||||
mp3 = EasyMP3(self.location, ID3=ID3)
|
||||
|
|
|
@ -28,6 +28,7 @@ class Ripper:
|
|||
def __init__(self, args={}):
|
||||
self.args = args
|
||||
self.locations = []
|
||||
self.type = None
|
||||
try:
|
||||
client_credentials_manager = SpotifyClientCredentials(os.environ["SPOTIFY_CLIENT_ID"], os.environ["SPOTIFY_CLIENT_SECRET"])
|
||||
self.spotify = spotipy.Spotify(client_credentials_manager=client_credentials_manager)
|
||||
|
@ -36,6 +37,52 @@ class Ripper:
|
|||
self.spotify = spotipy.Spotify()
|
||||
self.authorized = False
|
||||
|
||||
def post_processing(self, locations):
|
||||
post_processors = self.args.get("post_processors")
|
||||
if post_processors:
|
||||
if type(post_processors.get("location")) is str:
|
||||
for index, loc in enumerate(locations):
|
||||
new_file_name = post_processors["location"] + "/" + loc
|
||||
os.rename(loc, new_file_name)
|
||||
locations[index] = new_file_name
|
||||
if post_processors.get("organize") == True:
|
||||
if self.type == "album":
|
||||
for index, loc in enumerate(locations):
|
||||
mp3 = Metadata(loc)
|
||||
new_loc = ""
|
||||
if len(loc.split("/")) > 1:
|
||||
new_loc = "/".join(loc.split("/")[0:-1])
|
||||
file_name = loc.split("/")[-1]
|
||||
else:
|
||||
file_name = loc
|
||||
artist, album = mp3.read_tag("artist")[0], mp3.read_tag("album")
|
||||
new_loc += blank(artist, False)
|
||||
if album != []:
|
||||
new_loc += "/" + blank(album[0], False)
|
||||
if not os.path.exists(new_loc):
|
||||
os.makedirs(new_loc)
|
||||
new_loc += "/" + file_name
|
||||
loc = loc.replace("//", "/")
|
||||
new_loc = new_loc.replace("//", "/")
|
||||
os.rename(loc, new_loc)
|
||||
locations[index] = new_loc
|
||||
elif self.type == "playlist":
|
||||
for index, loc in enumerate(locations):
|
||||
new_loc = ""
|
||||
if len(loc.split("/")) > 1:
|
||||
new_loc = "/".join(loc.split("/")[0:-1])
|
||||
file_name = loc.split("/")[-1]
|
||||
else:
|
||||
file_name = loc
|
||||
new_loc += blank(self.playlist_title, False)
|
||||
if not os.path.exists(new_loc):
|
||||
os.makedirs(new_loc)
|
||||
loc = loc.replace("//", "/")
|
||||
new_loc = (new_loc + "/" + file_name).replace("//", "/")
|
||||
os.rename(loc, new_loc)
|
||||
|
||||
return locations
|
||||
|
||||
def find_yt_url(self, song=None, artist=None, additional_search="lyrics"):
|
||||
try:
|
||||
if not song: song = self.args["song_title"]
|
||||
|
@ -87,6 +134,12 @@ class Ripper:
|
|||
self.code = results[0]
|
||||
|
||||
return ("https://youtube.com" + self.code["href"], self.code["title"])
|
||||
|
||||
def album(self, title): # Alias for `spotify_list("album", ...)`
|
||||
return self.spotify_list("album", title)
|
||||
|
||||
def playlist(self, title, username): # Alias for `spotify_list("playlist", ...)`
|
||||
return self.spotify_list("playlist", title, username)
|
||||
|
||||
def spotify_list(self, type=None, title=None, username=None):
|
||||
try:
|
||||
|
@ -96,6 +149,9 @@ class Ripper:
|
|||
username = self.args["username"]
|
||||
except KeyError:
|
||||
raise ValueError("Must specify type/title/username in `args` with init, or in method arguments.")
|
||||
|
||||
if not self.type:
|
||||
self.type = type
|
||||
|
||||
if type == "album":
|
||||
search = title
|
||||
|
@ -138,6 +194,8 @@ class Ripper:
|
|||
|
||||
for track in the_list["tracks"]["items"]:
|
||||
if type == "playlist":
|
||||
self.playlist_title = the_list["name"] # For post-processors
|
||||
|
||||
file_prefix = str(len(tracks) + 1) + " - "
|
||||
track = track["track"]
|
||||
album = self.spotify.album(track["album"]["uri"])
|
||||
|
@ -178,7 +236,10 @@ class Ripper:
|
|||
if loc != False:
|
||||
#update_download_log_line_status(track, "downloaded")
|
||||
locations.append(loc)
|
||||
|
||||
|
||||
if self.type in ("album", "playlist"):
|
||||
return self.post_processing(locations)
|
||||
|
||||
#os.remove(".irs-download-log")
|
||||
return locations
|
||||
|
||||
|
@ -201,10 +262,13 @@ class Ripper:
|
|||
"disc_number": track["disc_number"],
|
||||
|
||||
"compilation": "", # If this method is being called, it's not a compilation
|
||||
"file_prefix": "" # And therefore, won't have a prefix
|
||||
"file_prefix": "" # And therefore, won't have a prefix
|
||||
}
|
||||
|
||||
def song(self, song, artist, data={}): # Takes data from `parse_song_data`
|
||||
if not self.type:
|
||||
self.type = "song"
|
||||
|
||||
try:
|
||||
if not song: song = self.args["song_title"]
|
||||
if not artist: artist = self.args["artist"]
|
||||
|
@ -266,5 +330,7 @@ class Ripper:
|
|||
m.add_tag("compilation", data["compilation"])
|
||||
m.add_album_art( str(data["album_art"]))
|
||||
|
||||
if self.type == "song":
|
||||
return self.post_processing([file_name])
|
||||
|
||||
return file_name
|
13
irs/utils.py
13
irs/utils.py
|
@ -27,7 +27,7 @@ def my_hook(d):
|
|||
|
||||
|
||||
#=================================
|
||||
# String Manipulation and Checking
|
||||
# Object Manipulation and Checking
|
||||
#=================================
|
||||
|
||||
def check_garbage_phrases(phrases, string, title):
|
||||
|
@ -70,7 +70,16 @@ def flatten(l):
|
|||
else:
|
||||
flattened_list.append(x)
|
||||
return flattened_list
|
||||
|
||||
|
||||
def remove_none_values(d):
|
||||
new_d = d
|
||||
for x in list(d.keys()):
|
||||
if type(new_d[x]) is list:
|
||||
new_d[x] = remove_none_values(d[x])
|
||||
elif new_d[x] == None:
|
||||
del new_d[x]
|
||||
return new_d
|
||||
|
||||
#=========================================
|
||||
# Download Log Reading/Updating/Formatting
|
||||
#=========================================
|
||||
|
|
2
setup.py
2
setup.py
|
@ -2,7 +2,7 @@ from setuptools import setup
|
|||
|
||||
setup(
|
||||
name='irs',
|
||||
version='6.0.1',
|
||||
version='6.1.1',
|
||||
description='A music downloader that just gets metadata.',
|
||||
url='https://github.com/kepoorhampond/irs',
|
||||
author='Kepoor Hampond',
|
||||
|
|
18
tests/post_processors.py
Normal file
18
tests/post_processors.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
from irs.ripper import Ripper
|
||||
import os
|
||||
|
||||
if not os.path.exists("test_dir"):
|
||||
os.makedirs("test_dir")
|
||||
Ripper({
|
||||
"post_processors": {
|
||||
"location": "test_dir/",
|
||||
"organize": True,
|
||||
}
|
||||
}).album("Da Frame 2R / Matador")
|
||||
|
||||
Ripper({
|
||||
"post_processors": {
|
||||
"location": "test_dir/",
|
||||
"organize": True,
|
||||
}
|
||||
}).playlist("IRS Testing", "prakkillian")
|
Loading…
Reference in a new issue