def add_release(self, release_id): self.cli.exit_if_offline(self.collection.ONLINE) #if args.add_release_id: if is_number(release_id): # setup.py argparser only allows integer, this is for calls from somewhere else #if db.search_release_id(conn, args.add_release_id): if self.collection.search_release_id(release_id): self.cli.print_help( "Release ID is already existing in DiscoBASE, won't add it to your Discogs collection." ) else: self.cli.print_help("Asking Discogs if release ID {:d} is valid.".format( release_id)) result = self.collection.d.release(release_id) artists = self.collection.d_artists_to_str(result.artists) if result: log.debug(dir(result)) self.cli.print_help("Adding \"{}\" to collection".format(result.title)) for folder in self.collection.me.collection_folders: if folder.id == 1: folder.add_release(release_id) #import_release(conn, d, me, args.add_release_id) #last_row_id = db.create_release(conn, result, collection_item = False) last_row_id = self.collection.create_release(result.id, result.title, artists, d_coll = True) if not last_row_id: #self.cli.print_help("This is not the release you are looking for!") self.cli.error_not_the_release()
def search_release_offline(self, id_or_title): if is_number(id_or_title): try: release = self._select_simple(['*'], 'release', 'discogs_id LIKE {}'.format( id_or_title, id_or_title), fetchone=True, orderby='d_artist') if release: return [release] else: release_not_found = None return release_not_found except Exception as Exc: log.error("Not found or Database Exception: %s\n", Exc) raise Exc else: try: releases = self._select_simple( ['*'], 'release', 'discogs_title LIKE "%{}%" OR d_artist LIKE "%{}%"'.format( id_or_title, id_or_title), fetchone=False, orderby='d_artist') if releases: log.debug("First found release: {}".format(releases[0])) log.debug("All found releases: {}".format(releases)) return releases # this is a list else: return None except Exception as Exc: log.error("Not found or Database Exception: %s\n", Exc) raise Exc
def add_new_mix(conn, name, played='', venue=''): log.debug("DB: add_new_mix got: {}, {}, {}.".format(name, played, venue)) cur = conn.cursor() cur.execute('''INSERT INTO mix (name, created, updated, played, venue) VALUES (?, datetime('now', 'localtime'), '', date(?), ?)''', (name, played, venue)) log.info("DB: cur.rowcount: %s", cur.rowcount) return cur.lastrowid
def search_release_title(conn, discogs_title): log.debug('DB: Search for Discogs Release Title or Artist: %s\n', discogs_title) cur = conn.cursor() cur.execute("SELECT * FROM release WHERE discogs_title LIKE ? OR d_artist LIKE ?", ("%"+discogs_title+"%", "%"+discogs_title+"%"), ) rows = cur.fetchall() log.debug('DB: search_release_title returns: %s', rows) return rows
def add_track_to_mix(conn, mix_id, release_id, track_no, track_pos=0, trans_rating='', trans_notes=''): log.debug("DB: add_track_to_mix got this: mix_id: {}, d_release_id: {}, track_no: {}, track_pos: {}, trans_rating: {}, trans_notes: {}".format(mix_id, release_id, track_no, track_pos, trans_rating, trans_notes)) cur = conn.cursor() cur.execute('''INSERT INTO mix_track (mix_id, d_release_id, d_track_no, track_pos, trans_rating, trans_notes) VALUES(?, ?, ?, ?, ?, ?)''', (mix_id, release_id, track_no, track_pos, trans_rating, trans_notes)) log.info("DB: cur.rowcount: %s", cur.rowcount) conn.commit() return cur.lastrowid
def get_tracks_from_position(conn, _mix_id, _pos): conn.row_factory = sqlite3.Row cur = conn.cursor() cur.execute('''SELECT mix_track_id, track_pos FROM mix_track WHERE mix_id == ? AND track_pos >= ? ''', (_mix_id, _pos)) rows = cur.fetchall() log.debug('DB: get_tracks_from_position: %s\n', rows) if len(rows) == 0: log.info('DB: get_tracks_from_position: Nothing found') return False else: return rows
def copy_mix(self): self.cli.print_help("Copying mix {} - {}.".format(self.mix.id, self.mix.name)) copy_tr = self.mix.get_tracks_to_copy() new_mix_name = self.cli.ask_user("How should the copy be named? ") new_mix_id = self.mix.create(self.mix.played, self.mix.venue, new_mix_name) new_mix = Mix(self.mix.db_conn, new_mix_id) for tr in copy_tr: log.debug("CTRL copy_mix: This is tr: {}, {}, {}, {}, {}, ".format( tr[0], tr[1], tr[2], tr[3], tr[4])) new_mix.add_track(tr[0], tr[1], tr[2], tr[3], tr[4]) #release, track_no, track_pos, trans_rating='', trans_notes='' new_mix.db_conn.commit() self.cli.print_help("Copy mix successful. New ID is {}.".format(new_mix.id))
def __init__(self, db_conn, mix_name_or_id, db_file=False): super(Mix, self).__init__(db_conn, db_file) # figuring out names and IDs, just logs and sets instance attributes, no exits here! self.name_or_id = mix_name_or_id self.id_existing = False self.name_existing = False self.info = [] self.name = False self.created = False self.updated = False self.played = False self.venue = False if is_number(mix_name_or_id): self.id = mix_name_or_id # if it's a mix-id, get mix-name and info try: self.info = self.get_mix_info() # FIXME info should also be available as single attrs: created, venue, etc. self.name = self.info[1] self.id_existing = True self.name_existing = True except: log.info("Mix ID is not existing yet!") #raise Exception # use this for debugging #raise SystemExit(1) else: self.name = mix_name_or_id # if it's a mix-name, get the id unless it's "all" # (default value, should only show mix list) if not self.name == "all": try: mix_id_tuple = db.get_mix_id(db_conn, self.name) log.info('%s', mix_id_tuple) self.id = mix_id_tuple[0] self.id_existing = True self.name_existing = True # load basic mix-info from DB # FIXME info should also be available as single attrs: created, venue, etc. # FIXME or okay? here we assume mix is existing and id could be fetched try: self.info = self.get_mix_info() self.name = self.info[1] except: log.info("Can't get mix info.") #raise Exception # use this for debugging except: log.info( "Can't get mix-name from id. Mix not existing yet?") #raise Exception # use this for debugging #raise SystemExit(1) if self.id_existing: self.created = self.info[2] self.played = self.info[4] self.venue = self.info[5] log.debug("MODEL: Mix info is {}.".format(self.info)) log.debug("MODEL: Name is {}.".format(self.name)) log.debug("MODEL: Played is {}.".format(self.played)) log.debug("MODEL: Venue is {}.".format(self.venue))
def view(self): if self.mix.id_existing: self.cli.tab_mix_info_header(self.mix.info) if self.user.WANTS_VERBOSE_MIX_TRACKLIST: full_mix = self.mix.get_full_mix(verbose = True) else: full_mix = self.mix.get_full_mix(verbose = False) if not full_mix: print_help("No tracks in mix yet.") else: # newline chars after 24 chars magic, our new row_list: # FIXME this has to move to Mix_cli class or maybe also useful in Mix_gui class? # in any case: move to separate method cut_pos = 16 full_mix_nl = [] # first convert list of tuples to list of lists: for tuple_row in full_mix: full_mix_nl.append(list(tuple_row)) # now put newlines if longer than cut_pos chars for i, row in enumerate(full_mix_nl): for j, field in enumerate(row): if not is_number(field) and field is not None: if len(field) > cut_pos: cut_pos_space = field.find(" ", cut_pos) log.debug("cut_pos_space index: %s", cut_pos_space) # don't edit if no space following (almost at end) if cut_pos_space == -1: edited_field = field log.debug(edited_field) else: edited_field = field[0:cut_pos_space] + "\n" + field[cut_pos_space+1:] log.debug(edited_field) #log.debug(field[0:cut_pos_space]) #log.debug(field[cut_pos_space:]) full_mix_nl[i][j] = edited_field # debug only for row in full_mix_nl: log.debug(str(row)) log.debug("") # now really if self.user.WANTS_VERBOSE_MIX_TRACKLIST: self.cli.tab_mix_table(full_mix_nl, _verbose = True) else: self.cli.tab_mix_table(full_mix_nl, _verbose = False) else: print_help("Mix \"{}\" is not existing yet!".format(self.mix.name_or_id))
def _select(self, sql_select, fetchone=False): log.info("DB-NEW: SQL: {}".format(sql_select)) self.cur.execute(sql_select) if fetchone: rows = self.cur.fetchone() else: rows = self.cur.fetchall() if rows: if len(rows) == 0: log.info('DB-NEW: Nothing found - rows length 0.') return False else: log.debug('DB-NEW: Found {} rows.'.format(len(rows))) return rows else: log.info('DB-NEW: Nothing found - rows NoneType.') return False
def get_d_release(self, release_id): try: r = self.d.release(release_id) log.debug("try to access r here to catch err {}".format(r.title)) return r except errors.HTTPError as HtErr: log.error('Release not existing on Discogs ({})'.format(HtErr)) #log.error("%s", HtErr) return False except urlerrors.NewConnectionError as ConnErr: log.error("%s", ConnErr) return False except urlerrors.MaxRetryError as RetryErr: log.error("%s", RetryErr) return False except Exception as Exc: log.error("Exception: %s", Exc) #raise Exc return False
def bulk_edit_tracks(self, fields_str, first_track): log.debug("bulk_edit_tracks args: {} {}".format(fields_str, first_track)) fields_list = fields_str.split(',') log.debug('fields split: {}'.format(fields_list)) if not first_track: first_track = 1 if self.mix.id_existing: for track in self.mix.get_full_mix(verbose = True): if not track['track_pos'] < first_track: self.cli.print_help( "Editing track {} | {} - {} | {} - {}".format( track['track_pos'], track['discogs_title'], track['d_track_no'], track['d_artist'], track['d_track_name'])) track_details = self.mix.get_one_mix_track(track['track_pos']) bulk_questions = [] for field in fields_list: #field=field.replace('d_', '') #log.info("checking field: {}".format(field)) for question in self.cli._edit_track_questions: if field == question[0]: #log.info("appending to bulk_questions list") bulk_questions.append(question) log.debug(bulk_questions) edit_answers = self._edit_track_ask_details(track_details, bulk_questions) update_ok = self.mix.update_mix_track_and_track_ext(track_details, edit_answers) print("") # just some space
def search_release_online(self, id_or_title): try: if is_number(id_or_title): release = self.d.release(id_or_title) #return '|'+str(release.id)+'|'+ str(release.title)+'|' return [release] else: releases = self.d.search(id_or_title, type='release') log.info("First found release: {}".format(releases[0])) log.debug("All found releases: {}".format(releases)) return releases except errors.HTTPError as HtErr: log.error("%s", HtErr) return False except urlerrors.NewConnectionError as ConnErr: log.error("%s", ConnErr) return False except urlerrors.MaxRetryError as RetryErr: log.error("%s", RetryErr) return False except Exception as Exc: log.error("Exception: %s", Exc) return False
def get_one_mix_track(conn, mix_id, position): conn.row_factory = sqlite3.Row cur = conn.cursor() log.debug('DB getting details of a mix-track by ID %s and position %s\n', mix_id, position) cur.execute('''SELECT track_pos, discogs_title, d_track_name, mix_track.d_track_no, trans_rating, trans_notes, key, key_notes, bpm, notes, mix_track_id, mix_track.d_release_id FROM mix_track INNER JOIN mix ON mix.mix_id = mix_track.mix_id INNER JOIN release ON mix_track.d_release_id = release.discogs_id LEFT OUTER JOIN track ON mix_track.d_release_id = track.d_release_id AND mix_track.d_track_no = track.d_track_no LEFT OUTER JOIN track_ext ON mix_track.d_release_id = track_ext.d_release_id AND mix_track.d_track_no = track_ext.d_track_no WHERE mix_track.mix_id == ? AND mix_track.track_pos == ?''', (mix_id, position)) rows = cur.fetchone() return rows
def __init__(self, db_conn=False, db_file=False): if db_conn: log.debug("DB-NEW: db_conn argument was handed over.") self.db_conn = db_conn else: log.debug("DB-NEW: Creating connection to db_file.") if not db_file: log.debug("DB-NEW: No db_file given, using default name.") db_file = './discobase.db' self.db_conn = self.create_conn(db_file) self.db_conn.row_factory = sqlite3.Row # also this was in each db.function before self.cur = self.db_conn.cursor( ) # we had this in each db function before self.configure_db() # set PRAGMA options
def update_mix_track_and_track_ext(self, track_details, edit_answers): mix_track_cols = [ 'd_release_id', 'd_track_no', 'track_pos', 'trans_rating', 'trans_notes' ] track_ext_cols = ['key', 'bpm', 'key_notes', 'notes'] values_mix_track = '' # mix_track update values_list_mix_track = [] values_track_ext = '' # track_ext update values_list_track_ext = [] cols_insert_track_ext = '' # track_ext insert values_insert_track_ext = '' # (the tuple is the same obviously) if 'track_pos' in edit_answers: #filter out track_pos='not a number' if edit_answers['track_pos'] == 'not a number': edit_answers.pop('track_pos') mix_track_edit = False # decide if it's table mix_track or track_ext track_ext_edit = False for key in edit_answers: if key in mix_track_cols: mix_track_edit = True if key in track_ext_cols: track_ext_edit = True if mix_track_edit: update_mix_track = 'UPDATE mix_track SET ' where_mix_track = 'WHERE mix_track_id == {}'.format( track_details['mix_track_id']) for cnt, answer in enumerate(edit_answers.items()): log.debug('key: {}, value: {}'.format(answer[0], answer[1])) if answer[0] in mix_track_cols: if values_mix_track == '': values_mix_track += "{} = ? ".format( answer[0], answer[1]) else: values_mix_track += ", {} = ? ".format( answer[0], answer[1]) values_list_mix_track.append(answer[1]) final_update_mix_track = update_mix_track + values_mix_track + where_mix_track log.info('DB-NEW: {}'.format(final_update_mix_track)) log.info( log.info('DB-NEW: {}'.format(tuple(values_list_mix_track)))) with self.db_conn: log.info("DB-NEW: Now really executing mix_track update...") self.execute_sql(final_update_mix_track, tuple(values_list_mix_track)) if track_ext_edit: update_track_ext = 'UPDATE track_ext SET ' insert_track_ext = 'INSERT INTO track_ext' where_track_ext = 'WHERE d_release_id == {} AND d_track_no == \"{}\"'.format( track_details['d_release_id'], track_details['d_track_no']) for cnt, answer in enumerate(edit_answers.items()): log.debug('key: {}, value: {}'.format(answer[0], answer[1])) if answer[0] in track_ext_cols: if values_track_ext == '': values_track_ext += "{} = ? ".format( answer[0], answer[1]) else: values_track_ext += ", {} = ? ".format( answer[0], answer[1]) values_list_track_ext.append(answer[1]) if values_insert_track_ext == '': cols_insert_track_ext += "{}".format(answer[0]) values_insert_track_ext += "?".format(answer[1]) else: cols_insert_track_ext += ", {}".format(answer[0]) values_insert_track_ext += ", ?".format(answer[1]) # the list is the same as with update final_update_track_ext = update_track_ext + values_track_ext + where_track_ext final_insert_track_ext = "{} ({}, d_release_id, d_track_no) VALUES ({}, ?, ?)".format( insert_track_ext, cols_insert_track_ext, values_insert_track_ext) log.info('DB-NEW: {}'.format(final_update_track_ext)) log.info('DB-NEW: {}'.format(tuple(values_list_track_ext))) log.info('DB-NEW: {}'.format(final_insert_track_ext)) values_insert_list_track_ext = values_list_track_ext[:] values_insert_list_track_ext.append(track_details['d_release_id']) values_insert_list_track_ext.append(track_details['d_track_no']) log.info('DB-NEW: {}'.format(tuple(values_insert_list_track_ext))) with self.db_conn: log.info( "DB-NEW: Now really executing track_ext update/insert...") log.info(values_list_track_ext) log.info(tuple(values_list_track_ext)) self.execute_sql(final_update_track_ext, tuple(values_list_track_ext)) if self.cur.rowcount == 0: log.info( "DB-NEW: UPDATE didn't change anything, trying INSERT..." .format(self.cur.rowcount)) self.execute_sql(final_insert_track_ext, tuple(values_insert_list_track_ext))
def me(self): discogs_me_o = self.collection.d log.debug("CTRL: Getting Collection.me instance from MODEL: %s", discogs_me_o) return discogs_me_o
def d(self): discogs_cli_o = self.collection.d log.debug("CTRL: Getting Collection.d instance from MODEL: %s", discogs_cli_o) return discogs_cli_o
def _add_track(self, _release_id, _release_title, _track_no, _pos): if not _track_no: track_to_add = self.cli.ask_user_for_track() else: log.debug("_track_no was given, value is".format(_track_no)) track_to_add = _track_no if _pos == None: log.debug("_pos was None, setting to 0") _pos = 0 log.debug("This is _pos: {}".format(_pos)) log.debug("This is track_to_add: {}".format(track_to_add)) log.debug("This is _release_id: %s", _release_id) log.debug("This is _release_title: %s", _release_title) if self.mix.id_existing: last_track = self.mix.get_last_track() log.debug("Currently last track in mix is: %s", last_track[0]) current_id = False if _pos: # a position to squeeze in the track was given # get current tracks >= pos tracks_to_shift = self.mix.get_tracks_from_position(_pos) if self.cli.really_add_track(track_to_add, _release_title, self.mix.id, _pos): current_id = self.mix.add_track(_release_id, track_to_add, track_pos = _pos) # all good? reorder tracks if current_id: log.info("Add track to mix successful, now reordering ...") self.mix.reorder_tracks_squeeze_in(_pos, tracks_to_shift) elif is_number(last_track[0]): # no position was given, tracks already mix if self.cli.really_add_track(track_to_add, _release_title, self.mix.id, last_track[0]+1): current_id = self.mix.add_track(_release_id, track_to_add, track_pos = last_track[0] + 1) else: # no position and it's the first track ever added if self.cli.really_add_track(track_to_add, _release_title, self.mix.id, 1): current_id = self.mix.add_track(_release_id, track_to_add, track_pos = 1) # FIXME untested if this is actually a proper sanity check log.debug("Value of current_id in add_offline_track: {}".format(current_id)) if current_id: self.view() #return True else: log.error("Add track to DB failed!") #return False else: self.cli.print_help("Mix ID {} is not existing yet.".format(self.mix.id)) return False
def __init__(self, _args): self.args = _args self.WANTS_ONLINE = True self.WANTS_TO_LIST_ALL_RELEASES = False self.WANTS_TO_SEARCH_FOR_RELEASE = False self.WANTS_TO_ADD_TO_MIX = False self.WANTS_TO_SHOW_MIX_OVERVIEW = False self.WANTS_TO_SHOW_MIX_TRACKLIST = False self.WANTS_TO_CREATE_MIX = False self.WANTS_TO_EDIT_MIX_TRACK = False self.WANTS_TO_PULL_TRACK_INFO = False self.WANTS_TO_PULL_TRACK_INFO_IN_MIX_MODE = False self.WANTS_VERBOSE_MIX_TRACKLIST = False self.WANTS_TO_REORDER_MIX_TRACKLIST = False self.WANTS_TO_ADD_AT_POSITION = False self.WANTS_TO_DELETE_MIX_TRACK = False self.WANTS_TO_ADD_RELEASE_IN_MIX_MODE = False self.WANTS_TO_ADD_AT_POS_IN_MIX_MODE = False self.WANTS_TO_COPY_MIX = False self.WANTS_TO_TRACK_SEARCH = False self.WANTS_TO_DELETE_MIX = False self.WANTS_TRACK_REPORT = False self.WANTS_TO_BULK_EDIT = False # RELEASE MODE: if hasattr(self.args, 'release_search'): if "all" in self.args.release_search: self.WANTS_TO_LIST_ALL_RELEASES = True self.WANTS_ONLINE = False else: self.WANTS_TO_SEARCH_FOR_RELEASE = True if (self.args.add_to_mix != 0 and self.args.track_to_add != 0 and self.args.add_at_pos): self.WANTS_TO_ADD_AT_POSITION = True #self.WANTS_TO_SHOW_MIX_TRACKLIST = True elif self.args.add_to_mix != 0 and self.args.track_to_add != 0: self.WANTS_TO_ADD_TO_MIX = True else: log.error( "args.add_to_mix, args.track_to_add or args.add_at_pos is 0" ) raise SystemExit(1) # MIX MODE if hasattr(self.args, 'mix_name'): if self.args.mix_name == "all": self.WANTS_TO_SHOW_MIX_OVERVIEW = True self.WANTS_ONLINE = False if self.args.create_mix == True: log.error("Please provide a mix name to be created!") log.error("(Mix name \"all\" is not valid.)") raise SystemExit(1) elif self.args.delete_mix == True: log.error("Please provide a mix name or ID to be deleted!") raise SystemExit(1) if self.args.discogs_update: self.WANTS_TO_PULL_TRACK_INFO_IN_MIX_MODE = True self.WANTS_ONLINE = True else: self.WANTS_TO_SHOW_MIX_TRACKLIST = True self.WANTS_ONLINE = False #if hasattr(self.args, 'create_mix') if self.args.create_mix: self.WANTS_TO_CREATE_MIX = True self.WANTS_ONLINE = False if self.args.edit_mix_track: self.WANTS_TO_EDIT_MIX_TRACK = True self.WANTS_ONLINE = False if self.args.verbose_tracklist: self.WANTS_VERBOSE_MIX_TRACKLIST = True self.WANTS_ONLINE = False if self.args.reorder_from_pos: self.WANTS_TO_REORDER_MIX_TRACKLIST = True self.WANTS_ONLINE = False if self.args.delete_track_pos: self.WANTS_TO_DELETE_MIX_TRACK = True self.WANTS_ONLINE = False if self.args.add_release_to_mix: self.WANTS_TO_ADD_RELEASE_IN_MIX_MODE = True self.WANTS_ONLINE = True if self.args.mix_mode_add_at_pos: self.WANTS_TO_ADD_AT_POS_IN_MIX_MODE = True if self.args.copy_mix: self.WANTS_TO_COPY_MIX = True self.WANTS_ONLINE = False if self.args.discogs_update: self.WANTS_TO_PULL_TRACK_INFO_IN_MIX_MODE = True self.WANTS_ONLINE = True if self.args.delete_mix: self.WANTS_TO_DELETE_MIX = True self.WANTS_ONLINE = False if self.args.bulk_edit: self.WANTS_TO_BULK_EDIT = True # TRACK MODE if hasattr(self.args, 'track_search'): self.WANTS_TO_TRACK_SEARCH = True if self.args.track_pull: self.WANTS_TO_PULL_TRACK_INFO = True else: self.WANTS_TRACK_REPORT = True log.debug("Entered Track-combination report.") #log.error("track search not implemented yet.") #raise SystemExit(1) if self.args.offline_mode == True: self.WANTS_ONLINE = False
def ONLINE(self): status = self.collection.ONLINE log.debug("CTRL: Collection model has ONLINE status %s", status) return status