mirror of
https://github.com/cooperhammond/irs.git
synced 2025-01-09 20:15:27 +00:00
Wrote a clean metadata tagger and spotify searcher
This commit is contained in:
parent
4fc24bf78d
commit
a67a37f737
104
r&d/spotify_search.py
Normal file
104
r&d/spotify_search.py
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
import re
|
||||||
|
|
||||||
|
import spotipy
|
||||||
|
from spotipy.oauth2 import SpotifyClientCredentials
|
||||||
|
|
||||||
|
|
||||||
|
CLIENT_ID = 'e4198f6a3f7b48029366f22528b5dc66'
|
||||||
|
CLIENT_SECRET = 'ba057d0621a5496bbb64edccf758bde5'
|
||||||
|
|
||||||
|
|
||||||
|
class SpotifySearcher:
|
||||||
|
"""Searches spotify for song, album, and playlist metadata."""
|
||||||
|
|
||||||
|
def authorize(self, client_id=None, client_secret=None):
|
||||||
|
"""Authorizes this class with spotify using client ids
|
||||||
|
:rtype: returns self class
|
||||||
|
"""
|
||||||
|
|
||||||
|
if not client_id:
|
||||||
|
client_id = 'e4198f6a3f7b48029366f22528b5dc66'
|
||||||
|
if not client_secret:
|
||||||
|
client_secret = 'ba057d0621a5496bbb64edccf758bde5'
|
||||||
|
|
||||||
|
try:
|
||||||
|
creds = SpotifyClientCredentials(client_id, client_secret)
|
||||||
|
self.authorized = True
|
||||||
|
self.spotify = spotipy.Spotify(client_credentials_manager=creds)
|
||||||
|
except Exception:
|
||||||
|
self.authorized = False
|
||||||
|
self.spotify = spotipy.Spotify()
|
||||||
|
|
||||||
|
return self
|
||||||
|
|
||||||
|
def find_song(self, song_title, artist_name, limit=50, offset=0):
|
||||||
|
"""Searches spotify for a song and grabs its metadata
|
||||||
|
:param song_title: a string, the title of the song you're looking for
|
||||||
|
:param artist_name: a string, the artist of the above song
|
||||||
|
:rtype: a dictionary of metadata about the song
|
||||||
|
"""
|
||||||
|
songs = self.spotify.search(q=song_title, type="track")["tracks"]
|
||||||
|
|
||||||
|
for song in songs["items"]:
|
||||||
|
if _simplify(song_title) in _simplify(song["name"]) and \
|
||||||
|
_simplify(artist_name) in _simplify(song["artists"][0]["name"]):
|
||||||
|
return song
|
||||||
|
|
||||||
|
if songs['next']:
|
||||||
|
return self.find_song(song_title, artist_name,
|
||||||
|
offset=offset + limit)
|
||||||
|
else:
|
||||||
|
print("There were no songs found by that name with that artist")
|
||||||
|
|
||||||
|
def find_album(self, album_title, artist_name=None, limit=50, offset=0):
|
||||||
|
"""Searches spotify for an album and grabs its contents and metadata
|
||||||
|
:param album_title: a string, the title of the album
|
||||||
|
:param artist_name: a string, the name of the artist of the album
|
||||||
|
:rtype: a dictionary of metadata about the album
|
||||||
|
"""
|
||||||
|
query = album_title
|
||||||
|
if artist_name:
|
||||||
|
query += " " + artist_name
|
||||||
|
albums = self.spotify.search(q=query, type="album")['albums']
|
||||||
|
|
||||||
|
for album in albums['items']:
|
||||||
|
if _simplify(album_title) in _simplify(album["name"]):
|
||||||
|
return self.spotify.album(album['uri'])
|
||||||
|
|
||||||
|
if albums['next']:
|
||||||
|
return self.find_album(album_title, artist_name,
|
||||||
|
offset=offset + limit)
|
||||||
|
else:
|
||||||
|
print("There were no albums found by that name with that artist")
|
||||||
|
|
||||||
|
def find_playlist(self, playlist_title, username, limit=50, offset=0):
|
||||||
|
"""Searches spotify for a playlist and grabs its contents and metadata
|
||||||
|
:param playlist_title: a string, the title of the playlist
|
||||||
|
:param username: a string, the username of the playlist creator/owner
|
||||||
|
:rtype: a dictionary of metadata about the playlist
|
||||||
|
"""
|
||||||
|
playlists = []
|
||||||
|
playlists = self.spotify.user_playlists(username, limit, offset)
|
||||||
|
|
||||||
|
for playlist in playlists['items']:
|
||||||
|
print(playlist['name'])
|
||||||
|
if _simplify(playlist_title) in _simplify(playlist['name']):
|
||||||
|
return self.spotify.user_playlist(username, playlist['id'])
|
||||||
|
|
||||||
|
if playlists['next']:
|
||||||
|
return self.find_playlist(playlist_title, username,
|
||||||
|
offset=offset + limit)
|
||||||
|
else:
|
||||||
|
print("There were no playlists by that name found.")
|
||||||
|
|
||||||
|
|
||||||
|
def _simplify(string):
|
||||||
|
"""Lowercases and strips all non alphanumeric characters from the string
|
||||||
|
:param string: a string to be modified
|
||||||
|
:rtype: the modified string
|
||||||
|
"""
|
||||||
|
if type(string) == bytes:
|
||||||
|
string = string.decode()
|
||||||
|
return re.sub(r'[^a-zA-Z0-9]+', '', string.lower())
|
||||||
|
|
||||||
|
print((SpotifySearcher().authorize().find_song("Bohemian Rhapsody", "Queenn")))
|
67
r&d/tagger.py
Normal file
67
r&d/tagger.py
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
import sys
|
||||||
|
|
||||||
|
if sys.version_info[0] >= 3:
|
||||||
|
from urllib.request import urlopen
|
||||||
|
elif sys.version_info[0] < 3:
|
||||||
|
from urllib import quote_plus, quote
|
||||||
|
from urllib import urlopen
|
||||||
|
|
||||||
|
from mutagen.mp3 import EasyMP3
|
||||||
|
from mutagen.easyid3 import EasyID3, EasyID3KeyError
|
||||||
|
from mutagen.id3 import APIC, ID3
|
||||||
|
|
||||||
|
|
||||||
|
class Tagger:
|
||||||
|
"""Attaches ID3 tags to MP3 files."""
|
||||||
|
|
||||||
|
def __init__(self, location):
|
||||||
|
"""Initializes the class and generates ID3 tags for the mp3
|
||||||
|
:param location: a string, the location of the mp3 that you want ID3
|
||||||
|
tags on
|
||||||
|
"""
|
||||||
|
EasyID3.RegisterTextKey("comment", "COMM")
|
||||||
|
self.location = location
|
||||||
|
self.mp3 = EasyID3(self.location)
|
||||||
|
|
||||||
|
def add_tag(self, tag, data):
|
||||||
|
"""Adds a tag to the mp3 file you specified in __init__ and saves it
|
||||||
|
:param tag: a string, the name of the tag you want to add to the mp3
|
||||||
|
valid tag names:
|
||||||
|
"title", "artist", "album", "genre", "tracknumber" (string),
|
||||||
|
"discnumber" (string),
|
||||||
|
"compilation" ("1" for true, "" for false)
|
||||||
|
:param data: a string, the data that you want to attach to the mp3
|
||||||
|
under the specified tag name
|
||||||
|
"""
|
||||||
|
# For valid tags: `EasyID3.valid_keys.keys()`
|
||||||
|
self.mp3[tag] = data
|
||||||
|
self.mp3.save()
|
||||||
|
|
||||||
|
def read_tag(self, tag):
|
||||||
|
"""Tries to read a tag from the initialized mp3 file
|
||||||
|
:param tag: a string, the name of the tag you want to read
|
||||||
|
:rtype: an array with a string inside. The string inside the array is
|
||||||
|
the data you're requesting. If there's no tag associated or no data
|
||||||
|
attached with your requested tag, a blank array will be returned.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
return self.mp3[tag]
|
||||||
|
except EasyID3KeyError or KeyError:
|
||||||
|
return []
|
||||||
|
|
||||||
|
def add_album_art(self, image_url):
|
||||||
|
"""Adds album art to the initialized mp3 file
|
||||||
|
:param image_url: a string, the url of the image you want to attach to
|
||||||
|
the mp3
|
||||||
|
"""
|
||||||
|
mp3 = EasyMP3(self.location, ID3=ID3)
|
||||||
|
mp3.tags.add(
|
||||||
|
APIC(
|
||||||
|
encoding = 3,
|
||||||
|
mime = 'image/png',
|
||||||
|
type = 3,
|
||||||
|
desc = 'cover',
|
||||||
|
data = urlopen(image_url).read()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
mp3.save()
|
|
@ -121,7 +121,9 @@ def _simplify(string):
|
||||||
:param string: a string to be modified
|
:param string: a string to be modified
|
||||||
:rtype: the modified string
|
:rtype: the modified string
|
||||||
"""
|
"""
|
||||||
return re.sub(r'[^a-zA-Z0-9]+', '', string)
|
if type(string) == bytes:
|
||||||
|
string = string.decode()
|
||||||
|
return re.sub(r'[^a-zA-Z0-9]+', '', string.lower())
|
||||||
|
|
||||||
|
|
||||||
def _count_garbage_phrases(video_title, song_title):
|
def _count_garbage_phrases(video_title, song_title):
|
||||||
|
|
Loading…
Reference in a new issue