pull/884/head
Louis Vézina 4 years ago
parent d933108766
commit 8e134dcceb

@ -298,6 +298,8 @@ class EpisodesSubtitlesDownload(Resource):
history_log(1, sonarrSeriesId, sonarrEpisodeId, message, path, language_code, provider, score)
send_notifications(sonarrSeriesId, sonarrEpisodeId, message)
store_subtitles(path, episodePath)
else:
event_stream.write(type='episode', action='update', series=int(sonarrSeriesId), episode=int(sonarrEpisodeId))
return result, 201
except OSError:
pass
@ -637,6 +639,8 @@ class MovieSubtitlesDownload(Resource):
history_log_movie(1, radarrId, message, path, language_code, provider, score)
send_notifications_movie(radarrId, message)
store_subtitles_movie(path, moviePath)
else:
event_stream.write(type='movie', action='update', movie=int(radarrId))
return result, 201
except OSError:
pass
@ -953,7 +957,8 @@ class WantedSeries(Resource):
else:
monitored_only_query_string = ''
row_count = database.execute("SELECT COUNT(*) as count FROM table_episodes", only_one=True)['count']
row_count = database.execute("SELECT COUNT(*) as count FROM table_episodes WHERE missing_subtitles != '[]'" +
monitored_only_query_string, only_one=True)['count']
data = database.execute("SELECT table_shows.title as seriesTitle, "
"table_episodes.season || 'x' || table_episodes.episode as episode_number, "
"table_episodes.title as episodeTitle, table_episodes.missing_subtitles, "
@ -996,7 +1001,8 @@ class WantedMovies(Resource):
else:
monitored_only_query_string = ''
row_count = database.execute("SELECT COUNT(*) as count FROM table_movies", only_one=True)['count']
row_count = database.execute("SELECT COUNT(*) as count FROM table_movies WHERE missing_subtitles != '[]'" +
monitored_only_query_string, only_one=True)['count']
data = database.execute("SELECT title, missing_subtitles, radarrId, path, hearing_impaired, sceneName, "
"failedAttempts FROM table_movies WHERE missing_subtitles != '[]'" +
monitored_only_query_string + " ORDER BY _rowid_ DESC LIMIT ? OFFSET ?",

@ -93,7 +93,6 @@ def store_subtitles(original_path, reversed_path):
for episode in matching_episodes:
if episode:
logging.debug("BAZARR storing those languages to DB: " + str(actual_subtitles))
event_stream.write(type='episode', action='update', series=episode['sonarrSeriesId'], episode=episode['sonarrEpisodeId'])
list_missing_subtitles(epno=episode['sonarrEpisodeId'])
else:
logging.debug("BAZARR haven't been able to update existing subtitles to DB : " + str(actual_subtitles))
@ -165,7 +164,6 @@ def store_subtitles_movie(original_path, reversed_path):
for movie in matching_movies:
if movie:
logging.debug("BAZARR storing those languages to DB: " + str(actual_subtitles))
event_stream.write(type='movie', action='update', movie=movie['radarrId'])
list_missing_subtitles_movies(no=movie['radarrId'])
else:
logging.debug("BAZARR haven't been able to update existing subtitles to DB : " + str(actual_subtitles))
@ -299,6 +297,8 @@ def list_missing_subtitles_movies(no=None):
database.execute("UPDATE table_movies SET missing_subtitles=? WHERE radarrId=?",
(missing_subtitles_item[0], missing_subtitles_item[1]))
event_stream.write(type='movie', action='update', movie=missing_subtitles_item[1])
def series_full_scan_subtitles():
episodes = database.execute("SELECT path FROM table_episodes")

@ -608,76 +608,16 @@ def historymovies():
return render_template('historymovies.html')
@app.route('/wanted')
@login_required
def wanted():
return render_template('wanted.html', bazarr_version=bazarr_version, base_url=base_url, current_port=settings.general.port)
@app.route('/wantedseries')
@app.route('/wantedseries/')
@login_required
def wantedseries():
return render_template('wantedseries.html')
if settings.sonarr.getboolean('only_monitored'):
monitored_only_query_string = " AND monitored='True'"
else:
monitored_only_query_string = ''
missing_count = database.execute("SELECT COUNT(*) as count FROM table_episodes WHERE missing_subtitles != '[]'" +
monitored_only_query_string, only_one=True)['count']
page = request.data
if page == "":
page = "1"
page_size = int(settings.general.page_size)
offset = (int(page) - 1) * page_size
max_page = int(math.ceil(missing_count / (page_size + 0.0)))
data = database.execute("SELECT table_shows.title as seriesTitle, "
"table_episodes.season || 'x' || table_episodes.episode as episode_number, "
"table_episodes.title as episodeTitle, table_episodes.missing_subtitles, table_episodes.sonarrSeriesId, "
"table_episodes.path, table_shows.hearing_impaired, table_episodes.sonarrEpisodeId, "
"table_episodes.scene_name, table_episodes.failedAttempts FROM table_episodes "
"INNER JOIN table_shows on table_shows.sonarrSeriesId = table_episodes.sonarrSeriesId "
"WHERE table_episodes.missing_subtitles != '[]'" + monitored_only_query_string +
" ORDER BY table_episodes._rowid_ DESC LIMIT ? OFFSET ?", (page_size, offset))
# path_replace
dict_mapper.path_replace(data)
return render_template('wantedseries.html', bazarr_version=bazarr_version, rows=data, missing_count=missing_count, page=page,
max_page=max_page, base_url=base_url, page_size=page_size, current_port=settings.general.port)
@app.route('/wantedmovies')
@app.route('/wantedmovies/')
@login_required
def wantedmovies():
if settings.radarr.getboolean('only_monitored'):
monitored_only_query_string = " AND monitored='True'"
else:
monitored_only_query_string = ''
missing_count = database.execute("SELECT COUNT(*) as count FROM table_movies WHERE missing_subtitles != '[]'" +
monitored_only_query_string, only_one=True)['count']
page = request.args.page
if page == "":
page = "1"
page_size = int(settings.general.page_size)
offset = (int(page) - 1) * page_size
max_page = int(math.ceil(missing_count / (page_size + 0.0)))
data = database.execute("SELECT title, missing_subtitles, radarrId, path, hearing_impaired, sceneName, "
"failedAttempts FROM table_movies WHERE missing_subtitles != '[]'" +
monitored_only_query_string + " ORDER BY _rowid_ DESC LIMIT ? OFFSET ?",
(page_size, offset))
# path_replace
dict_mapper.path_replace_movie(data)
return render_template('wantedmovies.html', bazarr_version=bazarr_version, rows=data,
missing_count=missing_count, page=page, max_page=max_page, base_url=base_url, page_size=page_size,
current_port=settings.general.port)
return render_template('wantedmovies.html')
@app.route('/wanted_search_missing_subtitles')

@ -10,26 +10,30 @@ import requests
from whichcraft import which
from get_args import args
from config import settings, url_sonarr, url_radarr
from database import database
from websocket_handler import event_stream
from subliminal import region as subliminal_cache_region
import datetime
import glob
from threading import Event
def history_log(action, sonarr_series_id, sonarr_episode_id, description, video_path=None, language=None, provider=None,
score=None):
from database import database
thread = Event()
database.execute("INSERT INTO table_history (action, sonarrSeriesId, sonarrEpisodeId, timestamp, description,"
"video_path, language, provider, score) VALUES (?,?,?,?,?,?,?,?,?)",
(action, sonarr_series_id, sonarr_episode_id, time.time(), description, video_path, language,
provider, score))
event_stream.write(type='episodeHistory')
def history_log_movie(action, radarr_id, description, video_path=None, language=None, provider=None, score=None):
from database import database
database.execute("INSERT INTO table_history_movie (action, radarrId, timestamp, description, video_path, language, "
"provider, score) VALUES (?,?,?,?,?,?,?,?)",
(action, radarr_id, time.time(), description, video_path, language, provider, score))
event_stream.write(type='movieHistory')
def get_binary(name):

@ -169,39 +169,39 @@
<nav class="sidebar-nav">
<ul id="sidebarnav">
{% if settings.general.getboolean('use_sonarr') %}
<li id="series_nav"><a href="{{ url_for('series') }}"><i class="fas fa-play"></i><span
class="hide-menu"> Series</span></a>
</li>
<li id="series_nav"><a href="{{ url_for('series') }}"><i class="fas fa-play"></i><span
class="hide-menu"> Series</span></a>
</li>
{% endif %}
{% if settings.general.getboolean('use_radarr') %}
<li id="movies_nav"><a href="{{ url_for('movies') }}"><i class="fas fa-film"></i><span
class="hide-menu"> Movies</span></a>
</li>
{% endif %}
{% if settings.general.getboolean('use_sonarr') and settings.general.getboolean('use_radarr') %}
<li><a href="#"><i class="fas fa-clock"></i><span
class="hide-menu"> History</span></a>
<ul aria-expanded="false" class="collapse">
<li><a href="{{ url_for('historyseries') }}"> Series</a></li>
<li><a href="{{ url_for('historymovies') }}"> Movies</a></li>
</ul>
</li>
{% elif settings.general.getboolean('use_sonarr') and not settings.general.getboolean('use_radarr') %}
<li><a href="{{ url_for('historyseries') }}"><i class="fas fa-play"></i><span
class="hide-menu"> History</span></a>
</li>
{% elif settings.general.getboolean('use_radarr') and not settings.general.getboolean('use_sonarr') %}
<li><a href="{{ url_for('historymovies') }}"><i class="fas fa-play"></i><span
class="hide-menu"> History</span></a>
</li>
<li id="movies_nav"><a href="{{ url_for('movies') }}"><i class="fas fa-film"></i><span
class="hide-menu"> Movies</span></a>
</li>
{% endif %}
<li><a href="#"><i class="fas fa-exclamation-triangle"></i><span
class="hide-menu"> Wanted</span></a>
<li><a href="#"><i class="fas fa-clock"></i><span class="hide-menu"> History</span></a>
<ul aria-expanded="false" class="collapse">
<li><a href="/"> Missing</a></li>
<li><a href="/"> Cutoff Unmet</a></li>
{% if settings.general.getboolean('use_sonarr') %}
<li><a href="{{ url_for('historyseries') }}"> Series</a></li>
{% endif %}
{% if settings.general.getboolean('use_radarr') %}
<li><a href="{{ url_for('historymovies') }}"> Movies</a></li>
{% endif %}
</ul>
</li>
<li><a href="#"><i class="fas fa-exclamation-triangle"></i><span class="hide-menu"> Wanted</span></a>
<ul aria-expanded="false" class="collapse">
{% if settings.general.getboolean('use_sonarr') %}
<li><a href="{{ url_for('wantedseries') }}"> Series</a></li>
{% endif %}
{% if settings.general.getboolean('use_radarr') %}
<li><a href="{{ url_for('wantedmovies') }}"> Movies</a></li>
{% endif %}
</ul>
</li>
<li><a href="#"><i
class="fas fa-cogs"></i><span class="hide-menu"> Settings</span></a>
<ul aria-expanded="false" class="collapse">
@ -212,6 +212,7 @@
<li><a href="/"> Notifications</a></li>
</ul>
</li>
<li><a href="#"><i
class="fas fa-laptop"></i><span class="hide-menu"> System</span></a>
<ul aria-expanded="false" class="collapse">
@ -263,6 +264,7 @@
<div id="reconnect_overlay" class="overlay">
<div class="overlay-content">
<p style="color: white;">Connection to Backend Lost.</p>
<button class="btn btn-primary" onclick="window.location.reload()">Reload</button>
</div>
</div>

@ -745,13 +745,7 @@
url: "{{ url_for('api.episodes') }}?seriesid=" + event_json.series + "&episodeid=" + event_json.episode,
success: function (data) {
if (data.data.length) {
$('#episodes').DataTable().row(rowId).data(data.data[0]);
if ($('#episodes').DataTable().row(rowId).child.isShown()) {
$('#episodes').DataTable().draw('page');
$('#episodes').DataTable().row(rowId).child.show();
} else {
$('#episodes').DataTable().draw('page');
}
$('#episodes').DataTable().row(rowId).data(data.data[0]).draw('page');
$('[data-toggle="tooltip"]').tooltip({html: true});
}
}

@ -1,8 +0,0 @@
<!DOCTYPE html>
<html>
<body>
<div style='margin-bottom:2em; color:Gray;' class="ui center aligned container">
Bazarr Ver. {{bazarr_version}}
</div>
</body>
</html>

@ -1,126 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<script src="{{base_url}}static/jquery/jquery-latest.min.js"></script>
<script src="{{base_url}}static/semantic/semantic.min.js"></script>
<script src="{{base_url}}static/jquery/tablesort.js"></script>
<link rel="stylesheet" href="{{base_url}}static/semantic/semantic.min.css">
<link rel="apple-touch-icon" sizes="120x120" href="{{base_url}}static/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="{{base_url}}static/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="{{base_url}}static/favicon-16x16.png">
<link rel="manifest" href="{{base_url}}static/manifest.json">
<link rel="mask-icon" href="{{base_url}}static/safari-pinned-tab.svg" color="#5bbad5">
<link rel="shortcut icon" href="{{base_url}}static/favicon.ico">
<meta name="msapplication-config" content="{{base_url}}static/browserconfig.xml">
<meta name="theme-color" content="#ffffff">
<title>History - Bazarr</title>
<style>
body {
background-color: #272727;
}
#fondblanc {
background-color: #ffffff;
border-radius: 0;
box-shadow: 0 0 5px 5px #ffffff;
margin-top: 32px;
margin-bottom: 3em;
padding: 1em;
overflow-x:auto;
}
.fast.backward, .backward, .forward, .fast.forward {
cursor: pointer;
}
.fast.backward, .backward, .forward, .fast.forward { pointer-events: auto; }
.fast.backward.disabled, .backward.disabled, .forward.disabled, .fast.forward.disabled { pointer-events: none; }
.ui.tabular.menu > .disabled.item {
opacity: 0.45 !important;
pointer-events: none !important;
}
</style>
</head>
<body>
<div id='loader' class="ui page dimmer">
<div id="loader_text" class="ui indeterminate text loader">Loading...</div>
</div>
{% include('menu.html') %}
<div id="fondblanc" class="ui container">
<div class="ui top attached tabular menu">
<a id="series_tab" class="tabs item active" data-enabled="{{settings.general.getboolean('use_sonarr')}}" data-tab="series">Series</a>
<a id="movies_tab" class="tabs item" data-enabled="{{settings.general.getboolean('use_radarr')}}" data-tab="movies">Movies</a>
</div>
<div class="ui bottom attached tab segment" data-tab="series">
<div class="content">
<div id="content_series"></div>
</div>
</div>
<div class="ui bottom attached tab segment" data-tab="movies">
<div class="content">
<div id="content_movies"></div>
</div>
</div>
</div>
{% include('footer.html') %}
</body>
</html>
<script>
$('.menu .item')
.tab();
$('#series_tab').on('click', function() {
loadURLseries(1);
});
$('#movies_tab').on('click', function() {
loadURLmovies(1);
});
function loadURLseries(page) {
$.ajax({
url: "{{base_url}}historyseries?page=" + page,
beforeSend: function() { $('#loader').addClass('active'); },
complete: function() { $('#loader').removeClass('active'); },
cache: false
}).done(function(data) {
$("#content_series").html(data);
});
}
function loadURLmovies(page) {
$.ajax({
url: "{{base_url}}historymovies?page=" + page,
beforeSend: function() { $('#loader').addClass('active'); },
complete: function() { $('#loader').removeClass('active'); },
cache: false
}).done(function(data) {
$("#content_movies").html(data);
});
}
$('a:not(.tabs), button:not(.cancel, #download_log)').on('click', function(){
$('#loader').addClass('active');
});
if ($('#series_tab').data("enabled") === "True") {
$("#series_tab").removeClass('disabled');
} else {
$("#series_tab").addClass('disabled');
}
if ($('#movies_tab').data("enabled") === "True") {
$("#movies_tab").removeClass('disabled');
} else {
$("#movies_tab").addClass('disabled');
}
if ($('#series_tab').data("enabled") === "True") {
$( "#series_tab" ).trigger( "click" );
}
if ($('#series_tab').data("enabled") === "False" && $('#movies_tab').data("enabled") === "True") {
$( "#movies_tab" ).trigger( "click" );
}
</script>

@ -29,6 +29,10 @@
var table = $('#history_movies').DataTable({
"processing": false,
"serverSide": true,
language: {
zeroRecords: 'Nothing Found In Movies History',
processing: "Loading Movies History..."
},
"searching": false,
"ordering": false,
"responsive": true,
@ -68,6 +72,14 @@
}
]
});
});
events.on('event', function(event) {
var event_json = JSON.parse(event);
if (event_json.type === 'movieHistory') {
$('#history_movies').DataTable().ajax.reload(resetPaging=false);
$('[data-toggle="tooltip"]').tooltip({html: true});
}
});
});
</script>
{% endblock tail %}

