Example #1
0
class Controller:
    'The controller implements all application logic.'         
    def __init__(self, arguments):
        'Main entry point for iTunes-Discogs.'
        self.arguments = arguments
        self.config = Config(arguments.home)
        self.model = Model(self.config, arguments.database)
        self.itunes = iTunes(self.model, arguments.library)
        self.discogs = Discogs(self.model, arguments.junk)
                
        if arguments.cli:
            if not arguments.playlist:
                arguments.playlist = 'Library'
                
            for playlist in self.get_playlists().values():
                if playlist.Name == arguments.playlist:
                    self._process_playlist(playlist)
        else:
            Window(self)
            
        self.shutdown()
        
    def search(self, track):
        'Search storing results in the database.'
        track.search = self.discogs.search(track.Artist, track.Name)
        if track.search:
            self.model.set_bundle('track.search', track.PersistentID, track.search._id)
            if track.search.raw_results and not track.release:
                self.set_release(track, track.search.raw_results[0])
            
    def set_release(self, track, result):
        'Sets the track release to the specified result.'
        track.release = self.discogs.get_release(result)
        if track.release:
            self.model.set_bundle('track.release', track.PersistentID, track.release._id)
             
    def _process_playlist(self, playlist):
        'Resolve releases for the specified playlist.'
        for tid in playlist.Items:
            track = self.get_track(tid)
            if not track.release:
                self.search(track)
                if track.search and track.search.results():
                    self.set_release(track, track.search.results()[0])
                
    def shutdown(self):
        'Shutdown the worker thread and flush the database.'
        self.model.flush(self.arguments.database)
        
    def get_tracks(self):
        return self.itunes.library.tracks
    
    def get_track(self, tid):
        return self.get_tracks()[tid]
    
    def get_playlists(self):
        return self.itunes.library.playlists
        
    def get_playlist(self, pid):
        return self.get_playlists()[pid]
Example #2
0
 def __init__(self, path_to_excel, debug=False):
     self.excel = FilenameExcel(path_to_excel)
     self.file_list = self.excel.get_rows()
     self.discogs_client = Discogs()
     self.filtered_list = []
     self.full_properties_list = []
     self.no_properties_found_list = []
     self.debug = debug
     self.sleep_seconds = 3
Example #3
0
 def __init__(self, arguments):
     'Main entry point for iTunes-Discogs.'
     self.arguments = arguments
     self.config = Config(arguments.home)
     self.model = Model(self.config, arguments.database)
     self.itunes = iTunes(self.model, arguments.library)
     self.discogs = Discogs(self.model, arguments.junk)
             
     if arguments.cli:
         if not arguments.playlist:
             arguments.playlist = 'Library'
             
         for playlist in self.get_playlists().values():
             if playlist.Name == arguments.playlist:
                 self._process_playlist(playlist)
     else:
         Window(self)
         
     self.shutdown()
Example #4
0
    def __init__(self,
                 filepath,
                 delimiter=',',
                 encoding='utf-8',
                 quotechar='"'):
        self.discogs = Discogs()
        self.filepath = filepath
        self.delimiter = delimiter
        self.encoding = encoding
        self.quotechar = quotechar
        self.search_terms = ('title', 'artist', 'format', 'album', 'label',
                             'year')
        self.output_csv = 'output.csv'

        if not os.path.exists('images/'):
            os.mkdir('images/')
        self.image_path = 'images/'

        self.get_columns()
        self.get_param_dict()
Example #5
0
def update_playlist(playlist, logger=None):
    """
    Reads a playlist and attempts to find accurate release data on each song.
    """
    hist = History('history.p')
    d = Discogs(logger=logger)

    for song in read_playlist(playlist):
        if hist.check_recent(song.loc):
            continue
        try:
            artist = song.meta.tag.artist
            songname = song.meta.tag.title
        except AttributeError:
            continue

        release = d.get_first_release(artist, songname)
        if release:
            update = build_update(songname, release)
            song.update_info(update)
            song.save()
        hist.store(song.loc)
