Added a default so that playlists are automatically downloaded into one folder rather than being spread out across multiple artist folders and the such.

This commit is contained in:
Kepoor Hampond 2016-12-20 20:44:19 -08:00
parent 8678b934f8
commit aab301b25a
26 changed files with 1567 additions and 24 deletions

View file

@ -11,7 +11,7 @@ ___
usage: usage:
irs (-h | -v) irs (-h | -v)
irs [-l] irs [-l]
irs -p PLAYLIST [-c COMMAND] [-l] irs -p PLAYLIST [-ng] [-c COMMAND] [-l]
irs -a ARTIST (-s SONG | -A ALBUM [-st SEARCH_TERMS]) [-c COMMAND] [-l] irs -a ARTIST (-s SONG | -A ALBUM [-st SEARCH_TERMS]) [-c COMMAND] [-l]
Options: Options:
@ -31,9 +31,10 @@ Options:
-st SEARCH_TERMS, --search-terms SEARCH_TERMS -st SEARCH_TERMS, --search-terms SEARCH_TERMS
Only use if calling -A/--album. Acts as extra search Only use if calling -A/--album. Acts as extra search
terms when looking for the album. terms when looking for the album.
-l, --choose-link If supplied, will bring up a console choice for what -l, --choose-link If supplied, will bring up a console choice for what
link you want to download based off a list of titles. link you want to download based off a list of titles.
-ng, --no-organize Only use if calling -p/--playlist. Forces all files
downloaded to be organized normally.
``` ```
[![asciicast](https://asciinema.org/a/bcs7i0sjmka052wsdyxg5xrug.png)](https://asciinema.org/a/bcs7i0sjmka052wsdyxg5xrug?speed=3&autoplay=true) [![asciicast](https://asciinema.org/a/bcs7i0sjmka052wsdyxg5xrug.png)](https://asciinema.org/a/bcs7i0sjmka052wsdyxg5xrug?speed=3&autoplay=true)

View file

@ -5,7 +5,7 @@ HELP = \
usage: usage:
irs (-h | -v) irs (-h | -v)
irs [-l] irs [-l]
irs -p PLAYLIST [-c COMMAND] [-l] irs -p PLAYLIST [-ng] [-c COMMAND] [-l]
irs -a ARTIST (-s SONG | -A ALBUM [-st SEARCH_TERMS]) [-c COMMAND] [-l] irs -a ARTIST (-s SONG | -A ALBUM [-st SEARCH_TERMS]) [-c COMMAND] [-l]
Options: Options:
@ -25,9 +25,10 @@ Options:
-st SEARCH_TERMS, --search-terms SEARCH_TERMS -st SEARCH_TERMS, --search-terms SEARCH_TERMS
Only use if calling -A/--album. Acts as extra search Only use if calling -A/--album. Acts as extra search
terms when looking for the album. terms when looking for the album.
-l, --choose-link If supplied, will bring up a console choice for what -l, --choose-link If supplied, will bring up a console choice for what
link you want to download based off a list of titles. link you want to download based off a list of titles.
-ng, --no-organize Only use if calling -p/--playlist. Forces all files
downloaded to be organized normally.
""" """
import argparse import argparse
@ -36,29 +37,51 @@ from sys import exit
from .manage import * from .manage import *
from .utils import * from .utils import *
def console(): def console(args):
system("clear") system("clear")
media = None media = None
while type(media) is not int: while type(media) is not int:
print (bc.HEADER) print (bc.HEADER)
print ("What type of media would you like to download?") print ("What type of media would you like to download?")
print ("\t1) Song\n\t2) Album") print ("\t1) Song")
print ("\t2) Album")
print ("\t3) Playlist")
try: try:
media = int(input(bc.YELLOW + bc.BOLD + ":: " + bc.ENDC)) media = int(input(bc.YELLOW + bc.BOLD + ":: " + bc.ENDC))
if media not in (1, 2, 3):
raise ValueError
except ValueError: except ValueError:
print (bc.FAIL + "\nPlease enter 1 or 2." + bc.ENDC) print (bc.FAIL + "\nPlease enter a valid number." + bc.ENDC)
print (bc.HEADER + "Artist of song/album ", end="") if media in (1, 2):
artist = input(bc.BOLD + bc.YELLOW + ": " + bc.ENDC) print (bc.HEADER + "Artist of song/album ", end="")
artist = input(bc.BOLD + bc.YELLOW + ": " + bc.ENDC)
if media == 1: if media == 1:
print (bc.HEADER + "Song you would like to download ", end="") print (bc.HEADER + "Song you would like to download ", end="")
song = input(bc.BOLD + bc.YELLOW + ": " + bc.ENDC) song = input(bc.BOLD + bc.YELLOW + ": " + bc.ENDC)
rip_mp3(song, artist) rip_mp3(song, artist, command=args.command, choose_link=args.link)
elif media == 2:
print (bc.HEADER + "Album you would like to download ", end="") elif media == 2:
album = input(bc.BOLD + bc.YELLOW + ": " + bc.ENDC) print (bc.HEADER + "Album you would like to download ", end="")
rip_album(album, artist) album = input(bc.BOLD + bc.YELLOW + ": " + bc.ENDC)
rip_album(album, artist, command=args.command, choose_link=args.link)
elif media == 3:
print (bc.HEADER + "Playlist file name ", end="")
playlist = input(bc.BOLD + bc.YELLOW + ": " + bc.ENDC)
organize = ""
while organize not in ("y", "n", "yes", "no", ""):
print (bc.HEADER + "Would you like to place all songs into a single folder? (Y/n)", end="")
organize = input(bc.BOLD + bc.YELLOW + ": " + bc.ENDC).lower()
if organize in ("y", "yes", ""):
rip_playlist(playlist, command=args.command, choose_link=args.link, \
no_organize=True)
elif organize in ("n", "no"):
rip_playlist(playlist, command=args.command, choose_link=args.link)
def main(): def main():
parser = argparse.ArgumentParser(add_help=False) parser = argparse.ArgumentParser(add_help=False)
@ -72,6 +95,8 @@ def main():
parser.add_argument('-p', '--playlist', dest="playlist", \ parser.add_argument('-p', '--playlist', dest="playlist", \
help="Specify playlist filename. Each line should be formatted like so: SONGNAME - ARTIST") help="Specify playlist filename. Each line should be formatted like so: SONGNAME - ARTIST")
parser.add_argument('-ng', '--no-organize', action="store_false", dest="no_organize", \
help="Only use if calling -p/--playlist. Forces all files downloaded to be organizes normally.")
media = parser.add_mutually_exclusive_group() media = parser.add_mutually_exclusive_group()
media.add_argument('-s', '--song', dest="song", help="Specify song name of the artist.") media.add_argument('-s', '--song', dest="song", help="Specify song name of the artist.")
@ -80,6 +105,9 @@ def main():
parser.add_argument('-st', '--search-terms', dest="search_terms", \ parser.add_argument('-st', '--search-terms', dest="search_terms", \
help="Only use if calling -A/--album. Acts as extra search terms for the album.") help="Only use if calling -A/--album. Acts as extra search terms for the album.")
parser.add_argument('-o', '--order-files', action='store_true', dest="order_files",\
help="Only use if callign with -p/--playlist or -A/--album. Adds a digit to front of each file specifying order.")
args = parser.parse_args() args = parser.parse_args()
@ -106,10 +134,10 @@ def main():
exit(1) exit(1)
elif not args.artist and not args.playlist: elif not args.artist and not args.playlist:
console() console(args)
elif args.playlist: elif args.playlist:
rip_playlist(args.playlist, args.command, choose_link=args.link) rip_playlist(args.playlist, args.command, choose_link=args.link, no_organize=args.no_organize)
elif args.artist: elif args.artist:
if args.album: if args.album:

View file

@ -32,7 +32,7 @@ def find_mp3(song, artist,
given_up_score = 0 given_up_score = 0
if not choose_link: if not choose_link:
print (bc.YELLOW + "Finding youtube link ...", end="\r") print (bc.YELLOW + "\nFinding youtube link ...", end="\r")
while in_title == False: while in_title == False:
i += 1 i += 1
given_up_score += 1 given_up_score += 1
@ -76,7 +76,9 @@ def find_mp3(song, artist,
def rip_playlist(file_name, def rip_playlist(file_name,
command=None, # Whether to run a special user-supplied command. command=None, # Whether to run a special user-supplied command.
choose_link=False, # Whether to allow the user to choose the link. choose_link=False, # Whether to allow the user to choose the link.
no_organize=True, # Whether to organize the file downloaded.
): ):
try: try:
file = open(file_name, 'r') file = open(file_name, 'r')
except Exception: except Exception:
@ -85,12 +87,46 @@ def rip_playlist(file_name,
errors = [] errors = []
song_number = 0
for line in file: for line in file:
if line.strip() == "":
pass
try: try:
arr = line.strip("\n").split(" - ") arr = line.strip("\n").split(" - ")
song = arr[0] song = arr[0]
artist = arr[1] artist = arr[1]
rip_mp3(song, artist, command=command)
if os.path.isdir(artist):
remove = False
else:
remove = True
location = rip_mp3(song, artist, command=command)
song_number += 1
locations = location.split("/")
# Enter... the reorganizing...
if no_organize:
folder_name = ("playlist - " + file_name)[:40]
if not os.path.isdir(folder_name):
os.makedirs(folder_name)
os.rename(location, "%s/%s - %s" % (folder_name, song_number, locations[-1]))
if remove:
import shutil # Only import this if I have to.
shutil.rmtree(locations[0])
if os.path.isfile(filename)
os.rename(filename, folder_name + "/" + filename)
os.rename(folder_name, folder_name.replace("playlist"))
except Exception as e: except Exception as e:
errors.append(line + color(" : ", ["YELLOW"]) + bc.FAIL + str(e) + bc.ENDC) errors.append(line + color(" : ", ["YELLOW"]) + bc.FAIL + str(e) + bc.ENDC)
@ -176,7 +212,7 @@ def rip_mp3(song, artist,
tracknum=None, # to specify the tracknumber in the album. tracknum=None, # to specify the tracknumber in the album.
album_art_url=None, # if you want to save a lot of time trying to find album cover. album_art_url=None, # if you want to save a lot of time trying to find album cover.
command=None, # For running a command with the song's location. command=None, # For running a command with the song's location.
choose_link=False # Whether to allow the user to choose the link. choose_link=False, # Whether to allow the user to choose the link.
): ):
audio_code = find_mp3(song, artist) audio_code = find_mp3(song, artist)
@ -204,7 +240,6 @@ def rip_mp3(song, artist,
if not part_of_album: if not part_of_album:
location = artist_folder location = artist_folder
if album and part_of_album: if album and part_of_album:
album_folder = artist + "/" + album album_folder = artist + "/" + album
if not os.path.isdir(album_folder): if not os.path.isdir(album_folder):
@ -226,3 +261,5 @@ def rip_mp3(song, artist,
if command: if command:
loc = location + "/" + filename loc = location + "/" + filename
os.system((command.replace("%(loc)s", '"%s"' % loc) + " &")) os.system((command.replace("%(loc)s", '"%s"' % loc) + " &"))
return (location + "/" + filename)

View file

@ -2,7 +2,7 @@ from setuptools import setup
setup( setup(
name='irs', name='irs',
version='1.5.10', version='1.6.10',
description='A music downloader that just gets metadata.', description='A music downloader that just gets metadata.',
url='https://github.com/kepoorhampond/irs', url='https://github.com/kepoorhampond/irs',
author='Kepoor Hampond', author='Kepoor Hampond',

View file

View file

@ -0,0 +1,153 @@
#!/usr/bin python
HELP = \
"""
usage:
irs (-h | -v)
irs [-l]
irs -p PLAYLIST [-ng] [-c COMMAND] [-l]
irs -a ARTIST (-s SONG | -A ALBUM [-st SEARCH_TERMS]) [-c COMMAND] [-l]
Options:
-h, --help show this help message and exit
-v, --version Display the version and exit.
-c COMMAND, --command COMMAND
Run a background command with each song's location.
Example: `-c "rhythmbox %(loc)s"`
-a ARTIST, --artist ARTIST
Specify the artist name.
-p PLAYLIST, --playlist PLAYLIST
Specify playlist filename. Each line in the file
should be formatted like so: `SONGNAME - ARTIST`
-s SONG, --song SONG Specify song name of the artist.
-A ALBUM, --album ALBUM
Specify album name of the artist.
-st SEARCH_TERMS, --search-terms SEARCH_TERMS
Only use if calling -A/--album. Acts as extra search
terms when looking for the album.
-l, --choose-link If supplied, will bring up a console choice for what
link you want to download based off a list of titles.
-ng, --no-organize Only use if calling -p/--playlist. Forces all files
downloaded to be organized normally.
"""
import argparse
from os import system
from sys import exit
from .manage import *
from .utils import *
def console(args):
system("clear")
media = None
while type(media) is not int:
print (bc.HEADER)
print ("What type of media would you like to download?")
print ("\t1) Song")
print ("\t2) Album")
print ("\t3) Playlist")
try:
media = int(input(bc.YELLOW + bc.BOLD + ":: " + bc.ENDC))
if media not in (1, 2, 3):
raise ValueError
except ValueError:
print (bc.FAIL + "\nPlease enter a valid number." + bc.ENDC)
if media in (1, 2):
print (bc.HEADER + "Artist of song/album ", end="")
artist = input(bc.BOLD + bc.YELLOW + ": " + bc.ENDC)
if media == 1:
print (bc.HEADER + "Song you would like to download ", end="")
song = input(bc.BOLD + bc.YELLOW + ": " + bc.ENDC)
rip_mp3(song, artist, command=args.command, choose_link=args.link)
elif media == 2:
print (bc.HEADER + "Album you would like to download ", end="")
album = input(bc.BOLD + bc.YELLOW + ": " + bc.ENDC)
rip_album(album, artist, command=args.command, choose_link=args.link)
elif media == 3:
print (bc.HEADER + "Playlist file name ", end="")
playlist = input(bc.BOLD + bc.YELLOW + ": " + bc.ENDC)
organize = ""
while organize not in ("y", "n", "yes", "no", ""):
print (bc.HEADER + "Would you like to place all songs into a single folder? (Y/n)", end="")
organize = input(bc.BOLD + bc.YELLOW + ": " + bc.ENDC).lower()
if organize in ("y", "yes", ""):
rip_playlist(playlist, command=args.command, choose_link=args.link, \
no_organize=True)
elif organize in ("n", "no"):
rip_playlist(playlist, command=args.command, choose_link=args.link)
def main():
parser = argparse.ArgumentParser(add_help=False)
parser.add_argument('-h', '--help', action='store_true', dest='help')
parser.add_argument('-v', '--version', dest="version", action='store_true', help="Display the version and exit.")
parser.add_argument('-c', '--command', dest="command", help="Run a background command with each song's location.")
parser.add_argument('-a', '--artist', dest="artist", help="Specify the artist name.")
parser.add_argument('-l', '--choose-link', action='store_true', dest="link", \
help="Whether or not to choose the link from a list of titles.")
parser.add_argument('-p', '--playlist', dest="playlist", \
help="Specify playlist filename. Each line should be formatted like so: SONGNAME - ARTIST")
parser.add_argument('-ng', '--no-organize', action="store_false", dest="no_organize", \
help="Only use if calling -p/--playlist. Forces all files downloaded to be organizes normally.")
media = parser.add_mutually_exclusive_group()
media.add_argument('-s', '--song', dest="song", help="Specify song name of the artist.")
media.add_argument('-A', '--album', dest="album", help="Specify album name of the artist.")
parser.add_argument('-st', '--search-terms', dest="search_terms", \
help="Only use if calling -A/--album. Acts as extra search terms for the album.")
parser.add_argument('-o', '--order-files', action='store_true', dest="order_files",\
help="Only use if callign with -p/--playlist or -A/--album. Adds a digit to front of each file specifying order.")
args = parser.parse_args()
if args.help:
global HELP
print (HELP)
elif args.version:
import pkg_resources
print ("\n\n" + color("Ingenious Redistribution System", ["HEADER", "BOLD"]))
print ("Homepage: " + color("https://github.com/kepoorhampond/irs", ["OKGREEN"]))
print ("License: " + color("The GNU", ["YELLOW"]) + " (http://www.gnu.org/licenses/gpl.html)")
print ("Version: " + pkg_resources.get_distribution("irs").version)
print ("\n")
exit(0)
elif not args.album and args.search_terms:
parser.error("error: must supply -A/--album if you are going to supply -st/--search-terms")
exit(1)
elif args.artist and not (args.album or args.song):
print ("error: must specify -A/--album or -s/--song if specifying -a/--artist")
exit(1)
elif not args.artist and not args.playlist:
console(args)
elif args.playlist:
rip_playlist(args.playlist, args.command, choose_link=args.link, no_organize=args.no_organize)
elif args.artist:
if args.album:
rip_album(args.album, args.artist, command=args.command, \
search=args.search_terms, choose_link=args.link)
elif args.song:
rip_mp3(args.song, args.artist, command=args.command, choose_link=args.link)
if __name__ == "__main__":
main()

View file

@ -0,0 +1,265 @@
# Powered by:
import youtube_dl
# Info getting
from urllib.request import urlopen
from urllib.parse import urlencode
# Info parsing
from re import findall
import os, json
from bs4 import BeautifulSoup
# Local utils
from .utils import *
from .metadata import *
def find_mp3(song, artist,
choose_link=False, # Whether to allow the user to choose the link.
):
os.system("clear")
print (color(song, ["BOLD", "UNDERLINE"]) + ' by ' + color(artist, ["BOLD", "UNDERLINE"]))
search_terms = song + " " + artist
query_string = urlencode({"search_query" : (search_terms)})
html_content = urlopen("http://www.youtube.com/results?" + query_string)
search_results = findall(r'href=\"\/watch\?v=(.{11})', html_content.read().decode())
in_title = False
i = -1
given_up_score = 0
if not choose_link:
print (bc.YELLOW + "\nFinding youtube link ...", end="\r")
while in_title == False:
i += 1
given_up_score += 1
if given_up_score >= 10:
in_title = True
audio_url = ("http://www.youtube.com/watch?v=" + search_results[i])
title = strip_special_chars((BeautifulSoup(urlopen(audio_url), 'html.parser')).title.string.lower())
song_title = song.lower().split("/")
for song in song_title:
song = strip_special_chars(song)
if song in title and "full album" not in title:
in_title = True
print (bc.OKGREEN + "Found youtube link! \n" + bc.ENDC)
else:
results = []
print (bc.YELLOW + "Finding links ... " + bc.ENDC, end="\r")
for key in search_results[:10]:
results.append(BeautifulSoup(urlopen(("http://www.youtube.com/watch?v="\
+ key)), 'html.parser').title.string.replace(" - YouTube" , ""))
valid_choice = False
while valid_choice == False:
print (bc.HEADER + "What song would you like to download?")
index = 0
for result in results:
index += 1
print (" %s) %s" % (index, result))
i = int(input(bc.YELLOW + bc.BOLD + ":: " + bc.ENDC))
if i in tuple(range(1, 11)):
i -= 1
valid_choice = True
return search_results[i]
def rip_playlist(file_name,
command=None, # Whether to run a special user-supplied command.
choose_link=False, # Whether to allow the user to choose the link.
no_organize=True, # Whether to organize the file downloaded.
):
try:
file = open(file_name, 'r')
except Exception:
print (file_name + bc.FAIL + " could not be found." + bc.ENDC)
exit(1)
errors = []
song_number = 0
for line in file:
if line.strip() == "":
pass
try:
arr = line.strip("\n").split(" - ")
song = arr[0]
artist = arr[1]
if os.path.isdir(artist):
remove = False
else:
remove = True
location = rip_mp3(song, artist, command=command)
song_number += 1
locations = location.split("/")
# Enter... the reorganizing...
if no_organize:
folder_name = ("playlist - " + file_name)[:40]
if not os.path.isdir(folder_name):
os.makedirs(folder_name)
os.rename(location, "%s/%s - %s" % (folder_name, song_number, locations[-1]))
if remove:
import shutil # Only import this if I have to.
shutil.rmtree(locations[0])
if os.path.isfile(filename)
os.rename(filename, folder_name + "/" + filename)
os.rename(folder_name, folder_name.replace("playlist"))
except Exception as e:
errors.append(line + color(" : ", ["YELLOW"]) + bc.FAIL + str(e) + bc.ENDC)
if len(errors) > 0:
print (bc.FAIL + "Something was wrong with the formatting of the following lines:" + bc.ENDC)
for i in errors:
print ("\t%s" % i)
def rip_album(album, artist,
tried=False, # for if it can't find the album the first time
search="album", # ditto
command=None, # For running a command with the song's location
choose_link=False # Whether to allow the user to choose the link.
):
if search in (None, False):
search = "album"
visible_texts = search_google(album, artist, search)
errors = []
try:
songs = []
num = True
for i, j in enumerate(visible_texts):
if 'Songs' in j:
if visible_texts[i + 1] == "1":
indexed = i
while num == True:
try:
if type(int(visible_texts[indexed])) is int:
a = visible_texts[indexed + 1]
songs.append(a)
indexed += 1
except:
indexed += 1
if indexed >= 1000:
num = False
else:
pass
print ("")
print (bc.HEADER + "Album Contents:" + bc.ENDC)
for i, j in enumerate(songs):
print (bc.OKBLUE + " - " + j + bc.ENDC)
print (bc.YELLOW + "\nFinding album cover ... " + bc.ENDC, end="\r")
album_art_url = get_albumart_url(album, artist)
print (bc.OKGREEN + "Album cover found: " + bc.ENDC + album_art_url)
for i, j in enumerate(songs):
song = j
print (color("\n%s/%s - " % (i + 1, len(songs)), ["UNDERLINE"]), end="")
rip_mp3(j, artist, part_of_album=True, album=album, tracknum=i + 1, \
album_art_url=album_art_url, command=command, choose_link=choose_link)
if len(errors) > 0:
for error in errors: print (error)
else:
print (bc.BOLD + bc.UNDERLINE + album + bc.ENDC + bc.OKGREEN + " downloaded successfully!\n")
except Exception as e:
if str(e) == "local variable 'indexed' referenced before assignment" or str(e) == 'list index out of range':
if tried != True:
print (bc.OKBLUE + "Trying to find album ..." + bc.ENDC)
rip_album(album, artist, tried=True, search="", choose_link=choose_link)
else:
print (bc.FAIL + 'Could not find album "%s"' % album + bc.ENDC)
else:
errors.append(bc.FAIL + "There was a problem with downloading: " + bc.ENDC + song + "\n" + str(e))
pass
def rip_mp3(song, artist,
part_of_album=False, # neccessary for creating folders.
album=None, # if you want to specify an album and save a bit of time.
tracknum=None, # to specify the tracknumber in the album.
album_art_url=None, # if you want to save a lot of time trying to find album cover.
command=None, # For running a command with the song's location.
choose_link=False, # Whether to allow the user to choose the link.
):
audio_code = find_mp3(song, artist)
filename = strip_special_chars(song) + ".mp3"
ydl_opts = {
'format': 'bestaudio/best',
#'quiet': True,
'postprocessors': [{
'key': 'FFmpegExtractAudio',
'preferredcodec': 'mp3',
}],
}
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
ydl.download(["http://www.youtube.com/watch?v=" + audio_code])
artist_folder = artist
if not os.path.isdir(artist_folder):
os.makedirs(artist_folder)
if not part_of_album:
location = artist_folder
if album and part_of_album:
album_folder = artist + "/" + album
if not os.path.isdir(album_folder):
os.makedirs(album_folder)
location = album_folder
for file in os.listdir("."):
if audio_code in file:
os.rename(file, location + "/" + filename)
parse_metadata(song, artist, location, filename, tracknum=tracknum, album=album, album_art_url=album_art_url)
print (color(song, ["BOLD", "UNDERLINE"]) + bc.OKGREEN + ' downloaded successfully!'+ bc.ENDC)
print ("")
if command:
loc = location + "/" + filename
os.system((command.replace("%(loc)s", '"%s"' % loc) + " &"))
return (location + "/" + filename)

View file

@ -0,0 +1,166 @@
# MP3 Metadata editing
from mutagen.mp3 import MP3, EasyMP3
from mutagen.easyid3 import EasyID3
from mutagen.id3 import ID3, APIC
# Info getting
from urllib.parse import quote_plus, quote
from urllib.request import urlopen, Request
# Info parsing
import json
from re import match
from bs4 import BeautifulSoup
# Local utils
from .utils import *
def search_google(song, artist, search_terms=""):
def visible(element):
if element.parent.name in ['style', 'script', '[document]', 'head', 'title']:
return False
elif match('<!--.*-->', str(element)):
return False
return True
string = "%s %s %s" % (song, artist, search_terms)
filename = 'http://www.google.com/search?q=' + quote_plus(string)
hdr = {
'User-Agent':'Mozilla/5.0',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
}
texts = BeautifulSoup(urlopen(Request(filename, \
headers=hdr)).read(), 'html.parser').findAll(text=True)
return list(filter(visible, texts))
def parse_metadata(song, artist, location, filename,
tracknum="",
album="",
album_art_url=""
):
googled = search_google(song, artist)
mp3file = MP3("%s/%s" % (location, filename), ID3=EasyID3)
# Song title
mp3file['title'] = song
mp3file.save()
print("")
print (bc.OKGREEN + "Title parsed: " + bc.ENDC + mp3file['title'][0])
# Artist
mp3file['artist'] = artist
mp3file.save()
print (bc.OKGREEN + "Artist parsed: " + bc.ENDC + mp3file['artist'][0])
# Album
try:
if not album:
for i, j in enumerate(googled):
if "Album:" in j:
album = (googled[i + 1])
except Exception as e:
album = None
if album:
mp3file['album'] = album
print (bc.OKGREEN + "Album parsed: " + bc.ENDC + mp3file['album'][0])
else:
print (bc.FAIL + "Album not parsed.")
mp3file.save()
# Release date
for i, j in enumerate(googled):
if "Released:" in j:
date = (googled[i + 1])
try:
mp3file['date'] = date
print (bc.OKGREEN + "Release date parsed: " + bc.ENDC + mp3file['date'][0])
except Exception:
mp3file['date'] = ""
pass
mp3file.save()
# Track number
if tracknum:
mp3file['tracknumber'] = str(tracknum)
mp3file.save()
# Album art
try:
if album:
if not album_art_url:
print (bc.YELLOW + "Parsing album art ..." + bc.ENDC, end="\r")
temp_url = get_albumart_url(album, artist)
embed_mp3(temp_url, location + "/" + filename)
print (bc.OKGREEN + "Album art parsed: " + bc.ENDC + temp_url)
else: # If part of an album, it should do this.
embed_mp3(album_art_url, location + "/" + filename)
print (bc.OKGREEN + "Album art parsed." + bc.ENDC)
except Exception as e:
print (bc.FAIL + "Album art not parsed: " + bc.ENDC + str(e))
def embed_mp3(albumart_url, song_location):
image = urlopen(albumart_url)
audio = EasyMP3(song_location, ID3=ID3)
try:
audio.add_tags()
except Exception as e:
pass
audio.tags.add(
APIC(
encoding = 3,
mime = 'image/png',
type = 3,
desc = 'Cover',
data = image.read()
)
)
audio.save()
def get_albumart_url(album, artist):
def test_404(url):
try:
urlopen(albumart).read()
except Exception:
return False
return True
tries = 0
album = "%s %s Album Art" % (artist, album)
url = ("https://www.google.com/search?q=" + quote(album.encode('utf-8')) + "&source=lnms&tbm=isch")
header = {
'User-Agent':
'''
Mozilla/5.0 (Windows NT 6.1; WOW64)
AppleWebKit/537.36 (KHTML,like Gecko)
Chrome/43.0.2357.134 Safari/537.36
'''
}
soup = BeautifulSoup(urlopen(Request(url, headers=header)), "html.parser")
albumart_divs = soup.findAll("div", {"class": "rg_meta"})
albumart = json.loads(albumart_divs[tries].text)["ou"]
while not test_404(albumart):
tries += 1
albumart = json.loads(albumart_divs[tries].text)["ou"]
return albumart

View file

@ -0,0 +1,55 @@
import sys
def strip_special_chars(string):
special_chars = "\ / : * ? \" < > | - ( )".split(" ")
for char in special_chars:
string.replace(char, "")
return string
def supports_color():
"""
Returns True if the running system's terminal supports color, and False
otherwise.
"""
plat = sys.platform
supported_platform = plat != 'Pocket PC' and (plat != 'win32' or
'ANSICON' in os.environ)
# isatty is not always implemented, #6223.
is_a_tty = hasattr(sys.stdout, 'isatty') and sys.stdout.isatty()
if not supported_platform or not is_a_tty:
return False
return True
if supports_color():
class bc:
HEADER = '\033[95m'
OKBLUE = '\033[94m'
OKGREEN = '\033[32m'
WARNING = '\033[93m'
FAIL = '\033[91m'
ENDC = '\033[0m'
BOLD = '\033[1m'
UNDERLINE = '\033[4m'
GRAY = '\033[30m'
YELLOW = '\033[33m'
else:
class bc:
HEADER = ''
OKBLUE = ''
OKGREEN = ''
WARNING = ''
FAIL = ''
ENDC = ''
BOLD = ''
UNDERLINE = ''
GRAY = ''
YELLOW = ''
def color(text, colors=[]):
if colors == []:
raise "Must have definitions when calling color(text, colors=[])"
color_string = ""
for color in colors:
color_string += "bc.%s + " % color
color_string = color_string[:-2]
return (bc.ENDC + eval(color_string) + text + bc.ENDC)

BIN
v2.0/dist/irs-1.5.10-py3.5.egg vendored Normal file

Binary file not shown.

View file

@ -0,0 +1,10 @@
Metadata-Version: 1.0
Name: irs
Version: 1.5.10
Summary: A music downloader that just gets metadata.
Home-page: https://github.com/kepoorhampond/irs
Author: Kepoor Hampond
Author-email: kepoorh@gmail.com
License: GNU
Description: UNKNOWN
Platform: UNKNOWN

View file

@ -0,0 +1,13 @@
setup.cfg
setup.py
irs/__init__.py
irs/__main__.py
irs/manage.py
irs/metadata.py
irs/utils.py
irs.egg-info/PKG-INFO
irs.egg-info/SOURCES.txt
irs.egg-info/dependency_links.txt
irs.egg-info/entry_points.txt
irs.egg-info/requires.txt
irs.egg-info/top_level.txt

View file

@ -0,0 +1 @@

View file

@ -0,0 +1,3 @@
[console_scripts]
irs = irs.__main__:main

View file

@ -0,0 +1,4 @@
bs4
mutagen
youtube-dl
requests

View file

@ -0,0 +1 @@
irs

80
v2.0/irs/__main__.py Normal file
View file

@ -0,0 +1,80 @@
#!/usr/bin python
HELP = \
"""
usage:
irs (-h | -v)
irs [-l]
irs -p PLAYLIST [-ng] [-c COMMAND] [-l]
irs -a ARTIST (-s SONG | -A ALBUM [-st SEARCH_TERMS]) [-c COMMAND] [-l]
Options:
-h, --help show this help message and exit
-v, --version Display the version and exit.
-c COMMAND, --command COMMAND
Run a background command with each song's location.
Example: `-c "rhythmbox %(loc)s"`
-a ARTIST, --artist ARTIST
Specify the artist name.
-p PLAYLIST, --playlist PLAYLIST
Specify playlist filename. Each line in the file
should be formatted like so: `SONGNAME - ARTIST`
-s SONG, --song SONG Specify song name of the artist.
-A ALBUM, --album ALBUM
Specify album name of the artist.
-st SEARCH_TERMS, --search-terms SEARCH_TERMS
Only use if calling -A/--album. Acts as extra search
terms when looking for the album.
-l, --choose-link If supplied, will bring up a console choice for what
link you want to download based off a list of titles.
-ng, --no-organize Only use if calling -p/--playlist. Forces all files
downloaded to be organized normally.
"""
# For exiting
from sys import exit
# Parsing args
import argparse
# Import the manager
from .manager import Manager
def main():
parser = argparse.ArgumentParser(add_help=False)
parser.add_argument('-h', '--help', action='store_true', dest='help')
parser.add_argument('-v', '--version', dest="version", action='store_true', help="Display the version and exit.")
parser.add_argument('-c', '--command', dest="command", help="Run a background command with each song's location.")
parser.add_argument('-a', '--artist', dest="artist", help="Specify the artist name.")
parser.add_argument('-l', '--choose-link', action='store_true', dest="link", \
help="Whether or not to choose the link from a list of titles.")
parser.add_argument('-p', '--playlist', dest="playlist", \
help="Specify playlist filename. Each line should be formatted like so: SONGNAME - ARTIST")
parser.add_argument('-ng', '--no-organize', action="store_false", dest="no_organize", \
help="Only use if calling -p/--playlist. Forces all files downloaded to be organizes normally.")
media = parser.add_mutually_exclusive_group()
media.add_argument('-s', '--song', dest="song", help="Specify song name of the artist.")
media.add_argument('-A', '--album', dest="album", help="Specify album name of the artist.")
parser.add_argument('-st', '--search-terms', dest="search_terms", \
help="Only use if calling -A/--album. Acts as extra search terms for the album.")
parser.add_argument('-o', '--order-files', action='store_true', dest="order_files",\
help="Only use if callign with -p/--playlist or -A/--album. Adds a digit to front of each file specifying order.")
args = parser.parse_args()
if args.help:
global HELP
print (HELP)
exit(1)
Manager(args).main
if __name__ == "__main__":
main()

42
v2.0/irs/manager.py Normal file
View file

@ -0,0 +1,42 @@
from os import system
from sys import exit
from .manage import *
from .utils import *
class Manager:
def __init__(self, args):
self.args = args
def main():
args = self.a
if args.version:
import pkg_resources
print ("\n\n" + color("Ingenious Redistribution System", ["HEADER", "BOLD"]))
print ("Homepage: " + color("https://github.com/kepoorhampond/irs", ["OKGREEN"]))
print ("License: " + color("The GNU", ["YELLOW"]) + " (http://www.gnu.org/licenses/gpl.html)")
print ("Version: " + pkg_resources.get_distribution("irs").version)
print ("\n")
exit(0)
elif not args.album and args.search_terms:
parser.error("error: must supply -A/--album if you are going to supply -st/--search-terms")
exit(1)
elif args.artist and not (args.album or args.song):
print ("error: must specify -A/--album or -s/--song if specifying -a/--artist")
exit(1)
elif not args.artist and not args.playlist:
console(args)
elif args.playlist:
rip_playlist(args.playlist, args.command, choose_link=args.link, no_organize=args.no_organize)
elif args.artist:
if args.album:
rip_album(args.album, args.artist, command=args.command, \
search=args.search_terms, choose_link=args.link)
elif args.song:
rip_mp3(args.song, args.artist, command=args.command, choose_link=args.link)

89
v2.0/irs/metadata.py Normal file
View file

@ -0,0 +1,89 @@
# MP3 Metadata editing
from mutagen.mp3 import MP3, EasyMP3
from mutagen.easyid3 import EasyID3
from mutagen.id3 import ID3, APIC
# Info getting
from urllib.parse import quote_plus, quote
from urllib.request import urlopen, Request
# Info parsing
import json
from re import match
from bs4 import BeautifulSoup
# Local utils
from .utils import *
class Metadata:
def __init__(self, song, artist, location):
self.song = song
self.artist = artist
self.location = location
self.info = search_google(song, artist)
self.mp3 = MP3("%s/%s" % (location, filename), ID3=EasyID3)
def parse_title():
self.mp3['title'] = self.song
self.mp3.save()
print (bc.OKGREEN + "Title parsed: " + bc.ENDC + self.mp3['title'][0])
def parse_artist():
self.mp3['artist'] = self.artist
self.mp3.save()
print (bc.OKGREEN + "Artist parsed: " + bc.ENDC + self.mp3['artist'][0])
def parse_album(album=None):
try:
if not album:
for i, j in enumerate(self.info):
if "Album:" in j:
album = (self.info[i + 1])
except Exception as e:
album = None
if album:
self.mp3['album'] = album
print (bc.OKGREEN + "Album parsed: " + bc.ENDC + self.mp3['album'][0])
else:
print (bc.FAIL + "Album not parsed.")
self.mp3.save()
def parse_release_date():
for i, j in enumerate(self.info):
if "Released:" in j:
date = (self.info[i + 1])
try:
self.mp3['date'] = date
print (bc.OKGREEN + "Release date parsed: " + bc.ENDC + self.mp3['date'][0])
except Exception:
self.mp3['date'] = ""
pass
self.mp3.save()
def search_google(self, song, artist, search_terms=""):
def visible(element):
if element.parent.name in ['style', 'script', '[document]', 'head', 'title']:
return False
elif match('<!--.*-->', str(element)):
return False
return True
search_terms = "%s %s %s" % (song, artist, search_terms)
url = 'http://www.google.com/search?q=' + quote_plus(string)
hdr = {
'User-Agent':'Mozilla/5.0',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
}
texts = BeautifulSoup(urlopen(Request(filename, \
headers=hdr)).read(), 'html.parser').findAll(text=True)
return list(filter(visible, texts))

55
v2.0/irs/utils.py Normal file
View file

@ -0,0 +1,55 @@
import sys
def strip_special_chars(string):
special_chars = "\ / : * ? \" < > | - ( )".split(" ")
for char in special_chars:
string.replace(char, "")
return string
def supports_color():
"""
Returns True if the running system's terminal supports color, and False
otherwise.
"""
plat = sys.platform
supported_platform = plat != 'Pocket PC' and (plat != 'win32' or
'ANSICON' in os.environ)
# isatty is not always implemented, #6223.
is_a_tty = hasattr(sys.stdout, 'isatty') and sys.stdout.isatty()
if not supported_platform or not is_a_tty:
return False
return True
if supports_color():
class bc:
HEADER = '\033[95m'
OKBLUE = '\033[94m'
OKGREEN = '\033[32m'
WARNING = '\033[93m'
FAIL = '\033[91m'
ENDC = '\033[0m'
BOLD = '\033[1m'
UNDERLINE = '\033[4m'
GRAY = '\033[30m'
YELLOW = '\033[33m'
else:
class bc:
HEADER = ''
OKBLUE = ''
OKGREEN = ''
WARNING = ''
FAIL = ''
ENDC = ''
BOLD = ''
UNDERLINE = ''
GRAY = ''
YELLOW = ''
def color(text, colors=[]):
if colors == []:
raise "Must have definitions when calling color(text, colors=[])"
color_string = ""
for color in colors:
color_string += "bc.%s + " % color
color_string = color_string[:-2]
return (bc.ENDC + eval(color_string) + text + bc.ENDC)

0
v2.0/old/__init__.py Normal file
View file

153
v2.0/old/__main__.py Normal file
View file

@ -0,0 +1,153 @@
#!/usr/bin python
HELP = \
"""
usage:
irs (-h | -v)
irs [-l]
irs -p PLAYLIST [-ng] [-c COMMAND] [-l]
irs -a ARTIST (-s SONG | -A ALBUM [-st SEARCH_TERMS]) [-c COMMAND] [-l]
Options:
-h, --help show this help message and exit
-v, --version Display the version and exit.
-c COMMAND, --command COMMAND
Run a background command with each song's location.
Example: `-c "rhythmbox %(loc)s"`
-a ARTIST, --artist ARTIST
Specify the artist name.
-p PLAYLIST, --playlist PLAYLIST
Specify playlist filename. Each line in the file
should be formatted like so: `SONGNAME - ARTIST`
-s SONG, --song SONG Specify song name of the artist.
-A ALBUM, --album ALBUM
Specify album name of the artist.
-st SEARCH_TERMS, --search-terms SEARCH_TERMS
Only use if calling -A/--album. Acts as extra search
terms when looking for the album.
-l, --choose-link If supplied, will bring up a console choice for what
link you want to download based off a list of titles.
-ng, --no-organize Only use if calling -p/--playlist. Forces all files
downloaded to be organized normally.
"""
import argparse
from os import system
from sys import exit
from .manage import *
from .utils import *
def console(args):
system("clear")
media = None
while type(media) is not int:
print (bc.HEADER)
print ("What type of media would you like to download?")
print ("\t1) Song")
print ("\t2) Album")
print ("\t3) Playlist")
try:
media = int(input(bc.YELLOW + bc.BOLD + ":: " + bc.ENDC))
if media not in (1, 2, 3):
raise ValueError
except ValueError:
print (bc.FAIL + "\nPlease enter a valid number." + bc.ENDC)
if media in (1, 2):
print (bc.HEADER + "Artist of song/album ", end="")
artist = input(bc.BOLD + bc.YELLOW + ": " + bc.ENDC)
if media == 1:
print (bc.HEADER + "Song you would like to download ", end="")
song = input(bc.BOLD + bc.YELLOW + ": " + bc.ENDC)
rip_mp3(song, artist, command=args.command, choose_link=args.link)
elif media == 2:
print (bc.HEADER + "Album you would like to download ", end="")
album = input(bc.BOLD + bc.YELLOW + ": " + bc.ENDC)
rip_album(album, artist, command=args.command, choose_link=args.link)
elif media == 3:
print (bc.HEADER + "Playlist file name ", end="")
playlist = input(bc.BOLD + bc.YELLOW + ": " + bc.ENDC)
organize = ""
while organize not in ("y", "n", "yes", "no", ""):
print (bc.HEADER + "Would you like to place all songs into a single folder? (Y/n)", end="")
organize = input(bc.BOLD + bc.YELLOW + ": " + bc.ENDC).lower()
if organize in ("y", "yes", ""):
rip_playlist(playlist, command=args.command, choose_link=args.link, \
no_organize=True)
elif organize in ("n", "no"):
rip_playlist(playlist, command=args.command, choose_link=args.link)
def main():
parser = argparse.ArgumentParser(add_help=False)
parser.add_argument('-h', '--help', action='store_true', dest='help')
parser.add_argument('-v', '--version', dest="version", action='store_true', help="Display the version and exit.")
parser.add_argument('-c', '--command', dest="command", help="Run a background command with each song's location.")
parser.add_argument('-a', '--artist', dest="artist", help="Specify the artist name.")
parser.add_argument('-l', '--choose-link', action='store_true', dest="link", \
help="Whether or not to choose the link from a list of titles.")
parser.add_argument('-p', '--playlist', dest="playlist", \
help="Specify playlist filename. Each line should be formatted like so: SONGNAME - ARTIST")
parser.add_argument('-ng', '--no-organize', action="store_false", dest="no_organize", \
help="Only use if calling -p/--playlist. Forces all files downloaded to be organizes normally.")
media = parser.add_mutually_exclusive_group()
media.add_argument('-s', '--song', dest="song", help="Specify song name of the artist.")
media.add_argument('-A', '--album', dest="album", help="Specify album name of the artist.")
parser.add_argument('-st', '--search-terms', dest="search_terms", \
help="Only use if calling -A/--album. Acts as extra search terms for the album.")
parser.add_argument('-o', '--order-files', action='store_true', dest="order_files",\
help="Only use if callign with -p/--playlist or -A/--album. Adds a digit to front of each file specifying order.")
args = parser.parse_args()
if args.help:
global HELP
print (HELP)
elif args.version:
import pkg_resources
print ("\n\n" + color("Ingenious Redistribution System", ["HEADER", "BOLD"]))
print ("Homepage: " + color("https://github.com/kepoorhampond/irs", ["OKGREEN"]))
print ("License: " + color("The GNU", ["YELLOW"]) + " (http://www.gnu.org/licenses/gpl.html)")
print ("Version: " + pkg_resources.get_distribution("irs").version)
print ("\n")
exit(0)
elif not args.album and args.search_terms:
parser.error("error: must supply -A/--album if you are going to supply -st/--search-terms")
exit(1)
elif args.artist and not (args.album or args.song):
print ("error: must specify -A/--album or -s/--song if specifying -a/--artist")
exit(1)
elif not args.artist and not args.playlist:
console(args)
elif args.playlist:
rip_playlist(args.playlist, args.command, choose_link=args.link, no_organize=args.no_organize)
elif args.artist:
if args.album:
rip_album(args.album, args.artist, command=args.command, \
search=args.search_terms, choose_link=args.link)
elif args.song:
rip_mp3(args.song, args.artist, command=args.command, choose_link=args.link)
if __name__ == "__main__":
main()

265
v2.0/old/manage.py Normal file
View file

@ -0,0 +1,265 @@
# Powered by:
import youtube_dl
# Info getting
from urllib.request import urlopen
from urllib.parse import urlencode
# Info parsing
from re import findall
import os, json
from bs4 import BeautifulSoup
# Local utils
from .utils import *
from .metadata import *
def find_mp3(song, artist,
choose_link=False, # Whether to allow the user to choose the link.
):
os.system("clear")
print (color(song, ["BOLD", "UNDERLINE"]) + ' by ' + color(artist, ["BOLD", "UNDERLINE"]))
search_terms = song + " " + artist
query_string = urlencode({"search_query" : (search_terms)})
html_content = urlopen("http://www.youtube.com/results?" + query_string)
search_results = findall(r'href=\"\/watch\?v=(.{11})', html_content.read().decode())
in_title = False
i = -1
given_up_score = 0
if not choose_link:
print (bc.YELLOW + "\nFinding youtube link ...", end="\r")
while in_title == False:
i += 1
given_up_score += 1
if given_up_score >= 10:
in_title = True
audio_url = ("http://www.youtube.com/watch?v=" + search_results[i])
title = strip_special_chars((BeautifulSoup(urlopen(audio_url), 'html.parser')).title.string.lower())
song_title = song.lower().split("/")
for song in song_title:
song = strip_special_chars(song)
if song in title and "full album" not in title:
in_title = True
print (bc.OKGREEN + "Found youtube link! \n" + bc.ENDC)
else:
results = []
print (bc.YELLOW + "Finding links ... " + bc.ENDC, end="\r")
for key in search_results[:10]:
results.append(BeautifulSoup(urlopen(("http://www.youtube.com/watch?v="\
+ key)), 'html.parser').title.string.replace(" - YouTube" , ""))
valid_choice = False
while valid_choice == False:
print (bc.HEADER + "What song would you like to download?")
index = 0
for result in results:
index += 1
print (" %s) %s" % (index, result))
i = int(input(bc.YELLOW + bc.BOLD + ":: " + bc.ENDC))
if i in tuple(range(1, 11)):
i -= 1
valid_choice = True
return search_results[i]
def rip_playlist(file_name,
command=None, # Whether to run a special user-supplied command.
choose_link=False, # Whether to allow the user to choose the link.
no_organize=True, # Whether to organize the file downloaded.
):
try:
file = open(file_name, 'r')
except Exception:
print (file_name + bc.FAIL + " could not be found." + bc.ENDC)
exit(1)
errors = []
song_number = 0
for line in file:
if line.strip() == "":
pass
try:
arr = line.strip("\n").split(" - ")
song = arr[0]
artist = arr[1]
if os.path.isdir(artist):
remove = False
else:
remove = True
location = rip_mp3(song, artist, command=command)
song_number += 1
locations = location.split("/")
# Enter... the reorganizing...
if no_organize:
folder_name = ("playlist - " + file_name)[:40]
if not os.path.isdir(folder_name):
os.makedirs(folder_name)
os.rename(location, "%s/%s - %s" % (folder_name, song_number, locations[-1]))
if remove:
import shutil # Only import this if I have to.
shutil.rmtree(locations[0])
if os.path.isfile(filename)
os.rename(filename, folder_name + "/" + filename)
os.rename(folder_name, folder_name.replace("playlist"))
except Exception as e:
errors.append(line + color(" : ", ["YELLOW"]) + bc.FAIL + str(e) + bc.ENDC)
if len(errors) > 0:
print (bc.FAIL + "Something was wrong with the formatting of the following lines:" + bc.ENDC)
for i in errors:
print ("\t%s" % i)
def rip_album(album, artist,
tried=False, # for if it can't find the album the first time
search="album", # ditto
command=None, # For running a command with the song's location
choose_link=False # Whether to allow the user to choose the link.
):
if search in (None, False):
search = "album"
visible_texts = search_google(album, artist, search)
errors = []
try:
songs = []
num = True
for i, j in enumerate(visible_texts):
if 'Songs' in j:
if visible_texts[i + 1] == "1":
indexed = i
while num == True:
try:
if type(int(visible_texts[indexed])) is int:
a = visible_texts[indexed + 1]
songs.append(a)
indexed += 1
except:
indexed += 1
if indexed >= 1000:
num = False
else:
pass
print ("")
print (bc.HEADER + "Album Contents:" + bc.ENDC)
for i, j in enumerate(songs):
print (bc.OKBLUE + " - " + j + bc.ENDC)
print (bc.YELLOW + "\nFinding album cover ... " + bc.ENDC, end="\r")
album_art_url = get_albumart_url(album, artist)
print (bc.OKGREEN + "Album cover found: " + bc.ENDC + album_art_url)
for i, j in enumerate(songs):
song = j
print (color("\n%s/%s - " % (i + 1, len(songs)), ["UNDERLINE"]), end="")
rip_mp3(j, artist, part_of_album=True, album=album, tracknum=i + 1, \
album_art_url=album_art_url, command=command, choose_link=choose_link)
if len(errors) > 0:
for error in errors: print (error)
else:
print (bc.BOLD + bc.UNDERLINE + album + bc.ENDC + bc.OKGREEN + " downloaded successfully!\n")
except Exception as e:
if str(e) == "local variable 'indexed' referenced before assignment" or str(e) == 'list index out of range':
if tried != True:
print (bc.OKBLUE + "Trying to find album ..." + bc.ENDC)
rip_album(album, artist, tried=True, search="", choose_link=choose_link)
else:
print (bc.FAIL + 'Could not find album "%s"' % album + bc.ENDC)
else:
errors.append(bc.FAIL + "There was a problem with downloading: " + bc.ENDC + song + "\n" + str(e))
pass
def rip_mp3(song, artist,
part_of_album=False, # neccessary for creating folders.
album=None, # if you want to specify an album and save a bit of time.
tracknum=None, # to specify the tracknumber in the album.
album_art_url=None, # if you want to save a lot of time trying to find album cover.
command=None, # For running a command with the song's location.
choose_link=False, # Whether to allow the user to choose the link.
):
audio_code = find_mp3(song, artist)
filename = strip_special_chars(song) + ".mp3"
ydl_opts = {
'format': 'bestaudio/best',
#'quiet': True,
'postprocessors': [{
'key': 'FFmpegExtractAudio',
'preferredcodec': 'mp3',
}],
}
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
ydl.download(["http://www.youtube.com/watch?v=" + audio_code])
artist_folder = artist
if not os.path.isdir(artist_folder):
os.makedirs(artist_folder)
if not part_of_album:
location = artist_folder
if album and part_of_album:
album_folder = artist + "/" + album
if not os.path.isdir(album_folder):
os.makedirs(album_folder)
location = album_folder
for file in os.listdir("."):
if audio_code in file:
os.rename(file, location + "/" + filename)
parse_metadata(song, artist, location, filename, tracknum=tracknum, album=album, album_art_url=album_art_url)
print (color(song, ["BOLD", "UNDERLINE"]) + bc.OKGREEN + ' downloaded successfully!'+ bc.ENDC)
print ("")
if command:
loc = location + "/" + filename
os.system((command.replace("%(loc)s", '"%s"' % loc) + " &"))
return (location + "/" + filename)

96
v2.0/old/metadata.py Normal file
View file

@ -0,0 +1,96 @@
def parse_metadata(song, artist, location, filename,
tracknum="",
album="",
album_art_url=""
):
# Release date
for i, j in enumerate(googled):
if "Released:" in j:
date = (googled[i + 1])
try:
mp3file['date'] = date
print (bc.OKGREEN + "Release date parsed: " + bc.ENDC + mp3file['date'][0])
except Exception:
mp3file['date'] = ""
pass
mp3file.save()
# Track number
if tracknum:
mp3file['tracknumber'] = str(tracknum)
mp3file.save()
# Album art
try:
if album:
if not album_art_url:
print (bc.YELLOW + "Parsing album art ..." + bc.ENDC, end="\r")
temp_url = get_albumart_url(album, artist)
embed_mp3(temp_url, location + "/" + filename)
print (bc.OKGREEN + "Album art parsed: " + bc.ENDC + temp_url)
else: # If part of an album, it should do this.
embed_mp3(album_art_url, location + "/" + filename)
print (bc.OKGREEN + "Album art parsed." + bc.ENDC)
except Exception as e:
print (bc.FAIL + "Album art not parsed: " + bc.ENDC + str(e))
def embed_mp3(albumart_url, song_location):
image = urlopen(albumart_url)
audio = EasyMP3(song_location, ID3=ID3)
try:
audio.add_tags()
except Exception as e:
pass
audio.tags.add(
APIC(
encoding = 3,
mime = 'image/png',
type = 3,
desc = 'Cover',
data = image.read()
)
)
audio.save()
def get_albumart_url(album, artist):
def test_404(url):
try:
urlopen(albumart).read()
except Exception:
return False
return True
tries = 0
album = "%s %s Album Art" % (artist, album)
url = ("https://www.google.com/search?q=" + quote(album.encode('utf-8')) + "&source=lnms&tbm=isch")
header = {
'User-Agent':
'''
Mozilla/5.0 (Windows NT 6.1; WOW64)
AppleWebKit/537.36 (KHTML,like Gecko)
Chrome/43.0.2357.134 Safari/537.36
'''
}
soup = BeautifulSoup(urlopen(Request(url, headers=header)), "html.parser")
albumart_divs = soup.findAll("div", {"class": "rg_meta"})
albumart = json.loads(albumart_divs[tries].text)["ou"]
while not test_404(albumart):
tries += 1
albumart = json.loads(albumart_divs[tries].text)["ou"]
return albumart

5
v2.0/setup.cfg Normal file
View file

@ -0,0 +1,5 @@
[bdist_wheel]
# This flag says that the code is written to work on both Python 2 and Python
# 3. If at all possible, it is good practice to do this. If you cannot, you
# will need to generate wheels for each Python version that you support.
universal=1

21
v2.0/setup.py Normal file
View file

@ -0,0 +1,21 @@
from setuptools import setup
setup(
name='irs',
version='1.5.10',
description='A music downloader that just gets metadata.',
url='https://github.com/kepoorhampond/irs',
author='Kepoor Hampond',
author_email='kepoorh@gmail.com',
license='GNU',
packages =['irs'],
install_requires=[
'bs4',
'mutagen',
'youtube-dl',
'requests',
],
entry_points = {
'console_scripts': ['irs = irs.__main__:main'],
},
)