Merge branch 'main' into dev

This commit is contained in:
JackDandy 2023-09-19 12:58:46 +01:00
commit 6bda4d7c8f
4 changed files with 79 additions and 63 deletions

View file

@ -19,6 +19,12 @@
* Add search of grouped options in shows drop down at view-show * Add search of grouped options in shows drop down at view-show
### 3.29.10 (2023-09-19 12:55:00 UTC)
* Fix Metacritic cards
* Fix Linux CI tests
### 3.29.9 (2023-09-17 23:25:00 UTC) ### 3.29.9 (2023-09-17 23:25:00 UTC)
* Fix Emby notifier library update * Fix Emby notifier library update

View file

@ -418,12 +418,12 @@ $(document).ready(function(){
#elif 'Metacritic' == $browse_type #elif 'Metacritic' == $browse_type
<optgroup label="Metacritic"> <optgroup label="Metacritic">
<option value="mc_newseries"#echo ('', selected)['newseries' == $mode]#>New seasons</option> <option value="mc_newseries"#echo ('', selected)['newseries' == $mode]#>New seasons</option>
<option value="mc_90days"#echo ('', selected)['90days' == $mode]#>Last 90 days</option> <option value="mc_explore"#echo ('', selected)['explore' == $mode]#>Explore</option>
<option value="mc_year"#echo ('', selected)['year' == $mode]#>By year</option> <option value="mc_popular"#echo ('', selected)['popular' == $mode]#>Popular</option>
<option value="mc_discussed"#echo ('', selected)['discussed' == $mode]#>Most discussed</option> <option value="mc_metascore"#echo ('', selected)['metascore' == $mode]#>By metascore</option>
<option value="mc_shared"#echo ('', selected)['shared' == $mode]#>Most shared</option> <option value="mc_userscore"#echo ('', selected)['userscore' == $mode]#>By userscore</option>
#if $kwargs and $kwargs.get('more') and 'newseries' in $mode #if $kwargs and $kwargs.get('more')
<option value="mc_newseries?more=1"#echo ('', selected + ' disabled')[mode.endswith('more')]#>... list more</option> <option value="mc_#echo $mode#?more=1"#echo ('', selected + ' disabled')[mode.endswith('more')]#>... list more</option>
#end if #end if
</optgroup> </optgroup>
#elif 'TMDB' == $browse_type #elif 'TMDB' == $browse_type

View file

@ -5002,23 +5002,23 @@ class AddShows(Home):
def mc_newseries(self, **kwargs): def mc_newseries(self, **kwargs):
return self.browse_mc( return self.browse_mc(
'release-date/new-series/date?', 'New Series at Metacritic', mode='newseries', **kwargs) '/all/all/all-time/new/', 'New Series at Metacritic', mode='newseries', **kwargs)
def mc_90days(self, **kwargs): def mc_explore(self, **kwargs):
return self.browse_mc( return self.browse_mc(
'score/metascore/90day/filtered?sort=desc&', 'Last 90 days at Metacritic', mode='90days', **kwargs) '/', 'Explore at Metacritic', mode='explore', **kwargs)
def mc_year(self, **kwargs): def mc_popular(self, **kwargs):
return self.browse_mc( return self.browse_mc(
'score/metascore/year/filtered?sort=desc&', 'By year at Metacritic', mode='year', **kwargs) '/all/all/all-time/popular/', 'Popular at Metacritic', mode='popular', **kwargs)
def mc_discussed(self, **kwargs): def mc_metascore(self, **kwargs):
return self.browse_mc( return self.browse_mc(
'score/metascore/discussed/filtered?sort=desc&', 'Most discussed at Metacritic', mode='discussed', **kwargs) '/all/all/all-time/metascore/', 'By metascore at Metacritic', mode='metascore', **kwargs)
def mc_shared(self, **kwargs): def mc_userscore(self, **kwargs):
return self.browse_mc( return self.browse_mc(
'score/metascore/shared/filtered?sort=desc&', 'Most shared at Metacritic', mode='shared', **kwargs) '/all/all/all-time/userscore/', 'By userscore at Metacritic', mode='userscore', **kwargs)
def browse_mc(self, url_path, browse_title, **kwargs): def browse_mc(self, url_path, browse_title, **kwargs):
@ -5026,76 +5026,86 @@ class AddShows(Home):
footnote = None footnote = None
page = 'more' in kwargs and '&page=1' or '' page = 'more' in kwargs and '&page=2' or ''
if page: if page:
kwargs['mode'] += '-more' kwargs['mode'] += '-more'
filtered = [] filtered = []
import browser_ua import browser_ua
url = 'https://www.metacritic.com/browse/tv/%sview=detailed%s' % (url_path, page) this_year = datetime.datetime.today().strftime('%Y')
url = f'https://www.metacritic.com/browse/tv{url_path}' \
f'?releaseYearMin={this_year}&releaseYearMax={this_year}{page}'
html = helpers.get_url(url, headers={'User-Agent': browser_ua.get_ua()}) html = helpers.get_url(url, headers={'User-Agent': browser_ua.get_ua()})
if html: if html:
try: try:
if re.findall('(<a[^>]+rel="next"[^>]+)', html)[0]: if re.findall('(c-navigationPagination_item--next)', html)[0]:
kwargs.update(dict(more=1)) kwargs.update(dict(more=1))
except (BaseException, Exception): except (BaseException, Exception):
pass pass
with BS4Parser(html, parse_only=dict(table={'class': (lambda at: at and 'clamp-list' in at)})) as tbl: with BS4Parser(html, parse_only=dict(div={'class': (lambda at: at and 'c-productListings' in at)})) as soup:
# with BS4Parser(html, features=['html5lib', 'permissive']) as soup: items = [] if not soup else soup.select('.c-finderProductCard_container')
items = [] if not tbl else tbl.find_all('tr')
oldest, newest, oldest_dt, newest_dt = None, None, 9999999, 0 oldest, newest, oldest_dt, newest_dt = None, None, 9999999, 0
for cur_row in items: rc_title = re.compile(r'(?i)(?::\s*season\s*\d+|\s*\((?:19|20)\d{2}\))?$')
rc_id = re.compile(r'(?i)[^A-Z0-9]')
rc_img = re.compile(r'(.*?)(/resize/[^?]+)?(/catalog/provider.*?\.(?:jpg|png)).*')
rc_season = re.compile(r'(\d+)(?:[.]\d*?)?$')
for idx, cur_row in enumerate(items):
try: try:
ids = dict(custom=cur_row.select('input[type="checkbox"]')[0].attrs['id'], name='mc') title = rc_title.sub(
info = cur_row.find('a', href=re.compile('^/tv')) '', cur_row.find('div', class_='c-finderProductCard_title').get('data-title').strip())
url_path = info['href'].strip()
images = {} # 2023-09-23 deprecated id at site, using title as id
img_uri = None # ids = dict(custom=cur_row.select('input[type="checkbox"]')[0].attrs['id'], name='mc')
img = info.find('img') ids = dict(custom=rc_id.sub('', title), name='mc')
if img and isinstance(img.attrs, dict):
title = img.attrs.get('alt') url_path = cur_row['href'].strip()
img_src = img.attrs.get('src').split('-') if not url_path.startswith('/tv/'):
img_uri = img_src.pop(0) continue
if img_src:
img_uri += '.' + img_src[0].split('.')[-1] images = None
images = dict(poster=dict(thumb='imagecache?path=browse/thumb/metac&source=%s' % img_uri)) img_src = (cur_row.find('img') or {}).get('src', '').strip()
if img_src:
img_uri = rc_img.sub(r'\1\3', img_src)
images = dict(poster=dict(thumb=f'imagecache?path=browse/thumb/metac&source={img_uri}'))
sickgear.CACHE_IMAGE_URL_LIST.add_url(img_uri) sickgear.CACHE_IMAGE_URL_LIST.add_url(img_uri)
if not title:
title = cur_row.find('h3').get_text()
title = re.sub(r'(?i)(?::\s*season\s*\d+|\s*\((?:19|20)\d{2}\))?$', '', title.strip())
ord_premiered = 0 ord_premiered = 0
str_premiered = '' str_premiered = ''
started_past = False started_past = False
date_tags = list(filter(lambda t: t.find('span'),
cur_row.find_all('div', class_='clamp-details')))
if date_tags:
ord_premiered, str_premiered, started_past, oldest_dt, newest_dt, oldest, newest, \
_, _, _, _ \
= self.sanitise_dates(date_tags[0].get_text().strip(), oldest_dt, newest_dt,
oldest, newest)
overview = cur_row.find('div', class_='summary').get_text().strip() dated = None
rating = None
rating_user = None # 2023-09-23 deprecated at site
meta_tags = cur_row.find_all('div', class_='c-finderProductCard_meta')
for tag in meta_tags:
meta_tag = tag.find('span', class_='u-text-uppercase')
if not dated and meta_tag:
dated = meta_tag
try: # a bad date caused a sanitise exception here
ord_premiered, str_premiered, started_past, oldest_dt, newest_dt, oldest, newest, \
_, _, _, _ = self.sanitise_dates(dated.get_text().strip(), oldest_dt, newest_dt,
oldest, newest)
except (BaseException, Exception):
pass
rating = cur_row.find('div', class_='clamp-metascore') meta_tag = tag.find('div', class_='c-siteReviewScore')
if rating: if not rating and meta_tag:
rating = rating.find('div', class_='metascore_w') rating = meta_tag
if rating:
rating = rating.get_text().strip() rating = rating.get_text().strip()
rating_user = cur_row.find('div', class_='clamp-userscore')
if rating_user:
rating_user = rating_user.find('div', class_='metascore_w')
if rating_user:
rating_user = rating_user.get_text().strip()
season = -1 if dated and rating:
break
overview = cur_row.find('div', class_='c-finderProductCard_description')
if overview:
overview = helpers.xhtml_escape(overview.get_text().strip()[:250:])
try: try:
season = re.findall(r'(\d+)(?:[.]\d*?)?$', url_path)[0] season = rc_season.findall(url_path)[0]
except(BaseException, Exception): except(BaseException, Exception):
pass season = -1
filtered.append(dict( filtered.append(dict(
ord_premiered=ord_premiered, ord_premiered=ord_premiered,
@ -5104,12 +5114,12 @@ class AddShows(Home):
episode_season=int(season), episode_season=int(season),
genres='', genres='',
ids=ids, ids=ids,
images='' if not img_uri else images, images=images or '',
overview='No overview yet' if not overview else helpers.xhtml_escape(overview[:250:]), overview=overview or 'No overview yet',
rating=0 if not rating else rating or 'TBD', rating=0 if not rating else rating or 'TBD',
rating_user='tbd' if not rating_user else int(helpers.try_float(rating_user) * 10) or 'tbd', rating_user='tbd' if not rating_user else int(helpers.try_float(rating_user) * 10) or 'tbd',
title=title, title=title,
url_src_db='https://www.metacritic.com/%s/' % url_path.strip('/'), url_src_db=f'https://www.metacritic.com/{url_path.strip("/")}/',
votes=None)) votes=None))
except (AttributeError, IndexError, KeyError, TypeError): except (AttributeError, IndexError, KeyError, TypeError):
@ -5121,7 +5131,7 @@ class AddShows(Home):
mode = kwargs.get('mode', '') mode = kwargs.get('mode', '')
if mode: if mode:
func = 'mc_%s' % mode func = f'mc_{mode}'
if callable(getattr(self, func, None)): if callable(getattr(self, func, None)):
sickgear.MC_MRU = func sickgear.MC_MRU = func
sickgear.save_config() sickgear.save_config()

View file

@ -18,8 +18,8 @@
import datetime import datetime
import unittest import unittest
import test_lib as test # must be before import sickgear
import sickgear import sickgear
import test_lib as test
from sickgear import db from sickgear import db
from sickgear.common import Quality, UNAIRED, SKIPPED, WANTED, WantedQualities, statusStrings from sickgear.common import Quality, UNAIRED, SKIPPED, WANTED, WantedQualities, statusStrings
from sickgear.show_queue import QueueItemAdd from sickgear.show_queue import QueueItemAdd