@ -31,9 +31,14 @@
var table = $('#history_series').DataTable({
"processing": true,
"serverSide": true,
language: {
zeroRecords: 'Nothing Found In Series History',
processing: "Loading Series History..."
},
"searching": false,
"ordering": false,
"lengthChange": false,
"responsive": true,
"pageLength": {{ settings.general.page_size }},
"ajax": "{{ url_for('api.historyseries') }}",
"columns": [
@ -71,6 +76,14 @@
}
]
});
});
events.on('event', function(event) {
var event_json = JSON.parse(event);
if (event_json.type === 'episodeHistory') {
$('#history_series').DataTable().ajax.reload(resetPaging=false);
$('[data-toggle="tooltip"]').tooltip({html: true});
}
});
});
</script>
{% endblock tail %}

@ -1,466 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<meta name="mobile-web-app-capable" content="yes"/>
<meta name="apple-mobile-web-app-capable" content="yes"/>
<link href="{{ url_for('static',filename='noty/noty.css') }}" rel="stylesheet">
<script src="{{ url_for('static',filename='noty/noty.min.js') }}" type="text/javascript"></script>
<style>
#divmenu {
padding-top: 1em;
}
.menu_segment {
padding: 0em !important;
border: none !important;
margin: 0em !important;
background: none !important;
}
#icon_menu {
background: transparent !important;
border: solid;
border-width: 1px;
border-color: white;
}
.prompt {
background-color: #333333 !important;
color: white !important;
border-radius: 3px !important;
}
.searchicon {
color: white !important;
}
.ui.progress .bar > .progress {
right: auto;
left: .5em;
color: black !important;
}
.ui.disabled.progress.notification_progress {
opacity: unset !important;
}
div.disabled {
pointer-events: none;
}
button.disabled {
pointer-events: none;
}
@media only screen and (max-width: 1024px) {
.logo {
width: 36px;
height: auto;
}
}
</style>
</head>
<body>
{% set throttled_providers_count = settings.general.throtteled_providers|length %}
<div id="divmenu" class="ui container">
<div class="ui grid">
<div class="three wide column">
<div class="ui compact segment menu_segment">
<a href="{{ url_for('redirect_root') }}"><img class="logo"
src="{{ url_for('static',filename='logo128.png') }}"></a>
</div>
</div>
<div class="ten wide right aligned compact column">
<div id="button_menu" class="ui center aligned segment menu_segment" hidden="hidden">
<div class="ui inverted compact borderless labeled icon massive menu menu_segment">
{% if settings.general.getboolean('use_sonarr') %}
<a class="item" href="{{ url_for('series') }}">
<i class="play icon"></i>
Series
</a>
{% endif %}
{% if settings.general.getboolean('use_radarr') %}
<a class="item" href="{{ url_for('movies') }}">
<i class="film icon"></i>
Movies
</a>
{% endif %}
<a class="item" href="{{ url_for('history') }}">
<i class="wait icon"></i>
History
</a>
<a class="item" href="{{ url_for('wanted') }}">
<i class="warning sign icon">
{% if settings.general.getboolean('use_sonarr') and wanted_series > 0 %}
<div id="wanted_series" class="floating ui tiny yellow label"
style="left:90% !important;top:0.5em !important;">
{{ wanted_series }}
</div>
{% endif %}
{% if settings.general.getboolean('use_radarr') and wanted_movies > 0 %}
<div id="wanted_movies" class="floating ui tiny green label"
style="left:90% !important;top:3em !important;">
{{ wanted_movies }}
</div>
{% endif %}
</i>
Wanted
</a>
<a class="item" href="{{ url_for('_settings') }}">
<i class="settings icon"></i>
Settings
</a>
<a class="item" href="{{ url_for('system') }}">
<i class="laptop icon">
{% if throttled_providers_count %}
<div class="floating ui tiny yellow label"
style="left:90% !important;top:0.5em !important;">
{{ throttled_providers_count }}
</div>
{% endif %}
</i>
System
</a>
<a id="donate" class="item" href="https://beerpay.io/morpheus65535/bazarr">
<i class="red heart icon"></i>
Donate
</a>
</div>
</div>
<div class="ui center aligned segment menu_segment">
<div class="ui grid">
<div id="search_column" class="centered column">
<div class="ui fluid search">
<div class="ui left icon fluid input">
<input class="prompt" type="text" placeholder="Search in your library">
<i class="searchicon search icon"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="three wide right aligned column">
<div id="dropdown_menu" class="ui segment menu_segment" hidden="hidden">
<div id="icon_menu" class="ui compact tiny icon menu">
<div id="dropdown_menu_button" class="ui floating right dropdown item">
<i class="inverted bars icon"></i>
<div class="ui menu">
{% if settings.general.getboolean('use_sonarr') %}
<a class="item" href="{{ url_for('series') }}">
<i class="play icon"></i>
Series
</a>
{% endif %}
{% if settings.general.getboolean('use_radarr') %}
<a class="item" href="{{ url_for('movies') }}">
<i class="film icon"></i>
Movies
</a>
{% endif %}
<a class="item" href="{{ url_for('history') }}">
<i class="wait icon"></i>
History
</a>
<a class="item" href="{{ url_for('wanted') }}">
<i class="warning sign icon"></i>
<span style="margin-right: 1em;">Wanted</span>
{% if settings.general.getboolean('use_sonarr') and wanted_series > 0 %}
<div class="ui tiny yellow label">
{{ wanted_series }}
</div>
{% endif %}
{% if settings.general.getboolean('use_radarr') and wanted_movies > 0 %}
<div class="ui tiny green label">
{{ wanted_movies }}
</div>
{% endif %}
</a>
<a class="item" href="{{ url_for('_settings') }}">
<i class="settings icon"></i>
Settings
</a>
<a class="item" href="{{ url_for('system') }}">
<i class="laptop icon">
{% if throttled_providers_count %}
<div class="floating ui tiny yellow label"
style="left:90% !important;top:0.5em !important;">
{{ throttled_providers_count }}
</div>
{% endif %}
</i>
System
</a>
<a id="donate" class="item" href="https://beerpay.io/morpheus65535/bazarr">
<i class="red heart icon"></i>
Donate
</a>
</div>
</div>
</div>
</div>
</div>
</div>
{% if update_required == '1' and restart_required == '1' %}
<div class='ui center aligned grid'>
<div class='fifteen wide column'>
<div class="ui red message">Bazarr Needs To Be Restarted To Apply The Last Update & Changes To General
Settings. Click <a href=# id="restart_link">Here</a> To Restart.
</div>
</div>
</div>
{% elif updaterequired == '1' %}
<div class='ui center aligned grid'>
<div class='fifteen wide column'>
<div class="ui red message">Bazarr Needs To Be Restarted To Apply Changes To The Last Update. Click <a
href=# id="restart_link">Here</a> To Restart.
</div>
</div>
</div>
{% elif restart_required == '1' %}
<div class='ui center aligned grid'>
<div class='fifteen wide column'>
<div class="ui red message">Bazarr Needs To Be Restarted To Apply Changes To General Settings. Click <a
href=# id="restart_link">Here</a> To Restart.
</div>
</div>
</div>
{% end %}
</div>
</body>
</html>
<script>
$('.ui.dropdown').dropdown();
$('.ui.search')
.search({
apiSettings: {
url: '{{base_url}}search_json/{query}',
onResponse: function (results) {
const response = {
results: []
};
$.each(results.items, function (index, item) {
response.results.push({
title: item.name,
url: item.url
});
});
return response;
}
},
minCharacters: 2
})
;
if (window.location.href.indexOf("episodes") > -1) {
$('.menu_segment').css('background', 'rgba(0, 0, 0, 0.8)');
$('.menu_segment').css('border-color', '#000000');
$('#divmenu').css('background', 'rgba(0, 0, 0, 0.8)');
$('#divmenu').css('box-shadow', '0 0 5px 5px #000000');
} else if (window.location.href.indexOf("movie/") > -1) {
$('.menu_segment').css('background', 'rgba(0, 0, 0, 0.9)');
$('.menu_segment').css('border-color', '#000000');
$('#divmenu').css('background', 'rgba(0, 0, 0, 0.8)');
$('#divmenu').css('box-shadow', '0 0 5px 5px #000000');
} else {
$('.menu_segment').css('background', '#272727');
$('.menu_segment').css('border-color', '#272727');
$('#divmenu').css('background', '#272727');
}
$('#restart_link').on('click', function () {
$('#loader_text').text("Bazarr is restarting. Please Wait...");
$.ajax({
url: {{url_for('restart')}},
async: true,
error: (function () {
setTimeout(function () {
setInterval(ping, 2000);
}, 8000);
})
})
});
function ping() {
$.ajax({
url: "{{url_for('redirect_root')}}",
success: function (result) {
window.location.href = "{{url_for('redirect_root')}}";
}
});
}
$(window).on('resize', function () {
if ($(window).width() < 1024) {
$('#button_menu').hide();
$('#dropdown_menu').show();
$('#search_column').removeClass('ten wide');
} else {
$('#dropdown_menu').hide();
$('#button_menu').show();
$('#search_column').addClass('ten wide');
}
}).resize();
var url_notifications = location.protocol + "//" + window.location.host + "{{base_url}}notifications";
var notificationTimeout;
var timeout;
var killer;
var item = {};
var length = {};
function doNotificationsAjax() {
$.ajax({
url: "{{url_for('notifications')}}",
success: function (data) {
if (data !== "") {
data = JSON.parse(data);
var msg = data[0];
var type = data[1];
var duration = data[2];
var button = data[3];
var queue = data[4];
var item = data[5];
var length = data[6];
if (length === 0) {
var message = msg;
} else {
var message = msg + '<p><div class="ui disabled progress notification_progress" data-value=' + item + ' data-total=' + length + ' style="margin-bottom: -0.25em"><div class="bar"><div class="progress"></div></div></div>'
}
if (duration === 'temporary') {
timeout = 3000;
killer = queue;
} else if (duration === 'long') {
timeout = 15000;
killer = queue;
} else {
timeout = false;
killer = false;
}
if (button === 'refresh') {
button = [Noty.button('Refresh', 'ui tiny primary button', function () {
window.location.reload()
})];
} else if (button === 'restart') {
// to be completed
button = [Noty.button('Restart', 'ui tiny primary button', function () {
alert('Restart Not Implemented Yet!')
})];
} else {
button = [];
}
new Noty({
text: message,
progressBar: false,
animation: {
open: null,
close: null
},
type: type,
layout: 'bottomRight',
theme: 'semanticui',
queue: queue,
timeout: timeout,
killer: killer,
buttons: button,
force: false
}).show();
$('.notification_progress').progress({
duration: 0,
autoSuccess: false,
label: 'ratio',
text: {
ratio: '{value} / {total}'
}
});
}
},
complete: function (data) {
// Schedule the next
if (data.responseText !== "") {
notificationTimeout = setTimeout(doNotificationsAjax, 100);
} else {
notificationTimeout = setTimeout(doNotificationsAjax, 5000);
}
},
error: function () {
notificationTimeout = setTimeout(doNotificationsAjax, 5000);
}
});
}
notificationTimeout = setTimeout(doNotificationsAjax, 1000);
var tasksTimeout;
function doTasksAjax() {
$.ajax({
url: "{{url_for('running_tasks_list')}}",
dataType: 'json',
success: function (data) {
$('#tasks > tbody > tr').each(function () {
if ($.inArray($(this).attr('id'), data['tasks']) > -1) {
$(this).find('td:last').find('div:first').addClass('disabled');
$(this).find('td:last').find('div:first').find('i:first').addClass('loading');
} else {
$(this).find('td:last').find('div:first').removeClass('disabled');
$(this).find('td:last').find('div:first').find('i:first').removeClass('loading');
}
});
if ($.inArray('wanted_search_missing_subtitles', data['tasks']) > -1) {
$('#wanted_search_missing_subtitles').addClass('disabled');
$('#wanted_search_missing_subtitles_movies').addClass('disabled');
$('#wanted_search_missing_subtitles').find('i:first').addClass('loading');
$('#wanted_search_missing_subtitles_movies').find('i:first').addClass('loading');
} else {
$('#wanted_search_missing_subtitles').removeClass('disabled');
$('#wanted_search_missing_subtitles_movies').removeClass('disabled');
$('#wanted_search_missing_subtitles').find('i:first').removeClass('loading');
$('#wanted_search_missing_subtitles_movies').find('i:first').removeClass('loading');
}
{% if 'no' in locals %}
if ($.inArray('search_missing_subtitles_{{no}}', data['tasks']) > -1) {
$('#search_missing_subtitles').addClass('disabled');
$('#search_missing_subtitles').find('i:first').addClass('loading');
} else {
$('#search_missing_subtitles').removeClass('disabled');
$('#search_missing_subtitles').find('i:first').removeClass('loading');
}
if ($.inArray('search_missing_subtitles_movie_{{no}}', data['tasks']) > -1) {
$('#search_missing_subtitles_movie').addClass('disabled');
$('#search_missing_subtitles_movie').find('i:first').addClass('loading');
} else {
$('#search_missing_subtitles_movie').removeClass('disabled');
$('#search_missing_subtitles_movie').find('i:first').removeClass('loading');
}
{% endif %}
},
complete: function (data) {
// Schedule the next
tasksTimeout = setTimeout(doTasksAjax, 5000);
}
});
}
tasksTimeout = setTimeout(doTasksAjax, 500);
$(window).bind('beforeunload', function () {
clearTimeout(tasksTimeout);
clearTimeout(notificationTimeout);
});
</script>

