Skip to content

Commit

Permalink
Added method for obtaining collections from the store, updated copyri…
Browse files Browse the repository at this point in the history
…ght and bumped version.
  • Loading branch information
SD4RK committed Apr 29, 2023
1 parent 388a154 commit 8ed09ac
Show file tree
Hide file tree
Showing 11 changed files with 103 additions and 13 deletions.
2 changes: 1 addition & 1 deletion docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
# -- Project information -----------------------------------------------------

project = 'epicstore_api'
copyright = '2020, SD4RK'
copyright = '2023, SD4RK'
author = 'SD4RK'


Expand Down
2 changes: 1 addition & 1 deletion epicstore_api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
An API wrapper for Epic Games Store
:copyright: (c) 2020-2022 SD4RK
:copyright: (c) 2020-2023 SD4RK
:license: MIT, see LICENSE for more details.
"""

Expand Down
37 changes: 32 additions & 5 deletions epicstore_api/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"""
MIT License
Copyright (c) 2020-2022 SD4RK
Copyright (c) 2020-2023 SD4RK
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand All @@ -29,7 +29,7 @@
import requests
from typing import Union, List, NamedTuple
from .exc import EGSNotFound, EGSException
from .models import EGSCategory, EGSProductType
from .models import EGSCategory, EGSProductType, EGSCollectionType
from .queries import (CATALOG_QUERY,
PROMOTIONS_QUERY,
CATALOG_TAGS_QUERY,
Expand All @@ -39,7 +39,8 @@
STORE_QUERY,
ADDONS_QUERY,
MEDIA_QUERY,
PRODUCT_REVIEWS_QUERY)
PRODUCT_REVIEWS_QUERY,
COLLECTION_QUERY)


class OfferData(NamedTuple):
Expand Down Expand Up @@ -135,6 +136,30 @@ def get_offers_data(
} for offer in offers]
)

def get_collection(self, collection: EGSCollectionType) -> dict:
"""Returns games from the collection by the given collection type
(see the documentation for CollectionType class).
:param collection: Needed collection type.
"""
raw = self._make_graphql_query(
COLLECTION_QUERY,
slug=collection.value,
# This query always returns 1004 error by default. That is not controlled by us and the error itself
# is happening even in the official EGS client itself, they're just ignoring it, so we will too.
suppress_errors=True
)
# Cleanup for the 1004 errors that always pop up by default to not mess someone up by this.
if 'errors' in raw:
for error in raw['errors'].copy():
service_response = json.loads(error.get('serviceResponse', {}))
if service_response:
if service_response.get('numericErrorCode') == 1004:
raw['errors'].remove(error)
if not raw['errors']:
raw.pop('errors')
return raw

def fetch_media(self, media_ref_id: str) -> dict:
"""Returns media-file (type of the file, its url and so on) by the
file's media ref ID.
Expand Down Expand Up @@ -404,6 +429,7 @@ def _make_graphql_query(
self,
query_string,
headers={},
suppress_errors=False,
*multiple_query_variables,
**variables
) -> dict:
Expand All @@ -413,7 +439,7 @@ def _make_graphql_query(
response = self._session.post(
'https://graphql.epicgames.com/graphql',
json={'query': query_string, 'variables': variables},
headers=headers
headers=headers,
).json()
else:
data = []
Expand All @@ -432,7 +458,8 @@ def _make_graphql_query(
json=data,
headers=headers
).json()
self._get_errors(response)
if not suppress_errors:
self._get_errors(response)
return response

@staticmethod
Expand Down
2 changes: 1 addition & 1 deletion epicstore_api/exc.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"""
MIT License
Copyright (c) 2020-2022 SD4RK
Copyright (c) 2020-2023 SD4RK
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
3 changes: 2 additions & 1 deletion epicstore_api/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"""
MIT License
Copyright (c) 2020-2022 SD4RK
Copyright (c) 2020-2023 SD4RK
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand All @@ -27,3 +27,4 @@

from .categories import EGSCategory
from .product_types import EGSProductType
from .collection_types import EGSCollectionType
2 changes: 1 addition & 1 deletion epicstore_api/models/categories.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"""
MIT License
Copyright (c) 2020-2022 SD4RK
Copyright (c) 2020-2023 SD4RK
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
42 changes: 42 additions & 0 deletions epicstore_api/models/collection_types.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# -*- coding: utf-8 -*-

