1
0
mirror of https://github.com/moparisthebest/SickRage synced 2024-12-04 15:12:23 -05:00

Fixes sickragetv/sickrage-issues#101 - Added code to mainDB to correct malformed episode statues, converted column default_ep_status field type from TEXT to NUMERIC, default to ep status UNKNOWN when loading from DB incase of exception errors.

Added git branch reset option to general settings github to help fix git update related issues.

 Added github username/password options to general settings github as a requirement for submitting issue tickets from app.

 Fixed issue with default ep status not showing correct value.

 Added ability to submit issue reports via errorlogs menu.

 Added errorlogs view button to error message displayed for webui errors.
This commit is contained in:
echel0n 2014-12-17 13:32:25 -08:00
parent 170d50c279
commit 6713ce0981
11 changed files with 202 additions and 78 deletions

View File

@ -37,7 +37,6 @@
#else
You don't have version checking turned on. Please turn on "Check for Update" in Config > General.<br />
#end if
<font color="red">You are using BETA software</font>
</td></tr>
<tr><td class="infoTableHeader">SR Config file:</td><td class="infoTableCell">$sickbeard.CONFIG_FILE</td></tr>
<tr><td class="infoTableHeader">SR Database file:</td><td class="infoTableCell">$db.dbFilename()</td></tr>

View File

@ -438,48 +438,14 @@
<div id="core-component-group3" class="component-group">
<div class="component-group">
<div class="component-group-desc">
<h3>Advanced Settings</h3>
</div>
<fieldset class="component-group-list">
<div class="field-pair">
<label>
<span class="component-title">Branch version:</span>
<span class="component-desc">
<select id="branchVersion" class="form-control form-control-inline input-sm pull-left">
#for $cur_branch in $sickbeard.versionCheckScheduler.action.list_remote_branches():
<option value="$cur_branch" #if $cur_branch == $sickbeard.BRANCH then 'selected="selected"' else ''#>$cur_branch</option>
#end for
</select>
<input class="btn btn-inline" style="margin-left: 6px;" type="button" id="branchCheckout" value="Checkout Branch">
<div class="clear-left"><p>select branch to use (restart required)</p></div>
</span>
</label>
</div>
<div class="field-pair">
<label for="git_remote">
<span class="component-title">Git remote for branch</span>
<span class="component-desc">
<input type="text" name="git_remote" id="git_remote" value="$sickbeard.GIT_REMOTE" class="form-control input-sm input300" />
<div class="clear-left"><p>default:origin. Access repo configured remotes (save then refresh browser)</p></div>
</span>
</label>
</div>
<div class="field-pair">
<label>
<span class="component-title">Git executable path</span>
<span class="component-desc">
<input type="text" name="git_path" value="$sickbeard.GIT_PATH" class="form-control input-sm input300" />
<div class="clear-left"><p>only needed if OS is unable to locate git from env</p></div>
</span>
</label>
</div>
<div class="field-pair">
<label>
<span class="component-title">CPU throttling:</span>
@ -548,6 +514,86 @@
<input type="submit" class="btn config_submitter" value="Save Changes" />
</fieldset>
</div>
<div class="component-group">
<div class="component-group-desc">
<h3>GitHub</h3>
<p>Options for github related features.</p>
</div>
<fieldset class="component-group-list">
<div class="field-pair">
<label>
<span class="component-title">Branch version:</span>
<span class="component-desc">
<select id="branchVersion" class="form-control form-control-inline input-sm pull-left">
#for $cur_branch in $sickbeard.versionCheckScheduler.action.list_remote_branches():
<option value="$cur_branch" #if $cur_branch == $sickbeard.BRANCH then 'selected="selected"' else ''#>$cur_branch</option>
#end for
</select>
<input class="btn btn-inline" style="margin-left: 6px;" type="button" id="branchCheckout" value="Checkout Branch">
<div class="clear-left"><p>select branch to use (restart required)</p></div>
</span>
</label>
</div>
<div class="field-pair">
<label for="git_username">
<span class="component-title">GitHub username</span>
<span class="component-desc">
<input type="text" name="git_username" id="git_username" value="$sickbeard.GIT_USERNAME" class="form-control input-sm input300" />
<div class="clear-left"><p>*** (REQUIRED FOR SUBMITTING ISSUES) ***</p></div>
</span>
</label>
</div>
<div class="field-pair">
<label for="git_password">
<span class="component-title">GitHub password</span>
<span class="component-desc">
<input type="password" name="git_password" id="git_password" value="$sickbeard.GIT_PASSWORD" class="form-control input-sm input300" />
<div class="clear-left"><p>*** (REQUIRED FOR SUBMITTING ISSUES) ***</p></div>
</span>
</label>
</div>
<div class="field-pair">
<label for="git_remote">
<span class="component-title">GitHub remote for branch</span>
<span class="component-desc">
<input type="text" name="git_remote" id="git_remote" value="$sickbeard.GIT_REMOTE" class="form-control input-sm input300" />
<div class="clear-left"><p>default:origin. Access repo configured remotes (save then refresh browser)</p></div>
</span>
</label>
</div>
<div class="field-pair">
<label>
<span class="component-title">Git executable path</span>
<span class="component-desc">
<input type="text" name="git_path" value="$sickbeard.GIT_PATH" class="form-control input-sm input300" />
<div class="clear-left"><p>only needed if OS is unable to locate git from env</p></div>
</span>
</label>
</div>
<div class="field-pair">
<label for="git_reset">
<span class="component-title">Git branch reset</span>
<span class="component-desc">
<input type="checkbox" name="git_reset" id="git_reset" #if True == $sickbeard.GIT_RESET then 'checked="checked"' else ''#/>
<p>reset git branch automatically to help resolve update issues</p>
</span>
</label>
</div>
<input type="submit" class="btn config_submitter" value="Save Changes" />
</fieldset>
</div>
</div><!-- /component-group3 //-->
<br/>