Example #6
0
 def _save_members(self, artist, metadata):
     for d in metadata.get('members', []):
         member_metadata = Discogs.get_resource(d['resource_url'])
         try:
             member = Artist.objects.get(discogs_id=int(d['id']))
         except Artist.DoesNotExist:
             member = Artist.objects.create(discogs_id=int(d['id']),
                                     name=d['name'])
         member_metadata = self._save_images(member, member_metadata)
         member.about = member_metadata.get('profile')
         member_metadata = self._remove_metadata_keys(member_metadata)
         member.set_metadata_object(member_metadata)
         member.save()
         ArtistMembership.objects.create(artist=artist, member=member,
                                         active=d['active'])
     artist.save()
     metadata = self._remove_metadata_keys(metadata)
     return metadata
Example #7
0
 def save(self):
     data = self.cleaned_data
     new = True
     metadata = Discogs.get_resource(data['resource_url'])
     try:
         artist = Artist.objects.get(discogs_id=metadata['id'])
         new = False
     except Artist.DoesNotExist:
         artist = Artist.objects.create(discogs_id=metadata['id'],
                                        name=metadata['name'],
                                        about=metadata.get('profile'))
     self.is_new = new
     if not new:
         return artist
     metadata = self._save_images(artist, metadata)
     metadata = self._save_members(artist, metadata)
     artist.set_metadata_object(metadata)
     artist.save()
     return artist
