mirror of
https://github.com/cooperhammond/irs.git
synced 2024-11-08 18:38:33 +00:00
Wrote out method song
in ripper
This commit is contained in:
parent
cfdec19136
commit
be13b60ba6
170
irs/metadata.py
170
irs/metadata.py
|
@ -1,11 +1,19 @@
|
|||
# MP3 Metadata editing
|
||||
from mutagen.mp3 import MP3, EasyMP3
|
||||
from mutagen.easyid3 import EasyID3
|
||||
from mutagen.id3 import ID3, APIC
|
||||
from mutagen.id3 import * # There's A LOT of stuff to import, forgive me.
|
||||
|
||||
# System
|
||||
import sys
|
||||
|
||||
# Info finding
|
||||
from urllib.parse import quote_plus, quote
|
||||
from urllib.request import urlopen, Request
|
||||
if sys.version_info[0] >= 3:
|
||||
from urllib.parse import quote_plus, quote
|
||||
from urllib.request import urlopen, Request
|
||||
elif sys.version_info[0] < 3:
|
||||
from urllib import quote_plus, quote
|
||||
from urllib import urlopen
|
||||
from urllib2 import Request
|
||||
|
||||
# Info parsing
|
||||
import json
|
||||
|
@ -13,135 +21,49 @@ from re import match
|
|||
from bs4 import BeautifulSoup
|
||||
|
||||
# Local utils
|
||||
from .utils import *
|
||||
import utils
|
||||
|
||||
# Powered by...
|
||||
import spotipy
|
||||
|
||||
class Metadata:
|
||||
def __init__(self, location, song, artist):
|
||||
def __init__(self, location):
|
||||
self.spotify = spotipy.Spotify()
|
||||
|
||||
self.song = song
|
||||
self.artist = artist
|
||||
self.location = location
|
||||
|
||||
self.info = self.search_google()
|
||||
self.mp3 = MP3(self.location, ID3=EasyID3)
|
||||
|
||||
def get_attr(self, attr):
|
||||
try:
|
||||
return self.mp3[attr][0]
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
def add_title(self):
|
||||
self.mp3['title'] = self.song
|
||||
self.mp3.save()
|
||||
return True
|
||||
|
||||
|
||||
def add_artist(self):
|
||||
self.mp3['artist'] = self.artist
|
||||
self.mp3.save()
|
||||
return True
|
||||
|
||||
|
||||
def add_album(self, album=None):
|
||||
try:
|
||||
if not album:
|
||||
for i, j in enumerate(self.info):
|
||||
if "Album:" in j:
|
||||
album = (self.info[i + 1])
|
||||
|
||||
self.mp3['album'] = album
|
||||
self.mp3.save()
|
||||
return True
|
||||
|
||||
except Exception:
|
||||
self.mp3['album'] = self.song
|
||||
self.mp3.save()
|
||||
return False
|
||||
|
||||
|
||||
def add_release_date(self, release_date=None):
|
||||
try:
|
||||
if not release_date:
|
||||
for i, j in enumerate(self.info):
|
||||
if "Released:" in j:
|
||||
date = (self.info[i + 1])
|
||||
|
||||
self.mp3['date'] = date
|
||||
self.mp3.save()
|
||||
return True
|
||||
except UnboundLocalError:
|
||||
return False
|
||||
|
||||
|
||||
def add_track_number(self, track_number):
|
||||
self.mp3['tracknumber'] = str(track_number)
|
||||
self.mp3.save()
|
||||
return True
|
||||
|
||||
|
||||
def get_album_art(self, artist, album, id=None):
|
||||
spotify = spotipy.Spotify()
|
||||
|
||||
if id:
|
||||
album = spotify.album(id)
|
||||
return album["images"][0]["url"]
|
||||
|
||||
results = spotify.search(q=artist + " " + album, type='album')
|
||||
items = results['albums']['items']
|
||||
if len(items) > 0:
|
||||
album = items[0]['images'][0]['url']
|
||||
return album
|
||||
|
||||
#self.mp3 = MP3(self.location, ID3=EasyID3)
|
||||
self.mp3 = EasyID3(self.location)
|
||||
|
||||
def add_tag(self, tag, data):
|
||||
# For valid tags: `EasyID3.valid_keys.keys()`
|
||||
audio[tag] = data
|
||||
audio.save()
|
||||
|
||||
def add_album_art(self, image_url):
|
||||
mp3 = EasyMP3(self.location, ID3=ID3)
|
||||
|
||||
try:
|
||||
mp3.add_tags()
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
if not image_url:
|
||||
image_url = self.get_album_art(self.artist, self.mp3["album"][0])
|
||||
|
||||
try:
|
||||
mp3.tags.add(
|
||||
APIC(
|
||||
encoding = 3,
|
||||
mime = 'image/png',
|
||||
type = 3,
|
||||
desc = 'cover',
|
||||
data = urlopen(image_url).read()
|
||||
)
|
||||
mp3.tags.add(
|
||||
APIC(
|
||||
encoding = 3,
|
||||
mime = 'image/png',
|
||||
type = 3,
|
||||
desc = 'cover',
|
||||
data = urlopen(image_url).read()
|
||||
)
|
||||
mp3.save()
|
||||
return image_url
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
def search_google(self, 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" % (self.song, self.artist, search_terms)
|
||||
url = 'http://www.google.com/search?q=' + quote_plus(search_terms)
|
||||
|
||||
hdr = {
|
||||
'User-Agent':'Mozilla/5.0',
|
||||
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
|
||||
}
|
||||
|
||||
texts = BeautifulSoup(urlopen(Request(url, \
|
||||
headers=hdr)).read(), 'html.parser').findAll(text=True)
|
||||
|
||||
return list(filter(visible, texts))
|
||||
)
|
||||
mp3.save()
|
||||
|
||||
def find_album(song, artist):
|
||||
tracks = self.spotify.search(q=song, type="track")
|
||||
for track in tracks:
|
||||
if utils.blank_include(track["name"], song):
|
||||
if utils.blank_include(track["artists"][0]["name"], artist):
|
||||
return track["album"], track
|
||||
|
||||
def parse_genre(genres):
|
||||
if genres != []:
|
||||
genres.reverse()
|
||||
genres = list(map(lambda x: x.replace("-", " "), genres))
|
||||
genres.sort(key=lambda x: len(x.split()))
|
||||
print (genres)
|
||||
return genres[0]
|
||||
else:
|
||||
return ""
|
|
@ -6,6 +6,7 @@ from spotipy.oauth2 import SpotifyClientCredentials
|
|||
# System
|
||||
import sys
|
||||
import os
|
||||
import glob
|
||||
|
||||
# Parsing
|
||||
from bs4 import BeautifulSoup
|
||||
|
@ -21,6 +22,7 @@ else:
|
|||
|
||||
# Local utilities
|
||||
import utils
|
||||
from metadata import *
|
||||
|
||||
class Ripper:
|
||||
def __init__(self, args={}):
|
||||
|
@ -36,10 +38,10 @@ class Ripper:
|
|||
|
||||
def find_yt_url(self, song=None, artist=None, additional_search="lyrics"):
|
||||
try:
|
||||
if not song: song = self.args["song"]
|
||||
if not song: song = self.args["song_title"]
|
||||
if not artist: artist = self.args["artist"]
|
||||
except ValueError:
|
||||
raise ValueError("Must have specify `song` and/or `artist` in either init with `args` or with method arguments.")
|
||||
raise ValueError("Must specify song_title/artist in `args` with init, or in method arguments.")
|
||||
|
||||
search_terms = song + " " + artist + " " + additional_search
|
||||
query_string = urlencode({"search_query" : (search_terms)})
|
||||
|
@ -85,10 +87,10 @@ class Ripper:
|
|||
def spotify_list(self, type=None, title=None, username=None):
|
||||
try:
|
||||
if not type: type = self.args["type"]
|
||||
if not title: title = self.args["title"]
|
||||
if not title: title = self.args["list_title"]
|
||||
if not username: username = self.args["username"]
|
||||
except ValueError:
|
||||
raise ValueError("Must specify type/title/username in `args` with init, or in method arguements.")
|
||||
raise ValueError("Must specify type/title/username in `args` with init, or in method arguments.")
|
||||
|
||||
if type == "album":
|
||||
search = title
|
||||
|
@ -128,6 +130,8 @@ class Ripper:
|
|||
for track in the_list["tracks"]:
|
||||
if type == "playlist":
|
||||
file_prefix = str(len(tracks)) + " - "
|
||||
elif type == "album":
|
||||
file_prefix = str(track["track_number"]) + " - "
|
||||
|
||||
data = {
|
||||
"name": track["name"],
|
||||
|
@ -137,7 +141,7 @@ class Ripper:
|
|||
"track_number": track["track_number"],
|
||||
"disc_number": track["disc_number"],
|
||||
"compilation": compilation,
|
||||
"file_prefix": file_prefix,
|
||||
"file_prefix": file_prefix,
|
||||
}
|
||||
|
||||
tracks.append(data)
|
||||
|
@ -161,4 +165,77 @@ class Ripper:
|
|||
locations.append(loc)
|
||||
|
||||
os.remove(".irs-download-log")
|
||||
return locations
|
||||
return locations
|
||||
|
||||
def song(song=None, artist=None, data={}):
|
||||
try:
|
||||
if not song: song = self.args["song_title"]
|
||||
if not artist: artist = self.args["artist"]
|
||||
except ValueError:
|
||||
raise ValueError("Must specify song_title/artist in `args` with init, or in method arguments.")
|
||||
|
||||
if data == {}: data = False
|
||||
|
||||
video_url, video_title = self.find_yt_url(song, artist)
|
||||
|
||||
print ('Downloading "%s" by "%s"' % (song, artist))
|
||||
|
||||
file_prefix = ""
|
||||
if data != False:
|
||||
file_prefix = data["file_prefix"]
|
||||
|
||||
file_name = file_prefix + utils.blank(song, False) + ".mp3"
|
||||
|
||||
ydl_opts = {
|
||||
'format': 'bestaudio/best',
|
||||
#'quiet': True,
|
||||
'postprocessors': [{
|
||||
'key': 'FFmpegExtractAudio',
|
||||
'preferredcodec': 'mp3',
|
||||
'preferredquality': '192',
|
||||
}],
|
||||
'logger': utils.MyLogger(),
|
||||
'progress_hooks': [utils.my_hook],
|
||||
}
|
||||
|
||||
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
|
||||
ydl.download([video_url])
|
||||
|
||||
for file in glob.glob("./*%s*" % video_title.split("/watch?v=")[-1]):
|
||||
os.rename(file, file_name)
|
||||
|
||||
if data == False:
|
||||
if "album" not in self.args:
|
||||
album, track = find_album_and_track(song, artist)
|
||||
else:
|
||||
album = self.args["album"]
|
||||
if album != None:
|
||||
genre = album["artists"][0]["genres"]
|
||||
|
||||
album_name = ""
|
||||
if album:
|
||||
if utils.check_garbage_phrases(["remastered", "explicit"], album.name, "")
|
||||
album_name = album["name"].split(" (")[0]
|
||||
else:
|
||||
album_name = album["name"]
|
||||
|
||||
genre = parse_genre(genre)
|
||||
|
||||
# Ease of Variables (copyright) (patent pending) (git yer filthy hands off)
|
||||
#
|
||||
# *5 Minutes Later*
|
||||
# Depecrated. It won't be the next big thing. :(
|
||||
|
||||
|
||||
m = Metadata(file_name)
|
||||
|
||||
m.add_tag( "title", song)
|
||||
m.add_tag( "artist", artist)
|
||||
m.add_tag( "comment", "Downloaded from: %s\n Video Title: %s" % (video_url, video_title))
|
||||
if album:
|
||||
m.add_tag("album", album_name)
|
||||
m.add_tag("genre", genre)
|
||||
m.add_tag("compilation", compilation)
|
||||
m.add_tag("tracknumber", track["track_number"])
|
||||
m.add_tag("discnumber", track["disc_number"])
|
||||
m.add_album_art( album["images"][0]["url"])
|
||||
|
|
57
irs/utils.py
57
irs/utils.py
|
@ -1,3 +1,27 @@
|
|||
#==========================
|
||||
# Youtube-DL Logs and Hooks
|
||||
#==========================
|
||||
|
||||
class MyLogger(object):
|
||||
def debug(self, msg):
|
||||
pass
|
||||
|
||||
def warning(self, msg):
|
||||
pass
|
||||
|
||||
def error(self, msg):
|
||||
print(msg)
|
||||
|
||||
|
||||
def my_hook(d):
|
||||
if d['status'] == 'finished':
|
||||
print('Done downloading, now converting ...')
|
||||
|
||||
|
||||
#=================================
|
||||
# String Manipulation and Checking
|
||||
#=================================
|
||||
|
||||
def check_garbage_phrases(phrases, string, title):
|
||||
for phrase in phrases:
|
||||
if phrase in blank(string):
|
||||
|
@ -28,10 +52,15 @@ def individual_word_match(match_against, match):
|
|||
if match_ag == word:
|
||||
matched.append(word)
|
||||
return (float(matched.uniq.size) / float(match_against.size))
|
||||
|
||||
|
||||
#=========================================
|
||||
# Download Log Reading/Updating/Formatting
|
||||
#=========================================
|
||||
|
||||
def format_download_log_line(track, download_status="not downloaded"):
|
||||
return " @@ ".join([t["name"], t["artist"], t["album"]["id"], \
|
||||
t["genre"], t["track_number"], t["disc_number"], t["compilation"], \
|
||||
t["genre"], t["track_number"], t["disc_number"], str(t["compilation"]), \
|
||||
t["prefix"], download_status]) + "\n"
|
||||
|
||||
def format_download_log_data(data):
|
||||
|
@ -40,6 +69,23 @@ def format_download_log_data(data):
|
|||
lines.append(format_download_log_line(track))
|
||||
return lines
|
||||
|
||||
def read_download_log(spotify):
|
||||
data = []
|
||||
with open(".irs-download-log", "r") as file:
|
||||
for line in file:
|
||||
line = line.split(" @@ ")
|
||||
data.append({
|
||||
"name": line[0],
|
||||
"artist": line[1],
|
||||
"album": spotify.album(line[2]),
|
||||
"genre": line[3],
|
||||
"track_number": line[4],
|
||||
"disc_number": line[5],
|
||||
"compilation": bool(line[6]),
|
||||
"file_prefix": line[7],
|
||||
})
|
||||
return data
|
||||
|
||||
def update_download_log_line_status(track, status="downloaded"):
|
||||
line_to_find = format_download_log_line(track)
|
||||
with open(".irs-download-log", "r") as input_file, \
|
||||
|
@ -49,4 +95,11 @@ def update_download_log_line_status(track, status="downloaded"):
|
|||
output_file.write(format_download_log_line(track, status))
|
||||
else:
|
||||
output_file.write(line)
|
||||
|
||||
|
||||
|
||||
#============================================
|
||||
# And Now, For Something Completely Different
|
||||
#============================================
|
||||
|
||||
def ease_of_variables(the_name, data):
|
||||
eval(the_name + " = " + data) # Forgive me my lord, for I have sinned
|
Loading…
Reference in a new issue