View File

@ -106,7 +106,7 @@
(this will set a default status to be applied to any newly added episodes)<br />
<select name="defaultEpStatus" id="defaultEpStatusSelect" class="form-control form-control-inline input-sm">
#for $curStatus in [$WANTED, $SKIPPED, $ARCHIVED, $IGNORED]:
<option value="$curStatus">$statusStrings[$curStatus]</option>
<option value="$curStatus" #if $curStatus == $show.default_ep_status then 'selected="selected"' else ''#>$statusStrings[$curStatus]</option>
#end for
</select><br />
<br />

View File

@ -89,6 +89,7 @@
\$("#SubMenu a:contains('Clear History')").addClass('btn clearhistory').html('<span class="ui-icon ui-icon-trash pull-left"></span> Clear History');
\$("#SubMenu a:contains('Trim History')").addClass('btn trimhistory').html('<span class="ui-icon ui-icon-trash pull-left"></span> Trim History');
\$("#SubMenu a[href$='/errorlogs/clearerrors/']").addClass('btn').html('<span class="ui-icon ui-icon-trash pull-left"></span> Clear Errors');
\$("#SubMenu a[href$='/errorlogs/submit_errors/']").addClass('btn').html('<span class="ui-icon ui-icon-arrowreturnthick-1-n pull-left"></span> Submit Errors');
\$("#SubMenu a:contains('Re-scan')").addClass('btn').html('<span class="ui-icon ui-icon-refresh pull-left"></span> Re-scan');
\$("#SubMenu a:contains('Backlog Overview')").addClass('btn').html('<span class="ui-icon ui-icon-refresh pull-left"></span> Backlog Overview');
\$("#SubMenu a[href$='/home/updatePLEX/']").addClass('btn').html('<span class="ui-icon ui-icon-refresh pull-left"></span> Update PLEX');

View File