Example #8
0
class Converter(object):
    def __init__(self, path_to_excel, debug=False):
        self.excel = FilenameExcel(path_to_excel)
        self.file_list = self.excel.get_rows()
        self.discogs_client = Discogs()
        self.filtered_list = []
        self.full_properties_list = []
        self.no_properties_found_list = []
        self.debug = debug
        self.sleep_seconds = 3

    def filter_doubles(self):
        last_file = None
        for file in self.file_list:
            filename = file[0]
            if filename[:-2] == last_file:
                # This one needs to be filtered out and the duration added to the previous one.
                self.filtered_list[-1][1].add_duration(Duration(file[1]))
            else:
                self.filtered_list.append([file[0], Duration(file[1])])
            last_file = filename[:-2]

    def add_search_terms(self):
        if not self.filtered_list:
            raise ValueError(
                "filtered_list is still empty. Did you initialize it yet?")

        for file in self.filtered_list:
            filename = file[0]
            # Remove everything after the third last point (extension...)
            filename_splitted = filename.split('.')
            search_term = '.'.join(filename_splitted[:-3])

            #search_term = filename.split('.', 1)[0]
            # Convert underscores to spaces
            search_term = search_term.replace("_", " ")
            search_term = search_term.replace("-", " ")
            search_term = search_term.replace("'", "")
            # remove trailing numbers or spaces.
            search_term = re.sub(r'^[ \d\.]*', '', search_term)
            file.append(search_term)

    def find_track_in_tracklist(self, file, tracks):
        best_matches = get_close_matches(file[2], tracks)
        if not best_matches:
            # Try again with less match terms.
            filename_without_extension = file[0].split('.', 1)[0]
            if '_' in filename_without_extension:
                # Split into pieces
                new_search_terms = filename_without_extension.split('_')
                for search_term in new_search_terms:
                    best_matches = get_close_matches(search_term, tracks)
                    if best_matches:
                        break
            elif '-' in filename_without_extension:
                # split into pieces
                new_search_terms = filename_without_extension.split('-')
                for search_term in new_search_terms:
                    best_matches = get_close_matches(search_term, tracks)
                    if best_matches:
                        break
            else:
                # last resort, just split into pieces with spaces
                new_search_terms = file[2].split(' ')
                for search_term in new_search_terms:
                    best_matches = get_close_matches(search_term, tracks)
                    if best_matches:
                        break

        if best_matches:
            track_title = best_matches[0]
            return track_title
        return False

    @staticmethod
    def build_tracklist(tracklist):
        expanded_tracklist = []
        for track in tracklist:
            if 'sub_tracks' in track.data.keys():
                # We're dealing with subtracks. Unpack them.
                for sub_track in track.data['sub_tracks']:
                    expanded_tracklist.append(sub_track)
            else:
                expanded_tracklist.append(track.data)
        return expanded_tracklist

    def find_properties_with_item(self, file):
        results = self.discogs_client.search_release(file[2])
        print(file[2])

        retries = 0
        while True:
            try:
                # Get the first result, we feel always lucky
                if not results:
                    # Try with the search term without parentheses content.
                    results = self.discogs_client.search_release(
                        re.sub(r'\(.*\)', '', file[2]))

                    if not results:
                        # Nothing found for this search term, return an empty properties dict with only the filename
                        print("Didn't find any results from discogs")
                        properties = {}
                        properties['Titel'] = file[0]
                        properties['Uitvoerder'] = ''
                        properties['Componist'] = ''
                        properties['Duurtijd'] = ''
                        properties['Label'] = ''
                        return properties

                release = results[0]
                break
            except:
                # sleep 3 seconds and try again
                time.sleep(self.sleep_seconds)
                print("I have tried {0} times for {1} seconds".format(
                    retries, self.sleep_seconds))
                if retries > 5:
                    raise RuntimeError(
                        "Cannot get search results after 6 retries!")

        retries = 0
        while True:
            try:
                release_tracklist = release.tracklist
                break
            except:
                # sleep 3 seconds and try again
                time.sleep(self.sleep_seconds)
                print("I have tried {0} times for {1} seconds".format(
                    retries, self.sleep_seconds))
                if retries > 5:
                    raise RuntimeError("Cannot get tracklist after 6 retries!")
                print("Failed fetching the tracklist. Retry")

        tracklist = self.build_tracklist(release_tracklist)
        tracks = [track['title'] for track in tracklist]
        if self.debug:
            print("release data and tracks data")
            print(release.data)
            print(tracks)
        track_name = self.find_track_in_tracklist(file, tracks)

        if not track_name:
            # If there's still no track found. It might be because the tracklist contains text between () which we don't like!
            # get this text out and repeat.
            tracks = [
                re.sub(r'\(.*\)', '', track['title']) for track in tracklist
            ]
            track_name = self.find_track_in_tracklist(file, tracks)
            if not track_name:
                # Nothing found for this search term, return an empty properties dict with only the filename
                print("Didn't find the correct track!")
                properties = {}
                properties['Titel'] = file[0]
                properties['Uitvoerder'] = ''
                properties['Componist'] = ''
                properties['Duurtijd'] = ''
                properties['Label'] = ''
                return properties
            else:
                for track in tracklist:
                    track_title = re.sub(r'\(.*\)', '', track['title'])
                    if track_title == track_name:
                        break
        else:
            for track in tracklist:
                if track['title'] == track_name:
                    break

        properties = {}
        properties['Titel'] = track['title']
        properties['Uitvoerder'] = ",".join(
            set([artist.name for artist in release.artists]))
        # Get all the writers
        writers = []
        if 'extraartists' in track.keys():
            for extra_artist in track['extraartists']:
                if extra_artist['role'] == 'Written-By' or extra_artist[
                        'role'] == 'Written-By, Composed By':
                    writers.append(extra_artist['name'])
            # if no writers found on the track. Let's get the writers of the release
        if not writers:
            if 'extraartists' in release.data.keys():
                for extra_artist in release.data['extraartists']:
                    if extra_artist['role'] == 'Written-By' or extra_artist[
                            'role'] == 'Written-By, Composed By':
                        writers.append(extra_artist['name'])

        properties['Componist'] = ",".join(set(writers))
        properties['Duurtijd'] = file[1].get_in_minutes_seconds()
        properties['Label'] = ",".join(
            set([label.name for label in release.labels]))
        print(properties)

        return properties

    def convert_to_full_properties(self):
        for file in self.filtered_list:
            print(file[0])
            properties = self.find_properties_with_item(file)
            if properties:
                self.full_properties_list.append(properties)
            else:
                # No properties found. Append it to another list.
                self.no_properties_found_list.append(file)

            # Sleep 1 second because the discogs api doesn't like us
            time.sleep(1)

    def export_to_csv(self, file_path, csv_columns=None):
        if not csv_columns:
            csv_columns = [
                'Volgnummer', 'Tijdscode', 'Titel', 'Aard', 'Performance',
                'Componist', 'Uitvoerder', 'Duurtijd', 'Rechthebbende',
                'Hoedanigheid', 'Jaar', 'ISRC', 'Label', 'Album', 'Cat Nr',
                'Track'
            ]

        try:
            with open(file_path, 'w') as csv_file:
                writer = csv.DictWriter(csv_file, fieldnames=csv_columns)
                writer.writeheader()
                for data in self.full_properties_list:
                    writer.writerow(data)
        except IOError:
            print("I/O error")

    def export_to_excel(self, file_path, excel_columns=None):
        if not excel_columns:
            excel_columns = [
                'Volgnummer', 'Tijdscode', 'Titel', 'Aard', 'Performance',
                'Componist', 'Uitvoerder', 'Duurtijd', 'Rechthebbende',
                'Hoedanigheid', 'Jaar', 'ISRC', 'Label', 'Album', 'Cat Nr',
                'Track'
            ]
        excel_writer = ExcelWriter(file_path)
        excel_writer.create_excel(self.full_properties_list, excel_columns)
