mirror of
https://github.com/cooperhammond/irs.git
synced 2025-02-27 23:16:46 +00:00
fixed stupid syntax error
This commit is contained in:
parent
aab301b25a
commit
b50675778b
|
@ -123,7 +123,7 @@ def rip_playlist(file_name,
|
|||
import shutil # Only import this if I have to.
|
||||
shutil.rmtree(locations[0])
|
||||
|
||||
if os.path.isfile(filename)
|
||||
if os.path.isfile(filename):
|
||||
os.rename(filename, folder_name + "/" + filename)
|
||||
|
||||
os.rename(folder_name, folder_name.replace("playlist"))
|
||||
|
|
2
setup.py
2
setup.py
|
@ -2,7 +2,7 @@ from setuptools import setup
|
|||
|
||||
setup(
|
||||
name='irs',
|
||||
version='1.6.10',
|
||||
version='1.6.11',
|
||||
description='A music downloader that just gets metadata.',
|
||||
url='https://github.com/kepoorhampond/irs',
|
||||
author='Kepoor Hampond',
|
||||
|
|
|
@ -1,153 +0,0 @@
|
|||
#!/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()
|
|
@ -1,265 +0,0 @@
|
|||
# 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)
|
|
@ -1,166 +0,0 @@
|
|||
# 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
|
|
@ -1,55 +0,0 @@
|
|||
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
BIN
v2.0/dist/irs-1.5.10-py3.5.egg
vendored
Binary file not shown.
|
@ -1,10 +0,0 @@
|
|||
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
|
|
@ -1,13 +0,0 @@
|
|||
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
|
|
@ -1 +0,0 @@
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
[console_scripts]
|
||||
irs = irs.__main__:main
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
bs4
|
||||
mutagen
|
||||
youtube-dl
|
||||
requests
|
|
@ -1 +0,0 @@
|
|||
irs
|
|
@ -1,80 +0,0 @@
|
|||
#!/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()
|
|
@ -1,42 +0,0 @@
|
|||
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)
|
|
@ -1,89 +0,0 @@
|
|||
# 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))
|
|
@ -1,55 +0,0 @@
|
|||
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)
|
|
@ -1,153 +0,0 @@
|
|||
#!/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()
|
|
@ -1,265 +0,0 @@
|
|||
# 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)
|
|
@ -1,96 +0,0 @@
|
|||
|
||||
|
||||
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
|
|
@ -1,5 +0,0 @@
|
|||
[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
|
|
@ -1,21 +0,0 @@
|
|||
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'],
|
||||
},
|
||||
)
|
Loading…
Reference in a new issue