Skip to content

Commit

Permalink
Merge branch 'development'
Browse files Browse the repository at this point in the history
  • Loading branch information
morpheus65535 committed Nov 20, 2017
2 parents 0f63cb1 + 3c216ad commit feaa375
Show file tree
Hide file tree
Showing 14 changed files with 343 additions and 194 deletions.
5 changes: 3 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
FROM lsiobase/alpine.python
FROM debian:buster

EXPOSE 6767

VOLUME /tv

# Update
RUN apk add --update build-base python-dev py2-pip py-setuptools jpeg-dev zlib-dev git libgit2-dev
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 master --single-branch https://github.com/morpheus65535/bazarr.git /bazarr
Expand Down
18 changes: 12 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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!!!):

Expand All @@ -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.

Expand Down
146 changes: 111 additions & 35 deletions bazarr.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
bazarr_version = '0.1.1'

from bottle import route, run, template, static_file, request, redirect
import bottle
bottle.debug(True)
bottle.TEMPLATES.clear()
#bottle.debug(True)
#bottle.TEMPLATES.clear()

import os
bottle.TEMPLATE_PATH.insert(0,os.path.join(os.path.dirname(__file__), 'views/'))
Expand Down Expand Up @@ -34,14 +36,15 @@

import logging
from logging.handlers import TimedRotatingFileHandler

logger = logging.getLogger('waitress')
db = sqlite3.connect(os.path.join(os.path.dirname(__file__), 'data/db/bazarr.db'))
c = db.cursor()
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()

Expand All @@ -64,6 +67,9 @@ def configure_logging():
f = OneLineExceptionFormatter('%(asctime)s|%(levelname)s|%(message)s|',
'%d/%m/%Y %H:%M:%S')
fh.setFormatter(f)
logging.getLogger("enzyme").setLevel(logging.ERROR)
logging.getLogger("apscheduler").setLevel(logging.WARNING)
logging.getLogger("subliminal").setLevel(logging.ERROR)
root = logging.getLogger()
root.setLevel(log_level)
root.addHandler(fh)
Expand Down Expand Up @@ -129,38 +135,15 @@ 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'))
conn.create_function("path_substitution", 1, path_replace)
c = conn.cursor()

series_details = []
series_details = c.execute("SELECT title, overview, poster, fanart, hearing_impaired FROM table_shows WHERE sonarrSeriesId LIKE ?", (str(no),)).fetchone()
series_details = c.execute("SELECT title, overview, poster, fanart, hearing_impaired, tvdbid FROM table_shows WHERE sonarrSeriesId LIKE ?", (str(no),)).fetchone()
tvdbid = series_details[5]

episodes = c.execute("SELECT title, path_substitution(path), season, episode, subtitles, sonarrSeriesId, missing_subtitles, sonarrEpisodeId FROM table_episodes WHERE sonarrSeriesId LIKE ? ORDER BY episode ASC", (str(no),)).fetchall()
episodes = reversed(sorted(episodes, key=operator.itemgetter(2)))
Expand All @@ -169,7 +152,7 @@ def episodes(no):
seasons_list.append(list(season))
c.close()

return template('episodes', no=no, details=series_details, seasons=seasons_list, url_sonarr_short=url_sonarr_short, base_url=base_url)
return template('episodes', no=no, details=series_details, seasons=seasons_list, url_sonarr_short=url_sonarr_short, base_url=base_url, tvdbid=tvdbid)

@route(base_url + 'scan_disk/<no:int>', method='GET')
def scan_disk(no):
Expand Down Expand Up @@ -302,7 +285,8 @@ def save_settings():
def check_update():
ref = request.environ['HTTP_REFERER']

check_and_apply_update()
result = check_and_apply_update()
logging.info(result)

redirect(ref)

Expand All @@ -318,11 +302,101 @@ def system():
for line in reversed(open(os.path.join(os.path.dirname(__file__), 'data/log/bazarr.log')).readlines()):
logs.append(line.rstrip())

def get_time_from_interval(interval):
interval_clean = interval.split('[')
interval_clean = interval_clean[1][:-1]
interval_split = interval_clean.split(':')

hour = interval_split[0]
minute = interval_split[1].lstrip("0")
second = interval_split[2].lstrip("0")

text = "every "
if hour != "0":
text = text + hour
if hour == "1":
text = text + " hour"
else:
text = text + " hours"

