From 57fb73bfa039cd90e4896960a8483c4365ea2e82 Mon Sep 17 00:00:00 2001 From: p0psicles Date: Sat, 5 Feb 2022 10:41:55 +0100 Subject: [PATCH 1/4] Fix addic7ed subliminal subtitle provider * credits to nixx --- medusa/init/__init__.py | 11 +- medusa/subtitle_providers/addic7ed.py | 296 ++++++++++++++++++ .../slim/src/components/subtitle-search.vue | 4 +- themes/dark/assets/js/medusa-runtime.js | 2 +- themes/light/assets/js/medusa-runtime.js | 2 +- 5 files changed, 306 insertions(+), 9 deletions(-) create mode 100644 medusa/subtitle_providers/addic7ed.py diff --git a/medusa/init/__init__.py b/medusa/init/__init__.py index 96b6de2ea4..5a69d24b96 100644 --- a/medusa/init/__init__.py +++ b/medusa/init/__init__.py @@ -212,15 +212,16 @@ def _configure_subliminal(): basename = __name__.split('.')[0] # Unregister - # for name in ('legendastv = subliminal.providers.legendastv:LegendasTVProvider',): - # provider_manager.internal_extensions.remove(name) - # provider_manager.registered_extensions.append(name) - # provider_manager.unregister(name) + for name in ('addic7ed = subliminal.providers.addic7ed:Addic7edProvider',): + provider_manager.internal_extensions.remove(name) + provider_manager.registered_extensions.append(name) + provider_manager.unregister(name) # Register for name in ('napiprojekt = subliminal.providers.napiprojekt:NapiProjektProvider', 'subtitulamos = {basename}.subtitle_providers.subtitulamos:SubtitulamosProvider'.format(basename=basename), - 'wizdom = {basename}.subtitle_providers.wizdom:WizdomProvider'.format(basename=basename)): + 'wizdom = {basename}.subtitle_providers.wizdom:WizdomProvider'.format(basename=basename), + 'addic7ed = {basename}.subtitle_providers.addic7ed:Addic7edProvider'.format(basename=basename)): provider_manager.register(name) refiner_manager.register('release = {basename}.refiners.release:refine'.format(basename=basename)) diff --git a/medusa/subtitle_providers/addic7ed.py b/medusa/subtitle_providers/addic7ed.py new file mode 100644 index 0000000000..6923f4596c --- /dev/null +++ b/medusa/subtitle_providers/addic7ed.py @@ -0,0 +1,296 @@ +# -*- coding: utf-8 -*- +import logging +import re +import hashlib + +from babelfish import Language, language_converters +from guessit import guessit +from requests import Session + +from subliminal.providers import ParserBeautifulSoup, Provider +from subliminal.cache import SHOW_EXPIRATION_TIME, region +from subliminal.exceptions import AuthenticationError, ConfigurationError, DownloadLimitExceeded +from subliminal.matches import guess_matches +from subliminal.subtitle import Subtitle, fix_line_ending +from subliminal.utils import sanitize +from subliminal.video import Episode + +logger = logging.getLogger(__name__) + +# language_converters.register('addic7ed = subliminal.converters.addic7ed:Addic7edConverter') + +# Series cell matching regex +show_cells_re = re.compile(b'.*?', re.DOTALL) + +#: Series header parsing regex +series_year_re = re.compile(r'^(?P[ \w\'.:(),*&!?-]+?)(?: \((?P\d{4})\))?$') + + +class Addic7edSubtitle(Subtitle): + """Addic7ed Subtitle.""" + provider_name = 'addic7ed' + + def __init__(self, language, hearing_impaired, page_link, series, season, episode, title, year, version, + download_link): + super(Addic7edSubtitle, self).__init__(language, hearing_impaired=hearing_impaired, page_link=page_link) + self.series = series + self.season = season + self.episode = episode + self.title = title + self.year = year + self.version = version + self.download_link = download_link + + @property + def id(self): + return self.download_link + + @property + def info(self): + return '{series}{yopen}{year}{yclose} s{season:02d}e{episode:02d}{topen}{title}{tclose}{version}'.format( + series=self.series, season=self.season, episode=self.episode, title=self.title, year=self.year or '', + version=self.version, yopen=' (' if self.year else '', yclose=')' if self.year else '', + topen=' - ' if self.title else '', tclose=' - ' if self.version else '' + ) + + def get_matches(self, video): + # series name + matches = guess_matches(video, { + 'title': self.series, + 'season': self.season, + 'episode': self.episode, + 'episode_title': self.title, + 'year': self.year, + 'release_group': self.version, + }) + + # resolution + if video.resolution and self.version and video.resolution in self.version.lower(): + matches.add('resolution') + # other properties + if self.version: + matches |= guess_matches(video, guessit(self.version, {'type': 'episode'}), partial=True) + + return matches + + +class Addic7edProvider(Provider): + """Addic7ed Provider.""" + languages = {Language('por', 'BR')} | {Language(l) for l in [ + 'ara', 'aze', 'ben', 'bos', 'bul', 'cat', 'ces', 'dan', 'deu', 'ell', 'eng', 'eus', 'fas', 'fin', 'fra', 'glg', + 'heb', 'hrv', 'hun', 'hye', 'ind', 'ita', 'jpn', 'kor', 'mkd', 'msa', 'nld', 'nor', 'pol', 'por', 'ron', 'rus', + 'slk', 'slv', 'spa', 'sqi', 'srp', 'swe', 'tha', 'tur', 'ukr', 'vie', 'zho' + ]} + video_types = (Episode,) + server_url = 'http://www.addic7ed.com/' + subtitle_class = Addic7edSubtitle + + def __init__(self, username=None, password=None): + if any((username, password)) and not all((username, password)): + raise ConfigurationError('Username and password must be specified') + + self.username = username + self.password = hashlib.md5(password.encode('utf-8')).hexdigest() + self.logged_in = False + self.cookies = {'wikisubtitlesuser': self.username, 'wikisubtitlespass': self.password} + + def initialize(self): + self.session = Session() + self.session.headers['User-Agent'] = self.user_agent + + # login + if self.username and self.password: + logger.debug('Logged in') + self.logged_in = True + + def terminate(self): + # logout + logger.debug('Logged out') + self.logged_in = False + + + @region.cache_on_arguments(expiration_time=SHOW_EXPIRATION_TIME) + def _get_show_ids(self): + """Get the ``dict`` of show ids per series by querying the `shows.php` page. + :return: show id per series, lower case and without quotes. + :rtype: dict + """ + # get the show page + logger.info('Getting show ids') + r = self.session.get(self.server_url + 'shows.php', timeout=20, cookies=self.cookies) + r.raise_for_status() + + # LXML parser seems to fail when parsing Addic7ed.com HTML markup. + # Last known version to work properly is 3.6.4 (next version, 3.7.0, fails) + # Assuming the site's markup is bad, and stripping it down to only contain what's needed. + show_cells = re.findall(show_cells_re, r.content) + if show_cells: + soup = ParserBeautifulSoup(b''.join(show_cells), ['lxml', 'html.parser']) + else: + # If RegEx fails, fall back to original r.content and use 'html.parser' + soup = ParserBeautifulSoup(r.content, ['html.parser']) + + # populate the show ids + show_ids = {} + for show in soup.select('td.vr > h3 > a[href^="/show/"]'): + show_ids[sanitize(show.text)] = int(show['href'][6:]) + logger.debug('Found %d show ids', len(show_ids)) + + return show_ids + + @region.cache_on_arguments(expiration_time=SHOW_EXPIRATION_TIME) + def _search_show_id(self, series, year=None): + """Search the show id from the `series` and `year`. + :param str series: series of the episode. + :param year: year of the series, if any. + :type year: int + :return: the show id, if found. + :rtype: int + """ + # addic7ed doesn't support search with quotes + series = series.replace('\'', ' ') + + # build the params + series_year = '%s %d' % (series, year) if year is not None else series + params = {'search': series_year, 'Submit': 'Search'} + + r = self.session.get('http://www.addic7ed.com/srch.php', params=params, timeout=10, cookies=self.cookies) + + # make the search + logger.info('Searching show ids with %r', params) + r.raise_for_status() + soup = ParserBeautifulSoup(r.content, ['lxml', 'html.parser']) + + # get the suggestion + suggestion = soup.select('span.titulo > a[href^="/show/"]') + if not suggestion: + logger.warning('Show id not found: no suggestion') + return None + if not sanitize(suggestion[0].i.text.replace('\'', ' ')) == sanitize(series_year): + logger.warning('Show id not found: suggestion does not match') + return None + show_id = int(suggestion[0]['href'][6:]) + logger.debug('Found show id %d', show_id) + + return show_id + + def get_show_id(self, series, year=None, country_code=None): + """Get the best matching show id for `series`, `year` and `country_code`. + First search in the result of :meth:`_get_show_ids` and fallback on a search with :meth:`_search_show_id`. + :param str series: series of the episode. + :param year: year of the series, if any. + :type year: int + :param country_code: country code of the series, if any. + :type country_code: str + :return: the show id, if found. + :rtype: int + """ + series_sanitized = sanitize(series).lower() + show_ids = self._get_show_ids() + show_id = None + + # attempt with country + if country_code: + logger.debug('Getting show id with country') + show_id = show_ids.get('%s %s' % (series_sanitized, country_code.lower())) + + # attempt with year + if not show_id and year: + logger.debug('Getting show id with year') + show_id = show_ids.get('%s %d' % (series_sanitized, year)) + + # attempt clean + if not show_id: + logger.debug('Getting show id') + show_id = show_ids.get(series_sanitized) + + # search as last resort + if not show_id: + logger.warning('Series %s not found in show ids', series) + show_id = self._search_show_id(series) + + return show_id + + def query(self, show_id, series, season, year=None, country=None): + # get the page of the season of the show + logger.info('Getting the page of show id %d, season %d', show_id, season) + r = self.session.get(self.server_url + 'show/%d' % show_id, params={'season': season}, timeout=60, cookies=self.cookies) + r.raise_for_status() + + if not r.content: + # Provider returns a status of 304 Not Modified with an empty content + # raise_for_status won't raise exception for that status code + logger.debug('No data returned from provider') + return [] + + soup = ParserBeautifulSoup(r.content, ['lxml', 'html.parser']) + + # loop over subtitle rows + match = series_year_re.match(soup.select('#header font')[0].text.strip()[:-10]) + series = match.group('series') + year = int(match.group('year')) if match.group('year') else None + subtitles = [] + for row in soup.select('tr.epeven'): + cells = row('td') + + # ignore incomplete subtitles + status = cells[5].text + if status != 'Completed': + logger.debug('Ignoring subtitle with status %s', status) + continue + + # read the item + language = Language.fromaddic7ed(cells[3].text) + hearing_impaired = bool(cells[6].text) + page_link = self.server_url + cells[2].a['href'][1:] + season = int(cells[0].text) + episode = int(cells[1].text) + title = cells[2].text + version = cells[4].text + download_link = cells[9].a['href'][1:] + + subtitle = self.subtitle_class(language, hearing_impaired, page_link, series, season, episode, title, year, + version, download_link) + logger.debug('Found subtitle %r', subtitle) + subtitles.append(subtitle) + + return subtitles + + def list_subtitles(self, video, languages): + # lookup show_id + titles = [video.series] + video.alternative_series + show_id = None + for title in titles: + show_id = self.get_show_id(title, video.year) + if show_id is not None: + break + + # query for subtitles with the show_id + if show_id is not None: + subtitles = [s for s in self.query(show_id, title, video.season, video.year) + if s.language in languages and s.episode == video.episode] + if subtitles: + return subtitles + else: + logger.error('No show id found for %r (%r)', video.series, {'year': video.year}) + + return [] + + def download_subtitle(self, subtitle): + # download the subtitle + logger.info('Downloading subtitle %r', subtitle) + r = self.session.get(self.server_url + subtitle.download_link, headers={'Referer': subtitle.page_link}, + timeout=20) + r.raise_for_status() + + if not r.content: + # Provider returns a status of 304 Not Modified with an empty content + # raise_for_status won't raise exception for that status code + logger.debug('Unable to download subtitle. No data returned from provider') + return + + # detect download limit exceeded + if r.headers['Content-Type'] == 'text/html': + raise DownloadLimitExceeded + + subtitle.content = fix_line_ending(r.content) \ No newline at end of file diff --git a/themes-default/slim/src/components/subtitle-search.vue b/themes-default/slim/src/components/subtitle-search.vue index 0edec20360..30641ee512 100644 --- a/themes-default/slim/src/components/subtitle-search.vue +++ b/themes-default/slim/src/components/subtitle-search.vue @@ -213,7 +213,7 @@ export default { this.displayQuestion = false; this.loading = true; this.loadingMessage = 'Searching for subtitles... '; - apiRoute('home/manualSearchSubtitles', { params: subtitleParams }) + apiRoute('home/manualSearchSubtitles', { params: subtitleParams, timeout: 120000 }) .then(response => { if (response.data.result === 'success') { this.subtitles.push(...response.data.subtitles); @@ -263,7 +263,7 @@ export default { this.loadingMessage = 'downloading subtitle... '; this.loading = true; - apiRoute('home/manualSearchSubtitles', { params }) + apiRoute('home/manualSearchSubtitles', { params, timeout: 120000 }) .then(response => { if (response.data.result === 'success') { // Update the show, as we have new information (subtitles) diff --git a/themes/dark/assets/js/medusa-runtime.js b/themes/dark/assets/js/medusa-runtime.js index 0a93e6f493..d1c03e3f74 100644 --- a/themes/dark/assets/js/medusa-runtime.js +++ b/themes/dark/assets/js/medusa-runtime.js @@ -1181,7 +1181,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var vuex__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! vuex */ \"./node_modules/vuex/dist/vuex.esm.js\");\n/* harmony import */ var vue_good_table__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! vue-good-table */ \"./node_modules/vue-good-table/dist/vue-good-table.esm.js\");\n/* harmony import */ var _api__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../api */ \"./src/api.js\");\n/* harmony import */ var _helpers__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./helpers */ \"./src/components/helpers/index.js\");\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n\n\n\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({\n name: 'subtitle-search',\n components: {\n StateSwitch: _helpers__WEBPACK_IMPORTED_MODULE_1__.StateSwitch,\n VueGoodTable: vue_good_table__WEBPACK_IMPORTED_MODULE_2__.VueGoodTable\n },\n props: {\n show: {\n type: Object,\n required: true\n },\n episode: {\n type: Object,\n required: true\n },\n lang: {\n type: String,\n required: false\n }\n },\n\n data() {\n return {\n columns: [{\n label: 'Filename',\n field: 'filename'\n }, {\n label: 'Language',\n field: 'lang'\n }, {\n label: 'Provider',\n field: 'provider'\n }, {\n label: 'Score',\n field: 'score',\n type: 'number'\n }, {\n label: 'Sub Score',\n field: 'sub_score',\n type: 'number'\n }, {\n label: 'Missing Matches',\n field: rowObj => {\n if (rowObj.missing_guess) {\n return rowObj.missing_guess.join(', ');\n }\n },\n type: 'array'\n }, {\n label: 'Download',\n field: 'download',\n sortable: false\n }],\n subtitles: [],\n displayQuestion: false,\n searchType: null,\n loading: false,\n loadingMessage: ''\n };\n },\n\n computed: { ...(0,vuex__WEBPACK_IMPORTED_MODULE_3__.mapState)({\n general: state => state.config.general\n }),\n ...(0,vuex__WEBPACK_IMPORTED_MODULE_3__.mapGetters)({\n getLastReleaseName: 'getLastReleaseName'\n }),\n\n releaseName() {\n const {\n episode,\n getLastReleaseName,\n show\n } = this;\n const lastKnownReleaseName = getLastReleaseName({\n showSlug: show.id.slug,\n episodeSlug: episode.slug\n });\n\n if (lastKnownReleaseName) {\n return `Select subtitle for release: ${lastKnownReleaseName}`;\n }\n\n return 'Could not get a downloaded release name from the history table';\n },\n\n subtitleParams() {\n const {\n episode,\n show\n } = this;\n const params = {\n showslug: show.id.slug,\n season: episode.season,\n episode: episode.episode\n };\n return params;\n }\n\n },\n\n mounted() {\n this.displayQuestion = true;\n },\n\n methods: { ...(0,vuex__WEBPACK_IMPORTED_MODULE_3__.mapActions)(['getShowEpisodeHistory']),\n\n autoSearch() {\n this.searchType = 'auto';\n const {\n lang,\n subtitleParams\n } = this;\n const params = subtitleParams;\n\n if (lang !== undefined) {\n params.lang = lang;\n }\n\n this.displayQuestion = false;\n this.loadingMessage = 'Searching for subtitles and downloading if available... ';\n this.loading = true;\n (0,_api__WEBPACK_IMPORTED_MODULE_0__.apiRoute)('home/searchEpisodeSubtitles', {\n params\n }).then(response => {\n if (response.data.result !== 'failure') {\n // Update the show, as we have new information (subtitles)\n // Let's emit an event, telling the displayShow component, to update the show using the api/store.\n this.$emit('update', {\n reason: 'new subtitles found',\n codes: response.data.subtitles,\n languages: response.data.languages\n });\n }\n }).catch(error => {\n console.log(`Error trying to search for subtitles. Error: ${error}`);\n }).finally(() => {\n // Cleanup\n this.loadingMessage = '';\n this.loading = false;\n this.close();\n });\n },\n\n manualSearch() {\n this.searchType = 'manual';\n const {\n episode,\n getShowEpisodeHistory,\n show,\n subtitleParams\n } = this;\n this.displayQuestion = false;\n this.loading = true;\n this.loadingMessage = 'Searching for subtitles... ';\n (0,_api__WEBPACK_IMPORTED_MODULE_0__.apiRoute)('home/manualSearchSubtitles', {\n params: subtitleParams\n }).then(response => {\n if (response.data.result === 'success') {\n this.subtitles.push(...response.data.subtitles); // Load episode history if we have subtitles.\n\n getShowEpisodeHistory({\n showSlug: show.id.slug,\n episodeSlug: episode.slug\n });\n }\n }).catch(error => {\n console.log(`Error trying to search for subtitles. Error: ${error}`);\n }).finally(() => {\n this.loading = false;\n });\n },\n\n redownloadLang() {\n const {\n subtitleParams\n } = this;\n (0,_api__WEBPACK_IMPORTED_MODULE_0__.apiRoute)('home/searchEpisodeSubtitles', {\n params: subtitleParams\n }).then(response => {\n if (response.data.result !== 'failure') {\n // Update the show, as we have new information (subtitles)\n // Let's emit an event, telling the displayShow component, to update the show using the api/store.\n this.$emit('update', {\n reason: 'new subtitles found',\n codes: response.data.subtitles,\n languages: response.data.languages\n });\n }\n }).catch(error => {\n console.log(`Error trying to search for subtitles. Error: ${error}`);\n }).finally(() => {\n // Cleanup\n this.loadingMessage = '';\n this.loading = false;\n this.close();\n });\n },\n\n pickSubtitle(subtitleId) {\n // Download and save this subtitle with the episode.\n const {\n subtitleParams\n } = this;\n const params = { ...subtitleParams,\n picked_id: subtitleId // eslint-disable-line camelcase\n\n };\n this.displayQuestion = false;\n this.loadingMessage = 'downloading subtitle... ';\n this.loading = true;\n (0,_api__WEBPACK_IMPORTED_MODULE_0__.apiRoute)('home/manualSearchSubtitles', {\n params\n }).then(response => {\n if (response.data.result === 'success') {\n // Update the show, as we have new information (subtitles)\n // Let's emit an event, telling the displayShow component, to update the show using the api/store.\n this.$emit('update', {\n reason: 'new subtitles found',\n codes: response.data.subtitles,\n languages: response.data.languages\n });\n }\n }).catch(error => {\n console.log(`Error trying to search for subtitles. Error: ${error}`);\n }).finally(() => {\n // Cleanup\n this.loadingMessage = '';\n this.loading = false;\n this.close();\n });\n },\n\n close() {\n this.$emit('close'); // Destroy the vue listeners, etc\n\n this.$destroy(); // Remove the element from the DOM\n\n this.$el.remove();\n }\n\n }\n});\n\n//# sourceURL=webpack://slim/./src/components/subtitle-search.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-1%5B0%5D.rules%5B0%5D!./node_modules/vue-loader/lib/index.js??vue-loader-options"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var vuex__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! vuex */ \"./node_modules/vuex/dist/vuex.esm.js\");\n/* harmony import */ var vue_good_table__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! vue-good-table */ \"./node_modules/vue-good-table/dist/vue-good-table.esm.js\");\n/* harmony import */ var _api__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../api */ \"./src/api.js\");\n/* harmony import */ var _helpers__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./helpers */ \"./src/components/helpers/index.js\");\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n\n\n\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({\n name: 'subtitle-search',\n components: {\n StateSwitch: _helpers__WEBPACK_IMPORTED_MODULE_1__.StateSwitch,\n VueGoodTable: vue_good_table__WEBPACK_IMPORTED_MODULE_2__.VueGoodTable\n },\n props: {\n show: {\n type: Object,\n required: true\n },\n episode: {\n type: Object,\n required: true\n },\n lang: {\n type: String,\n required: false\n }\n },\n\n data() {\n return {\n columns: [{\n label: 'Filename',\n field: 'filename'\n }, {\n label: 'Language',\n field: 'lang'\n }, {\n label: 'Provider',\n field: 'provider'\n }, {\n label: 'Score',\n field: 'score',\n type: 'number'\n }, {\n label: 'Sub Score',\n field: 'sub_score',\n type: 'number'\n }, {\n label: 'Missing Matches',\n field: rowObj => {\n if (rowObj.missing_guess) {\n return rowObj.missing_guess.join(', ');\n }\n },\n type: 'array'\n }, {\n label: 'Download',\n field: 'download',\n sortable: false\n }],\n subtitles: [],\n displayQuestion: false,\n searchType: null,\n loading: false,\n loadingMessage: ''\n };\n },\n\n computed: { ...(0,vuex__WEBPACK_IMPORTED_MODULE_3__.mapState)({\n general: state => state.config.general\n }),\n ...(0,vuex__WEBPACK_IMPORTED_MODULE_3__.mapGetters)({\n getLastReleaseName: 'getLastReleaseName'\n }),\n\n releaseName() {\n const {\n episode,\n getLastReleaseName,\n show\n } = this;\n const lastKnownReleaseName = getLastReleaseName({\n showSlug: show.id.slug,\n episodeSlug: episode.slug\n });\n\n if (lastKnownReleaseName) {\n return `Select subtitle for release: ${lastKnownReleaseName}`;\n }\n\n return 'Could not get a downloaded release name from the history table';\n },\n\n subtitleParams() {\n const {\n episode,\n show\n } = this;\n const params = {\n showslug: show.id.slug,\n season: episode.season,\n episode: episode.episode\n };\n return params;\n }\n\n },\n\n mounted() {\n this.displayQuestion = true;\n },\n\n methods: { ...(0,vuex__WEBPACK_IMPORTED_MODULE_3__.mapActions)(['getShowEpisodeHistory']),\n\n autoSearch() {\n this.searchType = 'auto';\n const {\n lang,\n subtitleParams\n } = this;\n const params = subtitleParams;\n\n if (lang !== undefined) {\n params.lang = lang;\n }\n\n this.displayQuestion = false;\n this.loadingMessage = 'Searching for subtitles and downloading if available... ';\n this.loading = true;\n (0,_api__WEBPACK_IMPORTED_MODULE_0__.apiRoute)('home/searchEpisodeSubtitles', {\n params\n }).then(response => {\n if (response.data.result !== 'failure') {\n // Update the show, as we have new information (subtitles)\n // Let's emit an event, telling the displayShow component, to update the show using the api/store.\n this.$emit('update', {\n reason: 'new subtitles found',\n codes: response.data.subtitles,\n languages: response.data.languages\n });\n }\n }).catch(error => {\n console.log(`Error trying to search for subtitles. Error: ${error}`);\n }).finally(() => {\n // Cleanup\n this.loadingMessage = '';\n this.loading = false;\n this.close();\n });\n },\n\n manualSearch() {\n this.searchType = 'manual';\n const {\n episode,\n getShowEpisodeHistory,\n show,\n subtitleParams\n } = this;\n this.displayQuestion = false;\n this.loading = true;\n this.loadingMessage = 'Searching for subtitles... ';\n (0,_api__WEBPACK_IMPORTED_MODULE_0__.apiRoute)('home/manualSearchSubtitles', {\n params: subtitleParams,\n timeout: 120000\n }).then(response => {\n if (response.data.result === 'success') {\n this.subtitles.push(...response.data.subtitles); // Load episode history if we have subtitles.\n\n getShowEpisodeHistory({\n showSlug: show.id.slug,\n episodeSlug: episode.slug\n });\n }\n }).catch(error => {\n console.log(`Error trying to search for subtitles. Error: ${error}`);\n }).finally(() => {\n this.loading = false;\n });\n },\n\n redownloadLang() {\n const {\n subtitleParams\n } = this;\n (0,_api__WEBPACK_IMPORTED_MODULE_0__.apiRoute)('home/searchEpisodeSubtitles', {\n params: subtitleParams\n }).then(response => {\n if (response.data.result !== 'failure') {\n // Update the show, as we have new information (subtitles)\n // Let's emit an event, telling the displayShow component, to update the show using the api/store.\n this.$emit('update', {\n reason: 'new subtitles found',\n codes: response.data.subtitles,\n languages: response.data.languages\n });\n }\n }).catch(error => {\n console.log(`Error trying to search for subtitles. Error: ${error}`);\n }).finally(() => {\n // Cleanup\n this.loadingMessage = '';\n this.loading = false;\n this.close();\n });\n },\n\n pickSubtitle(subtitleId) {\n // Download and save this subtitle with the episode.\n const {\n subtitleParams\n } = this;\n const params = { ...subtitleParams,\n picked_id: subtitleId // eslint-disable-line camelcase\n\n };\n this.displayQuestion = false;\n this.loadingMessage = 'downloading subtitle... ';\n this.loading = true;\n (0,_api__WEBPACK_IMPORTED_MODULE_0__.apiRoute)('home/manualSearchSubtitles', {\n params,\n timeout: 120000\n }).then(response => {\n if (response.data.result === 'success') {\n // Update the show, as we have new information (subtitles)\n // Let's emit an event, telling the displayShow component, to update the show using the api/store.\n this.$emit('update', {\n reason: 'new subtitles found',\n codes: response.data.subtitles,\n languages: response.data.languages\n });\n }\n }).catch(error => {\n console.log(`Error trying to search for subtitles. Error: ${error}`);\n }).finally(() => {\n // Cleanup\n this.loadingMessage = '';\n this.loading = false;\n this.close();\n });\n },\n\n close() {\n this.$emit('close'); // Destroy the vue listeners, etc\n\n this.$destroy(); // Remove the element from the DOM\n\n this.$el.remove();\n }\n\n }\n});\n\n//# sourceURL=webpack://slim/./src/components/subtitle-search.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-1%5B0%5D.rules%5B0%5D!./node_modules/vue-loader/lib/index.js??vue-loader-options"); /***/ }), diff --git a/themes/light/assets/js/medusa-runtime.js b/themes/light/assets/js/medusa-runtime.js index 0a93e6f493..d1c03e3f74 100644 --- a/themes/light/assets/js/medusa-runtime.js +++ b/themes/light/assets/js/medusa-runtime.js @@ -1181,7 +1181,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var vuex__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! vuex */ \"./node_modules/vuex/dist/vuex.esm.js\");\n/* harmony import */ var vue_good_table__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! vue-good-table */ \"./node_modules/vue-good-table/dist/vue-good-table.esm.js\");\n/* harmony import */ var _api__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../api */ \"./src/api.js\");\n/* harmony import */ var _helpers__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./helpers */ \"./src/components/helpers/index.js\");\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n\n\n\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({\n name: 'subtitle-search',\n components: {\n StateSwitch: _helpers__WEBPACK_IMPORTED_MODULE_1__.StateSwitch,\n VueGoodTable: vue_good_table__WEBPACK_IMPORTED_MODULE_2__.VueGoodTable\n },\n props: {\n show: {\n type: Object,\n required: true\n },\n episode: {\n type: Object,\n required: true\n },\n lang: {\n type: String,\n required: false\n }\n },\n\n data() {\n return {\n columns: [{\n label: 'Filename',\n field: 'filename'\n }, {\n label: 'Language',\n field: 'lang'\n }, {\n label: 'Provider',\n field: 'provider'\n }, {\n label: 'Score',\n field: 'score',\n type: 'number'\n }, {\n label: 'Sub Score',\n field: 'sub_score',\n type: 'number'\n }, {\n label: 'Missing Matches',\n field: rowObj => {\n if (rowObj.missing_guess) {\n return rowObj.missing_guess.join(', ');\n }\n },\n type: 'array'\n }, {\n label: 'Download',\n field: 'download',\n sortable: false\n }],\n subtitles: [],\n displayQuestion: false,\n searchType: null,\n loading: false,\n loadingMessage: ''\n };\n },\n\n computed: { ...(0,vuex__WEBPACK_IMPORTED_MODULE_3__.mapState)({\n general: state => state.config.general\n }),\n ...(0,vuex__WEBPACK_IMPORTED_MODULE_3__.mapGetters)({\n getLastReleaseName: 'getLastReleaseName'\n }),\n\n releaseName() {\n const {\n episode,\n getLastReleaseName,\n show\n } = this;\n const lastKnownReleaseName = getLastReleaseName({\n showSlug: show.id.slug,\n episodeSlug: episode.slug\n });\n\n if (lastKnownReleaseName) {\n return `Select subtitle for release: ${lastKnownReleaseName}`;\n }\n\n return 'Could not get a downloaded release name from the history table';\n },\n\n subtitleParams() {\n const {\n episode,\n show\n } = this;\n const params = {\n showslug: show.id.slug,\n season: episode.season,\n episode: episode.episode\n };\n return params;\n }\n\n },\n\n mounted() {\n this.displayQuestion = true;\n },\n\n methods: { ...(0,vuex__WEBPACK_IMPORTED_MODULE_3__.mapActions)(['getShowEpisodeHistory']),\n\n autoSearch() {\n this.searchType = 'auto';\n const {\n lang,\n subtitleParams\n } = this;\n const params = subtitleParams;\n\n if (lang !== undefined) {\n params.lang = lang;\n }\n\n this.displayQuestion = false;\n this.loadingMessage = 'Searching for subtitles and downloading if available... ';\n this.loading = true;\n (0,_api__WEBPACK_IMPORTED_MODULE_0__.apiRoute)('home/searchEpisodeSubtitles', {\n params\n }).then(response => {\n if (response.data.result !== 'failure') {\n // Update the show, as we have new information (subtitles)\n // Let's emit an event, telling the displayShow component, to update the show using the api/store.\n this.$emit('update', {\n reason: 'new subtitles found',\n codes: response.data.subtitles,\n languages: response.data.languages\n });\n }\n }).catch(error => {\n console.log(`Error trying to search for subtitles. Error: ${error}`);\n }).finally(() => {\n // Cleanup\n this.loadingMessage = '';\n this.loading = false;\n this.close();\n });\n },\n\n manualSearch() {\n this.searchType = 'manual';\n const {\n episode,\n getShowEpisodeHistory,\n show,\n subtitleParams\n } = this;\n this.displayQuestion = false;\n this.loading = true;\n this.loadingMessage = 'Searching for subtitles... ';\n (0,_api__WEBPACK_IMPORTED_MODULE_0__.apiRoute)('home/manualSearchSubtitles', {\n params: subtitleParams\n }).then(response => {\n if (response.data.result === 'success') {\n this.subtitles.push(...response.data.subtitles); // Load episode history if we have subtitles.\n\n getShowEpisodeHistory({\n showSlug: show.id.slug,\n episodeSlug: episode.slug\n });\n }\n }).catch(error => {\n console.log(`Error trying to search for subtitles. Error: ${error}`);\n }).finally(() => {\n this.loading = false;\n });\n },\n\n redownloadLang() {\n const {\n subtitleParams\n } = this;\n (0,_api__WEBPACK_IMPORTED_MODULE_0__.apiRoute)('home/searchEpisodeSubtitles', {\n params: subtitleParams\n }).then(response => {\n if (response.data.result !== 'failure') {\n // Update the show, as we have new information (subtitles)\n // Let's emit an event, telling the displayShow component, to update the show using the api/store.\n this.$emit('update', {\n reason: 'new subtitles found',\n codes: response.data.subtitles,\n languages: response.data.languages\n });\n }\n }).catch(error => {\n console.log(`Error trying to search for subtitles. Error: ${error}`);\n }).finally(() => {\n // Cleanup\n this.loadingMessage = '';\n this.loading = false;\n this.close();\n });\n },\n\n pickSubtitle(subtitleId) {\n // Download and save this subtitle with the episode.\n const {\n subtitleParams\n } = this;\n const params = { ...subtitleParams,\n picked_id: subtitleId // eslint-disable-line camelcase\n\n };\n this.displayQuestion = false;\n this.loadingMessage = 'downloading subtitle... ';\n this.loading = true;\n (0,_api__WEBPACK_IMPORTED_MODULE_0__.apiRoute)('home/manualSearchSubtitles', {\n params\n }).then(response => {\n if (response.data.result === 'success') {\n // Update the show, as we have new information (subtitles)\n // Let's emit an event, telling the displayShow component, to update the show using the api/store.\n this.$emit('update', {\n reason: 'new subtitles found',\n codes: response.data.subtitles,\n languages: response.data.languages\n });\n }\n }).catch(error => {\n console.log(`Error trying to search for subtitles. Error: ${error}`);\n }).finally(() => {\n // Cleanup\n this.loadingMessage = '';\n this.loading = false;\n this.close();\n });\n },\n\n close() {\n this.$emit('close'); // Destroy the vue listeners, etc\n\n this.$destroy(); // Remove the element from the DOM\n\n this.$el.remove();\n }\n\n }\n});\n\n//# sourceURL=webpack://slim/./src/components/subtitle-search.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-1%5B0%5D.rules%5B0%5D!./node_modules/vue-loader/lib/index.js??vue-loader-options"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var vuex__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! vuex */ \"./node_modules/vuex/dist/vuex.esm.js\");\n/* harmony import */ var vue_good_table__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! vue-good-table */ \"./node_modules/vue-good-table/dist/vue-good-table.esm.js\");\n/* harmony import */ var _api__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../api */ \"./src/api.js\");\n/* harmony import */ var _helpers__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./helpers */ \"./src/components/helpers/index.js\");\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n\n\n\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({\n name: 'subtitle-search',\n components: {\n StateSwitch: _helpers__WEBPACK_IMPORTED_MODULE_1__.StateSwitch,\n VueGoodTable: vue_good_table__WEBPACK_IMPORTED_MODULE_2__.VueGoodTable\n },\n props: {\n show: {\n type: Object,\n required: true\n },\n episode: {\n type: Object,\n required: true\n },\n lang: {\n type: String,\n required: false\n }\n },\n\n data() {\n return {\n columns: [{\n label: 'Filename',\n field: 'filename'\n }, {\n label: 'Language',\n field: 'lang'\n }, {\n label: 'Provider',\n field: 'provider'\n }, {\n label: 'Score',\n field: 'score',\n type: 'number'\n }, {\n label: 'Sub Score',\n field: 'sub_score',\n type: 'number'\n }, {\n label: 'Missing Matches',\n field: rowObj => {\n if (rowObj.missing_guess) {\n return rowObj.missing_guess.join(', ');\n }\n },\n type: 'array'\n }, {\n label: 'Download',\n field: 'download',\n sortable: false\n }],\n subtitles: [],\n displayQuestion: false,\n searchType: null,\n loading: false,\n loadingMessage: ''\n };\n },\n\n computed: { ...(0,vuex__WEBPACK_IMPORTED_MODULE_3__.mapState)({\n general: state => state.config.general\n }),\n ...(0,vuex__WEBPACK_IMPORTED_MODULE_3__.mapGetters)({\n getLastReleaseName: 'getLastReleaseName'\n }),\n\n releaseName() {\n const {\n episode,\n getLastReleaseName,\n show\n } = this;\n const lastKnownReleaseName = getLastReleaseName({\n showSlug: show.id.slug,\n episodeSlug: episode.slug\n });\n\n if (lastKnownReleaseName) {\n return `Select subtitle for release: ${lastKnownReleaseName}`;\n }\n\n return 'Could not get a downloaded release name from the history table';\n },\n\n subtitleParams() {\n const {\n episode,\n show\n } = this;\n const params = {\n showslug: show.id.slug,\n season: episode.season,\n episode: episode.episode\n };\n return params;\n }\n\n },\n\n mounted() {\n this.displayQuestion = true;\n },\n\n methods: { ...(0,vuex__WEBPACK_IMPORTED_MODULE_3__.mapActions)(['getShowEpisodeHistory']),\n\n autoSearch() {\n this.searchType = 'auto';\n const {\n lang,\n subtitleParams\n } = this;\n const params = subtitleParams;\n\n if (lang !== undefined) {\n params.lang = lang;\n }\n\n this.displayQuestion = false;\n this.loadingMessage = 'Searching for subtitles and downloading if available... ';\n this.loading = true;\n (0,_api__WEBPACK_IMPORTED_MODULE_0__.apiRoute)('home/searchEpisodeSubtitles', {\n params\n }).then(response => {\n if (response.data.result !== 'failure') {\n // Update the show, as we have new information (subtitles)\n // Let's emit an event, telling the displayShow component, to update the show using the api/store.\n this.$emit('update', {\n reason: 'new subtitles found',\n codes: response.data.subtitles,\n languages: response.data.languages\n });\n }\n }).catch(error => {\n console.log(`Error trying to search for subtitles. Error: ${error}`);\n }).finally(() => {\n // Cleanup\n this.loadingMessage = '';\n this.loading = false;\n this.close();\n });\n },\n\n manualSearch() {\n this.searchType = 'manual';\n const {\n episode,\n getShowEpisodeHistory,\n show,\n subtitleParams\n } = this;\n this.displayQuestion = false;\n this.loading = true;\n this.loadingMessage = 'Searching for subtitles... ';\n (0,_api__WEBPACK_IMPORTED_MODULE_0__.apiRoute)('home/manualSearchSubtitles', {\n params: subtitleParams,\n timeout: 120000\n }).then(response => {\n if (response.data.result === 'success') {\n this.subtitles.push(...response.data.subtitles); // Load episode history if we have subtitles.\n\n getShowEpisodeHistory({\n showSlug: show.id.slug,\n episodeSlug: episode.slug\n });\n }\n }).catch(error => {\n console.log(`Error trying to search for subtitles. Error: ${error}`);\n }).finally(() => {\n this.loading = false;\n });\n },\n\n redownloadLang() {\n const {\n subtitleParams\n } = this;\n (0,_api__WEBPACK_IMPORTED_MODULE_0__.apiRoute)('home/searchEpisodeSubtitles', {\n params: subtitleParams\n }).then(response => {\n if (response.data.result !== 'failure') {\n // Update the show, as we have new information (subtitles)\n // Let's emit an event, telling the displayShow component, to update the show using the api/store.\n this.$emit('update', {\n reason: 'new subtitles found',\n codes: response.data.subtitles,\n languages: response.data.languages\n });\n }\n }).catch(error => {\n console.log(`Error trying to search for subtitles. Error: ${error}`);\n }).finally(() => {\n // Cleanup\n this.loadingMessage = '';\n this.loading = false;\n this.close();\n });\n },\n\n pickSubtitle(subtitleId) {\n // Download and save this subtitle with the episode.\n const {\n subtitleParams\n } = this;\n const params = { ...subtitleParams,\n picked_id: subtitleId // eslint-disable-line camelcase\n\n };\n this.displayQuestion = false;\n this.loadingMessage = 'downloading subtitle... ';\n this.loading = true;\n (0,_api__WEBPACK_IMPORTED_MODULE_0__.apiRoute)('home/manualSearchSubtitles', {\n params,\n timeout: 120000\n }).then(response => {\n if (response.data.result === 'success') {\n // Update the show, as we have new information (subtitles)\n // Let's emit an event, telling the displayShow component, to update the show using the api/store.\n this.$emit('update', {\n reason: 'new subtitles found',\n codes: response.data.subtitles,\n languages: response.data.languages\n });\n }\n }).catch(error => {\n console.log(`Error trying to search for subtitles. Error: ${error}`);\n }).finally(() => {\n // Cleanup\n this.loadingMessage = '';\n this.loading = false;\n this.close();\n });\n },\n\n close() {\n this.$emit('close'); // Destroy the vue listeners, etc\n\n this.$destroy(); // Remove the element from the DOM\n\n this.$el.remove();\n }\n\n }\n});\n\n//# sourceURL=webpack://slim/./src/components/subtitle-search.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-1%5B0%5D.rules%5B0%5D!./node_modules/vue-loader/lib/index.js??vue-loader-options"); /***/ }), From 9eb6e87dfe6640306070e2e9d2ab783e9d7a16ce Mon Sep 17 00:00:00 2001 From: p0psicles Date: Sat, 5 Feb 2022 10:56:21 +0100 Subject: [PATCH 2/4] Add explanation on how to get the user id --- .../slim/src/components/config-subtitles.vue | 13 ++++++++++++- themes/dark/assets/js/medusa-runtime.js | 4 ++-- themes/light/assets/js/medusa-runtime.js | 4 ++-- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/themes-default/slim/src/components/config-subtitles.vue b/themes-default/slim/src/components/config-subtitles.vue index a1bfb44215..7150576e21 100644 --- a/themes-default/slim/src/components/config-subtitles.vue +++ b/themes-default/slim/src/components/config-subtitles.vue @@ -130,7 +130,18 @@
- + +
+