Example #9
0
import logging
import traceback

folders = Folder(ENV_PATHS)
# print(style.green('\n' + MY_PATH))

for folder in folders:

    print(style.yellow('\n---\n'))

    print(style.green(folder))
    print()

    files = File(folder)
    try:
        discogs = Discogs(files)
    except Exception as e:
        print(style.red('some error happened...'))
        logging.error(traceback.format_exc())
        continue

    if discogs == ENV_TAGGING_DONE:
        print(style.yellow(ENV_TAGGING_DONE))
        continue

    if discogs == ENV_TAGGING_TODO:
        print(style.yellow(ENV_TAGGING_TODO))
        continue

    Tagger(files, discogs)
Example #10
0
class ImageScraper:
    """
    Takes CSV file of music releases and searches Discogs API for cover image.
    Creates a dictionary mapping the column headers to search terms which can
    be customized.

    Cover images are saved in 'images' directory using the cover id from
    Discogs. Creates an output CSV copying each row and adding the cover id
    of 'Null' if nothing found.
    """
    def __init__(self,
                 filepath,
                 delimiter=',',
                 encoding='utf-8',
                 quotechar='"'):
        self.discogs = Discogs()
        self.filepath = filepath
        self.delimiter = delimiter
        self.encoding = encoding
        self.quotechar = quotechar
        self.search_terms = ('title', 'artist', 'format', 'album', 'label',
                             'year')
        self.output_csv = 'output.csv'

        if not os.path.exists('images/'):
            os.mkdir('images/')
        self.image_path = 'images/'

        self.get_columns()
        self.get_param_dict()

    def get_columns(self):
        """
        Returns the columns from CSV file as a list
        """
        with open(self.filepath, 'r', encoding=self.encoding) as file:
            csv_reader = csv.reader(file,
                                    delimiter=self.delimiter,
                                    quotechar=self.quotechar)
            headers = next(csv_reader)
            self.columns = [col for col in headers]

    def get_param_dict(self):
        self.param_dict = {}
        for i, col in enumerate(self.columns):
            for param in self.search_terms:
                if col.lower() == param:
                    self.param_dict[param] = i

    def confirm_dict(self):
        update_dict = True
        while update_dict:
            for param, col in self.param_dict.items():
                print(f'{param} found in column {col}')
            print('\nTo procede with these settings press Enter.')
            print('To add an item enter the header-text then col eg: title 1.')
            print('To delete an item enter the item eg: artist.')
            update_dict = input('> ')
            if update_dict:
                if len(update_dict.split()) == 2:
                    param, col = update_dict.split()
                    self.param_dict[param] = int(col)
                elif len(update_dict.split()) == 1:
                    del self.param_dict[update_dict]
                else:
                    print("I didn't understand that, please try again.")

    def get_search_params(self, row):
        """
        Takes row from csv file and returns a dictionary mapping the search
        parameters to their values
        """
        params = {}
        for k, v in self.param_dict.items():
            params[k] = row[v].replace(" ", "+")
        return params

    def run(self):
        with open(filepath, 'r', encoding=self.encoding) as input_file:
            csv_reader = csv.reader(input_file, delimiter=self.delimiter)
            next(csv_reader)
            for row in csv_reader:
                params = self.get_search_params(row)
                try:
                    response, cover_id = self.discogs.search(params)
                    with open(self.output_csv, 'a') as output_file:
                        output_csv = csv.writer(output_file)
                        output_csv.writerow(row + [cover_id])
                        with open(self.image_path + cover_id + '.jpg',
                                  'wb') as f:
                            shutil.copyfileobj(response.raw, f)
                        del response

                except TypeError:
                    with open(self.output_csv, 'a') as output_file:
                        output_csv = csv.writer(output_file)
                        output_csv.writerow(row + ['Null'])
                time.sleep(1.2)
