diff --git a/irs/manage.py b/irs/manage.py index 05556b9..4cbbaaf 100644 --- a/irs/manage.py +++ b/irs/manage.py @@ -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")) diff --git a/setup.py b/setup.py index 43fe8bb..4d3f91d 100644 --- a/setup.py +++ b/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', diff --git a/v2.0/build/lib/irs/__init__.py b/v2.0/build/lib/irs/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/v2.0/build/lib/irs/__main__.py b/v2.0/build/lib/irs/__main__.py deleted file mode 100644 index f1101a8..0000000 --- a/v2.0/build/lib/irs/__main__.py +++ /dev/null @@ -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() diff --git a/v2.0/build/lib/irs/manage.py b/v2.0/build/lib/irs/manage.py deleted file mode 100644 index 05556b9..0000000 --- a/v2.0/build/lib/irs/manage.py +++ /dev/null @@ -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) diff --git a/v2.0/build/lib/irs/metadata.py b/v2.0/build/lib/irs/metadata.py deleted file mode 100644 index 3dda37e..0000000 --- a/v2.0/build/lib/irs/metadata.py +++ /dev/null @@ -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 diff --git a/v2.0/build/lib/irs/utils.py b/v2.0/build/lib/irs/utils.py deleted file mode 100644 index 545c3b2..0000000 --- a/v2.0/build/lib/irs/utils.py +++ /dev/null @@ -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) diff --git a/v2.0/dist/irs-1.5.10-py3.5.egg b/v2.0/dist/irs-1.5.10-py3.5.egg deleted file mode 100644 index dd3beb4..0000000 Binary files a/v2.0/dist/irs-1.5.10-py3.5.egg and /dev/null differ diff --git a/v2.0/irs.egg-info/PKG-INFO b/v2.0/irs.egg-info/PKG-INFO deleted file mode 100644 index ed0ea49..0000000 --- a/v2.0/irs.egg-info/PKG-INFO +++ /dev/null @@ -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 diff --git a/v2.0/irs.egg-info/SOURCES.txt b/v2.0/irs.egg-info/SOURCES.txt deleted file mode 100644 index 3011688..0000000 --- a/v2.0/irs.egg-info/SOURCES.txt +++ /dev/null @@ -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 \ No newline at end of file diff --git a/v2.0/irs.egg-info/dependency_links.txt b/v2.0/irs.egg-info/dependency_links.txt deleted file mode 100644 index 8b13789..0000000 --- a/v2.0/irs.egg-info/dependency_links.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/v2.0/irs.egg-info/entry_points.txt b/v2.0/irs.egg-info/entry_points.txt deleted file mode 100644 index 047a3c6..0000000 --- a/v2.0/irs.egg-info/entry_points.txt +++ /dev/null @@ -1,3 +0,0 @@ -[console_scripts] -irs = irs.__main__:main - diff --git a/v2.0/irs.egg-info/requires.txt b/v2.0/irs.egg-info/requires.txt deleted file mode 100644 index a35c36c..0000000 --- a/v2.0/irs.egg-info/requires.txt +++ /dev/null @@ -1,4 +0,0 @@ -bs4 -mutagen -youtube-dl -requests diff --git a/v2.0/irs.egg-info/top_level.txt b/v2.0/irs.egg-info/top_level.txt deleted file mode 100644 index 098d8cc..0000000 --- a/v2.0/irs.egg-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -irs diff --git a/v2.0/irs/__main__.py b/v2.0/irs/__main__.py deleted file mode 100644 index 1408268..0000000 --- a/v2.0/irs/__main__.py +++ /dev/null @@ -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() diff --git a/v2.0/irs/manager.py b/v2.0/irs/manager.py deleted file mode 100644 index 348c46c..0000000 --- a/v2.0/irs/manager.py +++ /dev/null @@ -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) diff --git a/v2.0/irs/metadata.py b/v2.0/irs/metadata.py deleted file mode 100644 index 716e5a5..0000000 --- a/v2.0/irs/metadata.py +++ /dev/null @@ -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)) diff --git a/v2.0/irs/utils.py b/v2.0/irs/utils.py deleted file mode 100644 index 545c3b2..0000000 --- a/v2.0/irs/utils.py +++ /dev/null @@ -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) diff --git a/v2.0/old/__init__.py b/v2.0/old/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/v2.0/old/__main__.py b/v2.0/old/__main__.py deleted file mode 100644 index f1101a8..0000000 --- a/v2.0/old/__main__.py +++ /dev/null @@ -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() diff --git a/v2.0/old/manage.py b/v2.0/old/manage.py deleted file mode 100644 index 05556b9..0000000 --- a/v2.0/old/manage.py +++ /dev/null @@ -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) diff --git a/v2.0/old/metadata.py b/v2.0/old/metadata.py deleted file mode 100644 index fc633ad..0000000 --- a/v2.0/old/metadata.py +++ /dev/null @@ -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 diff --git a/v2.0/setup.cfg b/v2.0/setup.cfg deleted file mode 100644 index 79bc678..0000000 --- a/v2.0/setup.cfg +++ /dev/null @@ -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 diff --git a/v2.0/setup.py b/v2.0/setup.py deleted file mode 100644 index c00f65d..0000000 --- a/v2.0/setup.py +++ /dev/null @@ -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'], - }, -)