"""
MIT License
Copyright (c) 2020-2023 SD4RK
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""


from enum import Enum


class EGSCollectionType(Enum):
"""A helper enum that is used for the collections query
(see :meth:`epicstore_api.api.EpicGamesStoreAPI.get_collection`). You can see the game that fall under particular
collections under the free games on the main page of the Epic Games Store. Collections that are not included
(such as New Releases and Coming Soon can be obtained through catalog query with specific sort queries such as
sortBy=releaseDate and sortBy=comingSoon)."""
TOP_SELLERS = "top-sellers"
MOST_PLAYED = "most-played"
TOP_UPCOMING_WISHLISTED = "top-wishlisted"
MOST_POPULAR = "most-popular"
TOP_PLAYER_RATED = "top-player-reviewed"

2 changes: 1 addition & 1 deletion epicstore_api/models/product_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"""
MIT License
Copyright (c) 2020-2022 SD4RK
Copyright (c) 2020-2023 SD4RK
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
3 changes: 2 additions & 1 deletion epicstore_api/queries.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"""
MIT License
Copyright (c) 2020-2022 SD4RK
Copyright (c) 2020-2023 SD4RK
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down Expand Up @@ -35,4 +35,5 @@
MEDIA_QUERY = "\n query fetchMediaRef($mediaRefId: String!) {\n Media {\n getMediaRef(mediaRefId: $mediaRefId) {\n accountId\n outputs {\n duration\n url\n width\n height\n key\n contentType\n }\n namespace\n }\n }\n }\n"
PRODUCT_REVIEWS_QUERY = "\n query productReviewsQuery($sku: String!) {\n OpenCritic {\n productReviews(sku: $sku) {\n id\n name\n openCriticScore\n reviewCount\n percentRecommended\n openCriticUrl\n award\n topReviews {\n publishedDate\n externalUrl\n snippet\n language\n score\n author\n ScoreFormat {\n id\n description\n }\n OutletId\n outletName\n displayScore\n }\n }\n }\n }\n "
ADDONS_QUERY = "query getAddonsByNamespace($categories: String!, $count: Int!, $country: String!, $locale: String!, $namespace: String!, $sortBy: String!, $sortDir: String!) {\n Catalog {\n catalogOffers(namespace: $namespace, locale: $locale, params: {category: $categories, count: $count, country: $country, sortBy: $sortBy, sortDir: $sortDir}) {\n elements {\n countriesBlacklist\n customAttributes {\n key\n value\n }\n description\n developer\n effectiveDate\n id\n isFeatured\n keyImages {\n type\n url\n }\n lastModifiedDate\n longDescription\n namespace\n offerType\n productSlug\n releaseDate\n status\n technicalDetails\n title\n urlSlug\n }\n }\n }\n}\n"
COLLECTION_QUERY = "query collectionLayoutQuery($locale: String, $country: String!, $slug: String) {\n Storefront {\n collectionLayout(locale: $locale, slug: $slug) {\n _activeDate\n _locale\n _metaTags\n _slug\n _title\n _urlPattern\n lastModified\n regionBlock\n affiliateId\n takeover {\n banner {\n altText\n src\n }\n description\n eyebrow\n title\n }\n seo {\n title\n description\n keywords\n image {\n src\n altText\n }\n twitter {\n title\n description\n }\n og {\n title\n description\n image {\n src\n alt\n }\n }\n }\n collectionOffers {\n title\n id\n namespace\n description\n effectiveDate\n countriesBlacklist\n countriesWhitelist\n developerDisplayName\n publisherDisplayName\n keyImages {\n type\n url\n }\n seller {\n id\n name\n }\n releaseDate\n pcReleaseDate\n approximateReleasePlan {\n day\n month\n quarter\n year\n releaseDateType\n }\n prePurchase\n productSlug\n urlSlug\n url\n items {\n id\n namespace\n }\n customAttributes {\n key\n value\n }\n categories {\n path\n }\n linkedOfferId\n linkedOffer {\n effectiveDate\n customAttributes {\n key\n value\n }\n }\n catalogNs {\n mappings(pageType: \"productHome\") {\n pageSlug\n pageType\n }\n }\n offerMappings {\n pageSlug\n pageType\n }\n price(country: $country) {\n totalPrice {\n currencyCode\n currencyInfo {\n decimals\n symbol\n }\n discountPrice\n originalPrice\n voucherDiscount\n discount\n fmtPrice(locale: $locale) {\n originalPrice\n discountPrice\n intermediatePrice\n }\n }\n lineOffers {\n appliedRules {\n id\n endDate\n }\n }\n }\n }\n pageTheme {\n preferredMode\n light {\n theme\n accent\n }\n dark {\n theme\n accent\n }\n }\n redirect {\n code\n url\n }\n }\n }\n}\n"
# XXX: This code violates PEP 8, line > 79 chars
19 changes: 19 additions & 0 deletions examples/get_top_sellers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from epicstore_api import EpicGamesStoreAPI
from epicstore_api.models import EGSCollectionType


def main():
"""
Prints list of the current top sellers.
"""
api = EpicGamesStoreAPI()
top_sellers = api.get_collection(
EGSCollectionType.TOP_SELLERS
)['data']['Storefront']['collectionLayout']['collectionOffers']
print('Top sellers list:')
for game in top_sellers:
print(f'{game["title"]} - {game["price"]["totalPrice"]["fmtPrice"]["originalPrice"]}')


if __name__ == '__main__':
main()
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import setuptools

AUTHOR = 'SD4RK'
VERSION = '0.1.5'
VERSION = '0.1.6'

with open("README.md", "r") as fh:
long_description = fh.read()
Expand Down

0 comments on commit 8ed09ac

Please sign in to comment.