@ -115,6 +115,8 @@ GIT_REMOTE_URL = ''
CUR_COMMIT_BRANCH = ''
GIT_ORG = 'SiCKRAGETV'
GIT_REPO = 'SickRage'
GIT_USERNAME = None
GIT_PASSWORD = None
GIT_PATH = None
INIT_LOCK = Lock()
@ -522,7 +524,7 @@ def initialize(consoleLogging=True):
USE_FAILED_DOWNLOADS, DELETE_FAILED, ANON_REDIRECT, LOCALHOST_IP, TMDB_API_KEY, DEBUG, PROXY_SETTING, PROXY_INDEXERS, \
AUTOPOSTPROCESSER_FREQUENCY, DEFAULT_AUTOPOSTPROCESSER_FREQUENCY, MIN_AUTOPOSTPROCESSER_FREQUENCY, \
ANIME_DEFAULT, NAMING_ANIME, ANIMESUPPORT, USE_ANIDB, ANIDB_USERNAME, ANIDB_PASSWORD, ANIDB_USE_MYLIST, \
ANIME_SPLIT_HOME, SCENE_DEFAULT, PLAY_VIDEOS, BACKLOG_DAYS, GIT_ORG, GIT_REPO, gh
ANIME_SPLIT_HOME, SCENE_DEFAULT, PLAY_VIDEOS, BACKLOG_DAYS, GIT_ORG, GIT_REPO, GIT_USERNAME, GIT_PASSWORD, gh
if __INITIALIZED__:
return False
@ -558,14 +560,20 @@ def initialize(consoleLogging=True):
fileLogging = True
if not helpers.makeDir(LOG_DIR):
sys.stderr.write("!!! No log folder, logging to screen only!\n")
fileLogging=False
fileLogging = False
# init logging
logger.initLogging(consoleLogging=consoleLogging, fileLogging=fileLogging, debugLogging=DEBUG)
# git login info
GIT_USERNAME = check_setting_str(CFG, 'General', 'git_username', '')
GIT_PASSWORD = check_setting_str(CFG, 'General', 'git_password', '', censor_log=True)
# github api
try:gh = Github().get_organization(GIT_ORG).get_repo(GIT_REPO)
except:gh = None
try:
gh = Github(user_agent="SiCKRAGE").get_organization(GIT_ORG).get_repo(GIT_REPO)
except:
gh = None
# git reset on update
GIT_RESET = bool(check_setting_int(CFG, 'General', 'git_reset', 0))
@ -1131,7 +1139,7 @@ def initialize(consoleLogging=True):
(METADATA_WDTV, metadata.wdtv),
(METADATA_TIVO, metadata.tivo),
(METADATA_MEDE8ER, metadata.mede8er),
]:
]:
(cur_metadata_config, cur_metadata_class) = cur_metadata_tuple
tmp_provider = cur_metadata_class.metadata_class()
tmp_provider.set_config(cur_metadata_config)
@ -1401,6 +1409,8 @@ def save_config():
# For passwords you must include the word `password` in the item_name and add `helpers.encrypt(ITEM_NAME, ENCRYPTION_VERSION)` in save_config()
new_config['General'] = {}
new_config['General']['git_username'] = GIT_USERNAME
new_config['General']['git_password'] = GIT_PASSWORD
new_config['General']['git_reset'] = int(GIT_RESET)
new_config['General']['branch'] = BRANCH
new_config['General']['git_remote'] = GIT_REMOTE

View File

@ -1,5 +0,0 @@
import sickbeard
class BugTracker:
def submit_bug(self, title, error):
return sickbeard.gh.create_issue(title, error, labels=[sickbeard.gh().get_label(sickbeard.BRANCH)])

View File

@ -16,6 +16,7 @@
# You should have received a copy of the GNU General Public License
# along with SickRage. If not, see <http://www.gnu.org/licenses/>.
import re
import sys
import sickbeard
@ -261,6 +262,9 @@ class ErrorViewer():
def clear():
ErrorViewer.errors = []
@staticmethod
def get():
return ErrorViewer.errors
class UIError():
"""
@ -268,5 +272,7 @@ class UIError():
"""
def __init__(self, message):
self.title = sys.exc_info()[1].message or None
self.message = message
self.time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
self.exc_info = sys.exc_info() or None

View File

@ -236,8 +236,6 @@ class Quality:
def assumeQuality(name):
if name.lower().endswith((".avi", ".mp4")):
return Quality.SDTV
# elif name.lower().endswith(".mkv"):
# return Quality.HDTV
elif name.lower().endswith(".ts"):
return Quality.RAWHDTV
else:

View File

