diff --git a/CHANGELOG.md b/CHANGELOG.md index c590cc5393..45c0df7327 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +## 0.5.15 (23-07-2021) + +#### Improvements +- Improved Kodi12+ metadata creation. Use 'uniqueid' tag to specify indexer. ([9745](https://github.com/pymedusa/Medusa/pull/9745)) + +#### Fixes +- Fix prowl notifications ([9720](https://github.com/pymedusa/Medusa/pull/9720)) +- Fix provider ABNormal ([9721](https://github.com/pymedusa/Medusa/pull/9721)) +- Fix saving provider password ([9721](https://github.com/pymedusa/Medusa/pull/9721)) + +----- + ## 0.5.14 (06-07-2021) #### New Features diff --git a/medusa/clients/torrent/qbittorrent.py b/medusa/clients/torrent/qbittorrent.py index 9ebb5498d4..ef1b86622c 100644 --- a/medusa/clients/torrent/qbittorrent.py +++ b/medusa/clients/torrent/qbittorrent.py @@ -402,7 +402,7 @@ def get_status(self, info_hash): client_status.ratio = torrent['ratio'] * 1.0 # Store progress - client_status.progress = int(torrent['downloaded'] / torrent['size'] * 100) + client_status.progress = int(torrent['downloaded'] / torrent['size'] * 100) if torrent['size'] else 0 # Store destination client_status.destination = torrent['save_path'] diff --git a/medusa/common.py b/medusa/common.py index 9babd4b254..9511949943 100644 --- a/medusa/common.py +++ b/medusa/common.py @@ -39,7 +39,7 @@ log.logger.addHandler(logging.NullHandler()) INSTANCE_ID = text_type(uuid.uuid1()) -VERSION = '0.5.14' +VERSION = '0.5.15' USER_AGENT = 'Medusa/{version} ({system}; {release}; {instance})'.format( version=VERSION, system=platform.system(), release=platform.release(), instance=INSTANCE_ID) diff --git a/medusa/metadata/kodi_12plus.py b/medusa/metadata/kodi_12plus.py index 5934a3c323..6a54c3efcf 100644 --- a/medusa/metadata/kodi_12plus.py +++ b/medusa/metadata/kodi_12plus.py @@ -146,14 +146,24 @@ def _show_data(self, series_obj): mpaa = etree.SubElement(tv_node, 'mpaa') mpaa.text = my_show['contentrating'] - if getattr(my_show, 'id', None): - indexer_id = etree.SubElement(tv_node, 'id') - indexer_id.text = text_type(my_show['id']) + # Add main indexer + uniqueid = etree.SubElement(tv_node, 'uniqueid') + uniqueid.set('default', 'true') + uniqueid.set('type', series_obj.identifier.indexer.slug) + uniqueid.text = str(series_obj.identifier.id) + + for indexer_slug in ('tvdb', 'tmdb', 'imdb', 'tvmaze', 'anidb'): + if indexer_slug == series_obj.identifier.indexer.slug: + continue + + external_id = series_obj.externals.get(f'{indexer_slug}_id') + if not external_id: + continue uniqueid = etree.SubElement(tv_node, 'uniqueid') - uniqueid.set('type', series_obj.indexer_name) - uniqueid.set('default', 'true') - uniqueid.text = text_type(my_show['id']) + uniqueid.set('default', 'false') + uniqueid.set('type', indexer_slug) + uniqueid.text = str(external_id) if getattr(my_show, 'genre', None) and isinstance(my_show['genre'], string_types): for genre in self._split_info(my_show['genre']): diff --git a/medusa/notifiers/prowl.py b/medusa/notifiers/prowl.py index defc747267..54ce54bdab 100644 --- a/medusa/notifiers/prowl.py +++ b/medusa/notifiers/prowl.py @@ -42,30 +42,26 @@ def notify_snatch(self, title, message, ep_obj): message=message) def notify_download(self, ep_obj): - ep_name = ep_obj.pretty_name_with_quality() if app.PROWL_NOTIFY_ONDOWNLOAD: - show = self._parse_episode(ep_name) - recipients = self._generate_recipients(show) + recipients = self._generate_recipients(ep_obj.series) if not recipients: log.debug('Skipping prowl notify because there are no configured recipients') else: for api in recipients: self._send_prowl(prowl_api=api, prowl_priority=None, event=common.notifyStrings[common.NOTIFY_DOWNLOAD], - message=ep_name) + message=ep_obj.pretty_name_with_quality()) def notify_subtitle_download(self, ep_obj, lang): - ep_name = ep_obj.pretty_name() if app.PROWL_NOTIFY_ONSUBTITLEDOWNLOAD: - show = self._parse_episode(ep_name) - recipients = self._generate_recipients(show) + recipients = self._generate_recipients(ep_obj.series) if not recipients: log.debug('Skipping prowl notify because there are no configured recipients') else: for api in recipients: self._send_prowl(prowl_api=api, prowl_priority=None, event=common.notifyStrings[common.NOTIFY_SUBTITLE_DOWNLOAD], - message=ep_name + ' [' + lang + ']') + message=f'{ep_obj.pretty_name()} [{lang}]') def notify_git_update(self, new_version='??'): if app.USE_PROWL: diff --git a/medusa/providers/torrent/html/abnormal.py b/medusa/providers/torrent/html/abnormal.py index 266a9762d6..088e9ba9a5 100644 --- a/medusa/providers/torrent/html/abnormal.py +++ b/medusa/providers/torrent/html/abnormal.py @@ -9,10 +9,7 @@ from medusa import tv from medusa.bs4_parser import BS4Parser -from medusa.helper.common import ( - convert_size, - try_int, -) +from medusa.helper.common import convert_size from medusa.logger.adapters.style import BraceAdapter from medusa.providers.torrent.torrent_provider import TorrentProvider @@ -35,10 +32,10 @@ def __init__(self): self.password = None # URLs - self.url = 'https://abnormal.ws' + self.url = 'https://abn.lol' self.urls = { - 'login': urljoin(self.url, 'login.php'), - 'search': urljoin(self.url, 'torrents.php'), + 'login': urljoin(self.url, 'Home/Login'), + 'search': urljoin(self.url, 'Torrent'), } # Proper Strings @@ -64,18 +61,9 @@ def search(self, search_strings, age=0, ep_obj=None, **kwargs): # Search Params search_params = { - 'cat[]': [ - 'TV|SD|VOSTFR', - 'TV|HD|VOSTFR', - 'TV|SD|VF', - 'TV|HD|VF', - 'TV|PACK|FR', - 'TV|PACK|VOSTFR', - 'TV|EMISSIONS', - 'ANIME', - ], - 'order': 'Time', # Sorting: Available parameters: ReleaseName, Seeders, Leechers, Snatched, Size - 'way': 'DESC', # Both ASC and DESC are available for sort direction + 'SelectedCats': '1', # "Series" category + 'SortOn': 'Created', # Sorting: Available parameters: ReleaseName, Seeders, Leechers, Snatched, Size + 'SortOrder': 'DESC', # Both ASC and DESC are available for sort direction } for mode in search_strings: @@ -113,7 +101,7 @@ def parse(self, data, mode): items = [] with BS4Parser(data, 'html5lib') as html: - torrent_table = html.find(class_='torrent_table') + torrent_table = html.find(class_='table-rows') torrent_rows = torrent_table('tr') if torrent_table else [] # Continue only if at least one release is found @@ -122,7 +110,7 @@ def parse(self, data, mode): return items # Catégorie, Release, Date, DL, Size, C, S, L - labels = [label.get_text(strip=True) for label in torrent_rows[0]('td')] + labels = [label.get_text(strip=True) for label in torrent_rows[0]('th')] # Skip column headers for row in torrent_rows[1:]: @@ -132,13 +120,13 @@ def parse(self, data, mode): try: title = cells[labels.index('Release')].get_text(strip=True) - download = cells[labels.index('DL')].find('a', class_='tooltip')['href'] + download = cells[labels.index('DL')].find('a')['href'] download_url = urljoin(self.url, download) if not all([title, download_url]): continue - seeders = try_int(cells[labels.index('S')].get_text(strip=True)) - leechers = try_int(cells[labels.index('L')].get_text(strip=True)) + seeders = int(cells[labels.index('S')].get_text(strip=True)) + leechers = int(cells[labels.index('L')].get_text(strip=True)) # Filter unseeded torrent if seeders < self.minseed: @@ -150,7 +138,7 @@ def parse(self, data, mode): size_index = labels.index('Size') if 'Size' in labels else labels.index('Taille') torrent_size = cells[size_index].get_text() - size = convert_size(torrent_size, units=units) or -1 + size = convert_size(torrent_size.replace(',', '.'), units=units) or -1 item = { 'title': title, @@ -175,9 +163,16 @@ def login(self): if any(dict_from_cookiejar(self.session.cookies).values()): return True + # Retrieve __RequestVerificationToken + login_html = self.session.get(self.urls['login']) + with BS4Parser(login_html.text, 'html5lib') as html: + token = html.find('input', attrs={'name': '__RequestVerificationToken'}).get('value') + login_params = { - 'username': self.username, - 'password': self.password, + 'Username': self.username, + 'Password': self.password, + '__RequestVerificationToken': token, + 'RememberMe': True } response = self.session.post(self.urls['login'], data=login_params) @@ -185,7 +180,7 @@ def login(self): log.warning('Unable to connect to provider') return False - if "Votre nom d'utilisateur ou mot de passe est incorrect." in response.text: + if 'Erreur lors du login.' in response.text: log.warning('Invalid username or password. Check your settings') return False diff --git a/medusa/server/api/v2/providers.py b/medusa/server/api/v2/providers.py index 8fc473df43..a46ff123d3 100644 --- a/medusa/server/api/v2/providers.py +++ b/medusa/server/api/v2/providers.py @@ -425,6 +425,12 @@ def _set_common_settings(provider, config): except (AttributeError, KeyError): provider.username = None + if hasattr(provider, 'password'): + try: + provider.password = config['password'] + except (AttributeError, KeyError): + provider.password = None + if hasattr(provider, 'api_key'): try: provider.api_key = config['apikey'] diff --git a/themes-default/slim/package.json b/themes-default/slim/package.json index c6e6f073ff..ffe53ec111 100644 --- a/themes-default/slim/package.json +++ b/themes-default/slim/package.json @@ -43,7 +43,7 @@ "jquery": "3.6.0", "lodash": "4.17.21", "lozad": "1.16.0", - "sass": "1.35.1", + "sass": "1.35.2", "sass-loader": "12.1.0", "style-loader": "3.0.0", "stylelint-scss": "3.19.0", @@ -95,7 +95,7 @@ "eslint-plugin-import": "2.23.4", "eslint-plugin-jest": "24.3.6", "eslint-plugin-unicorn": "22.0.0", - "eslint-plugin-vue": "7.12.1", + "eslint-plugin-vue": "7.13.0", "file-loader": "6.2.0", "filemanager-webpack-plugin": "6.1.4", "glob": "7.1.7", @@ -114,7 +114,7 @@ "timekeeper": "2.2.0", "vue-jest": "3.0.7", "vue-loader": "15.9.7", - "webpack": "5.42.0", + "webpack": "5.44.0", "webpack-cli": "4.7.2" }, "stylelint": { diff --git a/themes-default/slim/src/components/display-show.vue b/themes-default/slim/src/components/display-show.vue index 7a09a1b3a7..5132c8aa9b 100644 --- a/themes-default/slim/src/components/display-show.vue +++ b/themes-default/slim/src/components/display-show.vue @@ -1,7 +1,7 @@