Merge branch 'development' into morpheus

# Conflicts:
#	bazarr/get_subtitle.py
#	bazarr/main.py
#	bazarr/utils.py
This commit is contained in:
Louis Vézina 2019-09-02 23:30:23 -04:00
commit 1b4e4e1495
10 changed files with 182 additions and 42 deletions

52
bazarr/analytics.py Normal file
View File

@ -0,0 +1,52 @@
# coding=utf-8
import cPickle as pickle
import base64
import random
import platform
import os
from pyga.requests import Event, Page, Tracker, Session, Visitor, Config
from pyga.entities import CustomVariable
from get_args import args
from config import settings
from utils import get_sonarr_version, get_radarr_version
sonarr_version = get_sonarr_version()
radarr_version = get_radarr_version()
def track_event(category=None, action=None, label=None):
if not settings.analytics.getboolean('enabled'):
print "no analytics"
return
anonymousConfig = Config()
anonymousConfig.anonimize_ip_address = True
tracker = Tracker('UA-138214134-3', 'none', conf=anonymousConfig)
try:
visitor = pickle.loads(base64.b64decode(settings.analytics.visitor))
except:
visitor = Visitor()
unique_id = long(random.getrandbits(32))
visitor.unique_id = unique_id
session = Session()
event = Event(category=category, action=action, label=label, value=1)
path = u"/" + u"/".join([category, action, label])
page = Page(path.lower())
tracker.add_custom_variable(CustomVariable(index=1, name='BazarrVersion', value=os.environ["BAZARR_VERSION"], scope=1))
tracker.add_custom_variable(CustomVariable(index=2, name='PythonVersion', value=platform.python_version(), scope=1))
tracker.add_custom_variable(CustomVariable(index=3, name='SonarrVersion', value=sonarr_version, scope=1))
tracker.add_custom_variable(CustomVariable(index=4, name='RadarrVersion', value=radarr_version, scope=1))
tracker.add_custom_variable(CustomVariable(index=5, name='OSVersion', value=platform.platform(), scope=1))
tracker.track_event(event, session, visitor)
tracker.track_pageview(page, session, visitor)
settings.analytics.visitor = base64.b64encode(pickle.dumps(visitor))
with open(os.path.join(args.config_dir, 'config', 'config.ini'), 'w+') as handle:
settings.write(handle)

View File

@ -122,6 +122,9 @@ defaults = {
},
'betaseries': {
'token': ''
},
'analytics': {
'enabled': 'True'
}
}

View File

