def get_movie_imdb_id(moviedb_id: int) -> tuple: """ Retrieve a movie's IMDB ID given it's MovieDB ID. :param int moviedb_id: The movie's MovieDB ID :return tuple: True = Success or False = Fail, The movie's IMDB ID or status message """ base_url = 'https://api.themoviedb.org/3/movie/' api_key = '?api_key=' + get_api_key() language = '&language=en-US' url = base_url + str(moviedb_id) + api_key + language response = moviedb_api_call(url) if response[0] is False: return response else: response_str = response[1] # print(response_str) # response_str = response_str.replace('\\\'', "'") # DEBUG # Logger.log_message(1, response_str) pattern = re.compile('"imdb_id":\s*"(tt\d{7})"') match = pattern.search(response_str) if match: return True, match.group(1) else: # MovieDB response does not match RegEx pattern. No IMDB ID. logger.log_message( 1, 'MovieDB response does not match RegEx pattern. No imdb_id found.') return False, 'WARNING: No IMDB found! '
def update_movie(movie: LibraryDBMovie) -> tuple: """ Update movie object in LibraryDB. :param LibraryDB_Movie movie: LibraryDB_Movie to be updated in LibraryDB :return tuple: Status code. True = Success or False = Error, string description of status """ conn = sqlite3.connect(globals.LIBRARYDB_PATH) try: c = conn.cursor() # UPDATE table_name SET column1 = value1, column2 = value2...., columnN = valueN WHERE [condition]; c.execute( 'UPDATE Titles SET name = ?, movie_db_id = ?, imdb_id = ?, genres = ?, description = ?, release_date = ?, ' + 'format = ?, posterUrl = ? WHERE title_id = ?', (movie.title, movie.movie_db_id, movie.imdb_id, movie.genre_ids, movie.description, movie.release_date, movie.title_format, movie.poster_url, movie.title_id)) conn.commit() conn.close() except Exception as err: conn.commit() conn.close() logger.log_message(0, str(err)) return False, "UPDATE ERROR: Check logs for details! " return True, 'Successful LibraryDB Update!'
def process_input(entry: str) -> tuple: """ Handle all option and special option actions. :param str entry: User's input :return tuple: True = Success or False = Fail, next menu or status message """ if entry.upper() == 'B': menu_manager.back() return False, '' elif entry.upper() == 'Q': # Quit quit() if len(entry) < 4: # Entry is too short or too long, redisplay prompt logger.log_message( 1, 'User entered less than four characters! ' + entry) return False, 'WARNING: Input was less than 4 characters! ' else: # Input is good, query MovieDB response = moviedb.query(entry) if response[0]: if len(response[1]) == 0: # logger.log_message(1, 'No movie found!') return False, 'WARNING: No movie found! ' else: # Movies found, open Movie_Select next_menu = MovieSelect(response[1], 'I') return True, next_menu else: return response
def process_input(entry: str) -> tuple: """ Handle all option and special option actions. :param str entry: User's input :return tuple: False (to drop back into the Menu Manager loop), status message or next menu """ if entry.upper() == 'B': menu_manager.back() return False, '' elif entry.upper() == 'Q': # Quit quit() # Check if entry is in the form of IMDB ID # tt9999999 if len(entry) != 9: # Entry is too short or too long, redisplay prompt logger.log_message( 1, 'Entry is ' + str(len(entry)) + ' characters long. Entry: ' + entry) return False, 'WARNING: Input should be 9 characters! ' else: pattern = re.compile('tt\d{7}') match = pattern.search(entry) # logger.log_message(1, 'Looking for regex match...') if match: # Matches IMDB ID form, query MovieDB # logger.log_message(1, 'Searching MovieDB...') response = _query_moviedb(entry) if response[0] is False: return response else: # logger.log_message(1, 'Proper IMDB ID entered, opening Format_Select.') format_menu = FormatSelect(response[1]) while True: response = format_menu.menu_logic() if response[0]: # If selection is in options/special_options, process input response = format_menu.process_input(response[1]) if response[0]: # If format was successfully selected, return LibraryDB_Movie object return True, MovieParams(response[1], 'I') else: # Format not successfully selected, back to format select menu format_menu.val_input = False format_menu.inval_prompt = response[1] continue else: # Format not successfully selected, back to format select menu format_menu.val_input = False format_menu.inval_prompt = response[1] continue else: # Entry is not IMDB ID, redisplay prompt logger.log_message(1, 'NOT AN IMDB ID! ' + entry) return False, 'NOT AN IMDB ID! '
def __init__(self, movie: LibraryDBMovie, mode: str): """ Create MovieParams menu object. :param LibraryDBMovie movie: Movie that needs edited. :param str mode: I or U, whether the movie is to be inserted or updated in LibraryDB """ prompt = 'Selection: ' self.mode = mode # Create a string of all the genre names of this movie genre_names = ' (' written = False for genre_num in movie.genre_ids.split(','): movie_genre = moviedb_genre.GENRE_DICT[genre_num] if movie_genre is Exception: logger.log_message(0, movie_genre) else: genre_names += movie_genre + ", " written = True if written: genre_names = genre_names[:-2] genre_names += ')' format_name = ' (' + librarydb_format.FORMAT_DICT[str(movie.title_format)] + ')' status_name = ' (' + librarydb_status.STATUS_DICT[str(movie.title_status)] + ')' options = { '1': 'Title: ' + movie.title, '2': 'MovieDB ID: ' + str(movie.movie_db_id), '3': 'Format: ' + str(movie.title_format) + format_name, '4': 'IMDB ID: ' + movie.imdb_id, '5': 'Genres: ' + movie.genre_ids + genre_names, '6': 'Description: ' + movie.description, '7': 'Release Date: ' + movie.release_date, '8': 'Poster URL: ' + movie.poster_url, '9': 'Status: ' + str(movie.title_status) + status_name } if mode == 'I': special_options = { 'I': 'Insert into LibraryDB', 'B': 'Back', 'Q': 'Exit' } elif mode == 'U': special_options = { 'U': 'Update LibraryDB Movie', 'B': 'Back', 'Q': 'Exit' } else: special_options = { 'B': 'Back', 'Q': 'Exit' } super().__init__(globals.VERSION + ' - ' + self.TITLE, prompt, options, special_options) self.movie = movie
def moviedb_api_call(url: str) -> tuple: """ Make MovieDB API call and return the server response. :param url: API call URL :return tuple: True = Success or False = Fail, server response or status message """ tries = 0 while True: try: response = urllib.request.urlopen(url) response_str = str(response.read()) break except HTTPError as err: logger.log_message(0, str(err)) tries += 1 if tries <= 5: logger.log_message(1, 'Retrying...(' + tries + ')') else: logger.log_message(0, 'Exceeded retry count. Try again later') return False, 'ERROR: Request to MovieDB timed out! ' except URLError as err: logger.log_message(0, str(err)) return False, 'ERROR: URLError, see logs! ' response_str = response_str.replace("\\\'", "'") response_str = response_str.replace("\\\\/", "") return True, response_str
def log_message(self, txt, nickname, time=None, typ=1): """ Log the messages in the archives. """ name = safeJID(self.name).bare if not logger.log_message(name, nickname, txt, date=time, typ=typ): self.core.information(_('Unable to write in the log file'), 'Error')
def log_message(self, txt, nickname, time=None, typ=1): """ Log the messages in the archives. """ name = safeJID(self.name).bare if not logger.log_message(name, nickname, txt, date=time, typ=typ): self.core.information('Unable to write in the log file', 'Error')
def query_by_imdb_id(imdb_id: str) -> tuple: """ Query MovieDB API using an IMDB ID. :param str imdb_id: IMDB ID in the form ttNNNNNNN :return tuple: True = Success or False = Fail, MovieDB_Movie object or status message """ base_url = 'https://api.themoviedb.org/3' api_key = 'api_key=' + get_api_key() find_by_imdb_id = '/find/' find_by_imdb_id2 = '?external_source=imdb_id&' url = base_url + find_by_imdb_id + imdb_id + find_by_imdb_id2 + api_key response = moviedb_api_call(url) if response[0] is False: return response else: response_str = response[1] # response_str = response_str.replace('\\\'', "'") # DEBUG # Logger.log_message(1, response_str) pattern = re.compile('"genre_ids":\[([\d,]+)\]' + '[\s\S]*' + '"id":([\d]+?),' + '[\s\S]*' + '"original_title":"([\s\S]+?)",' + '[\s\S]*' + '"overview":"([\s\S]+?)",' + '[\s\S]*' + '"release_date":"([\s\S]+?)",' + '[\s\S]*' + '"poster_path":"/([\s\S]+?)"') match = pattern.search(response_str) if match: movie = MovieDBMovie( match.group(3), int(match.group(2)), match.group(4), match.group(5), 'http://image.tmdb.org/t/p/original/' + match.group(6), match.group(1), imdb_id) return True, movie else: # MovieDB response does not match RegEx pattern. Incorrect imdb_id. logger.log_message( 1, 'MovieDB response does not match RegEx pattern. Incorrect imdb_id.' ) return False, 'WARNING: Movie not found! '
def __str__(self) -> str: """ Convert LibraryDB_Movie object into a string. :return str: String representation of the LibraryDB_Movie object """ str_rep = '' # Title str_rep += self.title # Release date if self.release_date is not None and self.release_date != '': str_rep += ' (' + self.release_date + ')' # Format try: format_name = librarydb_format.FORMAT_DICT[str(self.title_format)] str_rep += ' - ' + format_name except KeyError as err: logger.log_message(0, str(err)) # Status try: status_name = librarydb_status.STATUS_DICT[str(self.title_status)] str_rep += '\nStatus: ' + status_name except KeyError as err: logger.log_message(0, str(err)) # Genres if self.genre_ids is not None and self.genre_ids != '': str_rep += '\n' written = False for genre_num in self.genre_ids.split(','): movie_genre = moviedb_genre.GENRE_DICT[genre_num] if movie_genre is Exception: logger.log_message(0, movie_genre) else: str_rep += movie_genre + ", " written = True if written: str_rep = str_rep[:-2] # IMDB ID if self.imdb_id is not None and self.imdb_id != '': str_rep += '\nIMDB: ' + self.imdb_id + '\t' # MovieDB ID str_rep += 'MovieDB: ' + str(self.movie_db_id) else: str_rep += '\nMovieDB: ' + str(self.movie_db_id) # Poster URL if self.poster_url is not None and self.poster_url != '': str_rep += '\nPoster: ' + self.poster_url # Description if self.description is not None and self.description != '': str_rep += '\n' + self.description return str_rep
def search_by_title(entry: str) -> tuple: """ Query LibraryDB's movie titles for the search term. :param str entry: Search term :return tuple: True = Success or False = Error, List of LibraryDB movies """ try: conn = sqlite3.connect(globals.LIBRARYDB_PATH) c = conn.cursor() t = ('%' + entry + '%',) c.execute('SELECT * FROM Titles WHERE name LIKE ?', t) movies = [] while True: result = c.fetchone() if result is None: break else: movie = LibraryDBMovie(result[1], # title result[2], # movie_db_id result[7], # title_format result[9], # title_status result[3], # imdb_id result[4], # genre_ids result[5], # description result[6], # release_date result[8], # poster_url result[0]) # title_id movies.append(movie) conn.commit() conn.close() except Exception as err: logger.log_message(0, str(err)) return False, 'ERROR: Check logs. ' return True, movies
def insert_movie(movie: LibraryDBMovie) -> tuple: """ Insert movie object into LibraryDB. :param LibraryDB_Movie movie: LibraryDB_Movie to be inserted into LibraryDB :return tuple: Status code. True = Success or False = Error, string description of status """ conn = sqlite3.connect(globals.LIBRARYDB_PATH) try: c = conn.cursor() c.execute( 'INSERT INTO Titles (name, movie_db_id, imdb_id, genres, description, release_date, format, posterUrl) ' + 'VALUES (?,?,?,?,?,?,?,?)', (movie.title, movie.movie_db_id, movie.imdb_id, movie.genre_ids, movie.description, movie.release_date, movie.title_format, movie.poster_url)) conn.commit() conn.close() except Exception as err: conn.commit() conn.close() logger.log_message(0, str(err)) return False, "INSERT ERROR: Check logs for details! " return True, 'Successful LibraryDB Insert!'
def process_input(self, entry: str) -> tuple: """ Handle all option and special option actions. :param str entry: User's input :return tuple: True = Success or False = Fail, new value of parameter or status message """ if entry.upper() == 'B': return False, '' elif entry.upper() == 'Q': quit() # Check input validity # Check if key is in menu if self._param_name == 'format' or self._param_name == 'movie_db_id': try: entry = int(entry) except Exception as err: logger.log_message(0, str(err)) self.val_input = False return False, self._param_name + ' is not int! ' if self._param_name == 'format': try: librarydb_format.FORMAT_DICT[str(entry)] except KeyError: logger.log_message(0, 'Format not valid! ' + str(entry)) self.val_input = False return False, 'Format entered is not valid! ' # Add to movie object return True, str(entry) elif self._param_name == 'movie_db_id': # No special criteria, add to movie object return True, entry elif self._param_name == 'imdb_id' or self._param_name == 'genres' or self._param_name == 'release_date' \ or self._param_name == 'posterUrl' or self._param_name == 'name' or self._param_name == 'description': # String format if self._param_name == 'imdb_id': # Match IMDB ID in the form of 'tt9999999' p = re.compile('^tt\d{7}$') match = p.search(entry) if match: # Good input return True, entry else: self.val_input = False return False, 'Invalid IMDB ID! ' elif self._param_name == 'genres': print('genre regex check.') # Match genres in comma-separated list, without trailing comma p = re.compile('^(\d+)(,(\d+))*$') match = p.search(entry) if match: print('checking genres entered') for genre_num in entry.split(','): try: moviedb_genre.GENRE_DICT[genre_num] except KeyError: logger.log_message(0, str(genre_num) + ' is not a valid genre number!') self.val_input = False return False, str(genre_num) + ' is not a valid genre number! ' # Good input print('Good to go!') return True, entry else: self.val_input = False return False, 'Improper Genre string! ' elif self._param_name == 'release_date': # Match date YYYY-MM-DD p = re.compile('^(19|20)\d{2}-(0?[1-9]|1[0-2])-(0?[1-9]|[12]\d|3[01])$') match = p.search(entry) if match: # Good input return True, entry else: self.val_input = False return False, 'Improper release date format! ' elif self._param_name == 'posterUrl': # Match poster url p = re.compile('^(http|https)://image.tmdb.org/t/p/original/[\d\w]+.(jpg|png)$') match = p.search(entry) if match: # Good input return True, entry else: self.val_input = False return False, 'Improper poster url format! ' elif self._param_name == 'name': # No special criteria, add to movie object return True, entry elif self._param_name == 'description': # No special criteria, add to movie object return True, entry else: # param_name not properly set logger.log_message(0, 'param_name not properly set! ' + self._param_name) self.val_input = False return False, 'param_name not properly set! See logs. '
def update_movie(self, param_num: str, new_param_val: Union[str, int]) -> None: """ Update LibraryDB_Movie parameter. :param str param_num: Number of parameter to be updated :param Union[str, int] new_param_val: New value of the parameter :return None: Nothing """ if param_num == 0: # parameter wasn't properly updated. pass if param_num == '1': # Param_Edit title self.movie.title = new_param_val self._options[param_num] = 'Title: ' + new_param_val elif param_num == '2': # Param_Edit movie_db_id self.movie.movie_db_id = new_param_val self._options[param_num] = 'MovieDB ID: ' + new_param_val elif param_num == '3': # Param_Edit format self.movie.title_format = new_param_val format_name = ' (' + librarydb_format.FORMAT_DICT[new_param_val] + ')' self._options[param_num] = 'Format: ' + new_param_val + format_name elif param_num == '4': # Param_Edit imdb_id self.movie.imdb_id = new_param_val self._options[param_num] = 'IMDB ID: ' + new_param_val elif param_num == '5': # Param_Edit genres self.movie.genre_ids = new_param_val # Create a string of all the genre names of this movie genre_names = ' (' written = False for genre_num in new_param_val.split(','): movie_genre = moviedb_genre.GENRE_DICT[genre_num] if movie_genre is Exception: logger.log_message(0, movie_genre) else: genre_names += movie_genre + ', ' written = True if written: genre_names = genre_names[:-2] genre_names += ')' self._options[param_num] = 'Genres: ' + new_param_val + genre_names elif param_num == '6': # Param_Edit description self.movie.description = new_param_val self._options[param_num] = 'Description: ' + new_param_val elif param_num == '7': # Param_Edit release_data self.movie.release_date = new_param_val self._options[param_num] = 'Release Date: ' + new_param_val elif param_num == '8': # Param_Edit posterUrl self.movie.poster_url = new_param_val self._options[param_num] = 'Poster URL: ' + new_param_val else: logger.log_message(0, 'Param num not set in Movie_Params.update_movie()') status_message = StatusMessage('An Error Occurred', 'Press [Enter] to exit...', 'An error occurred in Movie_Params.update_movie(). See logs for details.') status_message.menu_logic() exit(1)