@ -341,7 +341,7 @@
radarrId: movieDetails['radarrId'],
tmdbid: movieDetails['tmdbId']
};
var cell = $(this).closest('td');
var cell = $(this).parent();
$.ajax({
url: "{{ url_for('api.moviesubtitlesdelete') }}",
type: "DELETE",
@ -361,12 +361,11 @@
sceneName: movieDetails['sceneName'],
language: $(this).attr("data-language"),
hi: movieDetails['hearing_impaired'],
forced: movieDetails['forced'],
forced:$(this).attr("data-forced"),
radarrId: movieDetails['radarrId'],
title: movieDetails['title']
};
var button = $(this).closest('button' +
'');
var button = $(this).closest('button' + '');
$.ajax({
url: "{{ url_for('api.moviesubtitlesdownload') }}",
type: "POST",
@ -500,7 +499,7 @@
radarrId: movieDetails['radarrId'],
title: movieDetails['title']
};
var cell = $(this).closest('td');
var cell = $(this).parent();
$.ajax({
url: "{{ url_for('api.moviesubtitlesmanualdownload') }}",
type: "POST",
@ -632,8 +631,8 @@
events.on('event', function(event) {
var event_json = JSON.parse(event);
if (event_json.movie === {{id}}) {
if (event_json.type === 'movie') {
if (event_json.type === 'movie') {
if (event_json.movie === {{id}}) {
movieDetailsRefresh();
}
}
@ -725,7 +724,11 @@
}
function missingAppendFunc(value) {
missing_languages += '<button class="get_subtitle btn btn-secondary btn-sm" type="button" data-toggle="tooltip" data-placement="right" data-original-title="' + value.name + '" data-language="' + value.code3 + '">' + value.code2 + ' <i class="fas fa-search"></i></button> ';
if (value.forced) {
missing_languages += '<button class="get_subtitle btn btn-secondary btn-sm" type="button" data-toggle="tooltip" data-placement="right" data-original-title="' + value.name + '" data-language="' + value.code3 + '" data-forced=' + value.forced + '>' + value.code2 + ':forced <i class="fas fa-search"></i></button> ';
} else {
missing_languages += '<button class="get_subtitle btn btn-secondary btn-sm" type="button" data-toggle="tooltip" data-placement="right" data-original-title="' + value.name + '" data-language="' + value.code3 + '" data-forced=' + value.forced + '>' + value.code2 + ' <i class="fas fa-search"></i></button> ';
}
}
$('#missingSubtitles').html(missing_languages);
@ -753,6 +756,7 @@
"paging": false,
"info": false,
"lengthChange": false,
"responsive": true,
"data" : movieDetails['subtitles'],
"columns" : [
{ "data" : null,

@ -122,7 +122,7 @@
url: "{{ url_for('api.movies') }}?radarrid=" + event_json.movie,
success: function (data) {
if (data.data.length) {
$('#movies').DataTable().row(rowId).data(data.data[0]);
$('#movies').DataTable().row(rowId).data(data.data[0]).draw('page');
$('[data-toggle="tooltip"]').tooltip({html: true});
}
}

@ -83,7 +83,7 @@
url: "{{ url_for('api.movies') }}?radarrid=" + event_json.movie,
success: function (data) {
if (data.data.length) {
$('#movies').DataTable().row(rowId).data(data.data[0]);
$('#movies').DataTable().row(rowId).data(data.data[0]).draw('page');
$('[data-toggle="tooltip"]').tooltip({html: true});
}
}
@ -108,6 +108,10 @@
var table = $('#movies').DataTable({
"processing": true,
"serverSide": true,
language: {
zeroRecords: 'No Movies Found',
processing: "Loading Movies..."
},
"searching": false,
"ordering": false,
"lengthChange": true,

@ -123,7 +123,7 @@
url: "{{ url_for('api.series') }}?seriesid=" + event_json.series,
success: function (data) {
if (data.data.length) {
$('#series').DataTable().row(rowId).data(data.data[0]);
$('#series').DataTable().row(rowId).data(data.data[0]).draw('page');
$('[data-toggle="tooltip"]').tooltip({html: true});
}
}
@ -142,6 +142,10 @@
var table = $('#series').DataTable({
"processing": true,
"serverSide": true,
language: {
zeroRecords: 'No Series Found',
processing: "Loading Series..."
},
"searching": false,
"ordering": false,
"lengthChange": false,

@ -83,7 +83,7 @@
url: "{{ url_for('api.series') }}?seriesid=" + event_json.series,
success: function (data) {
if (data.data.length) {
$('#series').DataTable().row(rowId).data(data.data[0]);
$('#series').DataTable().row(rowId).data(data.data[0]).draw('page');
$('[data-toggle="tooltip"]').tooltip({html: true});
}
}
@ -108,6 +108,10 @@
var table = $('#series').DataTable({
"processing": true,
"serverSide": true,
language: {
zeroRecords: 'No Series Found',
processing: "Loading Series..."
},
"searching": false,
"ordering": false,
"lengthChange": true,

@ -50,7 +50,6 @@
<div id='loader' class="ui page dimmer">
<div id='loader_text' class="ui indeterminate text loader">Loading...</div>
</div>
{% include('menu.html') %}
<div id="fondblanc" class="ui container">
<div class="ui basic icon buttons" style="float: right;">

@ -1,161 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<script src="{{base_url}}static/jquery/jquery-latest.min.js"></script>
<script src="{{base_url}}static/semantic/semantic.min.js"></script>
<script src="{{base_url}}static/jquery/tablesort.js"></script>
<link rel="stylesheet" href="{{base_url}}static/semantic/semantic.min.css">
<link rel="apple-touch-icon" sizes="120x120" href="{{base_url}}static/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="{{base_url}}static/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="{{base_url}}static/favicon-16x16.png">
<link rel="manifest" href="{{base_url}}static/manifest.json">
<link rel="mask-icon" href="{{base_url}}static/safari-pinned-tab.svg" color="#5bbad5">
<link rel="shortcut icon" href="{{base_url}}static/favicon.ico">
<meta name="msapplication-config" content="{{base_url}}static/browserconfig.xml">
<meta name="theme-color" content="#ffffff">
<title>Wanted - Bazarr</title>
<style>
body {
background-color: #272727;
}
#fondblanc {
background-color: #ffffff;
border-radius: 0;
box-shadow: 0 0 5px 5px #ffffff;
margin-top: 32px;
margin-bottom: 3em;
padding: 1em;
}
.fast.backward, .backward, .forward, .fast.forward {
cursor: pointer;
}
.fast.backward, .backward, .forward, .fast.forward { pointer-events: auto; }
.fast.backward.disabled, .backward.disabled, .forward.disabled, .fast.forward.disabled { pointer-events: none; }
.ui.tabular.menu > .disabled.item {
opacity: 0.45 !important;
pointer-events: none !important;
}
</style>
</head>
<body>
% from get_args import args
% import os
% from database import database
% import operator
% from config import settings
% from functools import reduce
%if settings.sonarr.getboolean('only_monitored'):
% episodes_missing_subtitles_clause = " AND monitored='True'"
%else:
% episodes_missing_subtitles_clause = ""
%end
%if settings.radarr.getboolean('only_monitored'):
% episodes_missing_subtitles_clause_movie = " AND monitored='True'"
%else:
% episodes_missing_subtitles_clause_movie = ""
%end
% wanted_series = database.execute("SELECT COUNT(*) as count FROM table_episodes WHERE missing_subtitles != '[]'" + episodes_missing_subtitles_clause, only_one=True)['count']
% wanted_movies = database.execute("SELECT COUNT(*) as count FROM table_movies WHERE missing_subtitles != '[]'" + episodes_missing_subtitles_clause_movie, only_one=True)['count']
<div id='loader' class="ui page dimmer">
<div id="loader_text" class="ui indeterminate text loader">Loading...</div>
</div>
% include('menu.tpl')
<div id="fondblanc" class="ui container">
<div class="ui top attached tabular menu">
<a id="series_tab" class="tabs item active" data-enabled="{{settings.general.getboolean('use_sonarr')}}" data-tab="series">Series
%if settings.general.getboolean('use_sonarr'):
<div class="ui tiny yellow label">
{{wanted_series}}
</div>
%end
</a>
<a id="movies_tab" class="tabs item" data-enabled="{{settings.general.getboolean('use_radarr')}}" data-tab="movies">Movies
%if settings.general.getboolean('use_radarr'):
<div class="ui tiny green label">
{{wanted_movies}}
</div>
%end
</a>
</div>
<div class="ui bottom attached tab segment" data-tab="series">
<div class="content">
<div id="content_series"></div>
</div>
</div>
<div class="ui bottom attached tab segment" data-tab="movies">
<div class="content">
<div id="content_movies"></div>
</div>
</div>
</div>
% include('footer.tpl')
</body>
</html>
<script>
$('.menu .item')
.tab()
;
$('#series_tab').on('click', function() {
loadURLseries(1);
});
$('#movies_tab').on('click', function() {
loadURLmovies(1);
});
function loadURLseries(page) {
$.ajax({
url: "{{base_url}}wantedseries?page=" + page,
beforeSend: function() { $('#loader').addClass('active'); },
complete: function() { $('#loader').removeClass('active'); },
cache: false
}).done(function(data) {
$("#content_series").html(data);
});
}
function loadURLmovies(page) {
$.ajax({
url: "{{base_url}}wantedmovies?page=" + page,
beforeSend: function() { $('#loader').addClass('active'); },
complete: function() { $('#loader').removeClass('active'); },
cache: false
}).done(function(data) {
$("#content_movies").html(data);
});
}
$('a:not(.tabs), button:not(.cancel, #download_log)').on('click', function(){
$('#loader').addClass('active');
});
if ($('#series_tab').data("enabled") === "True") {
$("#series_tab").removeClass('disabled');
} else {
$("#series_tab").addClass('disabled');
}
if ($('#movies_tab').data("enabled") === "True") {
$("#movies_tab").removeClass('disabled');
} else {
$("#movies_tab").addClass('disabled');
}
if ($('#series_tab').data("enabled") === "True") {
$( "#series_tab" ).trigger( "click" );
}
if ($('#series_tab').data("enabled") === "False" && $('#movies_tab').data("enabled") === "True") {
$( "#movies_tab" ).trigger( "click" );
}
</script>

@ -1,193 +1,59 @@
<!DOCTYPE html>
<html lang="en">
<head>
<script src="{{base_url}}static/jquery/jquery-latest.min.js"></script>
<script src="{{base_url}}static/semantic/semantic.min.js"></script>
<script src="{{base_url}}static/jquery/tablesort.js"></script>
<link rel="stylesheet" href="{{base_url}}static/semantic/semantic.min.css">
<link rel="apple-touch-icon" sizes="120x120" href="{{base_url}}static/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="{{base_url}}static/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="{{base_url}}static/favicon-16x16.png">
<link rel="manifest" href="{{base_url}}static/manifest.json">
<link rel="mask-icon" href="{{base_url}}static/safari-pinned-tab.svg" color="#5bbad5">
<link rel="shortcut icon" href="{{base_url}}static/favicon.ico">
<meta name="msapplication-config" content="{{base_url}}static/browserconfig.xml">
<meta name="theme-color" content="#ffffff">
<title>Wanted - Bazarr</title>
<style>
body {
background-color: #272727;
}
#tablehistory {
padding-top: 2em;
}
.fast.backward, .backward, .forward, .fast.forward {
cursor: pointer;
}
.fast.backward, .backward, .forward, .fast.forward { pointer-events: auto; }
.fast.backward.disabled, .backward.disabled, .forward.disabled, .fast.forward.disabled { pointer-events: none; }
</style>
</head>
<body>
%import ast
%from get_languages import *
<div id='loader' class="ui page dimmer">
<div id="loader_text" class="ui indeterminate text loader">Loading...</div>
</div>
{% extends '_main.html' %}
<div class="ui container">
<div class="ui right floated basic buttons">
<button id="wanted_search_missing_subtitles_movies" class="ui button"><i class="download icon"></i>Download wanted subtitles</button>
</div>
<table id="tablehistory" class="ui very basic selectable table">
<thead>
<tr>
<th>Movies</th>
<th>Missing Subtitle(s)</th>
</tr>
</thead>
<tbody>
%import time
%import pretty
%if len(rows) == 0:
<tr>
<td colspan="2">No Missing Subtitles.</td>
</tr>
%end
%for row in rows:
<tr class="selectable">
<td><a href="{{base_url}}movie/{{row['radarrId']}}">{{row['title']}}</a></td>
<td>
<%
missing_languages = ast.literal_eval(row['missing_subtitles'])
if missing_languages is not None:
from get_subtitle import search_active
from config import settings
for language in missing_languages:
if language.endswith(':forced'):
forced = True
else:
forced = False
end
if row['failedAttempts'] is not None and settings.general.getboolean('adaptive_searching') and language in row['failedAttempts']:
for lang in ast.literal_eval(row['failedAttempts']):
if language in lang:
active = search_active(lang[1])
if active:
%>
<a data-moviePath="{{row['path']}}" data-sceneName="{{row['sceneName']}}" data-language="{{alpha3_from_alpha2(str(language.split(':')[0]))}}" data-hi="{{row['hearing_impaired']}}" data-forced="{{forced}}" data-radarrId={{row['radarrId']}} data-title="{{row['title'].replace("'", "\'")}}" class="get_subtitle ui tiny label">
{{language}}
<i style="margin-left:3px; margin-right:0" class="search icon"></i>
</a>
%else:
<a data-tooltip="Automatic Searching Delayed (Adaptive Search)" data-position="top right" data-inverted="" data-moviePath="{{row['path']}}" data-sceneName="{{row['sceneName']}}" data-language="{{alpha3_from_alpha2(str(language.split(':')[0]))}}" data-hi="{{row['hearing_impaired']}}" data-forced="{{forced}}" data-radarrId={{row['radarrId']}} data-title="{{row['title'].replace("'", "\'")}}" class="get_subtitle ui tiny label">
{{language}}
<i style="margin-left:3px; margin-right:0" class="search red icon"></i>
</a>
%end
%end
%end
%else:
<a data-moviePath="{{row['path']}}" data-sceneName="{{row['sceneName']}}" data-language="{{alpha3_from_alpha2(str(language.split(':')[0]))}}" data-hi="{{row['hearing_impaired']}}" data-forced="{{forced}}" data-radarrId="{{row['radarrId']}}" data-title="{{row['title'].replace("'", "\'")}}" class="get_subtitle ui tiny label">
{{language}}
<i style="margin-left:3px; margin-right:0" class="search icon"></i>
</a>
%end
{% block title %}Wanted (Movies) - Bazarr{% endblock %}
%end
%end
</td>
</tr>
%end
</tbody>
</table>
%try: page_size
%except NameError: page_size = "25"
%end
%if page_size != -1:
<div class="ui grid">
<div class="three column row">
<div class="column"></div>
<div class="center aligned column">
<i class="\\
%if page == "1":
disabled\\
%end
fast backward icon"></i>
<i class="\\
%if page == "1":
disabled\\
%end
backward icon"></i>
{{page}} / {{max_page}}
<i class="\\
%if int(page) >= int(max_page):
disabled\\
%end
forward icon"></i>
<i class="\\
%if int(page) >= int(max_page):
disabled\\
%end
fast forward icon"></i>
</div>
<div class="right floated right aligned column">Total Records: {{missing_count}}</div>
</div>
</div>
%end
</div>
</body>
</html>
{% block bcleft %}
{% endblock bcleft %}
<script>
$('a, button:not(#wanted_search_missing_subtitles_movies)').on('click', function(){
$('#loader').addClass('active');
});
{% block bcright %}
$('.fast.backward').on('click', function(){
loadURLmovies(1);
});
$('.backward:not(.fast)').on('click', function(){
loadURLmovies({{int(page)-1}});
});
$('.forward:not(.fast)').on('click', function(){
loadURLmovies({{int(page)+1}});
});
$('.fast.forward').on('click', function(){
loadURLmovies({{int(max_page)}});
});
{% endblock bcright %}
$('#wanted_search_missing_subtitles_movies').on('click', function(){
$(this).addClass('disabled');
$(this).find('i:first').addClass('loading');
$.ajax({
url: '{{base_url}}wanted_search_missing_subtitles'
})
});
{% block body %}
<table id="wanted_movies" class="table table-striped" style="width:100%">
<thead>
<tr>
<th>Movies</th>
<th>Missing Subtitle(s)</th>
</tr>
</thead>
</table>
{% endblock body %}
$('.get_subtitle').on('click', function(){
const values = {
moviePath: $(this).attr("data-moviePath"),
sceneName: $(this).attr("data-sceneName"),
language: $(this).attr("data-language"),
hi: $(this).attr("data-hi"),
forced: $(this).attr("data-forced"),
radarrId: $(this).attr("data-radarrId"),
title: $(this).attr("data-title")
};
$('#loader_text').text("Downloading Subtitles...");
$('#loader').addClass('active');
$.ajax({
url: "{{base_url}}get_subtitle_movie",
type: "POST",
dataType: "json",
data: values
}).always(function () {
window.location.reload();
});
})
</script>
{% block tail %}
<script>
$(document).ready(function () {
var table = $('#wanted_movies').DataTable({
"processing": true,
"serverSide": true,
language: {
zeroRecords: 'No Missing Movies Subtitles',
processing: "Loading Missing Movies Subtitles..."
},
"searching": false,
"ordering": false,
"lengthChange": false,
"responsive": true,
"pageLength": {{ settings.general.page_size }},
"ajax": "{{ url_for('api.wantedmovies') }}",
"columns": [
{"data": null,
"render": function (data) {
return '<a href="' + "{{ url_for( 'movie', no='tempvalue' ) }}".replace("tempvalue", data.radarrId) + '">' + data.title + '</a>';
}
},
{"data": "missing_subtitles"}
]
});
events.on('event', function(event) {
var event_json = JSON.parse(event);
if (event_json.type === 'movie') {
$('#wanted_movies').DataTable().ajax.reload(resetPaging=false);
$('[data-toggle="tooltip"]').tooltip({html: true});
}
});
});
</script>
{% endblock tail %}

@ -1,201 +1,63 @@
<!DOCTYPE html>
<html lang="en">
<head>
<script src="{{base_url}}static/jquery/jquery-latest.min.js"></script>
<script src="{{base_url}}static/semantic/semantic.min.js"></script>
<script src="{{base_url}}static/jquery/tablesort.js"></script>
<link rel="stylesheet" href="{{base_url}}static/semantic/semantic.min.css">
<link rel="apple-touch-icon" sizes="120x120" href="{{base_url}}static/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="{{base_url}}static/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="{{base_url}}static/favicon-16x16.png">
<link rel="manifest" href="{{base_url}}static/manifest.json">
<link rel="mask-icon" href="{{base_url}}static/safari-pinned-tab.svg" color="#5bbad5">
<link rel="shortcut icon" href="{{base_url}}static/favicon.ico">
<meta name="msapplication-config" content="{{base_url}}static/browserconfig.xml">
<meta name="theme-color" content="#ffffff">
<title>Wanted - Bazarr</title>
<style>
body {
background-color: #272727;
}
#tablehistory {
padding-top: 2em;
}
.fast.backward, .backward, .forward, .fast.forward {
cursor: pointer;
}
.fast.backward, .backward, .forward, .fast.forward { pointer-events: auto; }
.fast.backward.disabled, .backward.disabled, .forward.disabled, .fast.forward.disabled { pointer-events: none; }
</style>
</head>
<body>
%import ast
%from get_languages import *
<div id='loader' class="ui page dimmer">
<div id="loader_text" class="ui indeterminate text loader">Loading...</div>
</div>
{% extends '_main.html' %}
<div class="ui container">
<div class="ui right floated basic buttons">
<button id="wanted_search_missing_subtitles" class="ui button"><i class="download icon"></i>Download wanted subtitles</button>
</div>
<table id="tablehistory" class="ui very basic selectable table">
<thead>
<tr>
<th>Series</th>
<th>Episode</th>
<th>Episode Title</th>
<th>Missing Subtitle(s)</th>
</tr>
</thead>
<tbody>
%import time
%import pretty
%if len(rows) == 0:
<tr>
<td colspan="4">No Missing Subtitles.</td>
</tr>
%end
%for row in rows:
<tr class="selectable">
<td><a href="{{base_url}}episodes/{{row['sonarrSeriesId']}}">{{row['seriesTitle']}}</a></td>
<td class="collapsing">
<%episode = str(row['episode_number']).split('x')%>
{{episode[0] + 'x' + episode[1].zfill(2)}}
</td>
<td>{{row['episodeTitle']}}</td>
<td>
<%
missing_languages = ast.literal_eval(row['missing_subtitles'])
if missing_languages is not None:
from get_subtitle import search_active
from config import settings
for language in missing_languages:
if language.endswith(':forced'):
forced = True
else:
forced = False
end
if row['failedAttempts'] is not None and settings.general.getboolean('adaptive_searching') and language in row['failedAttempts']:
for lang in ast.literal_eval(row['failedAttempts']):
if language in lang:
active = search_active(lang[1])
if active:
%>
<a data-episodePath="{{row['path']}}" data-sceneName="{{row['scene_name']}}" data-language="{{alpha3_from_alpha2(str(language.split(':')[0]))}}" data-hi="{{row['hearing_impaired']}}" data-forced="{{forced}}" data-sonarrSeriesId={{row['sonarrSeriesId']}} data-sonarrEpisodeId={{row['sonarrEpisodeId']}} data-title="{{row['seriesTitle'].replace("'", "\'")}}" class="get_subtitle ui tiny label">
{{language}}
<i style="margin-left:3px; margin-right:0" class="search icon"></i>
</a>
%else:
<a data-tooltip="Automatic Searching Delayed (Adaptive Search)" data-position="top right" data-inverted="" data-episodePath="{{row['path']}}" data-sceneName="{{row['scene_name']}}" data-language="{{alpha3_from_alpha2(str(language.split(':')[0]))}}" data-hi="{{row['hearing_impaired']}}" data-forced="{{forced}}" data-sonarrSeriesId={{row['sonarrSeriesId']}} data-sonarrEpisodeId={{row['sonarrEpisodeId']}} data-title="{{row['seriesTitle'].replace("'", "\'")}}" class="get_subtitle ui tiny label">
{{language}}
<i style="margin-left:3px; margin-right:0" class="search red icon"></i>
</a>
%end
%end
%end
%else:
<a data-episodePath="{{row['path']}}" data-sceneName="{{row['scene_name']}}" data-language="{{alpha3_from_alpha2(str(language.split(':')[0]))}}" data-hi="{{row['hearing_impaired']}}" data-forced="{{forced}}" data-sonarrSeriesId={{row['sonarrSeriesId']}} data-sonarrEpisodeId={{row['sonarrEpisodeId']}} data-title="{{row['seriesTitle'].replace("'", "\'")}}" class="get_subtitle ui tiny label">
{{language}}
<i style="margin-left:3px; margin-right:0" class="search icon"></i>
</a>
%end
{% block title %}Wanted (Series) - Bazarr{% endblock %}
%end
%end
</td>
</tr>
%end
</tbody>
</table>
%try: page_size
%except NameError: page_size = "25"
%end
%if page_size != -1:
<div class="ui grid">
<div class="three column row">
<div class="column"></div>
<div class="center aligned column">
<i class="\\
%if page == "1":
disabled\\
%end
fast backward icon"></i>
<i class="\\
%if page == "1":
disabled\\
%end
backward icon"></i>
{{page}} / {{max_page}}
<i class="\\
%if int(page) >= int(max_page):
disabled\\
%end
forward icon"></i>
<i class="\\
%if int(page) >= int(max_page):
disabled\\
%end
fast forward icon"></i>
</div>
<div class="right floated right aligned column">Total Records: {{missing_count}}</div>
</div>
</div>
%end
</div>
</body>
</html>
{% block bcleft %}
{% endblock bcleft %}
<script>
$('a, button:not(#wanted_search_missing_subtitles)').on('click', function(){
$('#loader').addClass('active');
});
{% block bcright %}
$('.fast.backward').on('click', function(){
loadURLseries(1);
});
$('.backward:not(.fast)').on('click', function(){
loadURLseries({{int(page)-1}});
});
$('.forward:not(.fast)').on('click', function(){
loadURLseries({{int(page)+1}});
});
$('.fast.forward').on('click', function(){
loadURLseries({{int(max_page)}});
});
{% endblock bcright %}
$('#wanted_search_missing_subtitles').on('click', function(){
$(this).addClass('disabled');
$(this).find('i:first').addClass('loading');
$.ajax({
url: '{{base_url}}wanted_search_missing_subtitles'
})
});
{% block body %}
<table id="wanted_series" class="table table-striped" style="width:100%">
<thead>
<tr>
<th>Series</th>
<th>Episode</th>
<th>Episode Title</th>
<th>Missing Subtitle(s)</th>
</tr>
</thead>
</table>
{% endblock body %}
$('.get_subtitle').on('click', function(){
const values = {
episodePath: $(this).attr("data-episodePath"),
sceneName: $(this).attr("data-sceneName"),
language: $(this).attr("data-language"),
hi: $(this).attr("data-hi"),
forced: $(this).attr("data-forced"),
sonarrSeriesId: $(this).attr("data-sonarrSeriesId"),
sonarrEpisodeId: $(this).attr("data-sonarrEpisodeId"),
title: $(this).attr("data-title")
};
$('#loader_text').text("Downloading Subtitles...");
$('#loader').addClass('active');
$.ajax({
url: "{{base_url}}get_subtitle",
type: "POST",
dataType: "json",
data: values
}).always(function () {
window.location.reload();
});
})
</script>
{% block tail %}
<script>
$(document).ready(function () {
var table = $('#wanted_series').DataTable({
"processing": true,
"serverSide": true,
language: {
zeroRecords: 'No Missing Series Subtitles',
processing: "Loading Missing Series Subtitles..."
},
"searching": false,
"ordering": false,
"lengthChange": false,
"responsive": true,
"pageLength": {{ settings.general.page_size }},
"ajax": "{{ url_for('api.wantedseries') }}",
"columns": [
{"data": null,
"render": function (data) {
return '<a href="' + "{{ url_for( 'episodes', no='tempvalue' ) }}".replace("tempvalue", data.sonarrSeriesId) + '">' + data.seriesTitle + '</a>';
}
},
{"data": "episode_number"},
{"data": "episodeTitle"},
{"data": "missing_subtitles"}
]
});
events.on('event', function(event) {
var event_json = JSON.parse(event);
if (event_json.type === 'episodes') {
$('#wanted_series').DataTable().ajax.reload(resetPaging=false);
$('[data-toggle="tooltip"]').tooltip({html: true});
}
});
});
</script>
{% endblock tail %}

Loading…
Cancel
Save