@ -27,7 +27,7 @@ from sickbeard import encodingKludge as ek
from sickbeard.name_parser.parser import NameParser, InvalidNameException, InvalidShowException
MIN_DB_VERSION = 9 # oldest db version we support migrating from
MAX_DB_VERSION = 41
MAX_DB_VERSION = 42
class MainSanityCheck(db.DBSanityCheck):
def check(self):
@ -37,6 +37,7 @@ class MainSanityCheck(db.DBSanityCheck):
self.fix_orphan_episodes()
self.fix_unaired_episodes()
self.fix_tvrage_show_statues()
self.fix_episode_statuses()
def fix_duplicate_shows(self, column='indexer_id'):
@ -107,7 +108,7 @@ class MainSanityCheck(db.DBSanityCheck):
if not self.connection.select("PRAGMA index_info('idx_tv_episodes_showid_airdate')"):
logger.log(u"Missing idx_tv_episodes_showid_airdate for TV Episodes table detected!, fixing...")
self.connection.action("CREATE INDEX idx_tv_episodes_showid_airdate ON tv_episodes(showid,airdate);")
self.connection.action("CREATE INDEX idx_tv_episodes_showid_airdate ON tv_episodes(showid, airdate);")
if not self.connection.select("PRAGMA index_info('idx_showid')"):
logger.log(u"Missing idx_showid for TV Episodes table detected!, fixing...")
@ -115,15 +116,15 @@ class MainSanityCheck(db.DBSanityCheck):
if not self.connection.select("PRAGMA index_info('idx_status')"):
logger.log(u"Missing idx_status for TV Episodes table detected!, fixing...")
self.connection.action("CREATE INDEX idx_status ON tv_episodes (status,season,episode,airdate)")
self.connection.action("CREATE INDEX idx_status ON tv_episodes (status, season, episode, airdate)")
if not self.connection.select("PRAGMA index_info('idx_sta_epi_air')"):
logger.log(u"Missing idx_sta_epi_air for TV Episodes table detected!, fixing...")
self.connection.action("CREATE INDEX idx_sta_epi_air ON tv_episodes (status,episode, airdate)")
self.connection.action("CREATE INDEX idx_sta_epi_air ON tv_episodes (status, episode, airdate)")
if not self.connection.select("PRAGMA index_info('idx_sta_epi_sta_air')"):
logger.log(u"Missing idx_sta_epi_sta_air for TV Episodes table detected!, fixing...")
self.connection.action("CREATE INDEX idx_sta_epi_sta_air ON tv_episodes (season,episode, status, airdate)")
self.connection.action("CREATE INDEX idx_sta_epi_sta_air ON tv_episodes (season, episode, status, airdate)")
def fix_unaired_episodes(self):
@ -163,6 +164,19 @@ class MainSanityCheck(db.DBSanityCheck):
for old_status, new_status in status_map.items():
self.connection.action("UPDATE tv_shows SET status = ? WHERE LOWER(status) = ?", [new_status, old_status])
def fix_episode_statuses(self):
sqlResults = self.connection.select("SELECT episode_id, showid FROM tv_episodes WHERE status IS NULL")
for cur_ep in sqlResults:
logger.log(u"MALFORMED episode status detected! episode_id: " + str(cur_ep["episode_id"]) + " showid: " + str(
cur_ep["showid"]), logger.DEBUG)
logger.log(u"Fixing malformed episode status with episode_id: " + str(cur_ep["episode_id"]))
self.connection.action("UPDATE tv_episodes SET status = ? WHERE episode_id = ?",
[common.UNKNOWN, cur_ep["episode_id"]])
else:
logger.log(u"No MALFORMED episode statuses, check passed")
def backupDatabase(version):
logger.log(u"Backing up database before upgrade")
if not helpers.backupVersionedFile(db.dbFilename(), version):
@ -187,7 +201,7 @@ class InitialSchema(db.SchemaUpgrade):
"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)",
"CREATE TABLE info (last_backlog NUMERIC, last_indexer NUMERIC, last_proper_search NUMERIC)",
"CREATE TABLE scene_numbering(indexer TEXT, indexer_id INTEGER, season INTEGER, episode INTEGER,scene_season INTEGER, scene_episode INTEGER, PRIMARY KEY(indexer_id, season, episode))",
"CREATE TABLE tv_shows (show_id INTEGER PRIMARY KEY, indexer_id NUMERIC, indexer TEXT, show_name TEXT, location TEXT, network TEXT, genre TEXT, classification TEXT, runtime NUMERIC, quality NUMERIC, airs TEXT, status TEXT, flatten_folders NUMERIC, paused NUMERIC, startyear NUMERIC, air_by_date NUMERIC, lang TEXT, subtitles NUMERIC, notify_list TEXT, imdb_id TEXT, last_update_indexer NUMERIC, dvdorder NUMERIC, archive_firstmatch NUMERIC, rls_require_words TEXT, rls_ignore_words TEXT, sports NUMERIC);",
"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, quality NUMERIC, airs TEXT, status TEXT, flatten_folders NUMERIC, paused NUMERIC, startyear NUMERIC, air_by_date NUMERIC, lang TEXT, subtitles NUMERIC, notify_list TEXT, imdb_id TEXT, last_update_indexer NUMERIC, dvdorder NUMERIC, archive_firstmatch NUMERIC, rls_require_words TEXT, rls_ignore_words TEXT, sports NUMERIC);",
"CREATE TABLE tv_episodes (episode_id INTEGER PRIMARY KEY, showid NUMERIC, indexerid NUMERIC, indexer TEXT, name TEXT, season NUMERIC, episode NUMERIC, description TEXT, airdate NUMERIC, hasnfo NUMERIC, hastbn NUMERIC, status NUMERIC, location TEXT, file_size NUMERIC, release_name TEXT, subtitles TEXT, subtitles_searchcount NUMERIC, subtitles_lastsearch TIMESTAMP, is_proper NUMERIC, scene_season NUMERIC, scene_episode NUMERIC);",
"CREATE UNIQUE INDEX idx_indexer_id ON tv_shows (indexer_id)",
"CREATE INDEX idx_showid ON tv_episodes (showid);",
@ -339,7 +353,7 @@ class RenameSeasonFolders(AddSizeAndSceneNameFields):
self.connection.action("ALTER TABLE tv_shows RENAME TO tmp_tv_shows")
self.connection.action(
"CREATE TABLE tv_shows (show_id INTEGER PRIMARY KEY, location TEXT, show_name TEXT, tvdb_id NUMERIC, network TEXT, genre TEXT, runtime NUMERIC, quality NUMERIC, airs TEXT, status TEXT, flatten_folders NUMERIC, paused NUMERIC, startyear NUMERIC, tvr_id NUMERIC, tvr_name TEXT, air_by_date NUMERIC, lang TEXT)")
sql = "INSERT INTO tv_shows(show_id, location, show_name, tvdb_id, network, genre, runtime, quality, airs, status, flatten_folders, paused, startyear, tvr_id, tvr_name, air_by_date, lang) SELECT show_id, location, show_name, tvdb_id, network, genre, runtime, quality, airs, status, seasonfolders, paused, startyear, tvr_id, tvr_name, air_by_date, lang FROM tmp_tv_shows"
sql = "INSERT INTO tv_shows SELECT * FROM tmp_tv_shows"
self.connection.action(sql)
# flip the values to be opposite of what they were before
@ -616,10 +630,8 @@ class ConvertTVShowsToIndexerScheme(AddSubtitlesSupport):
self.connection.action("DROP TABLE tmp_tv_shows")
self.connection.action("ALTER TABLE tv_shows RENAME TO tmp_tv_shows")
self.connection.action(
"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, quality NUMERIC, airs TEXT, status TEXT, flatten_folders NUMERIC, paused NUMERIC, startyear NUMERIC, air_by_date NUMERIC, lang TEXT, subtitles NUMERIC, notify_list TEXT, imdb_id TEXT, last_update_indexer NUMERIC, dvdorder NUMERIC)")
self.connection.action(
"INSERT INTO tv_shows(show_id, indexer_id, show_name, location, network, genre, runtime, quality, airs, status, flatten_folders, paused, startyear, air_by_date, lang, subtitles, notify_list, imdb_id, last_update_indexer, dvdorder) SELECT show_id, tvdb_id, show_name, location, network, genre, runtime, quality, airs, status, flatten_folders, paused, startyear, air_by_date, lang, subtitles, notify_list, imdb_id, last_update_tvdb, dvdorder FROM tmp_tv_shows")
self.connection.action("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, quality NUMERIC, airs TEXT, status TEXT, flatten_folders NUMERIC, paused NUMERIC, startyear NUMERIC, air_by_date NUMERIC, lang TEXT, subtitles NUMERIC, notify_list TEXT, imdb_id TEXT, last_update_indexer NUMERIC, dvdorder NUMERIC)")
self.connection.action("INSERT INTO tv_shows SELECT * FROM tmp_tv_shows")
self.connection.action("DROP TABLE tmp_tv_shows")
self.connection.action("CREATE UNIQUE INDEX idx_indexer_id ON tv_shows (indexer_id);")
@ -647,7 +659,7 @@ class ConvertTVEpisodesToIndexerScheme(ConvertTVShowsToIndexerScheme):
self.connection.action(
"CREATE TABLE tv_episodes (episode_id INTEGER PRIMARY KEY, showid NUMERIC, indexerid NUMERIC, indexer NUMERIC, name TEXT, season NUMERIC, episode NUMERIC, description TEXT, airdate NUMERIC, hasnfo NUMERIC, hastbn NUMERIC, status NUMERIC, location TEXT, file_size NUMERIC, release_name TEXT, subtitles TEXT, subtitles_searchcount NUMERIC, subtitles_lastsearch TIMESTAMP, is_proper NUMERIC)")
self.connection.action(
"INSERT INTO tv_episodes(episode_id, showid, indexerid, name, season, episode, description, airdate, hasnfo, hastbn, status, location, file_size, release_name, subtitles, subtitles_searchcount, subtitles_lastsearch, is_proper) SELECT episode_id, showid, tvdbid, name, season, episode, description, airdate, hasnfo, hastbn, status, location, file_size, release_name, subtitles, subtitles_searchcount, subtitles_lastsearch, is_proper FROM tmp_tv_episodes")
"INSERT INTO tv_episodes SELECT * FROM tmp_tv_episodes")
self.connection.action("DROP TABLE tmp_tv_episodes")
self.connection.action("CREATE INDEX idx_tv_episodes_showid_airdate ON tv_episodes(showid,airdate);")
@ -678,7 +690,7 @@ class ConvertIMDBInfoToIndexerScheme(ConvertTVEpisodesToIndexerScheme):
self.connection.action(
"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)")
self.connection.action(
"INSERT INTO imdb_info(indexer_id, imdb_id, title, year, akas, runtimes, genres, countries, country_codes, certificates, rating, votes, last_update) SELECT tvdb_id, imdb_id, title, year, akas, runtimes, genres, countries, country_codes, certificates, rating, votes, last_update FROM tmp_imdb_info")
"INSERT INTO imdb_info SELECT * FROM tmp_imdb_info")
self.connection.action("DROP TABLE tmp_imdb_info")
self.incDBVersion()
@ -701,7 +713,7 @@ class ConvertInfoToIndexerScheme(ConvertIMDBInfoToIndexerScheme):
self.connection.action(
"CREATE TABLE info (last_backlog NUMERIC, last_indexer NUMERIC, last_proper_search NUMERIC)")
self.connection.action(
"INSERT INTO info(last_backlog, last_indexer, last_proper_search) SELECT last_backlog, last_tvdb, last_proper_search FROM tmp_info")
"INSERT INTO info SELECT * FROM tmp_info")
self.connection.action("DROP TABLE tmp_info")
self.incDBVersion()
@ -944,6 +956,21 @@ class AddDefaultEpStatusToTvShows(AddVersionToTvEpisodes):
backupDatabase(41)
logger.log(u"Adding column default_ep_status to tv_shows")
self.addColumn("tv_shows", "default_ep_status", "TEXT", "")
self.addColumn("tv_shows", "default_ep_status", "NUMERIC", "-1")
self.incDBVersion()
class AlterTVShowsFieldTypes(AddDefaultEpStatusToTvShows):
def test(self):
return self.checkDBVersion() >= 42
def execute(self):
backupDatabase(42)
logger.log(u"Converting column indexer and default_ep_status field types to numeric")
self.connection.action("ALTER TABLE tv_shows RENAME TO tmp_tv_shows")
self.connection.action("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, quality NUMERIC, airs TEXT, status TEXT, flatten_folders NUMERIC, paused NUMERIC, startyear NUMERIC, air_by_date NUMERIC, lang TEXT, subtitles NUMERIC, notify_list TEXT, imdb_id TEXT, last_update_indexer NUMERIC, dvdorder NUMERIC, archive_firstmatch NUMERIC, rls_require_words TEXT, rls_ignore_words TEXT, sports NUMERIC, anime NUMERIC, scene NUMERIC, default_ep_status NUMERIC)")
self.connection.action("INSERT INTO tv_shows SELECT * FROM tmp_tv_shows")
self.connection.action("DROP TABLE tmp_tv_shows")
self.incDBVersion()