@ -36,6 +36,8 @@ from pyprobe.pyprobe import VideoFileParser
from database import TableShows, TableEpisodes, TableMovies, TableHistory, TableHistoryMovie
from peewee import fn, JOIN
from analytics import track_event
def get_video(path, title, sceneName, use_scenename, providers=None, media_type="movie"):
"""
@ -263,7 +265,9 @@ def download_subtitle(path, language, hi, forced, providers, providers_auth, sce
reversed_path = path_replace_reverse(path)
else:
reversed_path = path_replace_reverse_movie(path)
track_event(category=downloaded_provider, action=action, label=downloaded_language)
return message, reversed_path, downloaded_language_code2, downloaded_provider, subtitle.score, subtitle.language.forced
if not saved_any:
@ -480,7 +484,9 @@ def manual_download_subtitle(path, language, hi, forced, subtitle, provider, pro
reversed_path = path_replace_reverse(path)
else:
reversed_path = path_replace_reverse_movie(path)
track_event(category=downloaded_provider, action="downloaded", label=downloaded_language)
return message, reversed_path, downloaded_language_code2, downloaded_provider, subtitle.score, subtitle.language.forced
else:
logging.error(

View File

@ -43,12 +43,13 @@ from get_languages import load_language_in_db, language_from_alpha3
from get_providers import get_providers, get_providers_auth, list_throttled_providers
from get_series import *
from get_episodes import *
from get_movies import *
from list_subtitles import store_subtitles, store_subtitles_movie, series_scan_subtitles, movies_scan_subtitles, \
list_missing_subtitles, list_missing_subtitles_movies
from get_subtitle import download_subtitle, series_download_subtitles, movies_download_subtitles, \
manual_search, manual_download_subtitle, manual_upload_subtitle
from utils import history_log, history_log_movie
from utils import history_log, history_log_movie, get_sonarr_version, get_radarr_version
from scheduler import *
from notifier import send_notifications, send_notifications_movie
from config import settings, url_sonarr, url_radarr, url_radarr_short, url_sonarr_short, base_url
@ -1277,7 +1278,12 @@ def historymovies():
days_to_upgrade_subs = settings.general.days_to_upgrade_subs
minimum_timestamp = ((datetime.now() - timedelta(days=int(days_to_upgrade_subs))) -
datetime(1970, 1, 1)).total_seconds()
if settings.radarr.getboolean('only_monitored'):
movies_monitored_only_query_string = ' AND table_movies.monitored = "True"'
else:
movies_monitored_only_query_string = ""
if settings.general.getboolean('upgrade_manual'):
query_actions = [1, 2, 3]
else:
@ -1489,6 +1495,11 @@ def save_settings():
settings_general_update_restart = 'False'
else:
settings_general_update_restart = 'True'
settings_analytics_enabled = request.forms.get('settings_analytics_enabled')
if settings_analytics_enabled is None:
settings_analytics_enabled = 'False'
else:
settings_analytics_enabled = 'True'
settings_general_single_language = request.forms.get('settings_general_single_language')
if settings_general_single_language is None:
settings_general_single_language = 'False'
@ -1578,6 +1589,7 @@ def save_settings():
settings.general.branch = text_type(settings_general_branch)
settings.general.auto_update = text_type(settings_general_automatic)
settings.general.update_restart = text_type(settings_general_update_restart)
settings.analytics.enabled = text_type(settings_analytics_enabled)
settings.general.single_language = text_type(settings_general_single_language)
settings.general.minimum_score = text_type(settings_general_minimum_score)
settings.general.use_scenename = text_type(settings_general_scenename)
@ -1976,25 +1988,9 @@ def system():
logging.exception(
'BAZARR cannot parse releases caching file: ' + os.path.join(args.config_dir, 'config', 'releases.txt'))
use_sonarr = settings.general.getboolean('use_sonarr')
apikey_sonarr = settings.sonarr.apikey
sv = url_sonarr + "/api/system/status?apikey=" + apikey_sonarr
sonarr_version = ''
if use_sonarr:
try:
sonarr_version = requests.get(sv, timeout=15, verify=False).json()['version']
except:
pass
sonarr_version = get_sonarr_version()
use_radarr = settings.general.getboolean('use_radarr')
apikey_radarr = settings.radarr.apikey
rv = url_radarr + "/api/system/status?apikey=" + apikey_radarr
radarr_version = ''
if use_radarr:
try:
radarr_version = requests.get(rv, timeout=15, verify=False).json()['version']
except:
pass
radarr_version = get_radarr_version()
page_size = int(settings.general.page_size)

View File

@ -5,9 +5,11 @@ import time
import platform
import sys
import logging
import requests
from whichcraft import which
from get_args import args
from config import settings, url_sonarr, url_radarr
from database import TableHistory, TableHistoryMovie
from subliminal import region as subliminal_cache_region
@ -91,4 +93,32 @@ def cache_maintenance():
# archive cache
for fn in glob.iglob(os.path.join(args.config_dir, "*.archive")):
remove_expired(fn, pack_cache_validity)
remove_expired(fn, pack_cache_validity)
def get_sonarr_version():
use_sonarr = settings.general.getboolean('use_sonarr')
apikey_sonarr = settings.sonarr.apikey
sv = url_sonarr + "/api/system/status?apikey=" + apikey_sonarr
sonarr_version = ''
if use_sonarr:
try:
sonarr_version = requests.get(sv, timeout=15, verify=False).json()['version']
except:
sonarr_version = ''
return sonarr_version
def get_radarr_version():
use_radarr = settings.general.getboolean('use_radarr')
apikey_radarr = settings.radarr.apikey
rv = url_radarr + "/api/system/status?apikey=" + apikey_radarr
radarr_version = ''
if use_radarr:
try:
radarr_version = requests.get(rv, timeout=15, verify=False).json()['version']
except:
radarr_version = ''
return radarr_version

View File

@ -2,9 +2,15 @@
from datetime import datetime
from operator import itemgetter
import six
from pyga import utils
from pyga import exceptions
try:
from urlparse import urlparse
from urllib import unquote_plus
except ImportError as e:
from urllib.parse import urlparse
from urllib.parse import unquote_plus
__author__ = "Arun KR (kra3) <the1.arun@gmail.com>"
__license__ = "Simplified BSD"
@ -95,7 +101,7 @@ class Campaign(object):
@staticmethod
def create_from_referrer(url):
obj = Campaign(Campaign.TYPE_REFERRAL)
parse_rslt = six.moves.urllib.parse.urlparse(url)
parse_rslt = urlparse(url)
obj.source = parse_rslt.netloc
obj.content = parse_rslt.path
return obj
@ -114,7 +120,7 @@ class Campaign(object):
key, val = param.split('=')
try:
setattr(self, self.UTMZ_PARAM_MAP[key], six.moves.urllib.parse.unquote_plus(val))
setattr(self, self.UTMZ_PARAM_MAP[key], unquote_plus(val))
except KeyError:
continue

View File

@ -5,11 +5,18 @@ import calendar
from math import floor
from pyga.entities import Campaign, CustomVariable, Event, Item, Page, Session, SocialInteraction, Transaction, Visitor
import pyga.utils as utils
import six
try:
from urllib import urlencode
from urllib2 import Request as urllib_request
from urllib2 import urlopen
except ImportError as e:
from urllib.parse import urlencode
from urllib.request import Request as urllib_request
from urllib.request import urlopen
__author__ = "Arun KR (kra3) <the1.arun@gmail.com>"
__author__ = "Arun KR (kra3) <the1.arun@gmail.com"
__license__ = "Simplified BSD"
__version__ = '2.5.1'
__version__ = '2.6.1'
logger = logging.getLogger(__name__)
@ -42,7 +49,7 @@ class GIFRequest(object):
def build_http_request(self):
params = self.build_parameters()
query_string = six.moves.urllib.parse.urlencode(params.get_parameters())
query_string = urlencode(params.get_parameters())
query_string = query_string.replace('+', '%20')
# Mimic Javascript's encodeURIComponent() encoding for the query
@ -61,7 +68,7 @@ class GIFRequest(object):
headers = {}
headers['Host'] = self.config.endpoint.split('/')[2]
headers['User-Agent'] = self.user_agent
headers['User-Agent'] = self.user_agent or ''
headers['X-Forwarded-For'] = self.x_forwarded_for and self.x_forwarded_for or ''
if use_post:
@ -72,7 +79,7 @@ class GIFRequest(object):
logger.debug(url)
if post:
logger.debug(post)
return six.moves.urllib.request.Request(url, post, headers)
return urllib_request(url, post, headers)
def build_parameters(self):
'''Marker implementation'''
@ -84,7 +91,7 @@ class GIFRequest(object):
# Do not actually send the request if endpoint host is set to null
if self.config.endpoint:
response = six.moves.urllib.request.urlopen(
response = urlopen(
request, timeout=self.config.request_timeout)
return response
@ -240,7 +247,7 @@ class Request(GIFRequest):
'utmcct': campaign.content,
}
for k, v in param_map.iteritems():
for k, v in param_map.items():
if v:
# Only spaces and pluses get escaped in gaforflash and ga.js, so we do the same
params._utmz = '%s%s=%s%s' % (params._utmz, k,
@ -988,7 +995,7 @@ class X10(object):
except KeyError:
return char
return u''.join(map(_translate, value)).encode('utf-8', 'ignore')
return ''.join(map(_translate, str(value)))
def __render_data_type(self, data):
'''Given a data array for a certain type, render its string encoding.'''
@ -1032,7 +1039,7 @@ class X10(object):
def render_url_string(self):
result = ''
for project_id, project in self.project_data.iteritems():
for project_id, project in self.project_data.items():
result = '%s%s%s' % (
result, project_id, self.__render_project(project))

View File

@ -1,12 +1,21 @@
# -*- coding: utf-8 -*-
import logging
from __future__ import unicode_literals
from random import randint
import re
import six
import os
import sys
from datetime import datetime
try:
from urllib import quote
except ImportError as e:
from urllib.parse import quote
if sys.version_info < (3,):
text_type = unicode
else:
text_type = str
__author__ = "Arun KR (kra3) <the1.arun@gmail.com>"
__license__ = "Simplified BSD"
@ -60,7 +69,7 @@ def anonymize_ip(ip):
def encode_uri_components(value):
'''Mimics Javascript's encodeURIComponent() function for consistency with the GA Javascript client.'''
return convert_to_uri_component_encoding(six.moves.urllib.parse.quote(value))
return convert_to_uri_component_encoding(quote(value))
def convert_to_uri_component_encoding(value):
return value.replace('%21', '!').replace('%2A', '*').replace('%27', "'").replace('%28', '(').replace('%29', ')')
@ -107,7 +116,7 @@ def stringify(s, stype=None, fn=None):
# To do str(s). But, str() can fail on unicode. So, use .encode instead
if not stype or (stype == type(s)):
try:
return six.text_type(s)
return text_type(s)
#return s.encode('ascii', 'replace')
except AttributeError:
return str(s)

View File

@ -16,6 +16,7 @@ langdetect=1.0.7
peewee=3.9.6
py-pretty=1
pycountry=18.2.23
pyga=2.6.1
pyprobe=0.1.2 <-- modified version: do not update!!!
pysrt=1.1.1
pytz=2018.4

View File

@ -666,6 +666,30 @@
</div>
</div>
<div class="ui dividing header">Analytics</div>
<div class="twelve wide column">
<div class="ui grid">
<div class="middle aligned row">
<div class="right aligned four wide column">
<label>Enable</label>
</div>
<div class="one wide column">
<div id="settings_analytics_enabled" class="ui toggle checkbox" data-analytics={{settings.analytics.getboolean('enabled')}}>
<input name="settings_analytics_enabled" type="checkbox">
<label></label>
</div>
</div>
<div class="collapsed column">
<div class="collapsed center aligned column">
<div class="ui basic icon" data-tooltip="Send anonymous usage information, nothing that can identify you. This includes information on which providers you use, what languages you search for, Bazarr, Python, Sonarr, Radarr and OS version you are using. We will use this information to prioritize features and bug fixes. Please, keep this enabled as this is the only way we have to better understand how you use Bazarr." data-inverted="">
<i class="help circle large icon"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
% from get_args import args
@ -704,6 +728,12 @@
$("#settings_chmod_enabled").checkbox('uncheck');
}
if ($('#settings_analytics_enabled').data("analytics") === "True") {
$("#settings_analytics_enabled").checkbox('check');
} else {
$("#settings_analytics_enabled").checkbox('uncheck');
}
if ($('#settings_use_postprocessing').data("postprocessing") === "True") {
$("#settings_use_postprocessing").checkbox('check');
$("#settings_general_postprocessing_cmd_div").removeClass('disabled');