Add lots of comments

This commit is contained in:
Ritiek
2017-06-18 02:57:55 +05:30
parent c270aa8365
commit 80c167e702
3 changed files with 41 additions and 11 deletions

View File

@@ -13,10 +13,12 @@ def compare(file, metadata):
try: try:
if file.endswith('.mp3'): if file.endswith('.mp3'):
audiofile = EasyID3('Music/' + file) audiofile = EasyID3('Music/' + file)
# fetch track title metadata
already_tagged = audiofile['title'][0] == metadata['name'] already_tagged = audiofile['title'][0] == metadata['name']
elif file.endswith('.m4a'): elif file.endswith('.m4a'):
tag = {'title': '\xa9nam'} tag = {'title': '\xa9nam'}
audiofile = MP4('Music/' + file) audiofile = MP4('Music/' + file)
# fetch track title metadata
already_tagged = audiofile[tags['title']] == metadata['name'] already_tagged = audiofile[tags['title']] == metadata['name']
except KeyError: except KeyError:
already_tagged = False already_tagged = False
@@ -35,7 +37,7 @@ def embed(music_file, meta_tags, output_ext):
print('Cannot embed meta-tags into given output extension') print('Cannot embed meta-tags into given output extension')
def embed_mp3(music_file, meta_tags, output_ext): def embed_mp3(music_file, meta_tags, output_ext):
#EasyID3 is fun to use ;) # EasyID3 is fun to use ;)
audiofile = EasyID3('Music/' + music_file + output_ext) audiofile = EasyID3('Music/' + music_file + output_ext)
audiofile['artist'] = meta_tags['artists'][0]['name'] audiofile['artist'] = meta_tags['artists'][0]['name']
audiofile['albumartist'] = meta_tags['artists'][0]['name'] audiofile['albumartist'] = meta_tags['artists'][0]['name']

View File

@@ -58,6 +58,7 @@ def get_arguments():
return parser.parse_args() return parser.parse_args()
# check if input song is spotify link
def is_spotify(raw_song): def is_spotify(raw_song):
if (len(raw_song) == 22 and raw_song.replace(" ", "%20") == raw_song) or (raw_song.find('spotify') > -1): if (len(raw_song) == 22 and raw_song.replace(" ", "%20") == raw_song) or (raw_song.find('spotify') > -1):
return True return True
@@ -91,6 +92,7 @@ def generate_token():
return token return token
def generate_search_URL(song): def generate_search_URL(song):
# urllib2.quote() encodes URL with special characters
URL = "https://www.youtube.com/results?sp=EgIQAQ%253D%253D&q=" + quote(song) URL = "https://www.youtube.com/results?sp=EgIQAQ%253D%253D&q=" + quote(song)
return URL return URL
@@ -105,4 +107,4 @@ def grace_quit():
print('') print('')
print('') print('')
print('Exitting..') print('Exitting..')
exit() sys.exit()

View File

