mirror of
https://github.com/EDCD/EDMarketConnector.git
synced 2025-06-06 02:13:41 +03:00
Merge pull request #1773 from aussig/feature/847/capi-fleetcarrier
Feature/847/capi fleetcarrier
This commit is contained in:
commit
74b070ffe9
@ -476,6 +476,8 @@ class AppWindow(object):
|
|||||||
def __init__(self, master: tk.Tk): # noqa: C901, CCR001 # TODO - can possibly factor something out
|
def __init__(self, master: tk.Tk): # noqa: C901, CCR001 # TODO - can possibly factor something out
|
||||||
|
|
||||||
self.capi_query_holdoff_time = config.get_int('querytime', default=0) + companion.capi_query_cooldown
|
self.capi_query_holdoff_time = config.get_int('querytime', default=0) + companion.capi_query_cooldown
|
||||||
|
self.capi_fleetcarrier_query_holdoff_time = config.get_int('fleetcarrierquerytime', default=0) \
|
||||||
|
+ companion.capi_fleetcarrier_query_cooldown
|
||||||
|
|
||||||
self.w = master
|
self.w = master
|
||||||
self.w.title(applongname)
|
self.w.title(applongname)
|
||||||
@ -916,6 +918,9 @@ class AppWindow(object):
|
|||||||
|
|
||||||
def login(self):
|
def login(self):
|
||||||
"""Initiate CAPI/Frontier login and set other necessary state."""
|
"""Initiate CAPI/Frontier login and set other necessary state."""
|
||||||
|
should_return: bool
|
||||||
|
new_data: dict[str, Any]
|
||||||
|
|
||||||
should_return, new_data = killswitch.check_killswitch('capi.auth', {})
|
should_return, new_data = killswitch.check_killswitch('capi.auth', {})
|
||||||
if should_return:
|
if should_return:
|
||||||
logger.warning('capi.auth has been disabled via killswitch. Returning.')
|
logger.warning('capi.auth has been disabled via killswitch. Returning.')
|
||||||
@ -1086,6 +1091,54 @@ class AppWindow(object):
|
|||||||
play_sound=play_sound
|
play_sound=play_sound
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def capi_request_fleetcarrier_data(self, event=None) -> None:
|
||||||
|
"""
|
||||||
|
Perform CAPI fleetcarrier data retrieval and associated actions.
|
||||||
|
|
||||||
|
This is triggered by certain FleetCarrier journal events
|
||||||
|
|
||||||
|
:param event: Tk generated event details.
|
||||||
|
"""
|
||||||
|
logger.trace_if('capi.worker', 'Begin')
|
||||||
|
should_return: bool
|
||||||
|
new_data: dict[str, Any]
|
||||||
|
|
||||||
|
should_return, new_data = killswitch.check_killswitch('capi.request.fleetcarrier', {})
|
||||||
|
if should_return:
|
||||||
|
logger.warning('capi.fleetcarrier has been disabled via killswitch. Returning.')
|
||||||
|
self.status['text'] = 'CAPI fleetcarrier disabled by killswitch'
|
||||||
|
hotkeymgr.play_bad()
|
||||||
|
return
|
||||||
|
|
||||||
|
if not monitor.cmdr:
|
||||||
|
logger.trace_if('capi.worker', 'Aborting Query: Cmdr unknown')
|
||||||
|
# LANG: CAPI queries aborted because Cmdr name is unknown
|
||||||
|
self.status['text'] = _('CAPI query aborted: Cmdr name unknown')
|
||||||
|
return
|
||||||
|
|
||||||
|
if monitor.state['GameVersion'] is None:
|
||||||
|
logger.trace_if('capi.worker', 'Aborting Query: GameVersion unknown')
|
||||||
|
# LANG: CAPI queries aborted because GameVersion unknown
|
||||||
|
self.status['text'] = _('CAPI query aborted: GameVersion unknown')
|
||||||
|
return
|
||||||
|
|
||||||
|
if not companion.session.retrying:
|
||||||
|
if time() < self.capi_fleetcarrier_query_holdoff_time: # Was invoked while in cooldown
|
||||||
|
logger.debug('CAPI fleetcarrier query aborted, too soon since last request')
|
||||||
|
return
|
||||||
|
|
||||||
|
# LANG: Status - Attempting to retrieve data from Frontier CAPI
|
||||||
|
self.status['text'] = _('Fetching data...')
|
||||||
|
self.w.update_idletasks()
|
||||||
|
|
||||||
|
query_time = int(time())
|
||||||
|
logger.trace_if('capi.worker', 'Requesting fleetcarrier data')
|
||||||
|
config.set('fleetcarrierquerytime', query_time)
|
||||||
|
logger.trace_if('capi.worker', 'Calling companion.session.fleetcarrier')
|
||||||
|
companion.session.fleetcarrier(
|
||||||
|
query_time=query_time, tk_response_event=self._CAPI_RESPONSE_TK_EVENT_NAME
|
||||||
|
)
|
||||||
|
|
||||||
def capi_handle_response(self, event=None): # noqa: C901, CCR001
|
def capi_handle_response(self, event=None): # noqa: C901, CCR001
|
||||||
"""Handle the resulting data from a CAPI query."""
|
"""Handle the resulting data from a CAPI query."""
|
||||||
logger.trace_if('capi.worker', 'Handling response')
|
logger.trace_if('capi.worker', 'Handling response')
|
||||||
@ -1110,8 +1163,32 @@ class AppWindow(object):
|
|||||||
logger.error(msg)
|
logger.error(msg)
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
||||||
|
if capi_response.capi_data.source_endpoint == companion.session.FRONTIER_CAPI_PATH_FLEETCARRIER:
|
||||||
|
# Fleetcarrier CAPI response
|
||||||
|
# Validation
|
||||||
|
if 'name' not in capi_response.capi_data:
|
||||||
|
# LANG: No data was returned for the fleetcarrier from the Frontier CAPI
|
||||||
|
err = self.status['text'] = _('CAPI: No fleetcarrier data returned')
|
||||||
|
|
||||||
|
elif not capi_response.capi_data.get('name', {}).get('callsign'):
|
||||||
|
# LANG: We didn't have the fleetcarrier callsign when we should have
|
||||||
|
err = self.status['text'] = _("CAPI: Fleetcarrier data incomplete") # Shouldn't happen
|
||||||
|
|
||||||
|
else:
|
||||||
|
if __debug__: # Recording
|
||||||
|
companion.session.dump_capi_data(capi_response.capi_data)
|
||||||
|
|
||||||
|
err = plug.notify_capi_fleetcarrierdata(capi_response.capi_data)
|
||||||
|
self.status['text'] = err and err or ''
|
||||||
|
if err:
|
||||||
|
play_bad = True
|
||||||
|
|
||||||
|
self.capi_fleetcarrier_query_holdoff_time = capi_response.query_time \
|
||||||
|
+ companion.capi_fleetcarrier_query_cooldown
|
||||||
|
|
||||||
|
# Other CAPI response
|
||||||
# Validation
|
# Validation
|
||||||
if 'commander' not in capi_response.capi_data:
|
elif 'commander' not in capi_response.capi_data:
|
||||||
# This can happen with EGS Auth if no commander created yet
|
# This can happen with EGS Auth if no commander created yet
|
||||||
# LANG: No data was returned for the commander from the Frontier CAPI
|
# LANG: No data was returned for the commander from the Frontier CAPI
|
||||||
err = self.status['text'] = _('CAPI: No commander data returned')
|
err = self.status['text'] = _('CAPI: No commander data returned')
|
||||||
@ -1234,6 +1311,9 @@ class AppWindow(object):
|
|||||||
if err:
|
if err:
|
||||||
play_bad = True
|
play_bad = True
|
||||||
|
|
||||||
|
should_return: bool
|
||||||
|
new_data: dict[str, Any]
|
||||||
|
|
||||||
should_return, new_data = killswitch.check_killswitch('capi.request./market', {})
|
should_return, new_data = killswitch.check_killswitch('capi.request./market', {})
|
||||||
if should_return:
|
if should_return:
|
||||||
logger.warning("capi.request./market has been disabled by killswitch. Returning.")
|
logger.warning("capi.request./market has been disabled by killswitch. Returning.")
|
||||||
@ -1494,11 +1574,19 @@ class AppWindow(object):
|
|||||||
elif entry['event'] == 'Disembark' and entry.get('Taxi') and entry.get('OnStation'):
|
elif entry['event'] == 'Disembark' and entry.get('Taxi') and entry.get('OnStation'):
|
||||||
auto_update = True
|
auto_update = True
|
||||||
|
|
||||||
|
should_return: bool
|
||||||
|
new_data: dict[str, Any]
|
||||||
|
|
||||||
if auto_update:
|
if auto_update:
|
||||||
should_return, new_data = killswitch.check_killswitch('capi.auth', {})
|
should_return, new_data = killswitch.check_killswitch('capi.auth', {})
|
||||||
if not should_return:
|
if not should_return:
|
||||||
self.w.after(int(SERVER_RETRY * 1000), self.capi_request_data)
|
self.w.after(int(SERVER_RETRY * 1000), self.capi_request_data)
|
||||||
|
|
||||||
|
if entry['event'] in ('CarrierBuy', 'CarrierStats') and config.get_bool('capi_fleetcarrier'):
|
||||||
|
should_return, new_data = killswitch.check_killswitch('capi.request.fleetcarrier', {})
|
||||||
|
if not should_return:
|
||||||
|
self.w.after(int(SERVER_RETRY * 1000), self.capi_request_fleetcarrier_data)
|
||||||
|
|
||||||
if entry['event'] == 'ShutDown':
|
if entry['event'] == 'ShutDown':
|
||||||
# Enable WinSparkle automatic update checks
|
# Enable WinSparkle automatic update checks
|
||||||
# NB: Do this blindly, in case option got changed whilst in-game
|
# NB: Do this blindly, in case option got changed whilst in-game
|
||||||
|
84
PLUGINS.md
84
PLUGINS.md
@ -99,8 +99,8 @@ liable to change without notice.
|
|||||||
`from prefs import prefsVersion` - to allow for versioned preferences.
|
`from prefs import prefsVersion` - to allow for versioned preferences.
|
||||||
|
|
||||||
`from companion import CAPIData, SERVER_LIVE, SERVER_LEGACY, SERVER_BETA` -
|
`from companion import CAPIData, SERVER_LIVE, SERVER_LEGACY, SERVER_BETA` -
|
||||||
`CAPIData` is the actual type of `data` as passed into `cmdr_data()` and
|
`CAPIData` is the actual type of `data` as passed into `cmdr_data()`,
|
||||||
`cmdr_data_legacy()`.
|
`cmdr_data_legacy()` and `capi_fleetcarrier()`.
|
||||||
See [Commander Data from Frontier CAPI](#commander-data-from-frontier-capi))
|
See [Commander Data from Frontier CAPI](#commander-data-from-frontier-capi))
|
||||||
for further information.
|
for further information.
|
||||||
|
|
||||||
@ -561,9 +561,9 @@ See [Avoiding potential pitfalls](#avoiding-potential-pitfalls).
|
|||||||
### Events
|
### Events
|
||||||
|
|
||||||
Once you have created your plugin and EDMarketConnector has loaded it there
|
Once you have created your plugin and EDMarketConnector has loaded it there
|
||||||
are four other functions you can define to be notified by EDMarketConnector
|
are five other functions you can define to be notified by EDMarketConnector
|
||||||
when something happens: `journal_entry()`, `journal_entry_cqc()`,
|
when something happens: `journal_entry()`, `journal_entry_cqc()`,
|
||||||
`dashboard_entry()` and `cmdr_data()`.
|
`dashboard_entry()`, `cmdr_data()` and `capi_fleetcarrier()`.
|
||||||
|
|
||||||
Your events all get called on the main Tkinter loop so be sure not to block for
|
Your events all get called on the main Tkinter loop so be sure not to block for
|
||||||
very long or the app will appear to freeze. If you have a long running
|
very long or the app will appear to freeze. If you have a long running
|
||||||
@ -908,11 +908,11 @@ constants.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Commander Data from Frontier CAPI
|
### Data from Frontier CAPI
|
||||||
If a plugin has a `cmdr_data()` function it gets called when the application
|
|
||||||
has just fetched fresh Cmdr and station data from Frontier's CAPI servers,
|
#### Commander, Market and Shipyard Data
|
||||||
**but not for the Legacy galaxy**. See `cmdr_data_legacy()` below for Legacy
|
|
||||||
data handling.
|
If a plugin has a `cmdr_data()` function it gets called when the application has just fetched fresh CMDR, station and shipyard data from Frontier's CAPI servers, **but not for the Legacy galaxy**. See `cmdr_data_legacy()` below for Legacy data handling.
|
||||||
```python
|
```python
|
||||||
from companion import CAPIData, SERVER_LIVE, SERVER_LEGACY, SERVER_BETA
|
from companion import CAPIData, SERVER_LIVE, SERVER_LEGACY, SERVER_BETA
|
||||||
|
|
||||||
@ -940,29 +940,59 @@ def cmdr_data(data, is_beta):
|
|||||||
| :-------- | :--------------: | :------------------------------------------------------------------------------------------------------- |
|
| :-------- | :--------------: | :------------------------------------------------------------------------------------------------------- |
|
||||||
| `data` | `CAPIData` | `/profile` API response, with `/market` and `/shipyard` added under the keys `marketdata` and `shipdata` |
|
| `data` | `CAPIData` | `/profile` API response, with `/market` and `/shipyard` added under the keys `marketdata` and `shipdata` |
|
||||||
| `is_beta` | `bool` | If the game is currently in beta |
|
| `is_beta` | `bool` | If the game is currently in beta |
|
||||||
`CAPIData` is a class, which you can `from companion import CAPIDATA`, and is
|
|
||||||
based on `UserDict`. The actual data from CAPI queries is thus accessible
|
|
||||||
via python's normal `data['key']` syntax. However, being a class, it can also
|
|
||||||
have extra properties, such as `source_host`, as shown above. Plugin authors
|
|
||||||
are free to use *that* property, **but MUST NOT rely on any other extra
|
|
||||||
properties present in `CAPIData`, they are for internal use only.**
|
|
||||||
|
|
||||||
The contents of `data` will always have at least the data returned by a CAPI
|
#### Fleet Carrier Data
|
||||||
`/profile` query. If the player is docked at a station, and the relevant
|
|
||||||
services are available then the `lastStarport` key's value will have been
|
If a plugin has a `capi_fleetcarrier()` function it gets called when the application has just fetched fresh Fleetcarrier data from Frontier's CAPI servers. This is done when `CarrierBuy`or `CarrierStats` events are detected in the Player Journal. To avoid flooding Frontier's CAPI server, a throttle is applied to ensure a significant interval between requests (currently 15 mins). Also be aware that calls to the `/fleetcarrier` CAPI endpoint have been reported to take a very long time to return, potentially up to 20 minutes. Delays in responses from this endpoint could delay other CAPI queries.
|
||||||
augmented with `/market` and/or `/shipyard` data. **But do not assume this
|
|
||||||
will always be the case**.
|
```python
|
||||||
|
from companion import CAPIData, SERVER_LIVE, SERVER_LEGACY, SERVER_BETA
|
||||||
|
|
||||||
|
def capi_fleetcarrier(data):
|
||||||
|
"""
|
||||||
|
We have new data on our Fleet Carrier
|
||||||
|
"""
|
||||||
|
if data.get('name') is None or data['name'].get('callsign') is None:
|
||||||
|
raise ValueError("this isn't possible")
|
||||||
|
|
||||||
|
logger.info(data['name']['callsign'])
|
||||||
|
|
||||||
|
# Determining source galaxy for the data
|
||||||
|
if data.source_host == SERVER_LIVE:
|
||||||
|
...
|
||||||
|
|
||||||
|
elif data.source_host == SERVER_BETA:
|
||||||
|
...
|
||||||
|
|
||||||
|
elif data.source_host == SERVER_LEGACY:
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
| Parameter | Type | Description |
|
||||||
|
| :-------- | :--------------: | :------------------------------------------------------------------------------------------------------- |
|
||||||
|
| `data` | `CAPIData` | `/fleetcarrier` API response |
|
||||||
|
|
||||||
|
#### CAPIData and Available Properties
|
||||||
|
|
||||||
|
`CAPIData` is a class, which you can `from companion import CAPIDATA`, and is based on `UserDict`. The actual data from CAPI queries is thus accessible via python's normal `data['key']` syntax. However, being a class, it can also have extra properties, such as `source_host`, as shown in the code example above.
|
||||||
|
|
||||||
|
Plugin authors are free to use the following properties of `CAPIData`, **but MUST NOT rely on any other extra properties, they are for internal use only.**
|
||||||
|
|
||||||
|
| Property | Type | Description |
|
||||||
|
| :------------- | :--------------: | :------------------------------------------------------------------------------------------------------- |
|
||||||
|
| `data` | `Dict` | The data returned by the CAPI query. For the `cmdr_data()` callback, if the player is docked at a station, and the relevant services are available then the `lastStarport` key's value will have been augmented with `/market` and/or `/shipyard` data. **Do not assume this will always be the case**. |
|
||||||
|
| `source_host` | `str` | `SERVER_LIVE` \| `SERVER_BETA` \| `SERVER_LEGACY` the current galaxy mode. |
|
||||||
|
| `request_cmdr` | `str` | The name of the active CMDR _at the point the request was made_. In the case of a CAPI request taking a long time to return, the user may have switched CMDR during the request, so this may be different to the current CMDR. |
|
||||||
|
|
||||||
|
See [this documentation](https://github.com/Athanasius/fd-api/blob/main/docs/FrontierDevelopments-CAPI-endpoints.md) for details of the expected content structure and data for CAPI queries.
|
||||||
|
|
||||||
If there is a killswitch in effect for some of the CAPI endpoints, then the
|
If there is a killswitch in effect for some of the CAPI endpoints, then the
|
||||||
data passed to this function might not be as complete as you expect. Code
|
data passed to this function might not be as complete as you expect. Code
|
||||||
defensively.
|
defensively.
|
||||||
|
|
||||||
|
|
||||||
#### CAPI data for Legacy
|
#### CAPI data for Legacy
|
||||||
When CAPI data has been retrieved from the separate CAPI host for the Legacy
|
|
||||||
galaxy, because the Journal gameversion indicated the player is playing/last
|
When CAPI data has been retrieved from the separate CAPI host for the Legacy galaxy, because the Journal gameversion indicated the player is playing / last played in that galaxy, a different function will be called, `cmdr_data_legacy()`. Note that there is no legacy equivalent to `capi_fleetcarrier()`, so always use the `source_host` property to determine the user's galaxy.
|
||||||
played in that galaxy, a different function will be called,
|
|
||||||
`cmdr_data_legacy()`.
|
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def cmdr_data_legacy(data, is_beta):
|
def cmdr_data_legacy(data, is_beta):
|
||||||
@ -1082,7 +1112,7 @@ time after the corresponding `journal_entry()` event.
|
|||||||
## Error messages
|
## Error messages
|
||||||
|
|
||||||
You can display an error in EDMarketConnector's status area by returning a
|
You can display an error in EDMarketConnector's status area by returning a
|
||||||
string from your `journal_entry()`, `dashboard_entry()` or `cmdr_data()`
|
string from your `journal_entry()`, `dashboard_entry()`, `cmdr_data()` or `capi_fleetcarrier()`
|
||||||
function, or asynchronously (e.g. from a "worker" thread that is performing a
|
function, or asynchronously (e.g. from a "worker" thread that is performing a
|
||||||
long-running operation) by calling `plug.show_error()`. Either method will
|
long-running operation) by calling `plug.show_error()`. Either method will
|
||||||
cause the "bad" sound to be played (unless the user has muted sound).
|
cause the "bad" sound to be played (unless the user has muted sound).
|
||||||
@ -1311,7 +1341,7 @@ versions of EDMarketConnector:
|
|||||||
`Settings` > `Plugins` tab.
|
`Settings` > `Plugins` tab.
|
||||||
|
|
||||||
- Check that callback functions `plugin_prefs`, `prefs_changed`,
|
- Check that callback functions `plugin_prefs`, `prefs_changed`,
|
||||||
`journal_entry`, `dashboard_entry` and `cmdr_data`, if used, are declared
|
`journal_entry`, `dashboard_entry`, `cmdr_data` and `capi_fleetcarrier`, if used, are declared
|
||||||
with the correct number of arguments. Older versions of this app were
|
with the correct number of arguments. Older versions of this app were
|
||||||
tolerant of missing arguments in these function declarations.
|
tolerant of missing arguments in these function declarations.
|
||||||
|
|
||||||
|
58
companion.py
58
companion.py
@ -46,7 +46,9 @@ else:
|
|||||||
|
|
||||||
|
|
||||||
capi_query_cooldown = 60 # Minimum time between (sets of) CAPI queries
|
capi_query_cooldown = 60 # Minimum time between (sets of) CAPI queries
|
||||||
|
capi_fleetcarrier_query_cooldown = 60 * 15 # Minimum time between CAPI fleetcarrier queries
|
||||||
capi_default_requests_timeout = 10
|
capi_default_requests_timeout = 10
|
||||||
|
capi_fleetcarrier_requests_timeout = 60
|
||||||
auth_timeout = 30 # timeout for initial auth
|
auth_timeout = 30 # timeout for initial auth
|
||||||
|
|
||||||
# Used by both class Auth and Session
|
# Used by both class Auth and Session
|
||||||
@ -66,7 +68,8 @@ class CAPIData(UserDict):
|
|||||||
self,
|
self,
|
||||||
data: Union[str, Dict[str, Any], 'CAPIData', None] = None,
|
data: Union[str, Dict[str, Any], 'CAPIData', None] = None,
|
||||||
source_host: Optional[str] = None,
|
source_host: Optional[str] = None,
|
||||||
source_endpoint: Optional[str] = None
|
source_endpoint: Optional[str] = None,
|
||||||
|
request_cmdr: Optional[str] = None
|
||||||
) -> None:
|
) -> None:
|
||||||
if data is None:
|
if data is None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
@ -81,6 +84,7 @@ class CAPIData(UserDict):
|
|||||||
|
|
||||||
self.source_host = source_host
|
self.source_host = source_host
|
||||||
self.source_endpoint = source_endpoint
|
self.source_endpoint = source_endpoint
|
||||||
|
self.request_cmdr = request_cmdr
|
||||||
|
|
||||||
if source_endpoint is None:
|
if source_endpoint is None:
|
||||||
return
|
return
|
||||||
@ -326,7 +330,10 @@ class Auth(object):
|
|||||||
"""
|
"""
|
||||||
logger.debug(f'Trying for "{self.cmdr}"')
|
logger.debug(f'Trying for "{self.cmdr}"')
|
||||||
|
|
||||||
should_return, _ = killswitch.check_killswitch('capi.auth', {})
|
should_return: bool
|
||||||
|
new_data: dict[str, Any]
|
||||||
|
|
||||||
|
should_return, new_data = killswitch.check_killswitch('capi.auth', {})
|
||||||
if should_return:
|
if should_return:
|
||||||
logger.warning('capi.auth has been disabled via killswitch. Returning.')
|
logger.warning('capi.auth has been disabled via killswitch. Returning.')
|
||||||
return None
|
return None
|
||||||
@ -612,6 +619,8 @@ class Session(object):
|
|||||||
FRONTIER_CAPI_PATH_PROFILE = '/profile'
|
FRONTIER_CAPI_PATH_PROFILE = '/profile'
|
||||||
FRONTIER_CAPI_PATH_MARKET = '/market'
|
FRONTIER_CAPI_PATH_MARKET = '/market'
|
||||||
FRONTIER_CAPI_PATH_SHIPYARD = '/shipyard'
|
FRONTIER_CAPI_PATH_SHIPYARD = '/shipyard'
|
||||||
|
FRONTIER_CAPI_PATH_FLEETCARRIER = '/fleetcarrier'
|
||||||
|
|
||||||
# This is a dummy value, to signal to Session.capi_query_worker that we
|
# This is a dummy value, to signal to Session.capi_query_worker that we
|
||||||
# the 'station' triplet of queries.
|
# the 'station' triplet of queries.
|
||||||
_CAPI_PATH_STATION = '_edmc_station'
|
_CAPI_PATH_STATION = '_edmc_station'
|
||||||
@ -663,7 +672,10 @@ class Session(object):
|
|||||||
|
|
||||||
:return: True if login succeeded, False if re-authorization initiated.
|
:return: True if login succeeded, False if re-authorization initiated.
|
||||||
"""
|
"""
|
||||||
should_return, _ = killswitch.check_killswitch('capi.auth', {})
|
should_return: bool
|
||||||
|
new_data: dict[str, Any]
|
||||||
|
|
||||||
|
should_return, new_data = killswitch.check_killswitch('capi.auth', {})
|
||||||
if should_return:
|
if should_return:
|
||||||
logger.warning('capi.auth has been disabled via killswitch. Returning.')
|
logger.warning('capi.auth has been disabled via killswitch. Returning.')
|
||||||
return False
|
return False
|
||||||
@ -781,7 +793,10 @@ class Session(object):
|
|||||||
:return: The resulting CAPI data, of type CAPIData.
|
:return: The resulting CAPI data, of type CAPIData.
|
||||||
"""
|
"""
|
||||||
capi_data: CAPIData = CAPIData()
|
capi_data: CAPIData = CAPIData()
|
||||||
should_return, _ = killswitch.check_killswitch('capi.request.' + capi_endpoint, {})
|
should_return: bool
|
||||||
|
new_data: dict[str, Any]
|
||||||
|
|
||||||
|
should_return, new_data = killswitch.check_killswitch('capi.request.' + capi_endpoint, {})
|
||||||
if should_return:
|
if should_return:
|
||||||
logger.warning(f"capi.request.{capi_endpoint} has been disabled by killswitch. Returning.")
|
logger.warning(f"capi.request.{capi_endpoint} has been disabled by killswitch. Returning.")
|
||||||
return capi_data
|
return capi_data
|
||||||
@ -804,7 +819,7 @@ class Session(object):
|
|||||||
# r.status_code = 401
|
# r.status_code = 401
|
||||||
# raise requests.HTTPError
|
# raise requests.HTTPError
|
||||||
capi_json = r.json()
|
capi_json = r.json()
|
||||||
capi_data = CAPIData(capi_json, capi_host, capi_endpoint)
|
capi_data = CAPIData(capi_json, capi_host, capi_endpoint, monitor.cmdr)
|
||||||
self.capi_raw_data.record_endpoint(
|
self.capi_raw_data.record_endpoint(
|
||||||
capi_endpoint, r.content.decode(encoding='utf-8'),
|
capi_endpoint, r.content.decode(encoding='utf-8'),
|
||||||
datetime.datetime.utcnow()
|
datetime.datetime.utcnow()
|
||||||
@ -956,6 +971,10 @@ class Session(object):
|
|||||||
if query.endpoint == self._CAPI_PATH_STATION:
|
if query.endpoint == self._CAPI_PATH_STATION:
|
||||||
capi_data = capi_station_queries(query.capi_host)
|
capi_data = capi_station_queries(query.capi_host)
|
||||||
|
|
||||||
|
elif query.endpoint == self.FRONTIER_CAPI_PATH_FLEETCARRIER:
|
||||||
|
capi_data = capi_single_query(query.capi_host, self.FRONTIER_CAPI_PATH_FLEETCARRIER,
|
||||||
|
timeout=capi_fleetcarrier_requests_timeout)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
capi_data = capi_single_query(query.capi_host, self.FRONTIER_CAPI_PATH_PROFILE)
|
capi_data = capi_single_query(query.capi_host, self.FRONTIER_CAPI_PATH_PROFILE)
|
||||||
|
|
||||||
@ -1027,6 +1046,35 @@ class Session(object):
|
|||||||
auto_update=auto_update
|
auto_update=auto_update
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def fleetcarrier(
|
||||||
|
self, query_time: int, tk_response_event: Optional[str] = None,
|
||||||
|
play_sound: bool = False, auto_update: bool = False
|
||||||
|
) -> None:
|
||||||
|
"""
|
||||||
|
Perform CAPI query for fleetcarrier data.
|
||||||
|
|
||||||
|
:param query_time: When this query was initiated.
|
||||||
|
:param tk_response_event: Name of tk event to generate when response queued.
|
||||||
|
:param play_sound: Whether the app should play a sound on error.
|
||||||
|
:param auto_update: Whether this request was triggered automatically.
|
||||||
|
"""
|
||||||
|
capi_host = self.capi_host_for_galaxy()
|
||||||
|
if not capi_host:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Ask the thread worker to perform a fleetcarrier query
|
||||||
|
logger.trace_if('capi.worker', 'Enqueueing fleetcarrier request')
|
||||||
|
self.capi_request_queue.put(
|
||||||
|
EDMCCAPIRequest(
|
||||||
|
capi_host=capi_host,
|
||||||
|
endpoint=self.FRONTIER_CAPI_PATH_FLEETCARRIER,
|
||||||
|
tk_response_event=tk_response_event,
|
||||||
|
query_time=query_time,
|
||||||
|
play_sound=play_sound,
|
||||||
|
auto_update=auto_update
|
||||||
|
)
|
||||||
|
)
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
24
plug.py
24
plug.py
@ -405,6 +405,30 @@ def notify_capidata(
|
|||||||
return error
|
return error
|
||||||
|
|
||||||
|
|
||||||
|
def notify_capi_fleetcarrierdata(
|
||||||
|
data: companion.CAPIData
|
||||||
|
) -> Optional[str]:
|
||||||
|
"""
|
||||||
|
Send the latest CAPI Fleetcarrier data from the FD servers to each plugin.
|
||||||
|
|
||||||
|
:param data: The CAPIData returned in the CAPI response
|
||||||
|
:returns: Error message from the first plugin that returns one (if any)
|
||||||
|
"""
|
||||||
|
error = None
|
||||||
|
for plugin in PLUGINS:
|
||||||
|
fc_callback = plugin._get_func('capi_fleetcarrier')
|
||||||
|
if fc_callback is not None and callable(fc_callback):
|
||||||
|
try:
|
||||||
|
# Pass a copy of the CAPIData in case the callee modifies it
|
||||||
|
newerror = fc_callback(copy.deepcopy(data))
|
||||||
|
error = error or newerror
|
||||||
|
|
||||||
|
except Exception:
|
||||||
|
logger.exception(f'Plugin "{plugin.name}" failed on receiving Fleetcarrier data')
|
||||||
|
|
||||||
|
return error
|
||||||
|
|
||||||
|
|
||||||
def show_error(err: str) -> None:
|
def show_error(err: str) -> None:
|
||||||
"""
|
"""
|
||||||
Display an error message in the status line of the main window.
|
Display an error message in the status line of the main window.
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $#
|
# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $#
|
||||||
# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $#
|
# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $#
|
||||||
import tkinter
|
import tkinter
|
||||||
from typing import TYPE_CHECKING, Any, Mapping, MutableMapping, Optional
|
from typing import TYPE_CHECKING, Any, Dict, Mapping, MutableMapping, Optional
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
@ -168,6 +168,9 @@ def journal_entry( # noqa: CCR001
|
|||||||
:param state: `monitor.state`
|
:param state: `monitor.state`
|
||||||
:return: None if no error, else an error string.
|
:return: None if no error, else an error string.
|
||||||
"""
|
"""
|
||||||
|
should_return: bool
|
||||||
|
new_entry: Dict[str, Any] = {}
|
||||||
|
|
||||||
should_return, new_entry = killswitch.check_killswitch('plugins.eddb.journal', entry)
|
should_return, new_entry = killswitch.check_killswitch('plugins.eddb.journal', entry)
|
||||||
if should_return:
|
if should_return:
|
||||||
# LANG: Journal Processing disabled due to an active killswitch
|
# LANG: Journal Processing disabled due to an active killswitch
|
||||||
|
@ -402,6 +402,9 @@ class EDDNSender:
|
|||||||
:return: `True` for "now remove this message from the queue"
|
:return: `True` for "now remove this message from the queue"
|
||||||
"""
|
"""
|
||||||
logger.trace_if("plugin.eddn.send", "Sending message")
|
logger.trace_if("plugin.eddn.send", "Sending message")
|
||||||
|
should_return: bool
|
||||||
|
new_data: dict[str, Any]
|
||||||
|
|
||||||
should_return, new_data = killswitch.check_killswitch('plugins.eddn.send', json.loads(msg))
|
should_return, new_data = killswitch.check_killswitch('plugins.eddn.send', json.loads(msg))
|
||||||
if should_return:
|
if should_return:
|
||||||
logger.warning('eddn.send has been disabled via killswitch. Returning.')
|
logger.warning('eddn.send has been disabled via killswitch. Returning.')
|
||||||
|
@ -386,6 +386,9 @@ def journal_entry( # noqa: C901, CCR001
|
|||||||
|
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
|
should_return: bool
|
||||||
|
new_entry: Dict[str, Any] = {}
|
||||||
|
|
||||||
should_return, new_entry = killswitch.check_killswitch('plugins.inara.journal', entry, logger)
|
should_return, new_entry = killswitch.check_killswitch('plugins.inara.journal', entry, logger)
|
||||||
if should_return:
|
if should_return:
|
||||||
plug.show_error(_('Inara disabled. See Log.')) # LANG: INARA support disabled via killswitch
|
plug.show_error(_('Inara disabled. See Log.')) # LANG: INARA support disabled via killswitch
|
||||||
@ -1537,7 +1540,6 @@ def new_add_event(
|
|||||||
def clean_event_list(event_list: List[Event]) -> List[Event]:
|
def clean_event_list(event_list: List[Event]) -> List[Event]:
|
||||||
"""Check for killswitched events and remove or modify them as requested."""
|
"""Check for killswitched events and remove or modify them as requested."""
|
||||||
out = []
|
out = []
|
||||||
|
|
||||||
for e in event_list:
|
for e in event_list:
|
||||||
bad, new_event = killswitch.check_killswitch(f'plugins.inara.worker.{e.name}', e.data, logger)
|
bad, new_event = killswitch.check_killswitch(f'plugins.inara.worker.{e.name}', e.data, logger)
|
||||||
if bad:
|
if bad:
|
||||||
|
21
prefs.py
21
prefs.py
@ -470,6 +470,25 @@ class PreferencesDialog(tk.Toplevel):
|
|||||||
state=tk.NORMAL if config.get_str('journaldir') else tk.DISABLED
|
state=tk.NORMAL if config.get_str('journaldir') else tk.DISABLED
|
||||||
).grid(column=2, pady=self.PADY, sticky=tk.EW, row=row.get())
|
).grid(column=2, pady=self.PADY, sticky=tk.EW, row=row.get())
|
||||||
|
|
||||||
|
# CAPI settings
|
||||||
|
self.capi_fleetcarrier = tk.BooleanVar(value=config.get_bool('capi_fleetcarrier'))
|
||||||
|
|
||||||
|
ttk.Separator(config_frame, orient=tk.HORIZONTAL).grid(
|
||||||
|
columnspan=4, padx=self.PADX, pady=self.PADY*4, sticky=tk.EW, row=row.get()
|
||||||
|
)
|
||||||
|
|
||||||
|
nb.Label(
|
||||||
|
config_frame,
|
||||||
|
text=_('CAPI Settings') # LANG: Settings > Configuration - Label for CAPI section
|
||||||
|
).grid(padx=self.PADX, sticky=tk.W, row=row.get())
|
||||||
|
|
||||||
|
nb.Checkbutton(
|
||||||
|
config_frame,
|
||||||
|
# LANG: Configuration - Enable or disable the Fleet Carrier CAPI calls
|
||||||
|
text=_('Enable Fleetcarrier CAPI Queries'),
|
||||||
|
variable=self.capi_fleetcarrier
|
||||||
|
).grid(columnspan=4, padx=self.PADX, pady=(5, 0), sticky=tk.W, row=row.get())
|
||||||
|
|
||||||
if sys.platform in ('darwin', 'win32'):
|
if sys.platform in ('darwin', 'win32'):
|
||||||
ttk.Separator(config_frame, orient=tk.HORIZONTAL).grid(
|
ttk.Separator(config_frame, orient=tk.HORIZONTAL).grid(
|
||||||
columnspan=4, padx=self.PADX, pady=self.PADY*4, sticky=tk.EW, row=row.get()
|
columnspan=4, padx=self.PADX, pady=self.PADY*4, sticky=tk.EW, row=row.get()
|
||||||
@ -1244,6 +1263,8 @@ class PreferencesDialog(tk.Toplevel):
|
|||||||
else:
|
else:
|
||||||
config.set('journaldir', logdir)
|
config.set('journaldir', logdir)
|
||||||
|
|
||||||
|
config.set('capi_fleetcarrier', self.capi_fleetcarrier.get())
|
||||||
|
|
||||||
if sys.platform in ('darwin', 'win32'):
|
if sys.platform in ('darwin', 'win32'):
|
||||||
config.set('hotkey_code', self.hotkey_code)
|
config.set('hotkey_code', self.hotkey_code)
|
||||||
config.set('hotkey_mods', self.hotkey_mods)
|
config.set('hotkey_mods', self.hotkey_mods)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user