1-
21import logging as log
32import sys
43
76from galaxy .api .types import NextStep , Authentication , Game , LicenseInfo , LicenseType , LocalGame , LocalGameState
87from version import __version__
98
10- from consts import AUTH_PARAMS
119from backend import ParadoxClient
1210from http_client import AuthenticatedHttpClient
11+ from consts import AUTH_PARAMS , System , SYSTEM
1312
1413import pickle
1514import asyncio
1918import webbrowser
2019
2120from typing import Any , List , Optional
22-
23-
2421from local import LocalClient
2522
2623
@@ -30,7 +27,6 @@ def __init__(self, reader, writer, token):
3027 self ._http_client = AuthenticatedHttpClient (self .store_credentials )
3128 self .paradox_client = ParadoxClient (self ._http_client )
3229 self .local_client = LocalClient ()
33- self .prepare_sku = None
3430 self .owned_games_cache = None
3531
3632 self .local_games_cache = {}
@@ -39,17 +35,20 @@ def __init__(self, reader, writer, token):
3935 self .tick_counter = 0
4036
4137 self .local_games_called = None
38+ self .owned_games_called = None
4239
4340 self .update_installed_games_task = None
4441 self .update_running_games_task = None
42+ self .update_owned_games_task = None
43+
44+
4545
4646 async def authenticate (self , stored_credentials = None ):
4747 if stored_credentials :
4848 stored_cookies = pickle .loads (bytes .fromhex (stored_credentials ['cookie_jar' ]))
4949 self ._http_client .authenticate_with_cookies (stored_cookies )
5050 self ._http_client .set_auth_lost_callback (self .lost_authentication )
5151 acc_id = await self .paradox_client .get_account_id ()
52- self .prepare_sku = asyncio .create_task (self .paradox_client .prepare_sku ())
5352 return Authentication (str (acc_id ), 'Paradox' )
5453 if not stored_credentials :
5554 return NextStep ("web_session" , AUTH_PARAMS )
@@ -58,76 +57,85 @@ async def pass_login_credentials(self, step, credentials, cookies):
5857 self ._http_client .authenticate_with_cookies (cookies )
5958 self ._http_client .set_auth_lost_callback (self .lost_authentication )
6059 acc_id = await self .paradox_client .get_account_id ()
61- self .prepare_sku = asyncio .create_task (self .paradox_client .prepare_sku ())
6260 return Authentication (str (acc_id ), 'Paradox' )
6361
6462 async def get_owned_games (self ):
65- owned_games = await self .paradox_client .get_owned_games ()
66- await self .prepare_sku
67- games_to_send = []
68- sent_titles = set ()
69- for game in owned_games :
70- log .info (game )
71- if game ['sku' ] in self .paradox_client .paradox_launcher_skus and 'game' in game ['type' ]:
72- title = game ['title' ].replace (' (Paradox)' , '' )
73- title = title .split (':' )[0 ]
74- if title in sent_titles :
75- continue
76- sent_titles .add (title )
77- games_to_send .append (Game (title .lower ().replace (' ' , '_' ), title , None , LicenseInfo (LicenseType .SinglePurchase )))
78- self .owned_games_cache = games_to_send
79- return games_to_send
80-
81- async def get_local_games (self ):
82- games_path = self .local_client .games_path
83- if not games_path :
84- return []
85- local_games = os .listdir (games_path )
86-
8763 games_to_send = []
88- local_games_cache = {}
89- for local_game in local_games :
90- game_folder = os .path .join (games_path , local_game )
91- game_cpatch = os .path .join (game_folder , '.cpatch' , local_game )
92- try :
93- with open (os .path .join (game_cpatch , 'version' ))as game_cp :
94- version = game_cp .readline ()
95- with open (os .path .join (game_cpatch , 'repository.json' ), 'r' ) as js :
96- game_repository = json .load (js )
97- exe_path = game_repository ['content' ]['versions' ][version ]['exePath' ]
98- except FileNotFoundError :
99- continue
100- except Exception as e :
101- log .error (f"Unable to parse local game { local_game } { repr (e )} " )
102- continue
103-
104- local_games_cache [local_game ] = os .path .join (game_folder , exe_path )
105- games_to_send .append (LocalGame (local_game , LocalGameState .Installed ))
106- self .local_games_cache = local_games_cache
107- self .local_games_called = True
64+ try :
65+ owned_games = await self .paradox_client .get_owned_games ()
66+ sent_titles = set ()
67+ for game in owned_games :
68+ log .info (game )
69+ if 'game' in game ['type' ]:
70+ title = game ['title' ].replace (' (Paradox)' , '' )
71+ title = title .split (':' )[0 ]
72+ if title in sent_titles :
73+ continue
74+ sent_titles .add (title )
75+ games_to_send .append (Game (title .lower ().replace (' ' , '_' ), title , None , LicenseInfo (LicenseType .SinglePurchase )))
76+ self .owned_games_cache = games_to_send
77+ self .owned_games_called = True
78+ except Exception as e :
79+ log .error (f"Encountered exception while retriving owned games { repr (e )} " )
80+ self .owned_games_called = True
81+ raise e
10882 return games_to_send
10983
110- async def launch_game (self , game_id ):
111- exe_path = self .local_games_cache .get (game_id )
112- log .info (f"Launching { exe_path } " )
113- game_dir = os .path .join (self .local_client .games_path , game_id )
114- subprocess .Popen (exe_path ,cwd = game_dir )
84+ if SYSTEM == System .WINDOWS :
85+ async def get_local_games (self ):
86+ games_path = self .local_client .games_path
87+ if not games_path :
88+ self .local_games_called = True
89+ return []
90+ local_games = os .listdir (games_path )
91+
92+ games_to_send = []
93+ local_games_cache = {}
94+ for local_game in local_games :
95+ game_folder = os .path .join (games_path , local_game )
96+ game_cpatch = os .path .join (game_folder , '.cpatch' , local_game )
97+ try :
98+ with open (os .path .join (game_cpatch , 'version' ))as game_cp :
99+ version = game_cp .readline ()
100+ with open (os .path .join (game_cpatch , 'repository.json' ), 'r' ) as js :
101+ game_repository = json .load (js )
102+ exe_path = game_repository ['content' ]['versions' ][version ]['exePath' ]
103+ except FileNotFoundError :
104+ continue
105+ except Exception as e :
106+ log .error (f"Unable to parse local game { local_game } { repr (e )} " )
107+ continue
115108
116- async def install_game (self , game_id ):
117- bootstraper_exe = self .local_client .bootstraper_exe
118- if bootstraper_exe :
119- subprocess .Popen (bootstraper_exe )
120- return
121- log .info ("Local client not installed" )
122- webbrowser .open ('https://play.paradoxplaza.com' )
123-
124- async def uninstall_game (self , game_id ):
125- bootstraper_exe = self .local_client .bootstraper_exe
126- if bootstraper_exe :
127- subprocess .call (bootstraper_exe )
128- return
129- log .info ("Local client not installed" )
130- webbrowser .open ('https://play.paradoxplaza.com' )
109+ local_games_cache [local_game ] = os .path .join (game_folder , exe_path )
110+ games_to_send .append (LocalGame (local_game , LocalGameState .Installed ))
111+ self .local_games_cache = local_games_cache
112+ self .local_games_called = True
113+ return games_to_send
114+
115+ if SYSTEM == System .WINDOWS :
116+ async def launch_game (self , game_id ):
117+ exe_path = self .local_games_cache .get (game_id )
118+ log .info (f"Launching { exe_path } " )
119+ game_dir = os .path .join (self .local_client .games_path , game_id )
120+ subprocess .Popen (exe_path ,cwd = game_dir )
121+
122+ if SYSTEM == System .WINDOWS :
123+ async def install_game (self , game_id ):
124+ bootstraper_exe = self .local_client .bootstraper_exe
125+ if bootstraper_exe :
126+ subprocess .Popen (bootstraper_exe )
127+ return
128+ log .info ("Local client not installed" )
129+ webbrowser .open ('https://play.paradoxplaza.com' )
130+
131+ if SYSTEM == System .WINDOWS :
132+ async def uninstall_game (self , game_id ):
133+ bootstraper_exe = self .local_client .bootstraper_exe
134+ if bootstraper_exe :
135+ subprocess .call (bootstraper_exe )
136+ return
137+ log .info ("Local client not installed" )
138+ webbrowser .open ('https://play.paradoxplaza.com' )
131139
132140 async def update_installed_games (self ):
133141 games_path = self .local_client .games_path
@@ -165,18 +173,36 @@ async def update_running_games(self):
165173
166174 self .running_game = running_game
167175
176+ async def update_owned_games (self ):
177+ owned_games_cache = self .owned_games_cache
178+ owned_games = await self .get_owned_games ()
179+ log .info ("Looking for new games" )
180+ for game in owned_games :
181+ if game not in owned_games_cache :
182+ log .info (f"Adding game { game } " )
183+ self .add_game (game )
184+
185+
168186 def tick (self ):
169- if not self .local_games_called or sys .platform != 'win32' :
170- return
171187 self .tick_counter += 1
172188
189+ if not self .owned_games_called or (sys .platform == 'win32' and not self .local_games_called ):
190+ return
191+
192+ if self .tick_counter % 60 == 0 :
193+ if not self .update_owned_games_task or self .update_owned_games_task .done ():
194+ self .update_owned_games_task = asyncio .create_task (self .update_owned_games ())
195+
196+ if sys .platform != 'win32' :
197+ return
198+
173199 if not self .update_installed_games_task or self .update_installed_games_task .done ():
174200 self .update_installed_games_task = asyncio .create_task (self .update_installed_games ())
175201 if not self .update_running_games_task or self .update_running_games_task .done ():
176202 self .update_running_games_task = asyncio .create_task (self .update_running_games ())
177203
178- def shutdown (self ):
179- asyncio . create_task ( self ._http_client .close () )
204+ async def shutdown (self ):
205+ await self ._http_client .close ()
180206
181207 async def prepare_os_compatibility_context (self , game_ids : List [str ]) -> Any :
182208 return None
0 commit comments