View File

@ -240,7 +240,7 @@ class TVShow(object):
# if we get an anime get the real season and episode
if self.is_anime and absolute_number and not season and not episode:
myDB = db.DBConnection()
sql = "SELECT * FROM tv_episodes WHERE showid = ? and absolute_number = ? and season != 0"
sql = "SELECT * FROM tv_episodes WHERE showid = ? AND absolute_number = ? AND season != 0"
sqlResults = myDB.select(sql, [self.indexerid, absolute_number])
if len(sqlResults) == 1:
@ -282,7 +282,7 @@ class TVShow(object):
def should_update(self, update_date=datetime.date.today()):
# if show is not 'Ended' always update (status 'Continuing')
if 'Unknown' not in self.status and 'Ended' not in self.status:
if self.status == 'Continuing':
return True
# run logic against the current show latest aired and next unaired data to see if we should bypass 'Ended' status
@ -500,7 +500,7 @@ class TVShow(object):
try:
curEp = self.getEpisode(curSeason, curEpisode)
if not curEp:
raise exceptions.EpisodeNotFoundException
raise exceptions.EpisodeNotFoundException
# if we found out that the ep is no longer on TVDB then delete it from our database too
if deleteEp:
@ -957,7 +957,7 @@ class TVShow(object):
if not self.nextaired or self.nextaired and curDate > self.nextaired:
myDB = db.DBConnection()
sqlResults = myDB.select(
"SELECT airdate, season, episode FROM tv_episodes WHERE showid = ? AND airdate >= ? AND status in (?,?) ORDER BY airdate ASC LIMIT 1",
"SELECT airdate, season, episode FROM tv_episodes WHERE showid = ? AND airdate >= ? AND status IN (?,?) ORDER BY airdate ASC LIMIT 1",
[self.indexerid, datetime.date.today().toordinal(), UNAIRED, WANTED])
if sqlResults == None or len(sqlResults) == 0:
@ -1526,7 +1526,7 @@ class TVEpisode(object):
self.subtitles_lastsearch = sqlResults[0]["subtitles_lastsearch"]
self.airdate = datetime.date.fromordinal(int(sqlResults[0]["airdate"]))
# logger.log(u"1 Status changes from " + str(self.status) + " to " + str(sqlResults[0]["status"]), logger.DEBUG)
self.status = int(sqlResults[0]["status"])
self.status = int(sqlResults[0]["status"] or -1)
# don't overwrite my location
if sqlResults[0]["location"] and sqlResults[0]["location"]:
@ -1684,8 +1684,8 @@ class TVEpisode(object):
try:
self.airdate = datetime.date(rawAirdate[0], rawAirdate[1], rawAirdate[2])
except (ValueError, IndexError):
logger.log(u"Malformed air date retrieved from " + sickbeard.indexerApi(
self.indexer).name + " (" + self.show.name + " - " + str(season) + "x" + str(episode) + ")",
logger.log(u"Malformed air date of " + str(firstaired) + " retrieved from " + sickbeard.indexerApi(
self.indexer).name + " for (" + self.show.name + " - " + str(season) + "x" + str(episode) + ")",
logger.ERROR)
# if I'm incomplete on TVDB but I once was complete then just delete myself from the DB for now
if self.indexerid != -1:

View File

@ -24,8 +24,11 @@ import time
import urllib
import re
import datetime
import sys
import platform
import sickbeard
from github import Github
from sickbeard import config, sab
from sickbeard import clients
from sickbeard import history, notifiers, processTV
@ -180,9 +183,9 @@ class BaseHandler(RequestHandler):
<p>%s</p>
<h2>Request Info</h2>
<p>%s</p>
<button onclick="window.location='%s/errorlogs/';">View Log(Errors)</button>
</body>
</html>""" % (error, error,
trace_info, request_info))
</html>""" % (error, error, trace_info, request_info, sickbeard.WEB_ROOT))
def redirect(self, url, permanent=False, status=None):
if not url.startswith(sickbeard.WEB_ROOT):
@ -3437,7 +3440,8 @@ class ConfigGeneral(Config):
proxy_setting=None, proxy_indexers=None, anon_redirect=None, git_path=None, git_remote=None,
calendar_unprotected=None,
fuzzy_dating=None, trim_zero=None, date_preset=None, date_preset_na=None, time_preset=None,
indexer_timeout=None, play_videos=None, rootDir=None, theme_name=None):
indexer_timeout=None, play_videos=None, rootDir=None, theme_name=None,
git_reset=None, git_username=None, git_password=None):
results = []
@ -3459,6 +3463,9 @@ class ConfigGeneral(Config):
sickbeard.ANON_REDIRECT = anon_redirect
sickbeard.PROXY_SETTING = proxy_setting
sickbeard.PROXY_INDEXERS = config.checkbox_to_value(proxy_indexers)
sickbeard.GIT_USERNAME = git_username
sickbeard.GIT_PASSWORD = git_password
sickbeard.GIT_RESET = config.checkbox_to_value(git_reset)
sickbeard.GIT_PATH = git_path
sickbeard.GIT_REMOTE = git_remote
sickbeard.CALENDAR_UNPROTECTED = config.checkbox_to_value(calendar_unprotected)
@ -4637,7 +4644,7 @@ class ErrorLogs(WebRoot):
def ErrorLogsMenu(self):
menu = [
{'title': 'Clear Errors', 'path': 'errorlogs/clearerrors/'},
# { 'title': 'View Log', 'path': 'errorlogs/viewlog' },
{'title': 'Submit Errors', 'path': 'errorlogs/submit_errors/', 'requires': self.haveGitHub},
]
return menu
@ -4649,12 +4656,14 @@ class ErrorLogs(WebRoot):
return t.respond()
def haveGitHub(self):
if sickbeard.GIT_USERNAME and sickbeard.GIT_PASSWORD:
return True
def clearerrors(self):
classes.ErrorViewer.clear()
return self.redirect("/errorlogs/")
def viewlog(self, minLevel=logger.INFO, maxLines=500):
t = PageTemplate(rh=self, file="viewlogs.tmpl")
@ -4706,4 +4715,37 @@ class ErrorLogs(WebRoot):
t.logLines = result
t.minLevel = minLevel
return t.respond()
return t.respond()
def submit_errors(self):
title = "[APP SUBMITTED]: "
gh_org = sickbeard.GIT_ORG or 'SiCKRAGETV'
gh_repo = 'sickrage-issues'
self.gh_issues = Github(login_or_token=sickbeard.GIT_USERNAME, password=sickbeard.GIT_PASSWORD,
user_agent="SiCKRAGE").get_organization(gh_org).get_repo(gh_repo)
try:
for curError in sorted(classes.ErrorViewer.errors, key=lambda error: error.time, reverse=True)[:500]:
title = title + curError.title
message = u"### INFO\n"
message += u"Python Version: **" + sys.version[:120] + "**\n"
message += u"Operating System: **" + platform.platform() + "**\n"
message += u"Branch: **" + sickbeard.BRANCH + "**\n"
message += u"Commit: SiCKRAGETV/SickRage@" + sickbeard.CUR_COMMIT_HASH + "\n"
message += u"### ERROR\n"
message += u"```\n"
message += curError.message
message += u"```\n"
message += u"---\n"
message += u"_STAFF NOTIFIED_: @SiCKRAGETV/owners @SiCKRAGETV/moderators"
issue = self.gh_issues.create_issue(title, message)
if issue:
ui.notifications.message('Your issue ticket #%s was submitted successfully!' % issue.number)
except Exception as e:
logger.log(ex(e), logger.ERROR)
return self.redirect("/errorlogs/")