To bypass addic7ed captcha protection we authenticate using a set cookie. The cookie requires your user id and password.

+ You can find your user id by following these steps +
    +
  • Navigate and login on addic7ed.com
  • +
  • Click on My Profile
  • +
  • Click on your own username
  • +
  • Your user id should now be visible in the address bar
  • +
  • For example: https://www.addic7ed.com/user/12345
  • +
+
diff --git a/themes/dark/assets/js/medusa-runtime.js b/themes/dark/assets/js/medusa-runtime.js index d1c03e3f74..fc21668246 100644 --- a/themes/dark/assets/js/medusa-runtime.js +++ b/themes/dark/assets/js/medusa-runtime.js @@ -191,7 +191,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var vuex__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! vuex */ \"./node_modules/vuex/dist/vuex.esm.js\");\n/* harmony import */ var _helpers__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./helpers */ \"./src/components/helpers/index.js\");\n/* harmony import */ var vuedraggable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! vuedraggable */ \"./node_modules/vuedraggable/dist/vuedraggable.umd.js\");\n/* harmony import */ var vuedraggable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(vuedraggable__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var vue_nav_tabs_dist_vue_tabs_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! vue-nav-tabs/dist/vue-tabs.js */ \"./node_modules/vue-nav-tabs/dist/vue-tabs.js\");\n/* harmony import */ var vue_nav_tabs_dist_vue_tabs_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(vue_nav_tabs_dist_vue_tabs_js__WEBPACK_IMPORTED_MODULE_2__);\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n\n\n\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({\n name: 'config-subtitles',\n components: {\n AppLink: _helpers__WEBPACK_IMPORTED_MODULE_0__.AppLink,\n Draggable: (vuedraggable__WEBPACK_IMPORTED_MODULE_1___default()),\n ConfigSubtitleLanguages: _helpers__WEBPACK_IMPORTED_MODULE_0__.ConfigSubtitleLanguages,\n ConfigTemplate: _helpers__WEBPACK_IMPORTED_MODULE_0__.ConfigTemplate,\n ConfigTextbox: _helpers__WEBPACK_IMPORTED_MODULE_0__.ConfigTextbox,\n ConfigTextboxNumber: _helpers__WEBPACK_IMPORTED_MODULE_0__.ConfigTextboxNumber,\n ConfigToggleSlider: _helpers__WEBPACK_IMPORTED_MODULE_0__.ConfigToggleSlider,\n SelectList: _helpers__WEBPACK_IMPORTED_MODULE_0__.SelectList,\n VueTabs: vue_nav_tabs_dist_vue_tabs_js__WEBPACK_IMPORTED_MODULE_2__.VueTabs,\n VTab: vue_nav_tabs_dist_vue_tabs_js__WEBPACK_IMPORTED_MODULE_2__.VTab\n },\n\n data() {\n return {\n saving: false\n };\n },\n\n methods: { ...(0,vuex__WEBPACK_IMPORTED_MODULE_3__.mapActions)(['setConfig']),\n\n async save() {\n const {\n subtitles,\n setConfig\n } = this; // Disable the save button until we're done.\n\n this.saving = true;\n const section = 'main'; // Remove codeFilter key from object.\n\n const {\n codeFilter,\n wantedLanguages,\n ...rest\n } = subtitles;\n\n try {\n await setConfig({\n section,\n config: {\n subtitles: rest\n }\n });\n this.$snotify.success('Saved Subtitles config', 'Saved', {\n timeout: 5000\n });\n } catch (error) {\n this.$snotify.error('Error while trying to save subtitles config', 'Error');\n } finally {\n this.saving = false;\n }\n }\n\n },\n computed: { ...(0,vuex__WEBPACK_IMPORTED_MODULE_3__.mapState)({\n subtitles: state => state.config.subtitles,\n layout: state => state.config.layout\n })\n },\n filters: {\n capitalize: str => str.replace(/\\b\\w/g, str => str.toUpperCase())\n }\n});\n\n//# sourceURL=webpack://slim/./src/components/config-subtitles.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-1%5B0%5D.rules%5B0%5D!./node_modules/vue-loader/lib/index.js??vue-loader-options"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var vuex__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! vuex */ \"./node_modules/vuex/dist/vuex.esm.js\");\n/* harmony import */ var _helpers__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./helpers */ \"./src/components/helpers/index.js\");\n/* harmony import */ var vuedraggable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! vuedraggable */ \"./node_modules/vuedraggable/dist/vuedraggable.umd.js\");\n/* harmony import */ var vuedraggable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(vuedraggable__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var vue_nav_tabs_dist_vue_tabs_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! vue-nav-tabs/dist/vue-tabs.js */ \"./node_modules/vue-nav-tabs/dist/vue-tabs.js\");\n/* harmony import */ var vue_nav_tabs_dist_vue_tabs_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(vue_nav_tabs_dist_vue_tabs_js__WEBPACK_IMPORTED_MODULE_2__);\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n\n\n\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({\n name: 'config-subtitles',\n components: {\n AppLink: _helpers__WEBPACK_IMPORTED_MODULE_0__.AppLink,\n Draggable: (vuedraggable__WEBPACK_IMPORTED_MODULE_1___default()),\n ConfigSubtitleLanguages: _helpers__WEBPACK_IMPORTED_MODULE_0__.ConfigSubtitleLanguages,\n ConfigTemplate: _helpers__WEBPACK_IMPORTED_MODULE_0__.ConfigTemplate,\n ConfigTextbox: _helpers__WEBPACK_IMPORTED_MODULE_0__.ConfigTextbox,\n ConfigTextboxNumber: _helpers__WEBPACK_IMPORTED_MODULE_0__.ConfigTextboxNumber,\n ConfigToggleSlider: _helpers__WEBPACK_IMPORTED_MODULE_0__.ConfigToggleSlider,\n SelectList: _helpers__WEBPACK_IMPORTED_MODULE_0__.SelectList,\n VueTabs: vue_nav_tabs_dist_vue_tabs_js__WEBPACK_IMPORTED_MODULE_2__.VueTabs,\n VTab: vue_nav_tabs_dist_vue_tabs_js__WEBPACK_IMPORTED_MODULE_2__.VTab\n },\n\n data() {\n return {\n saving: false\n };\n },\n\n methods: { ...(0,vuex__WEBPACK_IMPORTED_MODULE_3__.mapActions)(['setConfig']),\n\n async save() {\n const {\n subtitles,\n setConfig\n } = this; // Disable the save button until we're done.\n\n this.saving = true;\n const section = 'main'; // Remove codeFilter key from object.\n\n const {\n codeFilter,\n wantedLanguages,\n ...rest\n } = subtitles;\n\n try {\n await setConfig({\n section,\n config: {\n subtitles: rest\n }\n });\n this.$snotify.success('Saved Subtitles config', 'Saved', {\n timeout: 5000\n });\n } catch (error) {\n this.$snotify.error('Error while trying to save subtitles config', 'Error');\n } finally {\n this.saving = false;\n }\n }\n\n },\n computed: { ...(0,vuex__WEBPACK_IMPORTED_MODULE_3__.mapState)({\n subtitles: state => state.config.subtitles,\n layout: state => state.config.layout\n })\n },\n filters: {\n capitalize: str => str.replace(/\\b\\w/g, str => str.toUpperCase())\n }\n});\n\n//# sourceURL=webpack://slim/./src/components/config-subtitles.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-1%5B0%5D.rules%5B0%5D!./node_modules/vue-loader/lib/index.js??vue-loader-options"); /***/ }), @@ -7277,7 +7277,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"render\": () => (/* binding */ render),\n/* harmony export */ \"staticRenderFns\": () => (/* binding */ staticRenderFns)\n/* harmony export */ });\nvar render = function() {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\"div\", { attrs: { id: \"config\" } }, [\n _c(\"div\", { attrs: { id: \"config-content\" } }, [\n _c(\n \"form\",\n {\n attrs: {\n id: \"configForm\",\n action: \"config/subtitles/saveSubtitles\",\n method: \"post\"\n },\n on: {\n submit: function($event) {\n $event.preventDefault()\n return _vm.save.apply(null, arguments)\n }\n }\n },\n [\n _c(\n \"vue-tabs\",\n [\n _c(\n \"v-tab\",\n {\n key: \"subtitles_search\",\n attrs: { title: \"Subtitles Search\" }\n },\n [\n _c(\n \"div\",\n {\n staticClass: \"row component-group\",\n attrs: { id: \"subtitles-search\" }\n },\n [\n _c(\n \"div\",\n {\n staticClass: \"component-group-desc col-xs-12 col-md-2\"\n },\n [\n _c(\"h3\", [_vm._v(\"Subtitles Search\")]),\n _vm._v(\" \"),\n _c(\"p\", [\n _vm._v(\n \"Settings that dictate how Medusa handles subtitles search results.\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\"div\", { staticClass: \"col-xs-12 col-md-10\" }, [\n _c(\n \"fieldset\",\n { staticClass: \"component-group-list\" },\n [\n _c(\n \"config-toggle-slider\",\n {\n attrs: {\n label: \"Search Subtitles\",\n id: \"search_subtitles\"\n },\n model: {\n value: _vm.subtitles.enabled,\n callback: function($$v) {\n _vm.$set(_vm.subtitles, \"enabled\", $$v)\n },\n expression: \"subtitles.enabled\"\n }\n },\n [\n _c(\"p\", [\n _vm._v(\n \"Search subtitles for episodes with DOWNLOADED status\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _vm.subtitles.enabled\n ? [\n _c(\n \"config-template\",\n {\n attrs: {\n label: \"Subtitle Languages\",\n labelFor: \"wanted_languages\"\n }\n },\n [\n _c(\"config-subtitle-languages\", {\n attrs: {\n id: \"wanted_languages\",\n languages:\n _vm.subtitles.wantedLanguages\n },\n on: {\n change: function($event) {\n _vm.subtitles.languages = $event.map(\n function(tag) {\n return tag.id\n }\n )\n }\n }\n })\n ],\n 1\n ),\n _vm._v(\" \"),\n _c(\n \"config-toggle-slider\",\n {\n attrs: {\n label:\n \"Download only one language (any)\",\n id: \"subtitles_stop_at_first\"\n },\n model: {\n value: _vm.subtitles.stopAtFirst,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"stopAtFirst\",\n $$v\n )\n },\n expression: \"subtitles.stopAtFirst\"\n }\n },\n [\n _c(\"p\", [\n _vm._v(\n \"Stop downloading subtitles after first download\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-toggle-slider\",\n {\n attrs: {\n label:\n \"Erase subtitles cache on next boot\",\n id: \"subtitles_erase_cache\"\n },\n model: {\n value: _vm.subtitles.eraseCache,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"eraseCache\",\n $$v\n )\n },\n expression: \"subtitles.eraseCache\"\n }\n },\n [\n _c(\"p\", [\n _vm._v(\n \"Erases all subtitles cache files. May fix some subtitles not being found\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-textbox\",\n {\n attrs: {\n label: \"Subtitle Directory\",\n id: \"subtitles_dir\"\n },\n model: {\n value: _vm.subtitles.location,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"location\",\n $$v\n )\n },\n expression: \"subtitles.location\"\n }\n },\n [\n _c(\"span\", [\n _vm._v(\n \"The directory where Medusa should store your \"\n ),\n _c(\"i\", [_vm._v(\"Subtitles\")]),\n _vm._v(\" files.\")\n ]),\n _vm._v(\" \"),\n _c(\"span\", [\n _c(\"b\", [_vm._v(\"Note:\")]),\n _vm._v(\n \" Leave empty if you want store subtitle in episode path.\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-textbox-number\",\n {\n attrs: {\n min: 1,\n step: 1,\n label: \"Subtitle Find Frequency\",\n id: \"subtitles_finder_frequency\"\n },\n model: {\n value: _vm.subtitles.finderFrequency,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"finderFrequency\",\n $$v\n )\n },\n expression: \"subtitles.finderFrequency\"\n }\n },\n [\n _c(\"span\", [\n _vm._v(\n \"time in hours between scans (default: 1)\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-toggle-slider\",\n {\n attrs: {\n label: \"Perfect matches\",\n id: \"subtitles_perfect_match\"\n },\n model: {\n value: _vm.subtitles.perfectMatch,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"perfectMatch\",\n $$v\n )\n },\n expression: \"subtitles.perfectMatch\"\n }\n },\n [\n _c(\"p\", [\n _vm._v(\n \"Only download subtitles that match release group\"\n )\n ]),\n _vm._v(\" \"),\n _c(\"p\", [\n _vm._v(\n \"If disabled you may get out of sync subtitles\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-toggle-slider\",\n {\n attrs: {\n label: \"Subtitles History\",\n id: \"subtitles_history\"\n },\n model: {\n value: _vm.subtitles.logHistory,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"logHistory\",\n $$v\n )\n },\n expression: \"subtitles.logHistory\"\n }\n },\n [\n _c(\"p\", [\n _vm._v(\n \"Log downloaded Subtitle on History page?\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-toggle-slider\",\n {\n attrs: {\n label: \"Subtitles Multi-Language\",\n id: \"subtitles_multi\"\n },\n model: {\n value: _vm.subtitles.multiLanguage,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"multiLanguage\",\n $$v\n )\n },\n expression: \"subtitles.multiLanguage\"\n }\n },\n [\n _c(\"p\", [\n _vm._v(\n \"Append language codes to subtitle filenames?\"\n )\n ]),\n _vm._v(\" \"),\n _c(\"span\", [\n _c(\"b\", [_vm._v(\"Note:\")]),\n _vm._v(\n \" This option is required if you use multiple subtitle languages.\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-toggle-slider\",\n {\n attrs: {\n label: \"Delete unwanted subtitles\",\n id: \"subtitles_keep_only_wanted\"\n },\n model: {\n value: _vm.subtitles.keepOnlyWanted,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"keepOnlyWanted\",\n $$v\n )\n },\n expression: \"subtitles.keepOnlyWanted\"\n }\n },\n [\n _c(\"p\", [\n _vm._v(\n \"Enable to delete unwanted subtitle languages bundled with release\"\n )\n ]),\n _vm._v(\" \"),\n _c(\"p\", [\n _vm._v(\n \"Avoid post-process releases with unwanted language subtitles when feature 'postpone if no subs' is enabled\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-toggle-slider\",\n {\n attrs: {\n label: \"Embedded Subtitles\",\n id: \"embedded_subtitles_all\"\n },\n model: {\n value: _vm.subtitles.ignoreEmbeddedSubs,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"ignoreEmbeddedSubs\",\n $$v\n )\n },\n expression:\n \"subtitles.ignoreEmbeddedSubs\"\n }\n },\n [\n _c(\"p\", [\n _vm._v(\n \"Ignore subtitles embedded inside video file?\"\n )\n ]),\n _vm._v(\" \"),\n _c(\"p\", [\n _c(\"b\", [_vm._v(\"Warning: \")]),\n _vm._v(\"this will ignore \"),\n _c(\"em\", [_vm._v(\"all\")]),\n _vm._v(\n \" embedded subtitles for every video file!\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-toggle-slider\",\n {\n attrs: {\n label: \"Unknown language\",\n id: \"embedded_subtitles_unknown_lang\"\n },\n model: {\n value:\n _vm.subtitles\n .acceptUnknownEmbeddedSubs,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"acceptUnknownEmbeddedSubs\",\n $$v\n )\n },\n expression:\n \"subtitles.acceptUnknownEmbeddedSubs\"\n }\n },\n [\n _c(\"p\", [\n _vm._v(\n \"Consider unknown embedded subtitles as wanted language to avoid postponing the post-processor\"\n )\n ]),\n _vm._v(\" \"),\n _c(\"p\", [\n _vm._v(\n \"Only works with setting 'Postpone post-processing' enabled\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-toggle-slider\",\n {\n attrs: {\n label: \"Hearing Impaired Subtitles\",\n id: \"subtitles_hearing_impaired\"\n },\n model: {\n value: _vm.subtitles.hearingImpaired,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"hearingImpaired\",\n $$v\n )\n },\n expression: \"subtitles.hearingImpaired\"\n }\n },\n [\n _c(\"p\", [\n _vm._v(\n \"Download hearing impaired style subtitles?\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-template\",\n {\n attrs: {\n \"label-for\": \"subtitles_pre_scripts\",\n label: \"Pre-Scripts\"\n }\n },\n [\n _c(\"select-list\", {\n attrs: {\n name: \"subtitles_pre_scripts\",\n id: \"subtitles_pre_scripts\",\n \"list-items\": _vm.subtitles.preScripts\n },\n on: {\n change: function($event) {\n _vm.subtitles.preScripts = $event.map(\n function(x) {\n return x.value\n }\n )\n }\n }\n }),\n _vm._v(\" \"),\n _c(\"p\", [\n _vm._v(\n \"Show's media filename is passed as argument for the pre-scripts. Pre-scripts are executed before trying to find subtitles from usual sources.\"\n )\n ])\n ],\n 1\n ),\n _vm._v(\" \"),\n _c(\n \"config-template\",\n {\n attrs: {\n \"label-for\": \"subtitles_pre_scripts\",\n label: \"Extra Scripts\"\n }\n },\n [\n _c(\"select-list\", {\n attrs: {\n name: \"subtitles_pre_scripts\",\n id: \"subtitles_pre_scripts\",\n \"list-items\":\n _vm.subtitles.extraScripts\n },\n on: {\n change: function($event) {\n _vm.subtitles.extraScripts = $event.map(\n function(x) {\n return x.value\n }\n )\n }\n }\n }),\n _vm._v(\" \"),\n _c(\n \"ul\",\n { staticClass: \"extra-scripts\" },\n [\n _c(\n \"li\",\n [\n _vm._v(\"See the \"),\n _c(\n \"app-link\",\n {\n staticClass: \"wiki\",\n attrs: {\n href: _vm.subtitles.wikiUrl\n }\n },\n [_c(\"strong\", [_vm._v(\"Wiki\")])]\n ),\n _vm._v(\n \" for a script arguments description.\"\n )\n ],\n 1\n ),\n _vm._v(\" \"),\n _c(\"li\", [\n _vm._v(\n \"Additional scripts separated by \"\n ),\n _c(\"b\", [_vm._v(\"|\")]),\n _vm._v(\".\")\n ]),\n _vm._v(\" \"),\n _c(\"li\", [\n _vm._v(\n \"Scripts are called after each episode has searched and downloaded subtitles.\"\n )\n ]),\n _vm._v(\" \"),\n _c(\"li\", [\n _vm._v(\n \"Only Python scripts are allowed to be executed.\"\n )\n ])\n ]\n )\n ],\n 1\n )\n ]\n : _vm._e(),\n _vm._v(\" \"),\n _c(\"input\", {\n staticClass: \"btn-medusa config_submitter\",\n attrs: { type: \"submit\", value: \"Save Changes\" }\n })\n ],\n 2\n )\n ])\n ]\n )\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"v-tab\",\n {\n key: \"subtitles_plugin\",\n attrs: { title: \"Subtitles Plugin\" }\n },\n [\n _c(\n \"div\",\n {\n staticClass: \"row component-group\",\n attrs: { id: \"subtitles-plugin\" }\n },\n [\n _c(\n \"div\",\n {\n staticClass: \"col-xs-12 col-md-2 component-group-desc\"\n },\n [\n _c(\"h3\", [_vm._v(\"Subtitle Providers\")]),\n _vm._v(\" \"),\n _c(\"p\", [\n _vm._v(\n \"Check off and drag the plugins into the order you want them to be used.\"\n )\n ]),\n _vm._v(\" \"),\n _c(\"p\", { staticClass: \"note\" }, [\n _vm._v(\"At least one plugin is required.\")\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"div\",\n { staticClass: \"col-xs-12 col-md-10\" },\n [\n _c(\n \"draggable\",\n {\n staticClass: \"list-group\",\n attrs: {\n id: \"service_order_list\",\n tag: \"ul\",\n handle: \".ui-state-default\"\n },\n model: {\n value: _vm.subtitles.services,\n callback: function($$v) {\n _vm.$set(_vm.subtitles, \"services\", $$v)\n },\n expression: \"subtitles.services\"\n }\n },\n _vm._l(_vm.subtitles.services, function(service) {\n return _c(\n \"li\",\n {\n key: service.name,\n staticClass: \"ui-state-default\",\n attrs: { id: service.name }\n },\n [\n _c(\"input\", {\n directives: [\n {\n name: \"model\",\n rawName: \"v-model\",\n value: service.enabled,\n expression: \"service.enabled\"\n }\n ],\n attrs: {\n type: \"checkbox\",\n id: \"enable_\" + service.name\n },\n domProps: {\n checked: service.enabled,\n checked: Array.isArray(service.enabled)\n ? _vm._i(service.enabled, null) > -1\n : service.enabled\n },\n on: {\n change: function($event) {\n var $$a = service.enabled,\n $$el = $event.target,\n $$c = $$el.checked ? true : false\n if (Array.isArray($$a)) {\n var $$v = null,\n $$i = _vm._i($$a, $$v)\n if ($$el.checked) {\n $$i < 0 &&\n _vm.$set(\n service,\n \"enabled\",\n $$a.concat([$$v])\n )\n } else {\n $$i > -1 &&\n _vm.$set(\n service,\n \"enabled\",\n $$a\n .slice(0, $$i)\n .concat($$a.slice($$i + 1))\n )\n }\n } else {\n _vm.$set(service, \"enabled\", $$c)\n }\n }\n }\n }),\n _vm._v(\" \"),\n _c(\n \"app-link\",\n {\n staticClass: \"imgLink\",\n attrs: { href: service.url }\n },\n [\n _c(\"img\", {\n staticStyle: {\n \"vertical-align\": \"middle\"\n },\n attrs: {\n src:\n \"images/subtitles/\" + service.image,\n alt: service.url,\n title: service.url,\n width: \"16\",\n height: \"16\"\n }\n })\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"span\",\n {\n staticStyle: {\n \"vertical-align\": \"middle\"\n }\n },\n [\n _vm._v(\n _vm._s(\n _vm._f(\"capitalize\")(service.name)\n )\n )\n ]\n ),\n _vm._v(\" \"),\n _c(\"span\", {\n staticClass:\n \"ui-icon ui-icon-arrowthick-2-n-s pull-right\",\n staticStyle: { \"vertical-align\": \"middle\" }\n })\n ],\n 1\n )\n }),\n 0\n ),\n _vm._v(\" \"),\n _c(\"br\"),\n _c(\"input\", {\n staticClass: \"btn-medusa config_submitter\",\n attrs: { type: \"submit\", value: \"Save Changes\" }\n }),\n _c(\"br\")\n ],\n 1\n )\n ]\n )\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"v-tab\",\n { key: \"plugin_settings\", attrs: { title: \"Plugin Settings\" } },\n [\n _c(\n \"div\",\n {\n staticClass: \"row component-group\",\n attrs: { id: \"plugin-settings\" }\n },\n [\n _c(\n \"div\",\n {\n staticClass: \"col-xs-12 col-md-2 component-group-desc\"\n },\n [\n _c(\"h3\", [_vm._v(\"Provider Settings\")]),\n _vm._v(\" \"),\n _c(\"p\", [\n _vm._v(\"Set user and password for each provider.\")\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\"div\", { staticClass: \"col-xs-12 col-md-10\" }, [\n _c(\n \"fieldset\",\n {\n staticClass: \"component-group-list\",\n staticStyle: {\n \"margin-left\": \"50px\",\n \"margin-top\": \"36px\"\n }\n },\n [\n _c(\"config-textbox\", {\n attrs: {\n label: \"Addic7ed User Name\",\n id: \"addic7ed_username\"\n },\n model: {\n value:\n _vm.subtitles.providerLogins.addic7ed.user,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles.providerLogins.addic7ed,\n \"user\",\n $$v\n )\n },\n expression:\n \"subtitles.providerLogins.addic7ed.user\"\n }\n }),\n _vm._v(\" \"),\n _c(\"config-textbox\", {\n attrs: {\n type: \"password\",\n label: \"Addic7ed Password\",\n id: \"addic7ed_password\"\n },\n model: {\n value:\n _vm.subtitles.providerLogins.addic7ed.pass,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles.providerLogins.addic7ed,\n \"pass\",\n $$v\n )\n },\n expression:\n \"subtitles.providerLogins.addic7ed.pass\"\n }\n }),\n _vm._v(\" \"),\n _c(\"config-textbox\", {\n attrs: {\n label: \"Opensubtitles User Name\",\n id: \"opensubtitles_username\"\n },\n model: {\n value:\n _vm.subtitles.providerLogins.opensubtitles\n .user,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles.providerLogins.opensubtitles,\n \"user\",\n $$v\n )\n },\n expression:\n \"subtitles.providerLogins.opensubtitles.user\"\n }\n }),\n _vm._v(\" \"),\n _c(\"config-textbox\", {\n attrs: {\n type: \"password\",\n label: \"Opensubtitles Password\",\n id: \"opensubtitles_password\"\n },\n model: {\n value:\n _vm.subtitles.providerLogins.opensubtitles\n .pass,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles.providerLogins.opensubtitles,\n \"pass\",\n $$v\n )\n },\n expression:\n \"subtitles.providerLogins.opensubtitles.pass\"\n }\n }),\n _vm._v(\" \"),\n _c(\"config-textbox\", {\n attrs: {\n label: \"Legendastv User Name\",\n id: \"legandas_username\"\n },\n model: {\n value:\n _vm.subtitles.providerLogins.legendastv.user,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles.providerLogins.legendastv,\n \"user\",\n $$v\n )\n },\n expression:\n \"subtitles.providerLogins.legendastv.user\"\n }\n }),\n _vm._v(\" \"),\n _c(\"config-textbox\", {\n attrs: {\n type: \"password\",\n label: \"Legendastv Password\",\n id: \"legandas_password\"\n },\n model: {\n value:\n _vm.subtitles.providerLogins.legendastv.pass,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles.providerLogins.legendastv,\n \"pass\",\n $$v\n )\n },\n expression:\n \"subtitles.providerLogins.legendastv.pass\"\n }\n }),\n _vm._v(\" \"),\n _c(\"input\", {\n staticClass: \"btn-medusa config_submitter\",\n attrs: { type: \"submit\", value: \"Save Changes\" }\n }),\n _c(\"br\")\n ],\n 1\n )\n ])\n ]\n )\n ]\n )\n ],\n 1\n )\n ],\n 1\n )\n ])\n ])\n}\nvar staticRenderFns = []\nrender._withStripped = true\n\n\n\n//# sourceURL=webpack://slim/./src/components/config-subtitles.vue?./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/vue-loader/lib/index.js??vue-loader-options"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"render\": () => (/* binding */ render),\n/* harmony export */ \"staticRenderFns\": () => (/* binding */ staticRenderFns)\n/* harmony export */ });\nvar render = function() {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\"div\", { attrs: { id: \"config\" } }, [\n _c(\"div\", { attrs: { id: \"config-content\" } }, [\n _c(\n \"form\",\n {\n attrs: {\n id: \"configForm\",\n action: \"config/subtitles/saveSubtitles\",\n method: \"post\"\n },\n on: {\n submit: function($event) {\n $event.preventDefault()\n return _vm.save.apply(null, arguments)\n }\n }\n },\n [\n _c(\n \"vue-tabs\",\n [\n _c(\n \"v-tab\",\n {\n key: \"subtitles_search\",\n attrs: { title: \"Subtitles Search\" }\n },\n [\n _c(\n \"div\",\n {\n staticClass: \"row component-group\",\n attrs: { id: \"subtitles-search\" }\n },\n [\n _c(\n \"div\",\n {\n staticClass: \"component-group-desc col-xs-12 col-md-2\"\n },\n [\n _c(\"h3\", [_vm._v(\"Subtitles Search\")]),\n _vm._v(\" \"),\n _c(\"p\", [\n _vm._v(\n \"Settings that dictate how Medusa handles subtitles search results.\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\"div\", { staticClass: \"col-xs-12 col-md-10\" }, [\n _c(\n \"fieldset\",\n { staticClass: \"component-group-list\" },\n [\n _c(\n \"config-toggle-slider\",\n {\n attrs: {\n label: \"Search Subtitles\",\n id: \"search_subtitles\"\n },\n model: {\n value: _vm.subtitles.enabled,\n callback: function($$v) {\n _vm.$set(_vm.subtitles, \"enabled\", $$v)\n },\n expression: \"subtitles.enabled\"\n }\n },\n [\n _c(\"p\", [\n _vm._v(\n \"Search subtitles for episodes with DOWNLOADED status\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _vm.subtitles.enabled\n ? [\n _c(\n \"config-template\",\n {\n attrs: {\n label: \"Subtitle Languages\",\n labelFor: \"wanted_languages\"\n }\n },\n [\n _c(\"config-subtitle-languages\", {\n attrs: {\n id: \"wanted_languages\",\n languages:\n _vm.subtitles.wantedLanguages\n },\n on: {\n change: function($event) {\n _vm.subtitles.languages = $event.map(\n function(tag) {\n return tag.id\n }\n )\n }\n }\n })\n ],\n 1\n ),\n _vm._v(\" \"),\n _c(\n \"config-toggle-slider\",\n {\n attrs: {\n label:\n \"Download only one language (any)\",\n id: \"subtitles_stop_at_first\"\n },\n model: {\n value: _vm.subtitles.stopAtFirst,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"stopAtFirst\",\n $$v\n )\n },\n expression: \"subtitles.stopAtFirst\"\n }\n },\n [\n _c(\"p\", [\n _vm._v(\n \"Stop downloading subtitles after first download\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-toggle-slider\",\n {\n attrs: {\n label:\n \"Erase subtitles cache on next boot\",\n id: \"subtitles_erase_cache\"\n },\n model: {\n value: _vm.subtitles.eraseCache,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"eraseCache\",\n $$v\n )\n },\n expression: \"subtitles.eraseCache\"\n }\n },\n [\n _c(\"p\", [\n _vm._v(\n \"Erases all subtitles cache files. May fix some subtitles not being found\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-textbox\",\n {\n attrs: {\n label: \"Subtitle Directory\",\n id: \"subtitles_dir\"\n },\n model: {\n value: _vm.subtitles.location,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"location\",\n $$v\n )\n },\n expression: \"subtitles.location\"\n }\n },\n [\n _c(\"span\", [\n _vm._v(\n \"The directory where Medusa should store your \"\n ),\n _c(\"i\", [_vm._v(\"Subtitles\")]),\n _vm._v(\" files.\")\n ]),\n _vm._v(\" \"),\n _c(\"span\", [\n _c(\"b\", [_vm._v(\"Note:\")]),\n _vm._v(\n \" Leave empty if you want store subtitle in episode path.\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-textbox-number\",\n {\n attrs: {\n min: 1,\n step: 1,\n label: \"Subtitle Find Frequency\",\n id: \"subtitles_finder_frequency\"\n },\n model: {\n value: _vm.subtitles.finderFrequency,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"finderFrequency\",\n $$v\n )\n },\n expression: \"subtitles.finderFrequency\"\n }\n },\n [\n _c(\"span\", [\n _vm._v(\n \"time in hours between scans (default: 1)\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-toggle-slider\",\n {\n attrs: {\n label: \"Perfect matches\",\n id: \"subtitles_perfect_match\"\n },\n model: {\n value: _vm.subtitles.perfectMatch,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"perfectMatch\",\n $$v\n )\n },\n expression: \"subtitles.perfectMatch\"\n }\n },\n [\n _c(\"p\", [\n _vm._v(\n \"Only download subtitles that match release group\"\n )\n ]),\n _vm._v(\" \"),\n _c(\"p\", [\n _vm._v(\n \"If disabled you may get out of sync subtitles\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-toggle-slider\",\n {\n attrs: {\n label: \"Subtitles History\",\n id: \"subtitles_history\"\n },\n model: {\n value: _vm.subtitles.logHistory,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"logHistory\",\n $$v\n )\n },\n expression: \"subtitles.logHistory\"\n }\n },\n [\n _c(\"p\", [\n _vm._v(\n \"Log downloaded Subtitle on History page?\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-toggle-slider\",\n {\n attrs: {\n label: \"Subtitles Multi-Language\",\n id: \"subtitles_multi\"\n },\n model: {\n value: _vm.subtitles.multiLanguage,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"multiLanguage\",\n $$v\n )\n },\n expression: \"subtitles.multiLanguage\"\n }\n },\n [\n _c(\"p\", [\n _vm._v(\n \"Append language codes to subtitle filenames?\"\n )\n ]),\n _vm._v(\" \"),\n _c(\"span\", [\n _c(\"b\", [_vm._v(\"Note:\")]),\n _vm._v(\n \" This option is required if you use multiple subtitle languages.\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-toggle-slider\",\n {\n attrs: {\n label: \"Delete unwanted subtitles\",\n id: \"subtitles_keep_only_wanted\"\n },\n model: {\n value: _vm.subtitles.keepOnlyWanted,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"keepOnlyWanted\",\n $$v\n )\n },\n expression: \"subtitles.keepOnlyWanted\"\n }\n },\n [\n _c(\"p\", [\n _vm._v(\n \"Enable to delete unwanted subtitle languages bundled with release\"\n )\n ]),\n _vm._v(\" \"),\n _c(\"p\", [\n _vm._v(\n \"Avoid post-process releases with unwanted language subtitles when feature 'postpone if no subs' is enabled\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-toggle-slider\",\n {\n attrs: {\n label: \"Embedded Subtitles\",\n id: \"embedded_subtitles_all\"\n },\n model: {\n value: _vm.subtitles.ignoreEmbeddedSubs,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"ignoreEmbeddedSubs\",\n $$v\n )\n },\n expression:\n \"subtitles.ignoreEmbeddedSubs\"\n }\n },\n [\n _c(\"p\", [\n _vm._v(\n \"Ignore subtitles embedded inside video file?\"\n )\n ]),\n _vm._v(\" \"),\n _c(\"p\", [\n _c(\"b\", [_vm._v(\"Warning: \")]),\n _vm._v(\"this will ignore \"),\n _c(\"em\", [_vm._v(\"all\")]),\n _vm._v(\n \" embedded subtitles for every video file!\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-toggle-slider\",\n {\n attrs: {\n label: \"Unknown language\",\n id: \"embedded_subtitles_unknown_lang\"\n },\n model: {\n value:\n _vm.subtitles\n .acceptUnknownEmbeddedSubs,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"acceptUnknownEmbeddedSubs\",\n $$v\n )\n },\n expression:\n \"subtitles.acceptUnknownEmbeddedSubs\"\n }\n },\n [\n _c(\"p\", [\n _vm._v(\n \"Consider unknown embedded subtitles as wanted language to avoid postponing the post-processor\"\n )\n ]),\n _vm._v(\" \"),\n _c(\"p\", [\n _vm._v(\n \"Only works with setting 'Postpone post-processing' enabled\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-toggle-slider\",\n {\n attrs: {\n label: \"Hearing Impaired Subtitles\",\n id: \"subtitles_hearing_impaired\"\n },\n model: {\n value: _vm.subtitles.hearingImpaired,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"hearingImpaired\",\n $$v\n )\n },\n expression: \"subtitles.hearingImpaired\"\n }\n },\n [\n _c(\"p\", [\n _vm._v(\n \"Download hearing impaired style subtitles?\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-template\",\n {\n attrs: {\n \"label-for\": \"subtitles_pre_scripts\",\n label: \"Pre-Scripts\"\n }\n },\n [\n _c(\"select-list\", {\n attrs: {\n name: \"subtitles_pre_scripts\",\n id: \"subtitles_pre_scripts\",\n \"list-items\": _vm.subtitles.preScripts\n },\n on: {\n change: function($event) {\n _vm.subtitles.preScripts = $event.map(\n function(x) {\n return x.value\n }\n )\n }\n }\n }),\n _vm._v(\" \"),\n _c(\"p\", [\n _vm._v(\n \"Show's media filename is passed as argument for the pre-scripts. Pre-scripts are executed before trying to find subtitles from usual sources.\"\n )\n ])\n ],\n 1\n ),\n _vm._v(\" \"),\n _c(\n \"config-template\",\n {\n attrs: {\n \"label-for\": \"subtitles_pre_scripts\",\n label: \"Extra Scripts\"\n }\n },\n [\n _c(\"select-list\", {\n attrs: {\n name: \"subtitles_pre_scripts\",\n id: \"subtitles_pre_scripts\",\n \"list-items\":\n _vm.subtitles.extraScripts\n },\n on: {\n change: function($event) {\n _vm.subtitles.extraScripts = $event.map(\n function(x) {\n return x.value\n }\n )\n }\n }\n }),\n _vm._v(\" \"),\n _c(\n \"ul\",\n { staticClass: \"extra-scripts\" },\n [\n _c(\n \"li\",\n [\n _vm._v(\"See the \"),\n _c(\n \"app-link\",\n {\n staticClass: \"wiki\",\n attrs: {\n href: _vm.subtitles.wikiUrl\n }\n },\n [_c(\"strong\", [_vm._v(\"Wiki\")])]\n ),\n _vm._v(\n \" for a script arguments description.\"\n )\n ],\n 1\n ),\n _vm._v(\" \"),\n _c(\"li\", [\n _vm._v(\n \"Additional scripts separated by \"\n ),\n _c(\"b\", [_vm._v(\"|\")]),\n _vm._v(\".\")\n ]),\n _vm._v(\" \"),\n _c(\"li\", [\n _vm._v(\n \"Scripts are called after each episode has searched and downloaded subtitles.\"\n )\n ]),\n _vm._v(\" \"),\n _c(\"li\", [\n _vm._v(\n \"Only Python scripts are allowed to be executed.\"\n )\n ])\n ]\n )\n ],\n 1\n )\n ]\n : _vm._e(),\n _vm._v(\" \"),\n _c(\"input\", {\n staticClass: \"btn-medusa config_submitter\",\n attrs: { type: \"submit\", value: \"Save Changes\" }\n })\n ],\n 2\n )\n ])\n ]\n )\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"v-tab\",\n {\n key: \"subtitles_plugin\",\n attrs: { title: \"Subtitles Plugin\" }\n },\n [\n _c(\n \"div\",\n {\n staticClass: \"row component-group\",\n attrs: { id: \"subtitles-plugin\" }\n },\n [\n _c(\n \"div\",\n {\n staticClass: \"col-xs-12 col-md-2 component-group-desc\"\n },\n [\n _c(\"h3\", [_vm._v(\"Subtitle Providers\")]),\n _vm._v(\" \"),\n _c(\"p\", [\n _vm._v(\n \"Check off and drag the plugins into the order you want them to be used.\"\n )\n ]),\n _vm._v(\" \"),\n _c(\"p\", { staticClass: \"note\" }, [\n _vm._v(\"At least one plugin is required.\")\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"div\",\n { staticClass: \"col-xs-12 col-md-10\" },\n [\n _c(\n \"draggable\",\n {\n staticClass: \"list-group\",\n attrs: {\n id: \"service_order_list\",\n tag: \"ul\",\n handle: \".ui-state-default\"\n },\n model: {\n value: _vm.subtitles.services,\n callback: function($$v) {\n _vm.$set(_vm.subtitles, \"services\", $$v)\n },\n expression: \"subtitles.services\"\n }\n },\n _vm._l(_vm.subtitles.services, function(service) {\n return _c(\n \"li\",\n {\n key: service.name,\n staticClass: \"ui-state-default\",\n attrs: { id: service.name }\n },\n [\n _c(\"input\", {\n directives: [\n {\n name: \"model\",\n rawName: \"v-model\",\n value: service.enabled,\n expression: \"service.enabled\"\n }\n ],\n attrs: {\n type: \"checkbox\",\n id: \"enable_\" + service.name\n },\n domProps: {\n checked: service.enabled,\n checked: Array.isArray(service.enabled)\n ? _vm._i(service.enabled, null) > -1\n : service.enabled\n },\n on: {\n change: function($event) {\n var $$a = service.enabled,\n $$el = $event.target,\n $$c = $$el.checked ? true : false\n if (Array.isArray($$a)) {\n var $$v = null,\n $$i = _vm._i($$a, $$v)\n if ($$el.checked) {\n $$i < 0 &&\n _vm.$set(\n service,\n \"enabled\",\n $$a.concat([$$v])\n )\n } else {\n $$i > -1 &&\n _vm.$set(\n service,\n \"enabled\",\n $$a\n .slice(0, $$i)\n .concat($$a.slice($$i + 1))\n )\n }\n } else {\n _vm.$set(service, \"enabled\", $$c)\n }\n }\n }\n }),\n _vm._v(\" \"),\n _c(\n \"app-link\",\n {\n staticClass: \"imgLink\",\n attrs: { href: service.url }\n },\n [\n _c(\"img\", {\n staticStyle: {\n \"vertical-align\": \"middle\"\n },\n attrs: {\n src:\n \"images/subtitles/\" + service.image,\n alt: service.url,\n title: service.url,\n width: \"16\",\n height: \"16\"\n }\n })\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"span\",\n {\n staticStyle: {\n \"vertical-align\": \"middle\"\n }\n },\n [\n _vm._v(\n _vm._s(\n _vm._f(\"capitalize\")(service.name)\n )\n )\n ]\n ),\n _vm._v(\" \"),\n _c(\"span\", {\n staticClass:\n \"ui-icon ui-icon-arrowthick-2-n-s pull-right\",\n staticStyle: { \"vertical-align\": \"middle\" }\n })\n ],\n 1\n )\n }),\n 0\n ),\n _vm._v(\" \"),\n _c(\"br\"),\n _c(\"input\", {\n staticClass: \"btn-medusa config_submitter\",\n attrs: { type: \"submit\", value: \"Save Changes\" }\n }),\n _c(\"br\")\n ],\n 1\n )\n ]\n )\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"v-tab\",\n { key: \"plugin_settings\", attrs: { title: \"Plugin Settings\" } },\n [\n _c(\n \"div\",\n {\n staticClass: \"row component-group\",\n attrs: { id: \"plugin-settings\" }\n },\n [\n _c(\n \"div\",\n {\n staticClass: \"col-xs-12 col-md-2 component-group-desc\"\n },\n [\n _c(\"h3\", [_vm._v(\"Provider Settings\")]),\n _vm._v(\" \"),\n _c(\"p\", [\n _vm._v(\"Set user and password for each provider.\")\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\"div\", { staticClass: \"col-xs-12 col-md-10\" }, [\n _c(\n \"fieldset\",\n {\n staticClass: \"component-group-list\",\n staticStyle: {\n \"margin-left\": \"50px\",\n \"margin-top\": \"36px\"\n }\n },\n [\n _c(\"config-textbox\", {\n attrs: {\n label: \"Addic7ed User ID\",\n id: \"addic7ed_username\"\n },\n model: {\n value:\n _vm.subtitles.providerLogins.addic7ed.user,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles.providerLogins.addic7ed,\n \"user\",\n $$v\n )\n },\n expression:\n \"subtitles.providerLogins.addic7ed.user\"\n }\n }),\n _vm._v(\" \"),\n _vm.subtitles.providerLogins.addic7ed.user\n ? _c(\n \"div\",\n { staticStyle: { \"margin-bottom\": \"4rem\" } },\n [\n _c(\"p\", { staticStyle: { color: \"red\" } }, [\n _vm._v(\n \"To bypass addic7ed captcha protection we authenticate using a set cookie. The cookie requires your user id and password.\"\n )\n ]),\n _vm._v(\" \"),\n _c(\"span\", [\n _vm._v(\n \"You can find your user id by following these steps\"\n )\n ]),\n _vm._v(\" \"),\n _c(\"ul\", [\n _c(\"li\", [\n _vm._v(\n \"Navigate and login on addic7ed.com\"\n )\n ]),\n _vm._v(\" \"),\n _c(\"li\", [_vm._v(\"Click on My Profile\")]),\n _vm._v(\" \"),\n _c(\"li\", [\n _vm._v(\"Click on your own username\")\n ]),\n _vm._v(\" \"),\n _c(\"li\", [\n _vm._v(\n \"Your user id should now be visible in the address bar\"\n )\n ]),\n _vm._v(\" \"),\n _c(\"li\", [\n _vm._v(\n \"For example: https://www.addic7ed.com/user/12345\"\n )\n ])\n ])\n ]\n )\n : _vm._e(),\n _vm._v(\" \"),\n _c(\"config-textbox\", {\n attrs: {\n type: \"password\",\n label: \"Addic7ed Password\",\n id: \"addic7ed_password\"\n },\n model: {\n value:\n _vm.subtitles.providerLogins.addic7ed.pass,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles.providerLogins.addic7ed,\n \"pass\",\n $$v\n )\n },\n expression:\n \"subtitles.providerLogins.addic7ed.pass\"\n }\n }),\n _vm._v(\" \"),\n _c(\"config-textbox\", {\n attrs: {\n label: \"Opensubtitles User Name\",\n id: \"opensubtitles_username\"\n },\n model: {\n value:\n _vm.subtitles.providerLogins.opensubtitles\n .user,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles.providerLogins.opensubtitles,\n \"user\",\n $$v\n )\n },\n expression:\n \"subtitles.providerLogins.opensubtitles.user\"\n }\n }),\n _vm._v(\" \"),\n _c(\"config-textbox\", {\n attrs: {\n type: \"password\",\n label: \"Opensubtitles Password\",\n id: \"opensubtitles_password\"\n },\n model: {\n value:\n _vm.subtitles.providerLogins.opensubtitles\n .pass,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles.providerLogins.opensubtitles,\n \"pass\",\n $$v\n )\n },\n expression:\n \"subtitles.providerLogins.opensubtitles.pass\"\n }\n }),\n _vm._v(\" \"),\n _c(\"config-textbox\", {\n attrs: {\n label: \"Legendastv User Name\",\n id: \"legandas_username\"\n },\n model: {\n value:\n _vm.subtitles.providerLogins.legendastv.user,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles.providerLogins.legendastv,\n \"user\",\n $$v\n )\n },\n expression:\n \"subtitles.providerLogins.legendastv.user\"\n }\n }),\n _vm._v(\" \"),\n _c(\"config-textbox\", {\n attrs: {\n type: \"password\",\n label: \"Legendastv Password\",\n id: \"legandas_password\"\n },\n model: {\n value:\n _vm.subtitles.providerLogins.legendastv.pass,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles.providerLogins.legendastv,\n \"pass\",\n $$v\n )\n },\n expression:\n \"subtitles.providerLogins.legendastv.pass\"\n }\n }),\n _vm._v(\" \"),\n _c(\"input\", {\n staticClass: \"btn-medusa config_submitter\",\n attrs: { type: \"submit\", value: \"Save Changes\" }\n }),\n _c(\"br\")\n ],\n 1\n )\n ])\n ]\n )\n ]\n )\n ],\n 1\n )\n ],\n 1\n )\n ])\n ])\n}\nvar staticRenderFns = []\nrender._withStripped = true\n\n\n\n//# sourceURL=webpack://slim/./src/components/config-subtitles.vue?./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/vue-loader/lib/index.js??vue-loader-options"); /***/ }), diff --git a/themes/light/assets/js/medusa-runtime.js b/themes/light/assets/js/medusa-runtime.js index d1c03e3f74..fc21668246 100644 --- a/themes/light/assets/js/medusa-runtime.js +++ b/themes/light/assets/js/medusa-runtime.js @@ -191,7 +191,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var vuex__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! vuex */ \"./node_modules/vuex/dist/vuex.esm.js\");\n/* harmony import */ var _helpers__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./helpers */ \"./src/components/helpers/index.js\");\n/* harmony import */ var vuedraggable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! vuedraggable */ \"./node_modules/vuedraggable/dist/vuedraggable.umd.js\");\n/* harmony import */ var vuedraggable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(vuedraggable__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var vue_nav_tabs_dist_vue_tabs_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! vue-nav-tabs/dist/vue-tabs.js */ \"./node_modules/vue-nav-tabs/dist/vue-tabs.js\");\n/* harmony import */ var vue_nav_tabs_dist_vue_tabs_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(vue_nav_tabs_dist_vue_tabs_js__WEBPACK_IMPORTED_MODULE_2__);\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n\n\n\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({\n name: 'config-subtitles',\n components: {\n AppLink: _helpers__WEBPACK_IMPORTED_MODULE_0__.AppLink,\n Draggable: (vuedraggable__WEBPACK_IMPORTED_MODULE_1___default()),\n ConfigSubtitleLanguages: _helpers__WEBPACK_IMPORTED_MODULE_0__.ConfigSubtitleLanguages,\n ConfigTemplate: _helpers__WEBPACK_IMPORTED_MODULE_0__.ConfigTemplate,\n ConfigTextbox: _helpers__WEBPACK_IMPORTED_MODULE_0__.ConfigTextbox,\n ConfigTextboxNumber: _helpers__WEBPACK_IMPORTED_MODULE_0__.ConfigTextboxNumber,\n ConfigToggleSlider: _helpers__WEBPACK_IMPORTED_MODULE_0__.ConfigToggleSlider,\n SelectList: _helpers__WEBPACK_IMPORTED_MODULE_0__.SelectList,\n VueTabs: vue_nav_tabs_dist_vue_tabs_js__WEBPACK_IMPORTED_MODULE_2__.VueTabs,\n VTab: vue_nav_tabs_dist_vue_tabs_js__WEBPACK_IMPORTED_MODULE_2__.VTab\n },\n\n data() {\n return {\n saving: false\n };\n },\n\n methods: { ...(0,vuex__WEBPACK_IMPORTED_MODULE_3__.mapActions)(['setConfig']),\n\n async save() {\n const {\n subtitles,\n setConfig\n } = this; // Disable the save button until we're done.\n\n this.saving = true;\n const section = 'main'; // Remove codeFilter key from object.\n\n const {\n codeFilter,\n wantedLanguages,\n ...rest\n } = subtitles;\n\n try {\n await setConfig({\n section,\n config: {\n subtitles: rest\n }\n });\n this.$snotify.success('Saved Subtitles config', 'Saved', {\n timeout: 5000\n });\n } catch (error) {\n this.$snotify.error('Error while trying to save subtitles config', 'Error');\n } finally {\n this.saving = false;\n }\n }\n\n },\n computed: { ...(0,vuex__WEBPACK_IMPORTED_MODULE_3__.mapState)({\n subtitles: state => state.config.subtitles,\n layout: state => state.config.layout\n })\n },\n filters: {\n capitalize: str => str.replace(/\\b\\w/g, str => str.toUpperCase())\n }\n});\n\n//# sourceURL=webpack://slim/./src/components/config-subtitles.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-1%5B0%5D.rules%5B0%5D!./node_modules/vue-loader/lib/index.js??vue-loader-options"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var vuex__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! vuex */ \"./node_modules/vuex/dist/vuex.esm.js\");\n/* harmony import */ var _helpers__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./helpers */ \"./src/components/helpers/index.js\");\n/* harmony import */ var vuedraggable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! vuedraggable */ \"./node_modules/vuedraggable/dist/vuedraggable.umd.js\");\n/* harmony import */ var vuedraggable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(vuedraggable__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var vue_nav_tabs_dist_vue_tabs_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! vue-nav-tabs/dist/vue-tabs.js */ \"./node_modules/vue-nav-tabs/dist/vue-tabs.js\");\n/* harmony import */ var vue_nav_tabs_dist_vue_tabs_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(vue_nav_tabs_dist_vue_tabs_js__WEBPACK_IMPORTED_MODULE_2__);\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n\n\n\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({\n name: 'config-subtitles',\n components: {\n AppLink: _helpers__WEBPACK_IMPORTED_MODULE_0__.AppLink,\n Draggable: (vuedraggable__WEBPACK_IMPORTED_MODULE_1___default()),\n ConfigSubtitleLanguages: _helpers__WEBPACK_IMPORTED_MODULE_0__.ConfigSubtitleLanguages,\n ConfigTemplate: _helpers__WEBPACK_IMPORTED_MODULE_0__.ConfigTemplate,\n ConfigTextbox: _helpers__WEBPACK_IMPORTED_MODULE_0__.ConfigTextbox,\n ConfigTextboxNumber: _helpers__WEBPACK_IMPORTED_MODULE_0__.ConfigTextboxNumber,\n ConfigToggleSlider: _helpers__WEBPACK_IMPORTED_MODULE_0__.ConfigToggleSlider,\n SelectList: _helpers__WEBPACK_IMPORTED_MODULE_0__.SelectList,\n VueTabs: vue_nav_tabs_dist_vue_tabs_js__WEBPACK_IMPORTED_MODULE_2__.VueTabs,\n VTab: vue_nav_tabs_dist_vue_tabs_js__WEBPACK_IMPORTED_MODULE_2__.VTab\n },\n\n data() {\n return {\n saving: false\n };\n },\n\n methods: { ...(0,vuex__WEBPACK_IMPORTED_MODULE_3__.mapActions)(['setConfig']),\n\n async save() {\n const {\n subtitles,\n setConfig\n } = this; // Disable the save button until we're done.\n\n this.saving = true;\n const section = 'main'; // Remove codeFilter key from object.\n\n const {\n codeFilter,\n wantedLanguages,\n ...rest\n } = subtitles;\n\n try {\n await setConfig({\n section,\n config: {\n subtitles: rest\n }\n });\n this.$snotify.success('Saved Subtitles config', 'Saved', {\n timeout: 5000\n });\n } catch (error) {\n this.$snotify.error('Error while trying to save subtitles config', 'Error');\n } finally {\n this.saving = false;\n }\n }\n\n },\n computed: { ...(0,vuex__WEBPACK_IMPORTED_MODULE_3__.mapState)({\n subtitles: state => state.config.subtitles,\n layout: state => state.config.layout\n })\n },\n filters: {\n capitalize: str => str.replace(/\\b\\w/g, str => str.toUpperCase())\n }\n});\n\n//# sourceURL=webpack://slim/./src/components/config-subtitles.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-1%5B0%5D.rules%5B0%5D!./node_modules/vue-loader/lib/index.js??vue-loader-options"); /***/ }), @@ -7277,7 +7277,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"render\": () => (/* binding */ render),\n/* harmony export */ \"staticRenderFns\": () => (/* binding */ staticRenderFns)\n/* harmony export */ });\nvar render = function() {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\"div\", { attrs: { id: \"config\" } }, [\n _c(\"div\", { attrs: { id: \"config-content\" } }, [\n _c(\n \"form\",\n {\n attrs: {\n id: \"configForm\",\n action: \"config/subtitles/saveSubtitles\",\n method: \"post\"\n },\n on: {\n submit: function($event) {\n $event.preventDefault()\n return _vm.save.apply(null, arguments)\n }\n }\n },\n [\n _c(\n \"vue-tabs\",\n [\n _c(\n \"v-tab\",\n {\n key: \"subtitles_search\",\n attrs: { title: \"Subtitles Search\" }\n },\n [\n _c(\n \"div\",\n {\n staticClass: \"row component-group\",\n attrs: { id: \"subtitles-search\" }\n },\n [\n _c(\n \"div\",\n {\n staticClass: \"component-group-desc col-xs-12 col-md-2\"\n },\n [\n _c(\"h3\", [_vm._v(\"Subtitles Search\")]),\n _vm._v(\" \"),\n _c(\"p\", [\n _vm._v(\n \"Settings that dictate how Medusa handles subtitles search results.\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\"div\", { staticClass: \"col-xs-12 col-md-10\" }, [\n _c(\n \"fieldset\",\n { staticClass: \"component-group-list\" },\n [\n _c(\n \"config-toggle-slider\",\n {\n attrs: {\n label: \"Search Subtitles\",\n id: \"search_subtitles\"\n },\n model: {\n value: _vm.subtitles.enabled,\n callback: function($$v) {\n _vm.$set(_vm.subtitles, \"enabled\", $$v)\n },\n expression: \"subtitles.enabled\"\n }\n },\n [\n _c(\"p\", [\n _vm._v(\n \"Search subtitles for episodes with DOWNLOADED status\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _vm.subtitles.enabled\n ? [\n _c(\n \"config-template\",\n {\n attrs: {\n label: \"Subtitle Languages\",\n labelFor: \"wanted_languages\"\n }\n },\n [\n _c(\"config-subtitle-languages\", {\n attrs: {\n id: \"wanted_languages\",\n languages:\n _vm.subtitles.wantedLanguages\n },\n on: {\n change: function($event) {\n _vm.subtitles.languages = $event.map(\n function(tag) {\n return tag.id\n }\n )\n }\n }\n })\n ],\n 1\n ),\n _vm._v(\" \"),\n _c(\n \"config-toggle-slider\",\n {\n attrs: {\n label:\n \"Download only one language (any)\",\n id: \"subtitles_stop_at_first\"\n },\n model: {\n value: _vm.subtitles.stopAtFirst,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"stopAtFirst\",\n $$v\n )\n },\n expression: \"subtitles.stopAtFirst\"\n }\n },\n [\n _c(\"p\", [\n _vm._v(\n \"Stop downloading subtitles after first download\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-toggle-slider\",\n {\n attrs: {\n label:\n \"Erase subtitles cache on next boot\",\n id: \"subtitles_erase_cache\"\n },\n model: {\n value: _vm.subtitles.eraseCache,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"eraseCache\",\n $$v\n )\n },\n expression: \"subtitles.eraseCache\"\n }\n },\n [\n _c(\"p\", [\n _vm._v(\n \"Erases all subtitles cache files. May fix some subtitles not being found\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-textbox\",\n {\n attrs: {\n label: \"Subtitle Directory\",\n id: \"subtitles_dir\"\n },\n model: {\n value: _vm.subtitles.location,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"location\",\n $$v\n )\n },\n expression: \"subtitles.location\"\n }\n },\n [\n _c(\"span\", [\n _vm._v(\n \"The directory where Medusa should store your \"\n ),\n _c(\"i\", [_vm._v(\"Subtitles\")]),\n _vm._v(\" files.\")\n ]),\n _vm._v(\" \"),\n _c(\"span\", [\n _c(\"b\", [_vm._v(\"Note:\")]),\n _vm._v(\n \" Leave empty if you want store subtitle in episode path.\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-textbox-number\",\n {\n attrs: {\n min: 1,\n step: 1,\n label: \"Subtitle Find Frequency\",\n id: \"subtitles_finder_frequency\"\n },\n model: {\n value: _vm.subtitles.finderFrequency,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"finderFrequency\",\n $$v\n )\n },\n expression: \"subtitles.finderFrequency\"\n }\n },\n [\n _c(\"span\", [\n _vm._v(\n \"time in hours between scans (default: 1)\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-toggle-slider\",\n {\n attrs: {\n label: \"Perfect matches\",\n id: \"subtitles_perfect_match\"\n },\n model: {\n value: _vm.subtitles.perfectMatch,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"perfectMatch\",\n $$v\n )\n },\n expression: \"subtitles.perfectMatch\"\n }\n },\n [\n _c(\"p\", [\n _vm._v(\n \"Only download subtitles that match release group\"\n )\n ]),\n _vm._v(\" \"),\n _c(\"p\", [\n _vm._v(\n \"If disabled you may get out of sync subtitles\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-toggle-slider\",\n {\n attrs: {\n label: \"Subtitles History\",\n id: \"subtitles_history\"\n },\n model: {\n value: _vm.subtitles.logHistory,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"logHistory\",\n $$v\n )\n },\n expression: \"subtitles.logHistory\"\n }\n },\n [\n _c(\"p\", [\n _vm._v(\n \"Log downloaded Subtitle on History page?\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-toggle-slider\",\n {\n attrs: {\n label: \"Subtitles Multi-Language\",\n id: \"subtitles_multi\"\n },\n model: {\n value: _vm.subtitles.multiLanguage,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"multiLanguage\",\n $$v\n )\n },\n expression: \"subtitles.multiLanguage\"\n }\n },\n [\n _c(\"p\", [\n _vm._v(\n \"Append language codes to subtitle filenames?\"\n )\n ]),\n _vm._v(\" \"),\n _c(\"span\", [\n _c(\"b\", [_vm._v(\"Note:\")]),\n _vm._v(\n \" This option is required if you use multiple subtitle languages.\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-toggle-slider\",\n {\n attrs: {\n label: \"Delete unwanted subtitles\",\n id: \"subtitles_keep_only_wanted\"\n },\n model: {\n value: _vm.subtitles.keepOnlyWanted,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"keepOnlyWanted\",\n $$v\n )\n },\n expression: \"subtitles.keepOnlyWanted\"\n }\n },\n [\n _c(\"p\", [\n _vm._v(\n \"Enable to delete unwanted subtitle languages bundled with release\"\n )\n ]),\n _vm._v(\" \"),\n _c(\"p\", [\n _vm._v(\n \"Avoid post-process releases with unwanted language subtitles when feature 'postpone if no subs' is enabled\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-toggle-slider\",\n {\n attrs: {\n label: \"Embedded Subtitles\",\n id: \"embedded_subtitles_all\"\n },\n model: {\n value: _vm.subtitles.ignoreEmbeddedSubs,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"ignoreEmbeddedSubs\",\n $$v\n )\n },\n expression:\n \"subtitles.ignoreEmbeddedSubs\"\n }\n },\n [\n _c(\"p\", [\n _vm._v(\n \"Ignore subtitles embedded inside video file?\"\n )\n ]),\n _vm._v(\" \"),\n _c(\"p\", [\n _c(\"b\", [_vm._v(\"Warning: \")]),\n _vm._v(\"this will ignore \"),\n _c(\"em\", [_vm._v(\"all\")]),\n _vm._v(\n \" embedded subtitles for every video file!\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-toggle-slider\",\n {\n attrs: {\n label: \"Unknown language\",\n id: \"embedded_subtitles_unknown_lang\"\n },\n model: {\n value:\n _vm.subtitles\n .acceptUnknownEmbeddedSubs,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"acceptUnknownEmbeddedSubs\",\n $$v\n )\n },\n expression:\n \"subtitles.acceptUnknownEmbeddedSubs\"\n }\n },\n [\n _c(\"p\", [\n _vm._v(\n \"Consider unknown embedded subtitles as wanted language to avoid postponing the post-processor\"\n )\n ]),\n _vm._v(\" \"),\n _c(\"p\", [\n _vm._v(\n \"Only works with setting 'Postpone post-processing' enabled\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-toggle-slider\",\n {\n attrs: {\n label: \"Hearing Impaired Subtitles\",\n id: \"subtitles_hearing_impaired\"\n },\n model: {\n value: _vm.subtitles.hearingImpaired,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"hearingImpaired\",\n $$v\n )\n },\n expression: \"subtitles.hearingImpaired\"\n }\n },\n [\n _c(\"p\", [\n _vm._v(\n \"Download hearing impaired style subtitles?\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-template\",\n {\n attrs: {\n \"label-for\": \"subtitles_pre_scripts\",\n label: \"Pre-Scripts\"\n }\n },\n [\n _c(\"select-list\", {\n attrs: {\n name: \"subtitles_pre_scripts\",\n id: \"subtitles_pre_scripts\",\n \"list-items\": _vm.subtitles.preScripts\n },\n on: {\n change: function($event) {\n _vm.subtitles.preScripts = $event.map(\n function(x) {\n return x.value\n }\n )\n }\n }\n }),\n _vm._v(\" \"),\n _c(\"p\", [\n _vm._v(\n \"Show's media filename is passed as argument for the pre-scripts. Pre-scripts are executed before trying to find subtitles from usual sources.\"\n )\n ])\n ],\n 1\n ),\n _vm._v(\" \"),\n _c(\n \"config-template\",\n {\n attrs: {\n \"label-for\": \"subtitles_pre_scripts\",\n label: \"Extra Scripts\"\n }\n },\n [\n _c(\"select-list\", {\n attrs: {\n name: \"subtitles_pre_scripts\",\n id: \"subtitles_pre_scripts\",\n \"list-items\":\n _vm.subtitles.extraScripts\n },\n on: {\n change: function($event) {\n _vm.subtitles.extraScripts = $event.map(\n function(x) {\n return x.value\n }\n )\n }\n }\n }),\n _vm._v(\" \"),\n _c(\n \"ul\",\n { staticClass: \"extra-scripts\" },\n [\n _c(\n \"li\",\n [\n _vm._v(\"See the \"),\n _c(\n \"app-link\",\n {\n staticClass: \"wiki\",\n attrs: {\n href: _vm.subtitles.wikiUrl\n }\n },\n [_c(\"strong\", [_vm._v(\"Wiki\")])]\n ),\n _vm._v(\n \" for a script arguments description.\"\n )\n ],\n 1\n ),\n _vm._v(\" \"),\n _c(\"li\", [\n _vm._v(\n \"Additional scripts separated by \"\n ),\n _c(\"b\", [_vm._v(\"|\")]),\n _vm._v(\".\")\n ]),\n _vm._v(\" \"),\n _c(\"li\", [\n _vm._v(\n \"Scripts are called after each episode has searched and downloaded subtitles.\"\n )\n ]),\n _vm._v(\" \"),\n _c(\"li\", [\n _vm._v(\n \"Only Python scripts are allowed to be executed.\"\n )\n ])\n ]\n )\n ],\n 1\n )\n ]\n : _vm._e(),\n _vm._v(\" \"),\n _c(\"input\", {\n staticClass: \"btn-medusa config_submitter\",\n attrs: { type: \"submit\", value: \"Save Changes\" }\n })\n ],\n 2\n )\n ])\n ]\n )\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"v-tab\",\n {\n key: \"subtitles_plugin\",\n attrs: { title: \"Subtitles Plugin\" }\n },\n [\n _c(\n \"div\",\n {\n staticClass: \"row component-group\",\n attrs: { id: \"subtitles-plugin\" }\n },\n [\n _c(\n \"div\",\n {\n staticClass: \"col-xs-12 col-md-2 component-group-desc\"\n },\n [\n _c(\"h3\", [_vm._v(\"Subtitle Providers\")]),\n _vm._v(\" \"),\n _c(\"p\", [\n _vm._v(\n \"Check off and drag the plugins into the order you want them to be used.\"\n )\n ]),\n _vm._v(\" \"),\n _c(\"p\", { staticClass: \"note\" }, [\n _vm._v(\"At least one plugin is required.\")\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"div\",\n { staticClass: \"col-xs-12 col-md-10\" },\n [\n _c(\n \"draggable\",\n {\n staticClass: \"list-group\",\n attrs: {\n id: \"service_order_list\",\n tag: \"ul\",\n handle: \".ui-state-default\"\n },\n model: {\n value: _vm.subtitles.services,\n callback: function($$v) {\n _vm.$set(_vm.subtitles, \"services\", $$v)\n },\n expression: \"subtitles.services\"\n }\n },\n _vm._l(_vm.subtitles.services, function(service) {\n return _c(\n \"li\",\n {\n key: service.name,\n staticClass: \"ui-state-default\",\n attrs: { id: service.name }\n },\n [\n _c(\"input\", {\n directives: [\n {\n name: \"model\",\n rawName: \"v-model\",\n value: service.enabled,\n expression: \"service.enabled\"\n }\n ],\n attrs: {\n type: \"checkbox\",\n id: \"enable_\" + service.name\n },\n domProps: {\n checked: service.enabled,\n checked: Array.isArray(service.enabled)\n ? _vm._i(service.enabled, null) > -1\n : service.enabled\n },\n on: {\n change: function($event) {\n var $$a = service.enabled,\n $$el = $event.target,\n $$c = $$el.checked ? true : false\n if (Array.isArray($$a)) {\n var $$v = null,\n $$i = _vm._i($$a, $$v)\n if ($$el.checked) {\n $$i < 0 &&\n _vm.$set(\n service,\n \"enabled\",\n $$a.concat([$$v])\n )\n } else {\n $$i > -1 &&\n _vm.$set(\n service,\n \"enabled\",\n $$a\n .slice(0, $$i)\n .concat($$a.slice($$i + 1))\n )\n }\n } else {\n _vm.$set(service, \"enabled\", $$c)\n }\n }\n }\n }),\n _vm._v(\" \"),\n _c(\n \"app-link\",\n {\n staticClass: \"imgLink\",\n attrs: { href: service.url }\n },\n [\n _c(\"img\", {\n staticStyle: {\n \"vertical-align\": \"middle\"\n },\n attrs: {\n src:\n \"images/subtitles/\" + service.image,\n alt: service.url,\n title: service.url,\n width: \"16\",\n height: \"16\"\n }\n })\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"span\",\n {\n staticStyle: {\n \"vertical-align\": \"middle\"\n }\n },\n [\n _vm._v(\n _vm._s(\n _vm._f(\"capitalize\")(service.name)\n )\n )\n ]\n ),\n _vm._v(\" \"),\n _c(\"span\", {\n staticClass:\n \"ui-icon ui-icon-arrowthick-2-n-s pull-right\",\n staticStyle: { \"vertical-align\": \"middle\" }\n })\n ],\n 1\n )\n }),\n 0\n ),\n _vm._v(\" \"),\n _c(\"br\"),\n _c(\"input\", {\n staticClass: \"btn-medusa config_submitter\",\n attrs: { type: \"submit\", value: \"Save Changes\" }\n }),\n _c(\"br\")\n ],\n 1\n )\n ]\n )\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"v-tab\",\n { key: \"plugin_settings\", attrs: { title: \"Plugin Settings\" } },\n [\n _c(\n \"div\",\n {\n staticClass: \"row component-group\",\n attrs: { id: \"plugin-settings\" }\n },\n [\n _c(\n \"div\",\n {\n staticClass: \"col-xs-12 col-md-2 component-group-desc\"\n },\n [\n _c(\"h3\", [_vm._v(\"Provider Settings\")]),\n _vm._v(\" \"),\n _c(\"p\", [\n _vm._v(\"Set user and password for each provider.\")\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\"div\", { staticClass: \"col-xs-12 col-md-10\" }, [\n _c(\n \"fieldset\",\n {\n staticClass: \"component-group-list\",\n staticStyle: {\n \"margin-left\": \"50px\",\n \"margin-top\": \"36px\"\n }\n },\n [\n _c(\"config-textbox\", {\n attrs: {\n label: \"Addic7ed User Name\",\n id: \"addic7ed_username\"\n },\n model: {\n value:\n _vm.subtitles.providerLogins.addic7ed.user,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles.providerLogins.addic7ed,\n \"user\",\n $$v\n )\n },\n expression:\n \"subtitles.providerLogins.addic7ed.user\"\n }\n }),\n _vm._v(\" \"),\n _c(\"config-textbox\", {\n attrs: {\n type: \"password\",\n label: \"Addic7ed Password\",\n id: \"addic7ed_password\"\n },\n model: {\n value:\n _vm.subtitles.providerLogins.addic7ed.pass,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles.providerLogins.addic7ed,\n \"pass\",\n $$v\n )\n },\n expression:\n \"subtitles.providerLogins.addic7ed.pass\"\n }\n }),\n _vm._v(\" \"),\n _c(\"config-textbox\", {\n attrs: {\n label: \"Opensubtitles User Name\",\n id: \"opensubtitles_username\"\n },\n model: {\n value:\n _vm.subtitles.providerLogins.opensubtitles\n .user,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles.providerLogins.opensubtitles,\n \"user\",\n $$v\n )\n },\n expression:\n \"subtitles.providerLogins.opensubtitles.user\"\n }\n }),\n _vm._v(\" \"),\n _c(\"config-textbox\", {\n attrs: {\n type: \"password\",\n label: \"Opensubtitles Password\",\n id: \"opensubtitles_password\"\n },\n model: {\n value:\n _vm.subtitles.providerLogins.opensubtitles\n .pass,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles.providerLogins.opensubtitles,\n \"pass\",\n $$v\n )\n },\n expression:\n \"subtitles.providerLogins.opensubtitles.pass\"\n }\n }),\n _vm._v(\" \"),\n _c(\"config-textbox\", {\n attrs: {\n label: \"Legendastv User Name\",\n id: \"legandas_username\"\n },\n model: {\n value:\n _vm.subtitles.providerLogins.legendastv.user,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles.providerLogins.legendastv,\n \"user\",\n $$v\n )\n },\n expression:\n \"subtitles.providerLogins.legendastv.user\"\n }\n }),\n _vm._v(\" \"),\n _c(\"config-textbox\", {\n attrs: {\n type: \"password\",\n label: \"Legendastv Password\",\n id: \"legandas_password\"\n },\n model: {\n value:\n _vm.subtitles.providerLogins.legendastv.pass,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles.providerLogins.legendastv,\n \"pass\",\n $$v\n )\n },\n expression:\n \"subtitles.providerLogins.legendastv.pass\"\n }\n }),\n _vm._v(\" \"),\n _c(\"input\", {\n staticClass: \"btn-medusa config_submitter\",\n attrs: { type: \"submit\", value: \"Save Changes\" }\n }),\n _c(\"br\")\n ],\n 1\n )\n ])\n ]\n )\n ]\n )\n ],\n 1\n )\n ],\n 1\n )\n ])\n ])\n}\nvar staticRenderFns = []\nrender._withStripped = true\n\n\n\n//# sourceURL=webpack://slim/./src/components/config-subtitles.vue?./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/vue-loader/lib/index.js??vue-loader-options"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"render\": () => (/* binding */ render),\n/* harmony export */ \"staticRenderFns\": () => (/* binding */ staticRenderFns)\n/* harmony export */ });\nvar render = function() {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\"div\", { attrs: { id: \"config\" } }, [\n _c(\"div\", { attrs: { id: \"config-content\" } }, [\n _c(\n \"form\",\n {\n attrs: {\n id: \"configForm\",\n action: \"config/subtitles/saveSubtitles\",\n method: \"post\"\n },\n on: {\n submit: function($event) {\n $event.preventDefault()\n return _vm.save.apply(null, arguments)\n }\n }\n },\n [\n _c(\n \"vue-tabs\",\n [\n _c(\n \"v-tab\",\n {\n key: \"subtitles_search\",\n attrs: { title: \"Subtitles Search\" }\n },\n [\n _c(\n \"div\",\n {\n staticClass: \"row component-group\",\n attrs: { id: \"subtitles-search\" }\n },\n [\n _c(\n \"div\",\n {\n staticClass: \"component-group-desc col-xs-12 col-md-2\"\n },\n [\n _c(\"h3\", [_vm._v(\"Subtitles Search\")]),\n _vm._v(\" \"),\n _c(\"p\", [\n _vm._v(\n \"Settings that dictate how Medusa handles subtitles search results.\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\"div\", { staticClass: \"col-xs-12 col-md-10\" }, [\n _c(\n \"fieldset\",\n { staticClass: \"component-group-list\" },\n [\n _c(\n \"config-toggle-slider\",\n {\n attrs: {\n label: \"Search Subtitles\",\n id: \"search_subtitles\"\n },\n model: {\n value: _vm.subtitles.enabled,\n callback: function($$v) {\n _vm.$set(_vm.subtitles, \"enabled\", $$v)\n },\n expression: \"subtitles.enabled\"\n }\n },\n [\n _c(\"p\", [\n _vm._v(\n \"Search subtitles for episodes with DOWNLOADED status\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _vm.subtitles.enabled\n ? [\n _c(\n \"config-template\",\n {\n attrs: {\n label: \"Subtitle Languages\",\n labelFor: \"wanted_languages\"\n }\n },\n [\n _c(\"config-subtitle-languages\", {\n attrs: {\n id: \"wanted_languages\",\n languages:\n _vm.subtitles.wantedLanguages\n },\n on: {\n change: function($event) {\n _vm.subtitles.languages = $event.map(\n function(tag) {\n return tag.id\n }\n )\n }\n }\n })\n ],\n 1\n ),\n _vm._v(\" \"),\n _c(\n \"config-toggle-slider\",\n {\n attrs: {\n label:\n \"Download only one language (any)\",\n id: \"subtitles_stop_at_first\"\n },\n model: {\n value: _vm.subtitles.stopAtFirst,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"stopAtFirst\",\n $$v\n )\n },\n expression: \"subtitles.stopAtFirst\"\n }\n },\n [\n _c(\"p\", [\n _vm._v(\n \"Stop downloading subtitles after first download\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-toggle-slider\",\n {\n attrs: {\n label:\n \"Erase subtitles cache on next boot\",\n id: \"subtitles_erase_cache\"\n },\n model: {\n value: _vm.subtitles.eraseCache,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"eraseCache\",\n $$v\n )\n },\n expression: \"subtitles.eraseCache\"\n }\n },\n [\n _c(\"p\", [\n _vm._v(\n \"Erases all subtitles cache files. May fix some subtitles not being found\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-textbox\",\n {\n attrs: {\n label: \"Subtitle Directory\",\n id: \"subtitles_dir\"\n },\n model: {\n value: _vm.subtitles.location,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"location\",\n $$v\n )\n },\n expression: \"subtitles.location\"\n }\n },\n [\n _c(\"span\", [\n _vm._v(\n \"The directory where Medusa should store your \"\n ),\n _c(\"i\", [_vm._v(\"Subtitles\")]),\n _vm._v(\" files.\")\n ]),\n _vm._v(\" \"),\n _c(\"span\", [\n _c(\"b\", [_vm._v(\"Note:\")]),\n _vm._v(\n \" Leave empty if you want store subtitle in episode path.\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-textbox-number\",\n {\n attrs: {\n min: 1,\n step: 1,\n label: \"Subtitle Find Frequency\",\n id: \"subtitles_finder_frequency\"\n },\n model: {\n value: _vm.subtitles.finderFrequency,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"finderFrequency\",\n $$v\n )\n },\n expression: \"subtitles.finderFrequency\"\n }\n },\n [\n _c(\"span\", [\n _vm._v(\n \"time in hours between scans (default: 1)\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-toggle-slider\",\n {\n attrs: {\n label: \"Perfect matches\",\n id: \"subtitles_perfect_match\"\n },\n model: {\n value: _vm.subtitles.perfectMatch,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"perfectMatch\",\n $$v\n )\n },\n expression: \"subtitles.perfectMatch\"\n }\n },\n [\n _c(\"p\", [\n _vm._v(\n \"Only download subtitles that match release group\"\n )\n ]),\n _vm._v(\" \"),\n _c(\"p\", [\n _vm._v(\n \"If disabled you may get out of sync subtitles\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-toggle-slider\",\n {\n attrs: {\n label: \"Subtitles History\",\n id: \"subtitles_history\"\n },\n model: {\n value: _vm.subtitles.logHistory,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"logHistory\",\n $$v\n )\n },\n expression: \"subtitles.logHistory\"\n }\n },\n [\n _c(\"p\", [\n _vm._v(\n \"Log downloaded Subtitle on History page?\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-toggle-slider\",\n {\n attrs: {\n label: \"Subtitles Multi-Language\",\n id: \"subtitles_multi\"\n },\n model: {\n value: _vm.subtitles.multiLanguage,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"multiLanguage\",\n $$v\n )\n },\n expression: \"subtitles.multiLanguage\"\n }\n },\n [\n _c(\"p\", [\n _vm._v(\n \"Append language codes to subtitle filenames?\"\n )\n ]),\n _vm._v(\" \"),\n _c(\"span\", [\n _c(\"b\", [_vm._v(\"Note:\")]),\n _vm._v(\n \" This option is required if you use multiple subtitle languages.\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-toggle-slider\",\n {\n attrs: {\n label: \"Delete unwanted subtitles\",\n id: \"subtitles_keep_only_wanted\"\n },\n model: {\n value: _vm.subtitles.keepOnlyWanted,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"keepOnlyWanted\",\n $$v\n )\n },\n expression: \"subtitles.keepOnlyWanted\"\n }\n },\n [\n _c(\"p\", [\n _vm._v(\n \"Enable to delete unwanted subtitle languages bundled with release\"\n )\n ]),\n _vm._v(\" \"),\n _c(\"p\", [\n _vm._v(\n \"Avoid post-process releases with unwanted language subtitles when feature 'postpone if no subs' is enabled\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-toggle-slider\",\n {\n attrs: {\n label: \"Embedded Subtitles\",\n id: \"embedded_subtitles_all\"\n },\n model: {\n value: _vm.subtitles.ignoreEmbeddedSubs,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"ignoreEmbeddedSubs\",\n $$v\n )\n },\n expression:\n \"subtitles.ignoreEmbeddedSubs\"\n }\n },\n [\n _c(\"p\", [\n _vm._v(\n \"Ignore subtitles embedded inside video file?\"\n )\n ]),\n _vm._v(\" \"),\n _c(\"p\", [\n _c(\"b\", [_vm._v(\"Warning: \")]),\n _vm._v(\"this will ignore \"),\n _c(\"em\", [_vm._v(\"all\")]),\n _vm._v(\n \" embedded subtitles for every video file!\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-toggle-slider\",\n {\n attrs: {\n label: \"Unknown language\",\n id: \"embedded_subtitles_unknown_lang\"\n },\n model: {\n value:\n _vm.subtitles\n .acceptUnknownEmbeddedSubs,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"acceptUnknownEmbeddedSubs\",\n $$v\n )\n },\n expression:\n \"subtitles.acceptUnknownEmbeddedSubs\"\n }\n },\n [\n _c(\"p\", [\n _vm._v(\n \"Consider unknown embedded subtitles as wanted language to avoid postponing the post-processor\"\n )\n ]),\n _vm._v(\" \"),\n _c(\"p\", [\n _vm._v(\n \"Only works with setting 'Postpone post-processing' enabled\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-toggle-slider\",\n {\n attrs: {\n label: \"Hearing Impaired Subtitles\",\n id: \"subtitles_hearing_impaired\"\n },\n model: {\n value: _vm.subtitles.hearingImpaired,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles,\n \"hearingImpaired\",\n $$v\n )\n },\n expression: \"subtitles.hearingImpaired\"\n }\n },\n [\n _c(\"p\", [\n _vm._v(\n \"Download hearing impaired style subtitles?\"\n )\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"config-template\",\n {\n attrs: {\n \"label-for\": \"subtitles_pre_scripts\",\n label: \"Pre-Scripts\"\n }\n },\n [\n _c(\"select-list\", {\n attrs: {\n name: \"subtitles_pre_scripts\",\n id: \"subtitles_pre_scripts\",\n \"list-items\": _vm.subtitles.preScripts\n },\n on: {\n change: function($event) {\n _vm.subtitles.preScripts = $event.map(\n function(x) {\n return x.value\n }\n )\n }\n }\n }),\n _vm._v(\" \"),\n _c(\"p\", [\n _vm._v(\n \"Show's media filename is passed as argument for the pre-scripts. Pre-scripts are executed before trying to find subtitles from usual sources.\"\n )\n ])\n ],\n 1\n ),\n _vm._v(\" \"),\n _c(\n \"config-template\",\n {\n attrs: {\n \"label-for\": \"subtitles_pre_scripts\",\n label: \"Extra Scripts\"\n }\n },\n [\n _c(\"select-list\", {\n attrs: {\n name: \"subtitles_pre_scripts\",\n id: \"subtitles_pre_scripts\",\n \"list-items\":\n _vm.subtitles.extraScripts\n },\n on: {\n change: function($event) {\n _vm.subtitles.extraScripts = $event.map(\n function(x) {\n return x.value\n }\n )\n }\n }\n }),\n _vm._v(\" \"),\n _c(\n \"ul\",\n { staticClass: \"extra-scripts\" },\n [\n _c(\n \"li\",\n [\n _vm._v(\"See the \"),\n _c(\n \"app-link\",\n {\n staticClass: \"wiki\",\n attrs: {\n href: _vm.subtitles.wikiUrl\n }\n },\n [_c(\"strong\", [_vm._v(\"Wiki\")])]\n ),\n _vm._v(\n \" for a script arguments description.\"\n )\n ],\n 1\n ),\n _vm._v(\" \"),\n _c(\"li\", [\n _vm._v(\n \"Additional scripts separated by \"\n ),\n _c(\"b\", [_vm._v(\"|\")]),\n _vm._v(\".\")\n ]),\n _vm._v(\" \"),\n _c(\"li\", [\n _vm._v(\n \"Scripts are called after each episode has searched and downloaded subtitles.\"\n )\n ]),\n _vm._v(\" \"),\n _c(\"li\", [\n _vm._v(\n \"Only Python scripts are allowed to be executed.\"\n )\n ])\n ]\n )\n ],\n 1\n )\n ]\n : _vm._e(),\n _vm._v(\" \"),\n _c(\"input\", {\n staticClass: \"btn-medusa config_submitter\",\n attrs: { type: \"submit\", value: \"Save Changes\" }\n })\n ],\n 2\n )\n ])\n ]\n )\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"v-tab\",\n {\n key: \"subtitles_plugin\",\n attrs: { title: \"Subtitles Plugin\" }\n },\n [\n _c(\n \"div\",\n {\n staticClass: \"row component-group\",\n attrs: { id: \"subtitles-plugin\" }\n },\n [\n _c(\n \"div\",\n {\n staticClass: \"col-xs-12 col-md-2 component-group-desc\"\n },\n [\n _c(\"h3\", [_vm._v(\"Subtitle Providers\")]),\n _vm._v(\" \"),\n _c(\"p\", [\n _vm._v(\n \"Check off and drag the plugins into the order you want them to be used.\"\n )\n ]),\n _vm._v(\" \"),\n _c(\"p\", { staticClass: \"note\" }, [\n _vm._v(\"At least one plugin is required.\")\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"div\",\n { staticClass: \"col-xs-12 col-md-10\" },\n [\n _c(\n \"draggable\",\n {\n staticClass: \"list-group\",\n attrs: {\n id: \"service_order_list\",\n tag: \"ul\",\n handle: \".ui-state-default\"\n },\n model: {\n value: _vm.subtitles.services,\n callback: function($$v) {\n _vm.$set(_vm.subtitles, \"services\", $$v)\n },\n expression: \"subtitles.services\"\n }\n },\n _vm._l(_vm.subtitles.services, function(service) {\n return _c(\n \"li\",\n {\n key: service.name,\n staticClass: \"ui-state-default\",\n attrs: { id: service.name }\n },\n [\n _c(\"input\", {\n directives: [\n {\n name: \"model\",\n rawName: \"v-model\",\n value: service.enabled,\n expression: \"service.enabled\"\n }\n ],\n attrs: {\n type: \"checkbox\",\n id: \"enable_\" + service.name\n },\n domProps: {\n checked: service.enabled,\n checked: Array.isArray(service.enabled)\n ? _vm._i(service.enabled, null) > -1\n : service.enabled\n },\n on: {\n change: function($event) {\n var $$a = service.enabled,\n $$el = $event.target,\n $$c = $$el.checked ? true : false\n if (Array.isArray($$a)) {\n var $$v = null,\n $$i = _vm._i($$a, $$v)\n if ($$el.checked) {\n $$i < 0 &&\n _vm.$set(\n service,\n \"enabled\",\n $$a.concat([$$v])\n )\n } else {\n $$i > -1 &&\n _vm.$set(\n service,\n \"enabled\",\n $$a\n .slice(0, $$i)\n .concat($$a.slice($$i + 1))\n )\n }\n } else {\n _vm.$set(service, \"enabled\", $$c)\n }\n }\n }\n }),\n _vm._v(\" \"),\n _c(\n \"app-link\",\n {\n staticClass: \"imgLink\",\n attrs: { href: service.url }\n },\n [\n _c(\"img\", {\n staticStyle: {\n \"vertical-align\": \"middle\"\n },\n attrs: {\n src:\n \"images/subtitles/\" + service.image,\n alt: service.url,\n title: service.url,\n width: \"16\",\n height: \"16\"\n }\n })\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"span\",\n {\n staticStyle: {\n \"vertical-align\": \"middle\"\n }\n },\n [\n _vm._v(\n _vm._s(\n _vm._f(\"capitalize\")(service.name)\n )\n )\n ]\n ),\n _vm._v(\" \"),\n _c(\"span\", {\n staticClass:\n \"ui-icon ui-icon-arrowthick-2-n-s pull-right\",\n staticStyle: { \"vertical-align\": \"middle\" }\n })\n ],\n 1\n )\n }),\n 0\n ),\n _vm._v(\" \"),\n _c(\"br\"),\n _c(\"input\", {\n staticClass: \"btn-medusa config_submitter\",\n attrs: { type: \"submit\", value: \"Save Changes\" }\n }),\n _c(\"br\")\n ],\n 1\n )\n ]\n )\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"v-tab\",\n { key: \"plugin_settings\", attrs: { title: \"Plugin Settings\" } },\n [\n _c(\n \"div\",\n {\n staticClass: \"row component-group\",\n attrs: { id: \"plugin-settings\" }\n },\n [\n _c(\n \"div\",\n {\n staticClass: \"col-xs-12 col-md-2 component-group-desc\"\n },\n [\n _c(\"h3\", [_vm._v(\"Provider Settings\")]),\n _vm._v(\" \"),\n _c(\"p\", [\n _vm._v(\"Set user and password for each provider.\")\n ])\n ]\n ),\n _vm._v(\" \"),\n _c(\"div\", { staticClass: \"col-xs-12 col-md-10\" }, [\n _c(\n \"fieldset\",\n {\n staticClass: \"component-group-list\",\n staticStyle: {\n \"margin-left\": \"50px\",\n \"margin-top\": \"36px\"\n }\n },\n [\n _c(\"config-textbox\", {\n attrs: {\n label: \"Addic7ed User ID\",\n id: \"addic7ed_username\"\n },\n model: {\n value:\n _vm.subtitles.providerLogins.addic7ed.user,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles.providerLogins.addic7ed,\n \"user\",\n $$v\n )\n },\n expression:\n \"subtitles.providerLogins.addic7ed.user\"\n }\n }),\n _vm._v(\" \"),\n _vm.subtitles.providerLogins.addic7ed.user\n ? _c(\n \"div\",\n { staticStyle: { \"margin-bottom\": \"4rem\" } },\n [\n _c(\"p\", { staticStyle: { color: \"red\" } }, [\n _vm._v(\n \"To bypass addic7ed captcha protection we authenticate using a set cookie. The cookie requires your user id and password.\"\n )\n ]),\n _vm._v(\" \"),\n _c(\"span\", [\n _vm._v(\n \"You can find your user id by following these steps\"\n )\n ]),\n _vm._v(\" \"),\n _c(\"ul\", [\n _c(\"li\", [\n _vm._v(\n \"Navigate and login on addic7ed.com\"\n )\n ]),\n _vm._v(\" \"),\n _c(\"li\", [_vm._v(\"Click on My Profile\")]),\n _vm._v(\" \"),\n _c(\"li\", [\n _vm._v(\"Click on your own username\")\n ]),\n _vm._v(\" \"),\n _c(\"li\", [\n _vm._v(\n \"Your user id should now be visible in the address bar\"\n )\n ]),\n _vm._v(\" \"),\n _c(\"li\", [\n _vm._v(\n \"For example: https://www.addic7ed.com/user/12345\"\n )\n ])\n ])\n ]\n )\n : _vm._e(),\n _vm._v(\" \"),\n _c(\"config-textbox\", {\n attrs: {\n type: \"password\",\n label: \"Addic7ed Password\",\n id: \"addic7ed_password\"\n },\n model: {\n value:\n _vm.subtitles.providerLogins.addic7ed.pass,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles.providerLogins.addic7ed,\n \"pass\",\n $$v\n )\n },\n expression:\n \"subtitles.providerLogins.addic7ed.pass\"\n }\n }),\n _vm._v(\" \"),\n _c(\"config-textbox\", {\n attrs: {\n label: \"Opensubtitles User Name\",\n id: \"opensubtitles_username\"\n },\n model: {\n value:\n _vm.subtitles.providerLogins.opensubtitles\n .user,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles.providerLogins.opensubtitles,\n \"user\",\n $$v\n )\n },\n expression:\n \"subtitles.providerLogins.opensubtitles.user\"\n }\n }),\n _vm._v(\" \"),\n _c(\"config-textbox\", {\n attrs: {\n type: \"password\",\n label: \"Opensubtitles Password\",\n id: \"opensubtitles_password\"\n },\n model: {\n value:\n _vm.subtitles.providerLogins.opensubtitles\n .pass,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles.providerLogins.opensubtitles,\n \"pass\",\n $$v\n )\n },\n expression:\n \"subtitles.providerLogins.opensubtitles.pass\"\n }\n }),\n _vm._v(\" \"),\n _c(\"config-textbox\", {\n attrs: {\n label: \"Legendastv User Name\",\n id: \"legandas_username\"\n },\n model: {\n value:\n _vm.subtitles.providerLogins.legendastv.user,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles.providerLogins.legendastv,\n \"user\",\n $$v\n )\n },\n expression:\n \"subtitles.providerLogins.legendastv.user\"\n }\n }),\n _vm._v(\" \"),\n _c(\"config-textbox\", {\n attrs: {\n type: \"password\",\n label: \"Legendastv Password\",\n id: \"legandas_password\"\n },\n model: {\n value:\n _vm.subtitles.providerLogins.legendastv.pass,\n callback: function($$v) {\n _vm.$set(\n _vm.subtitles.providerLogins.legendastv,\n \"pass\",\n $$v\n )\n },\n expression:\n \"subtitles.providerLogins.legendastv.pass\"\n }\n }),\n _vm._v(\" \"),\n _c(\"input\", {\n staticClass: \"btn-medusa config_submitter\",\n attrs: { type: \"submit\", value: \"Save Changes\" }\n }),\n _c(\"br\")\n ],\n 1\n )\n ])\n ]\n )\n ]\n )\n ],\n 1\n )\n ],\n 1\n )\n ])\n ])\n}\nvar staticRenderFns = []\nrender._withStripped = true\n\n\n\n//# sourceURL=webpack://slim/./src/components/config-subtitles.vue?./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/vue-loader/lib/index.js??vue-loader-options"); /***/ }), From f6abd25d4d7be02efde391cb83d4873da8455d40 Mon Sep 17 00:00:00 2001 From: p0psicles Date: Sat, 5 Feb 2022 10:58:04 +0100 Subject: [PATCH 3/4] Updated changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 369110f767..afc45d2b75 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ - Fix mass update status page, start a new snatch when changing status to failed. ([10213](https://github.com/pymedusa/Medusa/pull/10213)) - Fix changing process method in manual postprocessing. ([10220](https://github.com/pymedusa/Medusa/pull/10220)) - Fix saving season posters / banners when using tvdb ([10251](https://github.com/pymedusa/Medusa/pull/10251)) +- Fix Addic7ed.com subtitle provider ([10312](https://github.com/pymedusa/Medusa/pull/10312)) ----- From df9a27bbb9c09e8a80be6a0184275389c827f391 Mon Sep 17 00:00:00 2001 From: p0psicles Date: Sat, 5 Feb 2022 11:15:58 +0100 Subject: [PATCH 4/4] Fix flake --- medusa/subtitle_providers/addic7ed.py | 32 ++++++++++++++++++++------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/medusa/subtitle_providers/addic7ed.py b/medusa/subtitle_providers/addic7ed.py index 6923f4596c..a699c1c0e9 100644 --- a/medusa/subtitle_providers/addic7ed.py +++ b/medusa/subtitle_providers/addic7ed.py @@ -1,16 +1,20 @@ # -*- coding: utf-8 -*- +"""Custom subliminal addic7ed.com subtitle provider module.""" + +import hashlib import logging import re -import hashlib -from babelfish import Language, language_converters +from babelfish import Language + from guessit import guessit + from requests import Session -from subliminal.providers import ParserBeautifulSoup, Provider from subliminal.cache import SHOW_EXPIRATION_TIME, region -from subliminal.exceptions import AuthenticationError, ConfigurationError, DownloadLimitExceeded +from subliminal.exceptions import ConfigurationError, DownloadLimitExceeded from subliminal.matches import guess_matches +from subliminal.providers import ParserBeautifulSoup, Provider from subliminal.subtitle import Subtitle, fix_line_ending from subliminal.utils import sanitize from subliminal.video import Episode @@ -28,6 +32,7 @@ class Addic7edSubtitle(Subtitle): """Addic7ed Subtitle.""" + provider_name = 'addic7ed' def __init__(self, language, hearing_impaired, page_link, series, season, episode, title, year, version, @@ -43,10 +48,12 @@ def __init__(self, language, hearing_impaired, page_link, series, season, episod @property def id(self): + """Get id.""" return self.download_link @property def info(self): + """Get info.""" return '{series}{yopen}{year}{yclose} s{season:02d}e{episode:02d}{topen}{title}{tclose}{version}'.format( series=self.series, season=self.season, episode=self.episode, title=self.title, year=self.year or '', version=self.version, yopen=' (' if self.year else '', yclose=')' if self.year else '', @@ -54,6 +61,7 @@ def info(self): ) def get_matches(self, video): + """Get matches.""" # series name matches = guess_matches(video, { 'title': self.series, @@ -76,6 +84,7 @@ def get_matches(self, video): class Addic7edProvider(Provider): """Addic7ed Provider.""" + languages = {Language('por', 'BR')} | {Language(l) for l in [ 'ara', 'aze', 'ben', 'bos', 'bul', 'cat', 'ces', 'dan', 'deu', 'ell', 'eng', 'eus', 'fas', 'fin', 'fra', 'glg', 'heb', 'hrv', 'hun', 'hye', 'ind', 'ita', 'jpn', 'kor', 'mkd', 'msa', 'nld', 'nor', 'pol', 'por', 'ron', 'rus', @@ -95,6 +104,7 @@ def __init__(self, username=None, password=None): self.cookies = {'wikisubtitlesuser': self.username, 'wikisubtitlespass': self.password} def initialize(self): + """Initialize Addic7edProvider provider.""" self.session = Session() self.session.headers['User-Agent'] = self.user_agent @@ -104,14 +114,15 @@ def initialize(self): self.logged_in = True def terminate(self): + """Terminate.""" # logout logger.debug('Logged out') self.logged_in = False - @region.cache_on_arguments(expiration_time=SHOW_EXPIRATION_TIME) def _get_show_ids(self): """Get the ``dict`` of show ids per series by querying the `shows.php` page. + :return: show id per series, lower case and without quotes. :rtype: dict """ @@ -141,6 +152,7 @@ def _get_show_ids(self): @region.cache_on_arguments(expiration_time=SHOW_EXPIRATION_TIME) def _search_show_id(self, series, year=None): """Search the show id from the `series` and `year`. + :param str series: series of the episode. :param year: year of the series, if any. :type year: int @@ -148,7 +160,7 @@ def _search_show_id(self, series, year=None): :rtype: int """ # addic7ed doesn't support search with quotes - series = series.replace('\'', ' ') + series = series.replace("'", ' ') # build the params series_year = '%s %d' % (series, year) if year is not None else series @@ -166,7 +178,7 @@ def _search_show_id(self, series, year=None): if not suggestion: logger.warning('Show id not found: no suggestion') return None - if not sanitize(suggestion[0].i.text.replace('\'', ' ')) == sanitize(series_year): + if not sanitize(suggestion[0].i.text.replace("'", ' ')) == sanitize(series_year): logger.warning('Show id not found: suggestion does not match') return None show_id = int(suggestion[0]['href'][6:]) @@ -176,6 +188,7 @@ def _search_show_id(self, series, year=None): def get_show_id(self, series, year=None, country_code=None): """Get the best matching show id for `series`, `year` and `country_code`. + First search in the result of :meth:`_get_show_ids` and fallback on a search with :meth:`_search_show_id`. :param str series: series of the episode. :param year: year of the series, if any. @@ -212,6 +225,7 @@ def get_show_id(self, series, year=None, country_code=None): return show_id def query(self, show_id, series, season, year=None, country=None): + """Query provider to get all subitles for a specific show + season.""" # get the page of the season of the show logger.info('Getting the page of show id %d, season %d', show_id, season) r = self.session.get(self.server_url + 'show/%d' % show_id, params={'season': season}, timeout=60, cookies=self.cookies) @@ -257,6 +271,7 @@ def query(self, show_id, series, season, year=None, country=None): return subtitles def list_subtitles(self, video, languages): + """List Subitles.""" # lookup show_id titles = [video.series] + video.alternative_series show_id = None @@ -277,6 +292,7 @@ def list_subtitles(self, video, languages): return [] def download_subtitle(self, subtitle): + """Download subtitles.""" # download the subtitle logger.info('Downloading subtitle %r', subtitle) r = self.session.get(self.server_url + subtitle.download_link, headers={'Referer': subtitle.page_link}, @@ -293,4 +309,4 @@ def download_subtitle(self, subtitle): if r.headers['Content-Type'] == 'text/html': raise DownloadLimitExceeded - subtitle.content = fix_line_ending(r.content) \ No newline at end of file + subtitle.content = fix_line_ending(r.content)