Skip to content

Commit 252e4e8

Browse files
authored
Merge pull request #23 from AmineI/refactor
Major refactoring of the code base
2 parents 49974df + f426b63 commit 252e4e8

6 files changed

Lines changed: 255 additions & 183 deletions

File tree

addon.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
v0.6.1 (2019-01-03)
3737
- added windows support for list of installed games courtesy of @jared-skinner
3838
v0.6.3 (2020-03-08)
39-
- various bug fixes thanks to @Aminel
39+
- various bug fixes thanks to @AmineI
4040
- add plugin to games provider list
4141
</news>
4242
<assets>

resources/config.py

Lines changed: 0 additions & 9 deletions
This file was deleted.

resources/main.py

Lines changed: 92 additions & 145 deletions
Original file line numberDiff line numberDiff line change
@@ -1,222 +1,171 @@
11
import os
2-
import requests
32
import routing
4-
import shlex
5-
import subprocess
63
import sys
7-
import time
8-
import xbmc
9-
import xbmcaddon
10-
import xbmcgui
114
import xbmcplugin
125
import registry
13-
14-
from config import *
6+
import steam
7+
from util import *
158

169
__addon__ = xbmcaddon.Addon()
1710

1811
plugin = routing.Plugin()
1912

13+
14+
# Note : the Kodi routing plugin also obtains and casts the handle. We can use it through plugin.handle instead of redefining it.
15+
2016
@plugin.route('/')
2117
def index():
18+
xbmcplugin.addDirectoryItem(handle=plugin.handle, url=plugin.url_for(all_games), listitem=xbmcgui.ListItem('All games'), isFolder=True)
19+
xbmcplugin.addDirectoryItem(handle=plugin.handle, url=plugin.url_for(installed_games), listitem=xbmcgui.ListItem('Installed games'), isFolder=True)
20+
xbmcplugin.addDirectoryItem(handle=plugin.handle, url=plugin.url_for(recent_games), listitem=xbmcgui.ListItem('Recently played games'), isFolder=True)
21+
xbmcplugin.endOfDirectory(plugin.handle, succeeded=True)
2222

23-
handle = int(sys.argv[1])
24-
25-
xbmcplugin.addDirectoryItem(handle=handle, url=plugin.url_for(all), listitem=xbmcgui.ListItem('All games'), isFolder=True)
26-
xbmcplugin.addDirectoryItem(handle=handle, url=plugin.url_for(installed), listitem=xbmcgui.ListItem('Installed games'), isFolder=True)
27-
xbmcplugin.addDirectoryItem(handle=handle, url=plugin.url_for(recent), listitem=xbmcgui.ListItem('Recently played games'), isFolder=True)
28-
xbmcplugin.endOfDirectory(handle, succeeded=True)
2923

3024
@plugin.route('/all')
31-
def all():
32-
33-
if __addon__.getSetting('steam-id') == '' or __addon__.getSetting('steam-key') == '':
34-
35-
# ensure required data is available
25+
def all_games():
26+
if not all_required_credentials_available():
3627
return
3728

38-
handle = int(sys.argv[1])
39-
4029
try:
30+
steam_games_details = steam.get_user_games(__addon__.getSetting('steam-key'), __addon__.getSetting('steam-id'))
4131

42-
# query the steam web api for a full list of steam applications/games that belong to the user
43-
response = requests.get('https://api.steampowered.com/IPlayerService/GetOwnedGames/v0001/?key=' + __addon__.getSetting('steam-key') + '&steamid=' + __addon__.getSetting('steam-id') + '&include_appinfo=1&format=json', timeout=10)
44-
response.raise_for_status()
45-
46-
except requests.exceptions.RequestException as e:
47-
32+
except IOError as e:
4833
# something went wrong, can't scan the steam library
49-
notify = xbmcgui.Dialog()
50-
notify.notification('Error', 'An unexpected error has occurred while contacting Steam. Please ensure your Steam credentials are correct and then try again. If this problem persists please contact support.', xbmcgui.NOTIFICATION_ERROR)
51-
52-
log(str(e), xbmc.LOGERROR)
53-
34+
show_error(e, 'An unexpected error has occurred while contacting Steam. Please ensure your Steam credentials are correct and then try again. '
35+
'If this problem persists please contact support.')
5436
return
5537

56-
data = response.json()
57-
totalItems = data['response']['game_count']
58-
59-
for entry in data['response']['games']:
38+
directory_items = create_directory_items(steam_games_details)
39+
xbmcplugin.addDirectoryItems(plugin.handle, directory_items)
6040

61-
appid = entry['appid']
62-
name = entry['name']
41+
xbmcplugin.addSortMethod(plugin.handle, xbmcplugin.SORT_METHOD_LABEL)
42+
xbmcplugin.endOfDirectory(plugin.handle, succeeded=True)
6343

