mirror of
https://github.com/moparisthebest/SickRage
synced 2024-12-13 11:32:20 -05:00
Merge branch 'release/v4.0.2'
This commit is contained in:
commit
514e9d848f
@ -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>
|
||||
|
@ -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/>
|
||||
|
@ -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 />
|
||||
|
@ -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');
|
||||
|
@ -3,7 +3,7 @@ SickRage
|
||||
Video File Manager for TV Shows, It watches for new episodes of your favorite shows and when they are posted it does its magic.
|
||||
|
||||
## Branch Build Status
|
||||
[![Build Status](https://travis-ci.org/SiCKRAGETV/SickRage.svg?branch=develop)](https://travis-ci.org/SiCKRAGETV/SickRage)
|
||||
[![Build Status](https://travis-ci.org/SiCKRAGETV/SickRage.svg?branch=nightly)](https://travis-ci.org/SiCKRAGETV/SickRage)
|
||||
|
||||
## Features
|
||||
- XBMC library updates, poster/fanart downloads, and NFO/TBN generation
|
||||
|
@ -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
|
||||
|
@ -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)])
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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()
|
||||
|
@ -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"]:
|
||||
@ -1677,15 +1677,15 @@ class TVEpisode(object):
|
||||
self.description = getattr(myEp, 'overview', "")
|
||||
|
||||
firstaired = getattr(myEp, 'firstaired', None)
|
||||
if firstaired is None or firstaired in "0000-00-00":
|
||||
if not firstaired or firstaired == "0000-00-00":
|
||||
firstaired = str(datetime.date.fromordinal(1))
|
||||
rawAirdate = [int(x) for x in firstaired.split("-")]
|
||||
|
||||
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:
|
||||
|
@ -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):
|
||||
@ -200,9 +203,8 @@ class BaseHandler(RequestHandler):
|
||||
class WebHandler(BaseHandler):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(WebHandler, self).__init__(*args, **kwargs)
|
||||
|
||||
io_loop = IOLoop.current()
|
||||
executor = ThreadPoolExecutor(50)
|
||||
self.io_loop = IOLoop.current()
|
||||
self.executor = ThreadPoolExecutor(50)
|
||||
|
||||
@coroutine
|
||||
@asynchronous
|
||||
@ -3437,7 +3439,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 +3462,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 +4643,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 +4655,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")
|
||||
@ -4707,3 +4715,38 @@ class ErrorLogs(WebRoot):
|
||||
t.minLevel = minLevel
|
||||
|
||||
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)
|
||||
classes.ErrorViewer.clear()
|
||||
|
||||
except Exception as e:
|
||||
logger.log(ex(e), logger.ERROR)
|
||||
|
||||
return self.redirect("/errorlogs/")
|
@ -7,7 +7,7 @@ from sickbeard.webserve import LoginHandler, LogoutHandler, KeyHandler
|
||||
from sickbeard.webapi import ApiHandler
|
||||
from sickbeard import logger
|
||||
from sickbeard.helpers import create_https_certificates, generateApiKey
|
||||
from tornado.web import Application, StaticFileHandler, HTTPError, RedirectHandler
|
||||
from tornado.web import Application, StaticFileHandler, RedirectHandler
|
||||
from tornado.httpserver import HTTPServer
|
||||
from tornado.ioloop import IOLoop
|
||||
from tornado.routes import route
|
||||
|
Loading…
Reference in New Issue
Block a user