Post-Processors are reimplemented. Call them with -o and -l flags.

This commit is contained in:
Kepoor Hampond 2017-03-10 00:21:17 -08:00
parent fb09be845d
commit 5f1068e645
8 changed files with 136 additions and 13 deletions

View file

@ -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

View file

@ -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:
```

View file

@ -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())

View file

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

View file

@ -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

View file

@ -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
#=========================================

View file

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