Skip to content

Commit 106e462

Browse files
committed
Documentation refactoring, and minor optimizations.
In resolve_art_url - If no fallback art is defined for the requested art type, we don't check the URL availability anymore since there is no need to.
1 parent 9c6e80a commit 106e462

2 files changed

Lines changed: 52 additions & 45 deletions

File tree

resources/arts.py

Lines changed: 45 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from util import show_error
99

1010
__addon__ = xbmcaddon.Addon()
11-
enableArtFallback = __addon__.getSetting("enable-art-fallback") == 'true' # Kodi stores boolean settings as strings
11+
artFallbackEnabled = __addon__.getSetting("enable-art-fallback") == 'true' # Kodi stores boolean settings as strings
1212
minutesBeforeArtsExpiration = int(__addon__.getSetting("arts-expire-after-minutes")) # Default is 2 months
1313

1414
# define the cache file to reside in the ..\Kodi\userdata\addon_data\(your addon)
@@ -17,68 +17,75 @@
1717

1818
cached_requests = requests_cache.core.CachedSession(ART_AVAILABILITY_CACHE_FILE, backend='sqlite',
1919
expire_after=60 * minutesBeforeArtsExpiration,
20-
allowable_methods=('HEAD',),
21-
allowable_codes=(200, 404),
20+
allowable_methods=('HEAD',), allowable_codes=(200, 404),
2221
old_data_on_error=True,
2322
fast_save=True)
2423