if minute != "" and second != "":
text = text + ", "
elif minute == "" and second != "":
text = text + " and "
elif minute != "" and second == "":
text = text + " and "
if minute != "":
text = text + minute
if minute == "1":
text = text + " minute"
else:
text = text + " minutes"

if second != "":
text = text + " and "
if second != "":
text = text + second
if second == "1":
text = text + " second"
else:
text = text + " seconds"

return text

def get_time_from_cron(cron):
text = "at "
hour = str(cron[5])
minute = str(cron[6])
second = str(cron[7])

if hour != "0" and hour != "*":
text = text + hour
if hour == "0" or hour == "1":
text = text + " hour"
else:
text = text + " hours"

if minute != "*" and second != "0":
text = text + ", "
elif minute == "*" and second != "0":
text = text + " and "
elif minute != "0" and minute != "*" and second == "0":
text = text + " and "
if minute != "0" and minute != "*":
text = text + minute
if minute == "0" or minute == "1":
text = text + " minute"
else:
text = text + " minutes"

if second != "0" and second != "*":
text = text + " and "
if second != "0" and second != "*":
text = text + second
if second == "0" or second == "1":
text = text + " second"
else:
text = text + " seconds"

return text


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, get_time_from_interval(str(job.trigger)), pretty.date(job.next_run_time.replace(tzinfo=None)), job.id])
elif job.trigger.__str__().startswith('cron'):
task_list.append([job.name, get_time_from_cron(job.trigger.fields), 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)
return template('system', tasks=tasks, logs=logs, base_url=base_url, task_list=task_list, bazarr_version=bazarr_version)

@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():
Expand All @@ -331,6 +405,7 @@ def remove_subtitles():
subtitlesPath = request.forms.get('subtitlesPath')
sonarrSeriesId = request.forms.get('sonarrSeriesId')
sonarrEpisodeId = request.forms.get('sonarrEpisodeId')
tvdbid = request.forms.get('tvdbid')

try:
os.remove(subtitlesPath)
Expand All @@ -339,7 +414,7 @@ def remove_subtitles():
except OSError:
pass
store_subtitles(episodePath)
list_missing_subtitles(sonarrSeriesId)
list_missing_subtitles(tvdbid)

@route(base_url + 'get_subtitle', method='POST')
def get_subtitle():
Expand All @@ -350,6 +425,7 @@ def get_subtitle():
hi = request.forms.get('hi')
sonarrSeriesId = request.forms.get('sonarrSeriesId')
sonarrEpisodeId = request.forms.get('sonarrEpisodeId')
tvdbid = request.forms.get('tvdbid')

db = sqlite3.connect(os.path.join(os.path.dirname(__file__), 'data/db/bazarr.db'))
c = db.cursor()
Expand All @@ -366,9 +442,9 @@ def get_subtitle():
if result is not None:
history_log(1, sonarrSeriesId, sonarrEpisodeId, result)
store_subtitles(episodePath)
list_missing_subtitles(sonarrSeriesId)
list_missing_subtitles(tvdbid)
redirect(ref)
except OSError:
redirect(ref + '?error=2')
pass

run(host=ip, port=port, server='waitress')
12 changes: 8 additions & 4 deletions check_update.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import os
import pygit2

current_working_directory = os.getcwd()
current_working_directory = os.path.dirname(__file__)
repository_path = pygit2.discover_repository(current_working_directory)
local_repo = pygit2.Repository(repository_path)

Expand All @@ -15,13 +15,17 @@ def check_and_apply_update(repo=local_repo, remote_name='origin'):
merge_result, _ = repo.merge_analysis(remote_id)
# Up to date, do nothing
if merge_result & pygit2.GIT_MERGE_ANALYSIS_UP_TO_DATE:
print 'Up to date'
return
result = 'No new version of Bazarr available.'
pass
# We can just fastforward
elif merge_result & pygit2.GIT_MERGE_ANALYSIS_FASTFORWARD:
repo.checkout_tree(repo.get(remote_id))
master_ref = repo.lookup_reference('refs/heads/master')
master_ref = repo.lookup_reference('refs/heads/' + branch)
master_ref.set_target(remote_id)
repo.head.set_target(remote_id)
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')

return result
2 changes: 1 addition & 1 deletion create_db.sql
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Loading

0 comments on commit feaa375

Please sign in to comment.