@@ -8,7 +8,6 @@ from bs4 import BeautifulSoup
from titlecase import titlecase from titlecase import titlecase
from slugify import slugify from slugify import slugify
import spotipy import spotipy
import spotipy.oauth2 as oauth2
import pafy import pafy
import sys import sys
import os import os
@@ -20,7 +19,7 @@ try:
except ImportError: except ImportError:
import urllib.request as urllib2 import urllib.request as urllib2
# generate song title to be searched on YouTube # decode spotify link to "[artist] - [song]"
def generate_songname(raw_song): def generate_songname(raw_song):
if misc.is_spotify(raw_song): if misc.is_spotify(raw_song):
tags = generate_metadata(raw_song) tags = generate_metadata(raw_song)
@@ -30,8 +29,10 @@ def generate_songname(raw_song):
# fetch song's metadata from spotify # fetch song's metadata from spotify
def generate_metadata(raw_song): def generate_metadata(raw_song):
if misc.is_spotify(raw_song): if misc.is_spotify(raw_song):
# fetch track information directly if it is spotify link
meta_tags = spotify.track(raw_song) meta_tags = spotify.track(raw_song)
else: else:
# otherwise search on spotify and fetch information from first result
meta_tags = spotify.search(raw_song, limit=1)['tracks']['items'][0] meta_tags = spotify.search(raw_song, limit=1)['tracks']['items'][0]
artist = spotify.artist(meta_tags['artists'][0]['id']) artist = spotify.artist(meta_tags['artists'][0]['id'])
@@ -52,7 +53,9 @@ def generate_metadata(raw_song):
return meta_tags return meta_tags
def generate_YouTube_URL(raw_song): def generate_YouTube_URL(raw_song):
# decode spotify http link to "[artist] - [song]"
song = generate_songname(raw_song) song = generate_songname(raw_song)
# generate direct search YouTube URL
searchURL = misc.generate_search_URL(song) searchURL = misc.generate_search_URL(song)
item = urllib2.urlopen(searchURL).read() item = urllib2.urlopen(searchURL).read()
items_parse = BeautifulSoup(item, "html.parser") items_parse = BeautifulSoup(item, "html.parser")
@@ -62,32 +65,37 @@ def generate_YouTube_URL(raw_song):
print(song) print(song)
print('') print('')
print('0. Skip downloading this song') print('0. Skip downloading this song')
# fetch all video links on first page on YouTube
for x in items_parse.find_all('h3', {'class': 'yt-lockup-title'}): for x in items_parse.find_all('h3', {'class': 'yt-lockup-title'}):
# confirm the video result is not an advertisement
if not x.find('channel') == -1 or not x.find('googleads') == -1: if not x.find('channel') == -1 or not x.find('googleads') == -1:
print(str(check) + '. ' + x.get_text()) print(str(check) + '. ' + x.get_text())
links.append(x.find('a')['href']) links.append(x.find('a')['href'])
check += 1 check += 1
print('') print('')
# let user select the song to download
result = misc.input_link(links) result = misc.input_link(links)
if result is None: if result is None:
return None return None
else: else:
result = items_parse.find_all( # get video link of the first YouTube result
attrs={'class': 'yt-uix-tile-link'})[0]['href'] result = items_parse.find_all(attrs={'class': 'yt-uix-tile-link'})[0]['href']
while not result.find('channel') == - \ # confirm the video result is not an advertisement
1 or not result.find('googleads') == -1: # otherwise keep iterating until it is not
result = items_parse.find_all( while not result.find('channel') == -1 or not result.find('googleads') == -1:
attrs={'class': 'yt-uix-tile-link'})[check]['href'] result = items_parse.find_all(attrs={'class': 'yt-uix-tile-link'})[check]['href']
check += 1 check += 1
full_link = "youtube.com" + result full_link = "youtube.com" + result
return full_link return full_link
# parse track from YouTube # parse track from YouTube
def go_pafy(raw_song): def go_pafy(raw_song):
# video link of the video to extract audio from
trackURL = generate_YouTube_URL(raw_song) trackURL = generate_YouTube_URL(raw_song)
if trackURL is None: if trackURL is None:
return None return None
else: else:
# parse the YouTube video
return pafy.new(trackURL) return pafy.new(trackURL)
# title of the YouTube video # title of the YouTube video
@@ -100,22 +108,29 @@ def get_YouTube_title(content, number):
# fetch user playlists when using -u option # fetch user playlists when using -u option
def feed_playlist(username): def feed_playlist(username):
# fetch all user playlists
playlists = spotify.user_playlists(username) playlists = spotify.user_playlists(username)
links = [] links = []
check = 1 check = 1
# iterate over user playlists
for playlist in playlists['items']: for playlist in playlists['items']:
print(str(check) + '. ' + misc.fix_encoding(playlist['name']) + ' (' + str(playlist['tracks']['total']) + ' tracks)') print(str(check) + '. ' + misc.fix_encoding(playlist['name']) + ' (' + str(playlist['tracks']['total']) + ' tracks)')
links.append(playlist) links.append(playlist)
check += 1 check += 1
print('') print('')
# let user select playlist
playlist = misc.input_link(links) playlist = misc.input_link(links)
# fetch detailed information for playlist
results = spotify.user_playlist(playlist['owner']['id'], playlist['id'], fields="tracks,next") results = spotify.user_playlist(playlist['owner']['id'], playlist['id'], fields="tracks,next")
print('') print('')
# slugify removes any special characters # slugify removes any special characters
file = slugify(playlist['name'], ok='-_()[]{}') + '.txt' file = slugify(playlist['name'], ok='-_()[]{}') + '.txt'
print('Feeding ' + str(playlist['tracks']['total']) + ' tracks to ' + file) print('Feeding ' + str(playlist['tracks']['total']) + ' tracks to ' + file)
tracks = results['tracks'] tracks = results['tracks']
# write tracks to file
misc.feed_tracks(file, tracks) misc.feed_tracks(file, tracks)
# check if there are more pages
# 1 page = 50 results
while tracks['next']: while tracks['next']:
tracks = spotify.next(tracks) tracks = spotify.next(tracks)
misc.feed_tracks(file, tracks) misc.feed_tracks(file, tracks)
@@ -123,16 +138,19 @@ def feed_playlist(username):
def download_song(content): def download_song(content):
music_file = misc.generate_filename(content.title) music_file = misc.generate_filename(content.title)
if args.input_ext == '.webm': if args.input_ext == '.webm':
# download best available audio in .webm
link = content.getbestaudio(preftype='webm') link = content.getbestaudio(preftype='webm')
if link is not None: if link is not None:
link.download(filepath='Music/' + music_file + args.input_ext) link.download(filepath='Music/' + music_file + args.input_ext)
else: else:
# download best available audio in .webm
link = content.getbestaudio(preftype='m4a') link = content.getbestaudio(preftype='m4a')
if link is not None: if link is not None:
link.download(filepath='Music/' + music_file + args.input_ext) link.download(filepath='Music/' + music_file + args.input_ext)
# convert song from input_ext to output_ext # convert song from input_ext to output_ext
def convert_song(music_file): def convert_song(music_file):
# skip conversion if input_ext == output_ext
if not args.input_ext == args.output_ext: if not args.input_ext == args.output_ext:
print('Converting ' + music_file + args.input_ext + ' to ' + args.output_ext[1:]) print('Converting ' + music_file + args.input_ext + ' to ' + args.output_ext[1:])
if args.ffmpeg: if args.ffmpeg:
@@ -141,6 +159,7 @@ def convert_song(music_file):
convert_with_libav(music_file) convert_with_libav(music_file)
def convert_with_libav(music_file): def convert_with_libav(music_file):
# different path for windows
if os.name == 'nt': if os.name == 'nt':
avconv_path = 'Scripts\\avconv.exe' avconv_path = 'Scripts\\avconv.exe'
else: else:
@@ -260,8 +279,9 @@ def grab_list(file):
for raw_song in lines: for raw_song in lines:
try: try:
grab_single(raw_song, number=number) grab_single(raw_song, number=number)
# refresh token when it expires (after 1 hour) # token expires after 1 hour
except spotipy.oauth2.SpotifyOauthError: except spotipy.oauth2.SpotifyOauthError:
# refresh token when it expires
token = misc.generate_token() token = misc.generate_token()
global spotify global spotify
spotify = spotipy.Spotify(auth=token) spotify = spotipy.Spotify(auth=token)
@@ -269,7 +289,9 @@ def grab_list(file):
# detect network problems # detect network problems
except (urllib2.URLError, TypeError, IOError): except (urllib2.URLError, TypeError, IOError):
lines.append(raw_song) lines.append(raw_song)
# remove the downloaded song from .txt
misc.trim_song(file) misc.trim_song(file)
# and append it to the last line in .txt
with open(file, 'a') as myfile: with open(file, 'a') as myfile:
myfile.write(raw_song) myfile.write(raw_song)
print('Failed to download song. Will retry after other songs.') print('Failed to download song. Will retry after other songs.')
@@ -283,6 +305,7 @@ def grab_list(file):
# logic behind downloading some song # logic behind downloading some song
def grab_single(raw_song, number=None): def grab_single(raw_song, number=None):
# check if song is being downloaded from list
if number: if number:
islist = True islist = True
else: else:
@@ -290,7 +313,10 @@ def grab_single(raw_song, number=None):
content = go_pafy(raw_song) content = go_pafy(raw_song)
if content is None: if content is None:
return return
# print "[number]. [artist] - [song]" if downloading from list
# otherwise print "[artist] - [song]"
print(get_YouTube_title(content, number)) print(get_YouTube_title(content, number))
# generate file name of the song to download
music_file = misc.generate_filename(content.title) music_file = misc.generate_filename(content.title)
if not check_exists(music_file, raw_song, islist=islist): if not check_exists(music_file, raw_song, islist=islist):
download_song(content) download_song(content)