Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rare: use OS specific encoding in some cases #466

Merged
merged 5 commits into from
Oct 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions .github/workflows/job_cx-freeze-msi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ jobs:
python-version: '3.12'
check-latest: true
architecture: x64
- name: Install Build Dependencies
- name: Install build dependencies
run: pip3 install --upgrade cx_freeze wheel
- name: Install Target Dependencies
- name: Install target dependencies
run: |
pip3 install -r requirements.txt
pip3 install -r requirements-presence.txt
Expand All @@ -34,4 +34,5 @@ jobs:
uses: actions/upload-artifact@v4
with:
name: Rare-${{ inputs.version }}.msi
path: Rare.msi
path: Rare.msi

3 changes: 2 additions & 1 deletion .github/workflows/job_cx-freeze-zip.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
check-latest: true
architecture: x64
- name: Install build dependencies
run: pip3 install cx_freeze
run: pip3 install --upgrade cx_freeze wheel
- name: Install target dependencies
run: |
pip3 install -r requirements.txt
Expand All @@ -37,3 +37,4 @@ jobs:
with:
name: Rare-portable-windows-${{ inputs.version }}.zip
path: Rare.zip

1 change: 1 addition & 0 deletions .github/workflows/job_nuitka-linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ jobs:
run: >-
python -m nuitka
--assume-yes-for-downloads
--clang
--lto=no
--jobs=4
--static-libpython=no
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/job_nuitka-win.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
run: >-
python -m nuitka
--assume-yes-for-downloads
--msvc=latest
--mingw64
--lto=no
--jobs=4
--static-libpython=no
Expand Down
20 changes: 14 additions & 6 deletions rare/components/tabs/store/api/models/response.py
Original file line number Diff line number Diff line change
Expand Up @@ -408,12 +408,23 @@ def from_dict(cls: Type["DataModel"], src: Dict[str, Any]) -> "DataModel":

@dataclass
class ErrorModel:
message: str = None
correlationId: str = None
serviceResponse: str = None
unmapped: Dict[str, Any] = field(default_factory=dict)

def __str__(self):
return f"{self.correlationId} - {self.message}"

@classmethod
def from_dict(cls: Type["ErrorModel"], src: Dict[str, Any]) -> "ErrorModel":
d = src.copy()
return cls(unmapped=d)
return cls(
message=d.pop("message", ""),
correlationId= d.pop("correlationId", ""),
serviceResponse=d.pop("serviceResponse", ""),
unmapped=d
)


@dataclass
Expand All @@ -429,7 +440,7 @@ def from_dict(cls: Type["ExtensionsModel"], src: Dict[str, Any]) -> "ExtensionsM
@dataclass
class ResponseModel:
data: DataModel = None
errors: List[ErrorModel] = None
errors: Tuple[ErrorModel, ...] = None
extensions: ExtensionsModel = None
unmapped: Dict[str, Any] = field(default_factory=dict)

Expand All @@ -438,9 +449,6 @@ def from_dict(cls: Type["ResponseModel"], src: Dict[str, Any]) -> "ResponseModel
d = src.copy()
data = DataModel.from_dict(x) if (x := d.pop("data", {})) else None
_errors = d.pop("errors", [])
errors = [] if _errors else None
for item in _errors:
error = ErrorModel.from_dict(item)
errors.append(error)
errors = tuple(map(ErrorModel.from_dict, _errors))
extensions = ExtensionsModel.from_dict(x) if (x := d.pop("extensions", {})) else None
return cls(data=data, errors=errors, extensions=extensions, unmapped=d)
150 changes: 71 additions & 79 deletions rare/components/tabs/store/store_api.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from logging import getLogger
from typing import Callable, Tuple
from typing import Callable, Tuple, Any

from PySide6.QtCore import Signal, QObject
from PySide6.QtWidgets import QApplication
Expand Down Expand Up @@ -35,7 +35,6 @@ def __init__(self, token, language: str, country: str, installed):
self.language_code: str = language
self.country_code: str = country
self.locale = f"{self.language_code}-{self.country_code}"
self.locale = "en-US"
self.manager = QtRequests(parent=self)
self.authed_manager = QtRequests(token=token, parent=self)
self.cached_manager = QtRequests(cache=str(cache_dir().joinpath("store")), parent=self)
Expand All @@ -45,38 +44,34 @@ def __init__(self, token, language: str, country: str, installed):
self.browse_active = False
self.next_browse_request = tuple(())