Example #11
0
def main():
    if "--version" in sys.argv[1:] or "-v" in sys.argv[1:]:
        print(f"ytam version {version.version}")
        exit()

    if "--check" in sys.argv[1:] or "-k" in sys.argv[1:]:
        print("Initialising.")
        urls = Playlist(
            "https://www.youtube.com/playlist?list=PLOoPqX_q5JAVPMhHjYxcUc2bxTDMyGE-a"
        )
        playlist_title = urls.title
        start = 0
        end = len(urls)
        album = "Test Album"
        directory = f"music{SEP}"
        artist = "Test Artist"
        is_album = True
        proxies = None
        image = f"{BASE}{SEP}check{SEP}check.jpg"
        titles = f"{BASE}{SEP}check{SEP}check.txt"
        mp3 = True

    else:
        print("Initialising.")
        args = parse_args(sys.argv[1:])
        mp3 = args.mp3
        urls = Playlist(args.url)
        playlist_title = urls.title
        start = 0 if args.start is None else args.start - 1
        end = len(urls) if args.end is None else args.end
        directory = f"music{SEP}" if args.directory is None else args.directory
        proxies = None
        if args.proxy is not None:
            proxy_strings = [proxy.strip() for proxy in args.proxy.split(" ")]
            proxies = {}
            for proxy_string in proxy_strings:
                p = proxy_string.split("-")
                proxies[p[0]] = p[1]

        if args.discogs is not None:
            # do discogs error checks here
            try:
                d = Discogs(args.discogs)
                d.make_file(DEFAULT_TITLES)
                if (end - start) != d.num_tracks:
                    raise error.TracknumberMismatchError(
                        playlist_title, d.album)
                is_album = True
                album = d.album
                artist = d.artist
                image = d.image
                titles = DEFAULT_TITLES
            except (error.WrongMetadataLinkError, error.BrokenDiscogsLinkError,
                    error.TracknumberMismatchError) as e:
                print(f"Error: {e.message}")
                exit()

        else:
            album = playlist_title if args.album is None else args.album
            artist = "Unknown" if args.artist is None else args.artist
            is_album = False if args.album is None else True
            image = args.image
            titles = args.titles

    colorama.init()
    d = None
    try:
        if start >= len(urls):
            raise error.InvalidPlaylistIndexError(start, playlist_title)
        if end < start:
            raise error.IndicesOutOfOrderError()

        downloading_message = f"Downloading songs {font.apply('gb', start+1)} - {font.apply('gb', end)} from playlist {font.apply('gb', playlist_title)}"
        text_len = (len("Downloading songs ") + len(str(start)) + len(" - ") +
                    len(str(end)) + len(" from playlist ") +
                    len(playlist_title))
        print(downloading_message, f"\n{font.apply('gb', '─'*text_len)}")
        d = Downloader(
            list(enumerate(urls[start:end])),
            len(urls),
            album,
            directory,
            artist,
            is_album,
            titles,
            image,
            proxies,
            mp3,
        )
        d.start = start

        retry = True
        while retry:
            d.download()
            print(f"{font.apply('gb', '─'*text_len)}")
            print(
                f"{d.successful}/{len(urls[start:end])} downloaded successfully.\n"
            )
            if len(d.retry_urls) > 0:
                d.set_retries()
                urls_copy = d.urls.copy()
                user = input(
                    f"Retry {font.apply('fb', str(len(list(urls_copy))) + ' failed')} downloads? Y/N "
                )
                if not is_affirmative(user):
                    retry = False
                else:
                    print("\nRetrying.")
                    print(f"{font.apply('gb', '─'*len('Retrying.'))}")
            else:
                retry = False

    except (
            error.InvalidPlaylistIndexError,
            error.IndicesOutOfOrderError,
            error.TitlesNotFoundError,
            error.BadTitleFormatError,
    ) as e:
        print(f"Error: {e.message}")
Example #12
0
from discord.ext import commands
import random
import requests

discordToken = ""
filename = "D:/Repos/AudioManiac-Bot/credentials.json"

if filename:
    with open(filename, 'r') as f:
        data = json.load(f)
        discordToken = data["discordtoken"]

yt = Youtube()
yt.Init()

dscgs = Discogs()
dscgs.Init()

description = "An example bot to showcase the discord.ext.commands extension module."
bot = commands.Bot(command_prefix='?', description=description)


@bot.event
async def on_ready():
    print('Logged in as')
    print(bot.user.name)
    print(bot.user.id)
    print('------')


@bot.command()