64-
item = xbmcgui.ListItem(name)
65-
66-
item.addContextMenuItems([('Play', 'RunPlugin(plugin://plugin.program.steam.library/run/' + str(appid) + ')'), ('Install', 'RunPlugin(plugin://plugin.program.steam.library/install/' + str(appid) + ')')])
67-
item.setArt({ 'thumb': 'http://cdn.akamai.steamstatic.com/steam/apps/' + str(appid) + '/header.jpg', 'fanart': 'http://cdn.akamai.steamstatic.com/steam/apps/' + str(appid) + '/page_bg_generated_v6b.jpg' })
68-
69-
if not xbmcplugin.addDirectoryItem(handle=handle, url=plugin.url_for(run, id=str(appid)), listitem=item, totalItems=totalItems): break
70-
71-
xbmcplugin.addSortMethod(handle, xbmcplugin.SORT_METHOD_LABEL)
72-
xbmcplugin.endOfDirectory(handle, succeeded=True)
7344

7445
@plugin.route('/installed')
75-
def installed():
76-
77-
if __addon__.getSetting('steam-id') == '' or __addon__.getSetting('steam-key') == '':
78-
79-
# ensure required data is available
46+
def installed_games():
47+
if not all_required_credentials_available():
8048
return
8149

82-
if os.path.isdir(__addon__.getSetting('steam-path')) == False:
83-
50+
if not os.path.isdir(__addon__.getSetting('steam-path')):
8451
# ensure required data is available
85-
notify = xbmcgui.Dialog()
86-
notify.notification('Error', 'Unable to find your Steam path, please check your settings.', xbmcgui.NOTIFICATION_ERROR)
87-
52+
show_error(NameError("steam-path not found"), 'Unable to find your Steam path, please check your settings.')
8853
return
8954

90-
handle = int(sys.argv[1])
91-
9255
try:
56+
steam_games_details = steam.get_user_games(__addon__.getSetting('steam-key'), __addon__.getSetting('steam-id'))
9357

94-
# query the steam web api for a full list of steam applications/games that belong to the user
95-
response = requests.get('https://api.steampowered.com/IPlayerService/GetOwnedGames/v0001/?key=' + __addon__.getSetting('steam-key') + '&steamid=' + __addon__.getSetting('steam-id') + '&include_appinfo=1&format=json', timeout=10)
96-
response.raise_for_status()
97-
98-
except requests.exceptions.RequestException as e:
99-
58+
except IOError as e:
10059
# something went wrong, can't scan the steam library
101-
notify = xbmcgui.Dialog()
102-
notify.notification('Error', 'An unexpected error has occurred while contacting Steam. Please ensure your Steam credentials are correct and then try again. If this problem persists please contact support.', xbmcgui.NOTIFICATION_ERROR)
103-
104-
log(str(e), xbmc.LOGERROR)
105-
60+
show_error(e, 'An unexpected error has occurred while contacting Steam. Please ensure your Steam credentials are correct and then try again. '
61+
'If this problem persists please contact support.')
10662
return
10763

108-
apps = registry.get_registry_values(os.path.join(__addon__.getSetting('steam-path'), 'registry.vdf'))
109-
data = response.json()
110-
111-
for entry in data['response']['games']:
64+
installed_appids = registry.get_installed_steam_apps(os.path.join(__addon__.getSetting('steam-path'), 'registry.vdf'))
11265

113-
appid = entry['appid']
114-
name = entry['name']
66+
# filter out any applications not listed as installed
67+
steam_installed_games = filter(lambda app_entry: str(app_entry['appid']) in installed_appids, steam_games_details)
11568

116-
# filter out any applications not listed as installed
117-
if str(appid) not in apps: continue
118-
119-
item = xbmcgui.ListItem(name)
69+
directory_items = create_directory_items(steam_installed_games)
70+
xbmcplugin.addDirectoryItems(plugin.handle, directory_items)
12071

121-
item.addContextMenuItems([('Play', 'RunPlugin(plugin://plugin.program.steam.library/run/' + str(appid) + ')'), ('Install', 'RunPlugin(plugin://plugin.program.steam.library/install/' + str(appid) + ')')])
122-
item.setArt({ 'thumb': 'http://cdn.akamai.steamstatic.com/steam/apps/' + str(appid) + '/header.jpg', 'fanart': 'http://cdn.akamai.steamstatic.com/steam/apps/' + str(appid) + '/page_bg_generated_v6b.jpg' })
72+
xbmcplugin.addSortMethod(plugin.handle, xbmcplugin.SORT_METHOD_LABEL)
73+
xbmcplugin.endOfDirectory(plugin.handle, succeeded=True)
12374

