Better error management and improvemet to tasks schduler

pull/26/head
Louis Vézina 7 years ago
parent ee9ef5e790
commit 6c92df0861

@ -9,7 +9,7 @@ RUN apt-get update
RUN apt-get install -y build-essential python-dev python-pip python-setuptools libjpeg-dev zlib1g-dev git libgit2-dev libffi-dev
# Get application source from Github
RUN git clone -b development --single-branch https://github.com/morpheus65535/bazarr.git /bazarr
RUN git clone -b master --single-branch https://github.com/morpheus65535/bazarr.git /bazarr
VOLUME /bazarr/data

@ -64,7 +64,9 @@ Linux:
* Open your browser and go to `http://localhost:6767/`
## Docker:
* You can use [this image](https://hub.docker.com/r/morpheus65535/bazarr) to quickly build your own isolated app container. Thanks to [Linux Server](https://github.com/linuxserver) for the base image. It's based on the Linux instructions above. For more info about Docker check out the [official website](https://www.docker.com).
* You can use [this image](https://hub.docker.com/r/morpheus65535/bazarr) to quickly build your own isolated app container. It's based on the Linux instructions above. For more info about Docker check out the [official website](https://www.docker.com).
docker create --name=bazarr -v /etc/localtime:/etc/localtime:ro -v /etc/timezone:/etc/timezone:ro -v /path/to/series/directory:/tv -v /path/to/config/directory/on/host:/bazarr/data -p 6767:6767 --restart=always morpheus65535/bazarr:latest
## First run (important to read!!!):
@ -77,12 +79,16 @@ Linux:
* Configure Sonarr ip, port, base url, SSL and API key.
### 4 - In "Subliminal" tab:
* Configure enabled providers and enabled languages. Enabled languages are those that you are going to be able to assign to a series later.
### 5 - Save those settings and restart Bazarr.
### 5 - Save those settings and restart (important!!!) Bazarr.
### 6 - Wait 2 minutes
### 7 - On the "Series" page, you should now see all your series listed with a wrench icon on yellow background. Those are the series that need to be configured. Click on those one you want to get subtitles for and select desired languages. You don't have to do this for every series but it will looks cleaner without all this yellow ;-). If you don't want any substitles for a series, just click on the wrench icon and then on "Save" without selecting anything.
### 8 - On each series page, you should see episode files available on disk, existing subtitles and missing subtitles (in case you requested some and they aren't already existing).
* If you don't see your episodes right now, wait some more time. It take time to do the initial synchronization between Sonarr and Bazarr.
### 6 - On the "Series" page, click on "Update Series"
* You should now see all your series listed with a wrench icon on yellow background. Those are the series that need to be configured. Click on each one and select desired languages. You have to do this even if you don't want subtitles for a series. Just click on the wrench icon and then on "Save".
* When you've finished going trough all those series to configure desired languages, you have to "Update All Episodes" from the "Series" page. Don't be impatient, it will take about 1 minute by 1000 episodes Bazarr need to scan for existing internal and external subtitles. If Bazarr is accessing those episodes trough a network share, it's going to take much more longer than that. Keep in mind that Bazarr have to open each and every episode files to analyze the content.
* Once the scan is finished, you should be able to access episodes list for each series and see those missing subtitles on the wanted page.
### 9 - On "Wanted" page, you should see all the episodes who have missing subtitles.
### 10 - Have fun and keep in mind that providers may temporary refuse connection due to connection limit exceeded or problem on the provider web service.

@ -41,7 +41,7 @@ c.execute("SELECT log_level FROM table_settings_general")
log_level = c.fetchone()
log_level = log_level[0]
if log_level is None:
log_level = "WARNING"
log_level = "INFO"
log_level = getattr(logging, log_level)
c.close()
@ -129,30 +129,6 @@ def edit_series(no):
redirect(ref)
@route(base_url + 'update_series')
def update_series_list():
ref = request.environ['HTTP_REFERER']
update_series()
redirect(ref)
@route(base_url + 'update_all_episodes')
def update_all_episodes_list():
ref = request.environ['HTTP_REFERER']
update_all_episodes()
redirect(ref)
@route(base_url + 'add_new_episodes')
def add_new_episodes_list():
ref = request.environ['HTTP_REFERER']
add_new_episodes()
redirect(ref)
@route(base_url + 'episodes/<no:int>', method='GET')
def episodes(no):
conn = sqlite3.connect(os.path.join(os.path.dirname(__file__), 'data/db/bazarr.db'))
@ -321,10 +297,21 @@ def system():
task_list = []
for job in scheduler.get_jobs():
task_list.append([job.name, job.trigger.interval.__str__(), pretty.date(job.next_run_time.replace(tzinfo=None))])
if job.trigger.__str__().startswith('interval'):
task_list.append([job.name, job.trigger.interval.__str__(), pretty.date(job.next_run_time.replace(tzinfo=None)), job.id])
elif job.trigger.__str__().startswith('cron'):
task_list.append([job.name, job.trigger.__str__(), pretty.date(job.next_run_time.replace(tzinfo=None)), job.id])
return template('system', tasks=tasks, logs=logs, base_url=base_url, task_list=task_list)
@route(base_url + 'execute/<taskid>')
def execute_task(taskid):
ref = request.environ['HTTP_REFERER']
execute_now(taskid)
redirect(ref)
@route(base_url + 'remove_subtitles', method='POST')
def remove_subtitles():
episodePath = request.forms.get('episodePath')

@ -23,7 +23,7 @@ def check_and_apply_update(repo=local_repo, remote_name='origin'):
master_ref = repo.lookup_reference('refs/heads/master')
master_ref.set_target(remote_id)
repo.head.set_target(remote_id)
result = 'Bazarr updated to latest version.'
result = 'Bazarr updated to latest version and restarting.'
os.execlp('python', 'python', os.path.join(os.path.dirname(__file__), 'bazarr.py'))
else:
raise AssertionError('Unknown merge analysis result')

@ -40,7 +40,7 @@ CREATE TABLE "table_settings_general" (
`branch` TEXT,
`auto_update` INTEGER
);
INSERT INTO `table_settings_general` (ip,port,base_url,path_mapping,log_level, branch, auto_update) VALUES ('0.0.0.0',6767,'/',Null,'WARNING','master','True');
INSERT INTO `table_settings_general` (ip,port,base_url,path_mapping,log_level, branch, auto_update) VALUES ('0.0.0.0',6767,'/',Null,'INFO','master','True');
CREATE TABLE `table_scheduler` (
`id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
`name` TEXT NOT NULL,

@ -21,6 +21,7 @@ def update_all_episodes():
base_url_sonarr = ""
else:
base_url_sonarr = "/" + config_sonarr[2].strip("/")
apikey_sonarr = config_sonarr[4]
# Get current episodes id in DB
current_episodes_db = c.execute('SELECT sonarrEpisodeId FROM table_episodes').fetchall()
@ -32,7 +33,7 @@ def update_all_episodes():
seriesIdList = c.fetchall()
for seriesId in seriesIdList:
# Get episodes data for a series from Sonarr
url_sonarr_api_episode = protocol_sonarr + "://" + config_sonarr[0] + ":" + str(config_sonarr[1]) + base_url_sonarr + "/api/episode?seriesId=" + str(seriesId[0]) + "&apikey=" + config_sonarr[4]
url_sonarr_api_episode = protocol_sonarr + "://" + config_sonarr[0] + ":" + str(config_sonarr[1]) + base_url_sonarr + "/api/episode?seriesId=" + str(seriesId[0]) + "&apikey=" + apikey_sonarr
r = requests.get(url_sonarr_api_episode)
for episode in r.json():
if episode['hasFile']:
@ -80,7 +81,13 @@ def add_new_episodes():
base_url_sonarr = ""
else:
base_url_sonarr = "/" + config_sonarr[2].strip("/")
apikey_sonarr = config_sonarr[4]
if apikey_sonarr == None:
# Close database connection
c.close()
pass
else:
# Get current episodes in DB
current_episodes_db = c.execute('SELECT sonarrEpisodeId FROM table_episodes').fetchall()
current_episodes_db_list = [x[0] for x in current_episodes_db]
@ -91,9 +98,8 @@ def add_new_episodes():
seriesIdList = c.fetchall()
for seriesId in seriesIdList:
# Get episodes data for a series from Sonarr
url_sonarr_api_episode = protocol_sonarr + "://" + config_sonarr[0] + ":" + str(config_sonarr[1]) + base_url_sonarr + "/api/episode?seriesId=" + str(seriesId[0]) + "&apikey=" + config_sonarr[4]
url_sonarr_api_episode = protocol_sonarr + "://" + config_sonarr[0] + ":" + str(config_sonarr[1]) + base_url_sonarr + "/api/episode?seriesId=" + str(seriesId[0]) + "&apikey=" + apikey_sonarr
r = requests.get(url_sonarr_api_episode)
for episode in r.json():
if episode['hasFile']:
# Add shows in Sonarr to current shows list

@ -9,6 +9,9 @@ def update_series():
db = sqlite3.connect(os.path.join(os.path.dirname(__file__), 'data/db/bazarr.db'))
c = db.cursor()
if apikey_sonarr == None:
pass
else:
# Get shows data from Sonarr
url_sonarr_api_series = url_sonarr + "/api/series?apikey=" + apikey_sonarr
r = requests.get(url_sonarr_api_series)

@ -68,7 +68,7 @@ def store_subtitles(file):
def list_missing_subtitles(*no):
query_string = ''
try:
query_string = " WHERE table_episodes.sonarrSeriesId = " + str(no[0])
query_string = " WHERE table_shows.tvdbId = " + str(no[0])
except:
pass
conn_db = sqlite3.connect(os.path.join(os.path.dirname(__file__), 'data/db/bazarr.db'))
@ -79,21 +79,22 @@ def list_missing_subtitles(*no):
for episode_subtitles in episodes_subtitles:
actual_subtitles = []
actual_subtitles_list = []
desired_subtitles = []
missing_subtitles = []
if episode_subtitles[1] != None:
actual_subtitles = ast.literal_eval(episode_subtitles[1])
if episode_subtitles[2] != None:
desired_subtitles = ast.literal_eval(episode_subtitles[2])
actual_subtitles_list = []
if desired_subtitles == None:
missing_subtitles_global.append(tuple(['[]', episode_subtitles[0]]))
else:
for item in actual_subtitles:
actual_subtitles_list.append(item[0])
missing_subtitles = list(set(desired_subtitles) - set(actual_subtitles_list))
missing_subtitles_global.append(tuple([str(missing_subtitles), episode_subtitles[0]]))
else:
missing_subtitles_global.append(tuple(['[]', episode_subtitles[0]]))
c_db.executemany("UPDATE table_episodes SET missing_subtitles = ? WHERE sonarrEpisodeId = ?", (missing_subtitles_global))
conn_db.commit()
c_db.close()

@ -1,15 +1,22 @@
from get_general_settings import *
from get_series import *
from get_episodes import *
from list_subtitles import *
from get_subtitle import *
from check_update import *
from apscheduler.schedulers.background import BackgroundScheduler
from datetime import datetime
scheduler = BackgroundScheduler()
if automatic == 'True':
scheduler.add_job(check_and_apply_update, 'interval', hours=6, max_instances=1, coalesce=True, id='update_bazarr', name='Update bazarr from source on Github')
scheduler.add_job(update_series, 'interval', minutes=1, max_instances=1, coalesce=True, id='update_series', name='Update series list from Sonarr')
scheduler.add_job(add_new_episodes, 'interval', minutes=1, max_instances=1, coalesce=True, id='add_new_episodes', name='Add new episodes from Sonarr')
scheduler.add_job(update_all_episodes, 'cron', hour=4, max_instances=1, coalesce=True, id='update_all_episodes', name='Update all episodes from Sonarr')
scheduler.add_job(list_missing_subtitles, 'interval', minutes=5, max_instances=1, coalesce=True, id='list_missing_subtitles', name='Process missing subtitles for all series')
scheduler.add_job(wanted_search_missing_subtitles, 'interval', minutes=15, max_instances=1, coalesce=True, id='wanted_search_missing_subtitles', name='Search for wanted subtitles')
scheduler.start()
def execute_now(taskid):
scheduler.modify_job(taskid, jobstore=None, next_run_time=datetime.now())

@ -121,7 +121,7 @@
%if len(seasons) == 0:
<div id="fondblanc" class="ui container">
<h2 class="ui header">No episode file available for this series.</h2>
<h3 class="ui header">No episode file available for this series or Bazarr is still synchronizing with Sonarr. Please come back later.</h3>
</div>
%else:
%for season in seasons:

@ -78,12 +78,6 @@
</div>
<div id="fondblanc" class="ui container">
<div class="ui basic buttons">
<button id="update_series" class="ui button"><i class="refresh icon"></i>Update Series</button>
<button id="update_all_episodes" class="ui button"><i class="refresh icon"></i>Update All Episodes</button>
<button id="add_new_episodes" class="ui button"><i class="wait icon"></i>Add New Episodes</button>
</div>
<table id="tableseries" class="ui very basic selectable sortable table">
<thead>
<tr>
@ -111,7 +105,7 @@
%end
%end
</td>
<td>{{row[4]}}</td>
<td>{{!"" if row[4] == None else row[4]}}</td>
<td {{!"style='background-color: yellow;'" if row[4] == None else ""}}>
<%
subs_languages_list = []
@ -200,18 +194,6 @@
})
;
$('#update_series').click(function(){
window.location = '{{base_url}}update_series';
})
$('#update_all_episodes').click(function(){
window.location = '{{base_url}}update_all_episodes';
})
$('#add_new_episodes').click(function(){
window.location = '{{base_url}}add_new_episodes';
})
$('.config').click(function(){
sessionStorage.scrolly=$(window).scrollTop();

@ -85,6 +85,7 @@
<th>Name</th>
<th>Interval</th>
<th>Next Execution</th>
<th class="collapsing"></th>
</tr>
</thead>
<tbody>
@ -93,6 +94,11 @@
<td>{{task[0]}}</td>
<td>{{task[1]}}</td>
<td>{{task[2]}}</td>
<td class="collapsing">
<div class="execute ui inverted basic compact icon" data-tooltip="Execute {{task[0]}}" data-inverted="" data-taskid='{{task[3]}}'>
<i class="ui black refresh icon"></i>
</div>
</td>
</tr>
%end
</tbody>
@ -173,6 +179,10 @@ icon"></i></td>
.tab()
;
$('.execute').click(function(){
window.location = '{{base_url}}execute/' + $(this).data("taskid");
})
$('.log').click(function(){
$("#message").html($(this).data("message"));
$("#exception").html($(this).data("exception"));

Loading…
Cancel
Save