25-
# Todo : tweak fallbacks and arts to have the best look in Kodi
26-
# TODO note which are safe to use and which can be missing
27-
2824
# Dictionary containing for each art type, a base_url for the art (to format with appid / img_icon_path afterwards), and a fallback art type.
29-
arts_urls = { # {0} is appid, {1} is a special path provided by steam api for the icon
30-
'poster': {'base_url': 'http://cdn.akamai.steamstatic.com/steam/apps/{0}/library_600x900.jpg', 'fallback_media': 'landscape'},
31-
'banner': {'base_url': 'http://cdn.akamai.steamstatic.com/steam/apps/{0}/library_hero.jpg', 'fallback_media': 'landscape'},
32-
'landscape': {'base_url': 'http://cdn.akamai.steamstatic.com/steam/apps/{0}/header.jpg', 'fallback_media': None},
33-
'thumb': {'base_url': 'http://cdn.akamai.steamstatic.com/steam/apps/{0}/header.jpg', 'fallback_media': None},
34-
'fanart': {'base_url': 'http://cdn.akamai.steamstatic.com/steam/apps/{0}/library_hero.jpg', 'fallback_media': 'fanart2'},
35-
'fanart2': {'base_url': 'http://cdn.akamai.steamstatic.com/steam/apps/{0}/header.jpg', 'fallback_media': 'fanart3'},
36-
'fanart3': {'base_url': 'http://cdn.akamai.steamstatic.com/steam/apps/{0}/page_bg_generated_v6b.jpg', 'fallback_media': None},
37-
'icon': {'base_url': 'https://steamcdn-a.akamaihd.net/steamcommunity/public/images/apps/{0}/{1}.jpg', 'fallback_media': None},
38-
'clearlogo': {'base_url': 'http://cdn.akamai.steamstatic.com/steam/apps/{0}/logo.png', 'fallback_media': None} # No fallback possible for clearlogo
25+
ARTS_DATA = { # img_icon_path is a path provided by steam to get the icon. https://developer.valvesoftware.com/wiki/Steam_Web_API#GetOwnedGames_.28v0001.29
26+
'poster': {'base_url': 'http://cdn.akamai.steamstatic.com/steam/apps/{appid}/library_600x900.jpg', 'fallback_media': 'landscape'}, # Can return 404
27+
'banner': {'base_url': 'http://cdn.akamai.steamstatic.com/steam/apps/{appid}/library_hero.jpg', 'fallback_media': 'landscape'}, # Can return 404
28+
'landscape': {'base_url': 'http://cdn.akamai.steamstatic.com/steam/apps/{appid}/header.jpg', 'fallback_media': None},
29+
'thumb': {'base_url': 'http://cdn.akamai.steamstatic.com/steam/apps/{appid}/header.jpg', 'fallback_media': None},
30+
'fanart': {'base_url': 'http://cdn.akamai.steamstatic.com/steam/apps/{appid}/library_hero.jpg', 'fallback_media': 'fanart2'}, # Can return 404
31+
'fanart2': {'base_url': 'http://cdn.akamai.steamstatic.com/steam/apps/{appid}/header.jpg', 'fallback_media': 'fanart3'},
32+
'fanart3': {'base_url': 'http://cdn.akamai.steamstatic.com/steam/apps/{appid}/page_bg_generated_v6b.jpg', 'fallback_media': None},
33+
'icon': {'base_url': 'https://steamcdn-a.akamaihd.net/steamcommunity/public/images/apps/{appid}/{img_icon_path}.jpg', 'fallback_media': None},
34+
'clearlogo': {'base_url': 'http://cdn.akamai.steamstatic.com/steam/apps/{appid}/logo.png', 'fallback_media': None} # Can return 404
3935
}
4036

4137

4238
def is_art_url_available(url, timeout=2):
4339
"""
44-
Sends a HEAD request to check if an online resource is available. Uses a cache mechanism to speed things up or serve offline.
40+
Sends a HEAD request to check if an online resource is available. Uses a cache mechanism to speed things up or serve offline if a connection is unavailable.
4541
4642
:param url: url to check availability
47-
:param timeout: timeout of the request in seconds. Default 2
43+
:param timeout: timeout of the request in seconds. Default is 2
4844
:return: boolean False if the status code is between 400&600 , True otherwise
4945
"""
5046
result = False
5147
try:
5248
response = cached_requests.head(url, timeout=timeout)
53-
if not 400 <= response.status_code < 600: # We consider valid any status codes belwo 400 or above 600
49+
if not 400 <= response.status_code < 600: # We consider valid any status codes below 400 or above 600
5450
result = True
5551
except IOError:
5652
result = False
5753
return result
5854

5955

60-
def resolve_media_url(media_type, appid, img_icon_path=''):
61-
valid_media_url = None
62-
63-
art_data = arts_urls.get(media_type, None)
64-
65-
while valid_media_url is None and art_data is not None:
66-
art_url = art_data.get('base_url').format(appid, img_icon_path)
67-
if not enableArtFallback or is_art_url_available(art_url):
68-
# If art fallback is disabled, we directly assume the art url as valid.
69-
# If art fallback is enabled, we check if the art is available before proceeding
70-
valid_media_url = art_url
71-
else:
72-
# If the art is not available (and art fallback is enabled) we try with the defined fallback
73-
fallback_media_type = art_data.get("fallback", None)
74-
art_data = arts_urls.get(fallback_media_type, None)
75-
76-
if valid_media_url is None:
77-
show_error(None, "Issue obtaining a media", False)
56+
def resolve_art_url(art_type, appid, img_icon_path='', art_fallback_enabled=artFallbackEnabled):
57+
"""
58+
Resolve the art url of a specified game/app, for a given art type defined in the :const:`ARTS_DATA` dictionary.
59+
Handles fallback to another art type if needed (ie the requested one is unavailable and fallback is enabled).
60+
61+
:param art_type: a valid art type, defined in :const:`ARTS_DATA`
62+
:param appid: appid of the game/app we want to get the art for.
63+
:param img_icon_path: A path provided by steam to get the icon art url. https://developer.valvesoftware.com/wiki/Steam_Web_API#GetOwnedGames_.28v0001.29
64+
:param art_fallback_enabled: Whether to fall back to another art type if an art is unavailable. Defaults to the user addon settings, which default to true
65+
:return: resolved art URL. Can be the URL of another available art if .
66+
"""
67+
valid_art_url = None
68+
requested_art_data = ARTS_DATA.get(art_type, None)
69+
70+
while valid_art_url is None and requested_art_data is not None: # If the current media type is defined and we did not find a valid url yet
71+
art_url = requested_art_data.get('base_url').format(appid=appid, img_icon_path=img_icon_path) # We replace "{appid}" and "{img_icon_path}" in the url
72+
fallback_art_type = requested_art_data.get("fallback_media", None)
73+
if (not art_fallback_enabled) or (fallback_art_type is None) or is_art_url_available(art_url):
74+
# If art fallback is disabled, or if there is no fallback defined, we directly assume the art url as valid.
75+
# Otherwise, if art fallback is enabled and there is a fallback defined, we check if is_art_url_available before proceeding
76+
valid_art_url = art_url
77+
else: # If art fallback is enabled and art is not available, we set the current art data to the defined fallback, before retrying.
78+
requested_art_data = ARTS_DATA.get(fallback_art_type, None) # Art data will be None if the fallback_art_type does not exist in the art_urls dict
79+
80+
if valid_art_url is None: # If the previous loop could not find a valid media url among the defined art types
81+
show_error(None, "Issue obtaining a media", display_notification=False)
7882
return
7983

80-
return valid_media_url
84+
return valid_art_url
8185

8286

8387
def delete_cache():
88+
"""
89+
Deletes the cache containing the data about which art types are available or not
90+
"""
8491
os.remove(ART_AVAILABILITY_CACHE_FILE + ".sqlite")

resources/main.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -163,13 +163,13 @@ def create_arts_dictionary(app_entry):
163163
appid = str(app_entry['appid'])
164164

165165
art_dictionary = {
166-
'poster': arts.resolve_media_url('poster', appid), # plugin.url_for(resolve_media, media_type='poster', appid=appid), # library asset, often missing
167-
'landscape': arts.resolve_media_url('landscape', appid), # plugin.url_for(resolve_media, media_type='landscape', appid=appid),
168-
'banner': arts.resolve_media_url('banner', appid), # plugin.url_for(resolve_media, media_type='banner', appid=appid),
169-
'clearlogo': arts.resolve_media_url('clearlogo', appid), # plugin.url_for(resolve_media, media_type='clearlogo', appid=appid),
170-
'thumb': arts.resolve_media_url('thumb', appid), # plugin.url_for(resolve_media, media_type='thumb', appid=appid),
171-
'fanart': arts.resolve_media_url('fanart', appid), # plugin.url_for(resolve_media, media_type='fanart', appid=appid),
172-
'icon': arts.resolve_media_url('icon', appid, app_entry['img_icon_url'])
166+
'poster': arts.resolve_art_url('poster', appid),
167+
'landscape': arts.resolve_art_url('landscape', appid),
168+
'banner': arts.resolve_art_url('banner', appid),
169+
'clearlogo': arts.resolve_art_url('clearlogo', appid),
170+
'thumb': arts.resolve_art_url('thumb', appid),
171+
'fanart': arts.resolve_art_url('fanart', appid),
172+
'icon': arts.resolve_art_url('icon', appid, app_entry['img_icon_url'])
173173
}
174174
return art_dictionary
175175

0 commit comments

Comments
 (0)