124-
if not xbmcplugin.addDirectoryItem(handle=handle, url=plugin.url_for(run, id=str(appid)), listitem=item): break
125-
126-
xbmcplugin.addSortMethod(handle, xbmcplugin.SORT_METHOD_LABEL)
127-
xbmcplugin.endOfDirectory(handle, succeeded=True)
12875

12976
@plugin.route('/recent')
130-
def recent():
131-
132-
if __addon__.getSetting('steam-id') == '' or __addon__.getSetting('steam-key') == '':
133-
134-
# ensure required data is available
77+
def recent_games():
78+
if not all_required_credentials_available():
13579
return
13680

137-
handle = int(sys.argv[1])
138-
13981
try:
82+
steam_games_details = steam.get_user_games(__addon__.getSetting('steam-key'), __addon__.getSetting('steam-id'), recent_only=True)
14083

141-
# query the steam web api for a full list of steam applications/games that belong to the user
142-
response = requests.get('https://api.steampowered.com/IPlayerService/GetRecentlyPlayedGames/v0001/?key=' + __addon__.getSetting('steam-key') + '&steamid=' + __addon__.getSetting('steam-id') + '&include_appinfo=1&format=json', timeout=10)
143-
response.raise_for_status()
144-
145-
except requests.exceptions.RequestException as e:
146-
84+
except IOError as e:
14785
# something went wrong, can't scan the steam library
148-
notify = xbmcgui.Dialog()
149-
notify.notification('Error', 'An unexpected error has occurred while contacting Steam. Please ensure your Steam credentials are correct and then try again. If this problem persists please contact support.', xbmcgui.NOTIFICATION_ERROR)
150-
151-
log(str(e), xbmc.LOGERROR)
152-
86+
show_error(e, 'An unexpected error has occurred while contacting Steam. Please ensure your Steam credentials are correct and then try again. '
87+
'If this problem persists please contact support.')
15388
return
15489

155-
data = response.json()
156-
totalItems = data['response']['total_count']
90+
directory_items = create_directory_items(steam_games_details)
91+
xbmcplugin.addDirectoryItems(plugin.handle, directory_items)
15792

158-
for entry in data['response']['games']:
93+
xbmcplugin.addSortMethod(plugin.handle, xbmcplugin.SORT_METHOD_UNSORTED)
94+
xbmcplugin.endOfDirectory(plugin.handle, succeeded=True)
15995

160-
appid = entry['appid']
161-
name = entry['name']
16296

163-
item = xbmcgui.ListItem(name)
164-
item.setArt({ 'thumb': 'http://cdn.akamai.steamstatic.com/steam/apps/' + str(appid) + '/header.jpg', 'fanart': 'http://cdn.akamai.steamstatic.com/steam/apps/' + str(appid) + '/page_bg_generated_v6b.jpg' })
97+
@plugin.route('/install/<appid>')
98+
def install(appid):
99+
if not os.path.isfile(__addon__.getSetting('steam-exe')):
100+
# ensure required data is available
101+
show_error(NameError('steam-exe not found'), 'Unable to find your Steam executable, please check your settings.')
102+
return
165103

166-
if not xbmcplugin.addDirectoryItem(handle=handle, url=plugin.url_for(run, id=str(appid)), listitem=item, totalItems=totalItems): break
104+
steam.install(__addon__.getSetting('steam-exe'), appid)
167105

168-
xbmcplugin.addSortMethod(handle, xbmcplugin.SORT_METHOD_UNSORTED)
169-
xbmcplugin.endOfDirectory(handle, succeeded=True)
170106

171-
@plugin.route('/install/<id>')
172-
def install(id):
107+
@plugin.route('/run/<appid>')
108+
def run(appid):
109+
if not os.path.isfile(__addon__.getSetting('steam-exe')):
110+
# ensure required data is available
111+
show_error(NameError('steam-exe not found'), 'Unable to find your Steam executable, please check your settings.')
112+
return
173113

174-
if os.path.isfile(__addon__.getSetting('steam-exe')) == False:
114+
steam.run(__addon__.getSetting('steam-exe'), __addon__.getSetting('steam-args'), appid)
175115

176-
# ensure required data is available
177-
notify = xbmcgui.Dialog()
178-
notify.notification('Error', 'Unable to find your Steam executable, please check your settings.', xbmcgui.NOTIFICATION_ERROR)
179116

180-
return
117+
def create_directory_items(app_entries):
118+
"""
119+
Creates a list item for each game/app entry provided
181120
182-
log('executing ' + __addon__.getSetting('steam-exe') + ' steam://install/' + id)
121+
:param app_entries: array of game entries, with each entry containing at least keys : appid, name, img_icon_url, img_logo_url, playtime_forever
122+
:returns: an array of list items of the game entries, formatted like so : [(url,listItem,bool),..]
123+
"""
124+
directory_items = []
125+
for app_entry in app_entries:
126+
appid = str(app_entry['appid'])
127+
name = app_entry['name']
183128

