fixed stupid syntax error

This commit is contained in:
Kepoor Hampond 2016-12-21 11:57:00 -08:00
parent aab301b25a
commit b50675778b
24 changed files with 2 additions and 1479 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

Binary file not shown.

View file

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

View file

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

View file

@ -1 +0,0 @@

View file

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

View file

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

View file

@ -1 +0,0 @@
irs

View file

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

View file

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

View file

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

View file

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

View file

View file

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

View file

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

View file

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

View file

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

View file

@ -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'],
},
)