From f3479d3c1ea50a3d138ed1071a708df752ef8575 Mon Sep 17 00:00:00 2001 From: JackDandy Date: Wed, 14 Oct 2020 16:00:01 +0100 Subject: [PATCH] Change Trim/Clear history to hide items because the data is needed for core management. Change add sqlite db_support_column_rename flag var to db.py Change add sqlite db_supports_backup flag var to db.py --- CHANGES.md | 1 + sickbeard/__init__.py | 5 +++-- sickbeard/databases/mainDB.py | 32 +++++++++++++++++++++++++++----- sickbeard/db.py | 8 ++++++-- sickbeard/failed_history.py | 6 ------ sickbeard/history.py | 7 ++++--- sickbeard/show_updater.py | 10 +--------- sickbeard/webapi.py | 6 +++--- sickbeard/webserve.py | 8 +++++--- sickgear.py | 9 +-------- 10 files changed, 51 insertions(+), 41 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 61a671d..2c2a554 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,6 +4,7 @@ * Change `Discordapp` to `Discord` in line with company change * Change remove `app` from URL when calling webhook * Change remind user when testing Notifications config / Discord to update URL +* Change Trim/Clear history to hide items because the data is needed for core management * Fix incorrect text for some drop down list items in the apiBuilder view that affected some browsers * Fix connection skip error handling in tvdb_api * Add client parameter to pp class and add it to API sg.postprocess diff --git a/sickbeard/__init__.py b/sickbeard/__init__.py index 4ab2813..1d90c0c 100755 --- a/sickbeard/__init__.py +++ b/sickbeard/__init__.py @@ -54,6 +54,7 @@ from .tv import TVidProdid from .watchedstate import EmbyWatchedStateUpdater, PlexWatchedStateUpdater from adba.aniDBerrors import AniDBError +# noinspection PyProtectedMember from browser_ua import get_ua from configobj import ConfigObj from libtrakt import TraktAPI @@ -1920,11 +1921,11 @@ def save_config(): if int(src.enabled): new_config[src_id_uc][src_id] = int(src.enabled) - for attr in filter_iter(lambda a: None is not getattr(src, a, None), ('api_key', 'username', 'search_mode')): + for attr in filter_iter(lambda _a: None is not getattr(src, _a, None), ('api_key', 'username', 'search_mode')): if 'search_mode' != attr or 'eponly' != getattr(src, attr): new_config[src_id_uc]['%s_%s' % (src_id, attr)] = getattr(src, attr) - for attr in filter_iter(lambda a: None is not getattr(src, a, None), ( + for attr in filter_iter(lambda _a: None is not getattr(src, _a, None), ( 'enable_recentsearch', 'enable_backlog', 'enable_scheduled_backlog', 'scene_only', 'scene_loose', 'scene_loose_active', 'scene_rej_nuked', 'scene_nuked_active', diff --git a/sickbeard/databases/mainDB.py b/sickbeard/databases/mainDB.py index 2d1eafc..afa7e7a 100644 --- a/sickbeard/databases/mainDB.py +++ b/sickbeard/databases/mainDB.py @@ -28,7 +28,7 @@ import encodingKludge as ek from six import iteritems MIN_DB_VERSION = 9 # oldest db version we support migrating from -MAX_DB_VERSION = 20013 +MAX_DB_VERSION = 20014 TEST_BASE_VERSION = None # the base production db version, only needed for TEST db versions (>=100000) @@ -254,14 +254,14 @@ class InitialSchema(db.SchemaUpgrade): 'CREATE TABLE flags (flag PRIMARY KEY NOT NULL)', # history 'CREATE TABLE history (action NUMERIC, date NUMERIC, showid NUMERIC, season NUMERIC, episode NUMERIC,' - ' quality NUMERIC, resource TEXT, provider TEXT, version NUMERIC)', + ' quality NUMERIC, resource TEXT, provider TEXT, version NUMERIC, hide NUMERIC DEFAULT 0)', # imdb_info 'CREATE TABLE imdb_info (indexer_id INTEGER PRIMARY KEY, imdb_id TEXT, title TEXT, year NUMERIC,' ' akas TEXT, runtimes NUMERIC, genres TEXT, countries TEXT, country_codes TEXT, certificates TEXT,' ' rating TEXT, votes INTEGER, last_update NUMERIC)', # indexer_mapping 'CREATE TABLE indexer_mapping (indexer_id INTEGER, indexer NUMERIC, mindexer_id INTEGER NOT NULL,' - ' mindexer NUMERIC, date NUMERIC NOT NULL DEFAULT 0, status INTEGER NOT NULL DEFAULT 0,' + ' mindexer NUMERIC, date NUMERIC NOT NULL DEFAULT 0, status INTEGER NOT NULL DEFAULT 0,' ' PRIMARY KEY (indexer_id, indexer, mindexer))', 'CREATE INDEX idx_mapping ON indexer_mapping (indexer_id, indexer)', # info @@ -290,8 +290,8 @@ class InitialSchema(db.SchemaUpgrade): 'CREATE INDEX idx_status ON tv_episodes (status,season,episode,airdate)', # tv_episodes_watched 'CREATE TABLE tv_episodes_watched (tvep_id NUMERIC NOT NULL, clientep_id TEXT, label TEXT,' - ' played NUMERIC DEFAULT 0 NOT NULL, date_watched NUMERIC NOT NULL, date_added NUMERIC,' - ' status NUMERIC, location TEXT, file_size NUMERIC, hide INT DEFAULT 0 not null)', + ' played NUMERIC NOT NULL DEFAULT 0, date_watched NUMERIC NOT NULL, date_added NUMERIC,' + ' status NUMERIC, location TEXT, file_size NUMERIC, hide INT NOT NULL DEFAULT 0)', # tv_shows 'CREATE TABLE tv_shows (show_id INTEGER PRIMARY KEY, indexer_id NUMERIC, indexer NUMERIC,' ' show_name TEXT, location TEXT, network TEXT, genre TEXT, classification TEXT, runtime NUMERIC,' @@ -1668,3 +1668,25 @@ class RenameAllowBlockListTables(db.SchemaUpgrade): ]) return self.setDBVersion(20013) + + +# 20013 -> 20014 +class AddHistoryHideColumn(db.SchemaUpgrade): + def execute(self): + db.backup_database('sickbeard.db', self.checkDBVersion()) + + if not self.hasColumn('history', 'hide'): + self.upgrade_log('Adding hide column to history') + self.addColumn('history', 'hide', default=0, set_default=True) + + if self.hasTable('history_hide_backup'): + self.upgrade_log('Restoring hide status in history from backup') + self.connection.mass_action([ + ['UPDATE history SET hide = (SELECT hide FROM history_hide_backup as hh WHERE' + ' hh.ROWID = history.ROWID AND hh.showid = history.showid AND hh.indexer = history.indexer AND' + ' hh.season = history.season AND hh.episode = history.episode AND hh.action = history.action AND' + ' hh.date = history.date)'], + ['DROP TABLE history_hide_backup'] + ]) + + return self.setDBVersion(20014) diff --git a/sickbeard/db.py b/sickbeard/db.py index 67a578d..7240880 100644 --- a/sickbeard/db.py +++ b/sickbeard/db.py @@ -41,6 +41,8 @@ if False: db_lock = threading.Lock() +db_support_column_rename = (3, 25, 0) <= sqlite3.sqlite_version_info # type: bool +db_supports_backup = hasattr(sqlite3.Connection, 'backup') and (3, 6, 11) <= sqlite3.sqlite_version_info # type: bool def dbFilename(filename='sickbeard.db', suffix=None): @@ -439,8 +441,9 @@ class SchemaUpgrade(object): return column in self.connection.tableInfo(table_name) # noinspection SqlResolve - def addColumn(self, table, column, data_type='NUMERIC', default=0): - self.connection.action('ALTER TABLE [%s] ADD %s %s' % (table, column, data_type)) + def addColumn(self, table, column, data_type='NUMERIC', default=0, set_default=False): + self.connection.action('ALTER TABLE [%s] ADD %s %s%s' % + (table, column, data_type, ('', ' DEFAULT "%s"' % default)[set_default])) self.connection.action('UPDATE [%s] SET %s = ?' % (table, column), (default,)) def dropColumn(self, table, column): @@ -620,6 +623,7 @@ def MigrationCode(my_db): 20010: sickbeard.mainDB.AddIndexerToTables, 20011: sickbeard.mainDB.AddShowExludeGlobals, 20012: sickbeard.mainDB.RenameAllowBlockListTables, + 20013: sickbeard.mainDB.AddHistoryHideColumn, # 20002: sickbeard.mainDB.AddCoolSickGearFeature3, } diff --git a/sickbeard/failed_history.py b/sickbeard/failed_history.py index 63e66a0..cac8e8c 100644 --- a/sickbeard/failed_history.py +++ b/sickbeard/failed_history.py @@ -196,12 +196,6 @@ def remove_snatched(release, size, provider): [prepare_failed_name(release), size, provider]) -def remove_old_history(): - - db_action('DELETE FROM history WHERE date < %s' % - str((datetime.datetime.now() - datetime.timedelta(days=30)).strftime(dateFormat))) - - def has_failed(release, size, provider='%'): """ Returns True if a release has previously failed. diff --git a/sickbeard/history.py b/sickbeard/history.py index 2a2190e..4ca0a96 100644 --- a/sickbeard/history.py +++ b/sickbeard/history.py @@ -54,9 +54,10 @@ def _log_history_item(action, tvid, prodid, season, episode, quality, resource, my_db = db.DBConnection() my_db.action( - 'INSERT INTO history (action, date, showid, season, episode, quality, resource, provider, version, indexer)' - ' VALUES (?,?,?,?,?,?,?,?,?,?)', - [action, log_date, int(prodid), int(season), int(episode), quality, resource, provider, version, int(tvid)]) + 'INSERT INTO history' + ' (action, date, showid, season, episode, quality, resource, provider, version, indexer, hide)' + ' VALUES (?,?,?,?,?,?,?,?,?,?,?)', + [action, log_date, int(prodid), int(season), int(episode), quality, resource, provider, version, int(tvid), 0]) def log_snatch(search_result): diff --git a/sickbeard/show_updater.py b/sickbeard/show_updater.py index c82b587..926708f 100644 --- a/sickbeard/show_updater.py +++ b/sickbeard/show_updater.py @@ -23,7 +23,7 @@ import exceptions_helper from exceptions_helper import ex import sickbeard -from . import db, failed_history, logger, network_timezones, properFinder, ui +from . import db, logger, network_timezones, properFinder, ui # noinspection PyUnreachableCode if False: @@ -94,14 +94,6 @@ class ShowUpdater(object): logger.log('scene exceptions update error', logger.ERROR) logger.log(traceback.format_exc(), logger.ERROR) - # sure, why not? - if sickbeard.USE_FAILED_DOWNLOADS: - try: - failed_history.remove_old_history() - except (BaseException, Exception): - logger.log('Failed History cleanup error', logger.ERROR) - logger.log(traceback.format_exc(), logger.ERROR) - # clear the data of unused providers try: sickbeard.helpers.clear_unused_providers() diff --git a/sickbeard/webapi.py b/sickbeard/webapi.py index c398e12..ded0b18 100644 --- a/sickbeard/webapi.py +++ b/sickbeard/webapi.py @@ -1748,7 +1748,7 @@ class CMD_SickGearHistoryClear(ApiCall): def run(self): """ clear the sickgear history """ my_db = db.DBConnection() - my_db.action("DELETE FROM history WHERE 1=1") + my_db.action('UPDATE history SET hide = ? WHERE hide = 0', [1]) return _responds(RESULT_SUCCESS, msg="History cleared") @@ -1777,8 +1777,8 @@ class CMD_SickGearHistoryTrim(ApiCall): def run(self): """ trim the sickgear history """ my_db = db.DBConnection() - my_db.action("DELETE FROM history WHERE date < " + str( - (datetime.datetime.now() - datetime.timedelta(days=30)).strftime(history.dateFormat))) + my_db.action("UPDATE history SET hide = ? WHERE date < " + str( + (datetime.datetime.now() - datetime.timedelta(days=30)).strftime(history.dateFormat)), [1]) return _responds(RESULT_SUCCESS, msg="Removed history entries greater than 30 days old") diff --git a/sickbeard/webserve.py b/sickbeard/webserve.py index ccc1e73..8639212 100644 --- a/sickbeard/webserve.py +++ b/sickbeard/webserve.py @@ -6168,6 +6168,7 @@ class History(MainHandler): sql = 'SELECT h.*, show_name, s.indexer || ? || s.indexer_id AS tvid_prodid' \ ' FROM history h, tv_shows s' \ ' WHERE h.indexer=s.indexer AND h.showid=s.indexer_id' \ + ' AND h.hide = 0' \ ' ORDER BY date DESC%s' % (' LIMIT %s' % limit, '')['0' == limit] sql_result = my_db.select(sql, [TVidProdid.glue]) @@ -6273,6 +6274,7 @@ class History(MainHandler): ' WHERE h.showid=s.indexer_id' \ ' AND h.provider in ("%s")' % '","'.join(prov_list) + \ ' AND h.action in ("%s")' % '","'.join([str(x) for x in Quality.SNATCHED_ANY]) + \ + ' AND h.hide = 0' \ ' ORDER BY date DESC%s)' % (' LIMIT %s' % limit, '')['0' == limit] + \ ' GROUP BY provider' \ ' ORDER BY count DESC' @@ -6405,7 +6407,7 @@ class History(MainHandler): my_db = db.DBConnection() # noinspection SqlConstantCondition - my_db.action('DELETE FROM history WHERE 1=1') + my_db.action('UPDATE history SET hide = ? WHERE hide = 0', [1]) ui.notifications.message('History cleared') self.redirect('/history/') @@ -6413,8 +6415,8 @@ class History(MainHandler): def trim_history(self): my_db = db.DBConnection() - my_db.action('DELETE FROM history WHERE date < ' + str( - (datetime.datetime.now() - datetime.timedelta(days=30)).strftime(history.dateFormat))) + my_db.action('UPDATE history SET hide = ? WHERE date < ' + str( + (datetime.datetime.now() - datetime.timedelta(days=30)).strftime(history.dateFormat)), [1]) ui.notifications.message('Removed history entries greater than 30 days old') self.redirect('/history/') diff --git a/sickgear.py b/sickgear.py index fb9790d..f9d5273 100755 --- a/sickgear.py +++ b/sickgear.py @@ -85,7 +85,7 @@ sys.path.insert(1, os.path.abspath(os.path.join(os.path.dirname(__file__), 'lib' from configobj import ConfigObj from exceptions_helper import ex import sickbeard -from sickbeard import db, failed_history, logger, name_cache, network_timezones +from sickbeard import db, logger, name_cache, network_timezones from sickbeard.event_queue import Events from sickbeard.tv import TVShow from sickbeard.webserveInit import WebServer @@ -551,9 +551,6 @@ class SickGear(object): if not db.DBConnection().has_flag('kodi_nfo_default_removed'): sickbeard.metadata.kodi.remove_default_attr() - if sickbeard.USE_FAILED_DOWNLOADS: - failed_history.remove_old_history() - # Start an update if we're supposed to if self.force_update or sickbeard.UPDATE_SHOWS_ON_START: sickbeard.classes.loading_msg.message = 'Starting a forced show update' @@ -563,10 +560,6 @@ class SickGear(object): time.sleep(2) self.webserver.switch_handlers() - # # Launch browser - # if sickbeard.LAUNCH_BROWSER and not self.no_launch: - # sickbeard.launch_browser(self.start_port) - # main loop while True: time.sleep(1)