184-
# https://developer.valvesoftware.com/wiki/Steam_browser_protocol
185-
subprocess.call([__addon__.getSetting('steam-exe'), 'steam://install/' + id])
129+
run_url = plugin.url_for(run, appid=appid)
130+
item = xbmcgui.ListItem(name)
186131

187-
@plugin.route('/run/<id>')
188-
def run(id):
132+
item.addContextMenuItems([('Play', 'RunPlugin(' + run_url + ')'),
133+
('Install', 'RunPlugin(' + plugin.url_for(install, appid=appid) + ')')])
189134

190-
if os.path.isfile(__addon__.getSetting('steam-exe')) == False:
135+
art_dictionary = create_arts_dictionary(app_entry)
136+
item.setArt(art_dictionary)
191137

192-
# ensure required data is available
193-
notify = xbmcgui.Dialog()
194-
notify.notification('Error', 'Unable to find your Steam executable, please check your settings.', xbmcgui.NOTIFICATION_ERROR)
138+
directory_items.append((run_url, item, False))
195139

196-
return
140+
return directory_items
197141

198-
userArgs = shlex.split(__addon__.getSetting('steam-args'))
199142

200-
log('executing ' + __addon__.getSetting('steam-exe') + ' ' + __addon__.getSetting('steam-args') + ' steam://rungameid/' + id)
143+
def create_arts_dictionary(app_entry):
144+
"""
145+
Creates a dictionary of arts keys and their associated links, for a given app entry.
146+
:param app_entry: dictionary of app informations, containing at least the keys : appid, img_icon_url, img_logo_url
147+
:return: dictionary of arts for the app.
148+
"""
149+
art_dictionary = {'thumb': 'http://cdn.akamai.steamstatic.com/steam/apps/' + str(app_entry['appid']) + '/header.jpg',
150+
'fanart': 'http://cdn.akamai.steamstatic.com/steam/apps/' + str(app_entry['appid']) + '/page_bg_generated_v6b.jpg'}
151+
return art_dictionary
201152

202-
# https://developer.valvesoftware.com/wiki/Steam_browser_protocol
203-
subprocess.call([__addon__.getSetting('steam-exe')] + userArgs + ['steam://rungameid/' + id])
204153

205154
def main():
206-
207155
log('steam-id = ' + __addon__.getSetting('steam-id'))
208156
log('steam-key = ' + __addon__.getSetting('steam-key'))
209157
log('steam-exe = ' + __addon__.getSetting('steam-exe'))
210158
log('steam-path = ' + __addon__.getSetting('steam-path'))
211159

212160
# backwards compatibility for versions prior to 0.6.0
213-
if __addon__.getSetting('steam-id') != '' and __addon__.getSetting('steam-key') != '' and __addon__.getSetting('steam-path') != '' and __addon__.getSetting('steam-exe') == '':
161+
if __addon__.getSetting('steam-id') != '' and __addon__.getSetting('steam-key') != '' \
162+
and __addon__.getSetting('steam-path') != '' and __addon__.getSetting('steam-exe') == '':
214163

215-
__addon__.setSetting('steam-exe', __addon__.getSetting('steam-path'));
164+
__addon__.setSetting('steam-exe', __addon__.getSetting('steam-path'))
216165

217166
if sys.platform == "linux" or sys.platform == "linux2":
218167

219-
__addon__.setSetting('steam-path', os.path.expanduser('~/.steam'));
168+
__addon__.setSetting('steam-path', os.path.expanduser('~/.steam'))
220169

221170
elif sys.platform == "win32":
222171

@@ -233,7 +182,7 @@ def main():
233182
if sys.platform == "linux" or sys.platform == "linux2":
234183

235184
__addon__.setSetting('steam-exe', '/usr/bin/steam')
236-
__addon__.setSetting('steam-path', os.path.expanduser('~/.steam'));
185+
__addon__.setSetting('steam-path', os.path.expanduser('~/.steam'))
237186

238187
elif sys.platform == "darwin":
239188

@@ -251,13 +200,11 @@ def main():
251200
__addon__.setSetting('steam-path', os.path.expandvars('%ProgramFiles(x86)%\\Steam\\Steam.exe'))
252201

253202
if __addon__.getSetting('version') == '':
254-
255203
# first time run, store version
256-
__addon__.setSetting('version', '0.6.0');
204+
__addon__.setSetting('version', '0.6.0')
257205

258206
# prompt the user to configure the plugin with their steam details
259-
if __addon__.getSetting('steam-id') == '' or __addon__.getSetting('steam-key') == '':
260-
207+
if not all_required_credentials_available():
261208
__addon__.openSettings()
262209

263210
plugin.run()

0 commit comments

Comments
 (0)