def get_free(self, handle_func: callable):
def get_free(self, callback: callable):
url = "https://store-site-backend-static-ipv4.ak.epicgames.com/freeGamesPromotions"
params = {
"locale": self.locale,
"country": self.country_code,
"allowCountries": self.country_code,
}
self.manager.get(url, lambda data: self.__handle_free_games(data, handle_func), params=params)
self.manager.get(url, lambda data: self.__handle_free_games(data, callback), params=params)

@staticmethod
def __handle_free_games(data, handle_func):
def __handle_free_games(data, callback):
try:
response = ResponseModel.from_dict(data)
results: Tuple[CatalogOfferModel, ...] = response.data.catalog.searchStore.elements
handle_func(results)
except KeyError as e:
if DEBUG():
raise e
logger.error("Free games Api request failed")
handle_func(["error", "Key error"])
return
except Exception as e:
if response.errors:
for error in response.errors:
logger.error(error)
elements = response.data.catalog.searchStore.elements
except (Exception, AttributeError, KeyError) as e:
if DEBUG():
raise e
logger.error(f"Free games Api request failed: {e}")
handle_func(["error", e])
return
elements = False
logger.error("Free games request failed with: %s", e)
callback(elements)

def get_wishlist(self, handle_func):
def get_wishlist(self, callback):
self.authed_manager.post(
graphql_url,
lambda data: self.__handle_wishlist(data, handle_func),
lambda data: self.__handle_wishlist(data, callback),
{
"query": wishlist_query,
"variables": {
Expand All @@ -88,26 +83,21 @@ def get_wishlist(self, handle_func):
)

@staticmethod
def __handle_wishlist(data, handle_func):
def __handle_wishlist(data, callback):
try:
response = ResponseModel.from_dict(data)
if response.errors:
logger.error(response.errors)
handle_func(response.data.wishlist.wishlistItems.elements)
except KeyError as e:
for error in response.errors:
logger.error(error)
elements = response.data.wishlist.wishlistItems.elements
except (Exception, AttributeError, KeyError) as e:
if DEBUG():
raise e
logger.error("Free games API request failed")
handle_func(["error", "Key error"])
return
except Exception as e:
if DEBUG():
raise e
logger.error(f"Free games API request failed")
handle_func(["error", e])
return
elements = False
logger.error("Wishlist request failed with: %s", e)
callback(elements)

def search_game(self, name, handler):
def search_game(self, name, callback):
payload = {
"query": search_query,
"variables": {
Expand All @@ -125,60 +115,56 @@ def search_game(self, name, handler):
},
}

self.manager.post(graphql_url, lambda data: self.__handle_search(data, handler), payload)
self.manager.post(graphql_url, lambda data: self.__handle_search(data, callback), payload)

@staticmethod
def __handle_search(data, handler):
def __handle_search(data, callback):
try:
response = ResponseModel.from_dict(data)
handler(response.data.catalog.searchStore.elements)
except KeyError as e:
if DEBUG():
raise e
logger.error(str(e))
handler([])
except Exception as e:
if response.errors:
for error in response.errors:
logger.error(error)
elements = response.data.catalog.searchStore.elements
except (Exception, AttributeError, KeyError) as e:
if DEBUG():
raise e
logger.error(f"Search Api request failed: {e}")
handler([])
return
elements = False
logger.error("Search request failed with: %s", e)
callback(elements)

def browse_games(self, browse_model: SearchStoreQuery, handle_func):
def browse_games(self, browse_model: SearchStoreQuery, callback):
if self.browse_active:
self.next_browse_request = (browse_model, handle_func)
self.next_browse_request = (browse_model, callback)
return
self.browse_active = True
payload = {
"query": search_query,
"variables": browse_model.to_dict()
}
self.manager.post(graphql_url, lambda data: self.__handle_browse_games(data, handle_func), payload)
self.manager.post(graphql_url, lambda data: self.__handle_browse_games(data, callback), payload)

def __handle_browse_games(self, data, handle_func):
def __handle_browse_games(self, data, callback):
self.browse_active = False
if data is None:
data = {}
if not self.next_browse_request:
try:
response = ResponseModel.from_dict(data)
handle_func(response.data.catalog.searchStore.elements)
except KeyError as e:
if response.errors:
for error in response.errors:
logger.error(error)
elements = response.data.catalog.searchStore.elements
except (Exception, AttributeError, KeyError) as e:
if DEBUG():
raise e
logger.error(str(e))
handle_func([])
except Exception as e:
if DEBUG():
raise e
logger.error(f"Browse games Api request failed: {e}")
handle_func([])
return
elements = False
logger.error("Browse request failed with: %s", e)
callback(elements)
else:
self.browse_games(*self.next_browse_request) # pylint: disable=E1120
self.next_browse_request = tuple(())

# def get_game_config_graphql(self, namespace: str, handle_func):
# def get_game_config_graphql(self, namespace: str, callback):
# payload = {
# "query": config_query,
# "variables": {
Expand All @@ -192,24 +178,24 @@ def __make_graphql_query(self):
def __make_api_query(self):
pass

def get_game_config_cms(self, slug: str, is_bundle: bool, handle_func):
def get_game_config_cms(self, slug: str, is_bundle: bool, callback):
url = "https://store-content.ak.epicgames.com/api"
url += f"/{self.locale}/content/{'products' if not is_bundle else 'bundles'}/{slug}"
self.manager.get(url, lambda data: self.__handle_get_game(data, handle_func))
self.manager.get(url, lambda data: self.__handle_get_game(data, callback))

@staticmethod
def __handle_get_game(data, handle_func):
def __handle_get_game(data, callback):
try:
product = DieselProduct.from_dict(data)
handle_func(product)
callback(product)
except Exception as e:
if DEBUG():
raise e
logger.error(str(e))
# handle_func({})
# callback({})

# needs a captcha
def add_to_wishlist(self, namespace, offer_id, handle_func: callable):
def add_to_wishlist(self, namespace, offer_id, callback: callable):
payload = {
"query": wishlist_add_query,
"variables": {
Expand All @@ -219,21 +205,24 @@ def add_to_wishlist(self, namespace, offer_id, handle_func: callable):
"locale": self.locale,
},
}
self.authed_manager.post(graphql_url, lambda data: self._handle_add_to_wishlist(data, handle_func), payload)
self.authed_manager.post(graphql_url, lambda data: self._handle_add_to_wishlist(data, callback), payload)

def _handle_add_to_wishlist(self, data, handle_func):
def _handle_add_to_wishlist(self, data, callback):
try:
response = ResponseModel.from_dict(data)
data = response.data.wishlist.addToWishlist
handle_func(data.success)
if response.errors:
for error in response.errors:
logger.error(error)
success = response.data.wishlist.addToWishlist.success
except Exception as e:
if DEBUG():
raise e
logger.error(str(e))
handle_func(False)
logger.error("Add to wishlist request failed with: %s", e)
success = False
callback(success)
self.update_wishlist.emit()

def remove_from_wishlist(self, namespace, offer_id, handle_func: callable):
def remove_from_wishlist(self, namespace, offer_id, callback: callable):
payload = {
"query": wishlist_remove_query,
"variables": {
Expand All @@ -242,17 +231,20 @@ def remove_from_wishlist(self, namespace, offer_id, handle_func: callable):
"operation": "REMOVE",
},
}
self.authed_manager.post(graphql_url, lambda data: self._handle_remove_from_wishlist(data, handle_func),
self.authed_manager.post(graphql_url, lambda data: self._handle_remove_from_wishlist(data, callback),
payload)

def _handle_remove_from_wishlist(self, data, handle_func):
def _handle_remove_from_wishlist(self, data, callback):
try:
response = ResponseModel.from_dict(data)
data = response.data.wishlist.removeFromWishlist
handle_func(data.success)
if response.errors:
for error in response.errors:
logger.error(error)
success = response.data.wishlist.removeFromWishlist.success
except Exception as e:
if DEBUG():
raise e
logger.error(str(e))
handle_func(False)
logger.error("Remove from wishlist request failed with: %s", e)
success = False
callback(success)
self.update_wishlist.emit()
Loading