Skip to content

Commit

Permalink
version 0.31
Browse files Browse the repository at this point in the history
  • Loading branch information
FriendsOfGalaxy committed Mar 1, 2021
1 parent a4cd018 commit 00c87de
Show file tree
Hide file tree
Showing 10 changed files with 302 additions and 189 deletions.
1 change: 1 addition & 0 deletions requirements/app.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
galaxy.plugin.api==0.64
certifi==2019.3.9
beautifulsoup4==4.9.3
3 changes: 2 additions & 1 deletion src/http_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,12 @@ async def request(self, method, *args, **kwargs):

async def get(self, url, *args, **kwargs):
silent = kwargs.pop('silent', False)
get_json = kwargs.pop('get_json', True)
response = await self.request("GET", *args, url=url, **kwargs)
try:
raw_response = '***' if silent else await response.text()
logging.debug("Response for:\n{url}\n{data}".format(url=url, data=raw_response))
return await response.json()
return await response.json() if get_json else await response.text()
except ValueError:
logging.exception("Invalid response data for:\n{url}".format(url=url))
raise UnknownBackendResponse()
Expand Down
50 changes: 50 additions & 0 deletions src/parsers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import json
import logging
from typing import List, Dict

from bs4 import BeautifulSoup
from galaxy.api.errors import UnknownBackendResponse
from galaxy.api.types import SubscriptionGame


logger = logging.getLogger(__name__)


class PSNGamesParser:

_SUBSCRIBED_GAMES_PAGINATOR_CSS_CLASS = 'ems-sdk-strand-paginator'
_SUBSCRIBED_GAMES_CSS_CLASS = 'ems-sdk-product-tile-link'
_GAME_DATA_TAG = 'data-telemetry-meta'

def parse(self, response) -> List[SubscriptionGame]:
try:
games = self._subscription_games(response)
except NotFoundSubscriptionPaginator:
raise UnknownBackendResponse(f"HTML TAG: {self._SUBSCRIBED_GAMES_PAGINATOR_CSS_CLASS} was not found in response.")
else:
return [
SubscriptionGame(game_id=game['titleId'], game_title=game['name'])
for game in games if game.get('name') and game.get('titleId') and not game['name'].startswith('PlayStation')
]

def _subscription_games(self, response: str) -> List[Dict]:
"""Scrapes all PS Plus Monthly games from https://store.playstation.com/subscriptions"""

parsed_html = BeautifulSoup(response, 'html.parser')
paginator = parsed_html.find("div", class_=self._SUBSCRIBED_GAMES_PAGINATOR_CSS_CLASS)
if not paginator:
raise NotFoundSubscriptionPaginator
logger.debug("HTML response slice of %s tag: \n%s" % (self._SUBSCRIBED_GAMES_PAGINATOR_CSS_CLASS, paginator.decode_contents()))
games = paginator.find_all("a", class_=self._SUBSCRIBED_GAMES_CSS_CLASS)
result = []
for game in games:
try:
game_data = getattr(game, 'attrs', {}).get(self._GAME_DATA_TAG)
result.append(json.loads(game_data))
except (json.JSONDecodeError, TypeError) as e:
logger.error(e)
return result


class NotFoundSubscriptionPaginator(Exception):
pass
3 changes: 1 addition & 2 deletions src/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,7 @@ async def get_subscriptions(self) -> List[Subscription]:
return [Subscription(subscription_name="PlayStation PLUS", end_time=None, owned=is_plus_active)]

async def get_subscription_games(self, subscription_name: str, context: Any) -> AsyncGenerator[List[SubscriptionGame], None]:
account_info = await self._psn_client.get_account_info()
yield await self._psn_client.get_subscription_games(account_info)
yield await self._psn_client.get_subscription_games()

async def get_owned_games(self):
async def filter_and_patch_games(titles: List[Game]) -> List[Game]:
Expand Down
27 changes: 5 additions & 22 deletions src/psn_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from galaxy.api.types import Achievement, Game, LicenseInfo, UserInfo, UserPresence, PresenceState, SubscriptionGame
from galaxy.api.consts import LicenseType
from http_client import paginate_url
from psn_store import PSNFreePlusStore, AccountUserInfo
from parsers import PSNGamesParser

# game_id_list is limited to 5 IDs per request
GAME_DETAILS_URL = "https://pl-tpy.np.community.playstation.net/trophy/v1/apps/trophyTitles" \
Expand Down Expand Up @@ -50,6 +50,8 @@

ACCOUNTS_URL = "https://accounts.api.playstation.com/api/v1/accounts/{user_id}"

PSN_PLUS_SUBSCRIPTIONS_URL = 'https://store.playstation.com/subscriptions'

DEFAULT_LIMIT = 100
MAX_TITLE_IDS_PER_REQUEST = 5

Expand Down Expand Up @@ -289,24 +291,5 @@ def friends_with_presence_parser(response):
"totalResults"
)

async def get_account_info(self) -> AccountUserInfo:
def account_user_parser(data):
td = date_today() - datetime.fromisoformat(data['dateOfBirth'])
age = td.days // 365
return AccountUserInfo(data['region'], data['legalCountry'], data['language'], age)

return await self.fetch_data(account_user_parser, ACCOUNTS_URL.format(user_id='me'), silent=True)

async def get_subscription_games(self, account_info: AccountUserInfo) -> List[SubscriptionGame]:
def games_parser(data):
return [
SubscriptionGame(
game_id=item['id'].split('-')[1],
game_title=item['attributes']['name']
)
for item in data['included']
if item['type'] in ['game', 'game-related']
]

store = PSNFreePlusStore(self._http_client, account_info)
return await self.fetch_data(games_parser, store.games_container_url)
async def get_subscription_games(self) -> List[SubscriptionGame]:
return await self.fetch_data(PSNGamesParser().parse, PSN_PLUS_SUBSCRIPTIONS_URL, get_json=False, silent=True)
49 changes: 0 additions & 49 deletions src/psn_store.py

This file was deleted.

3 changes: 3 additions & 0 deletions src/version.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
__version__ = "0.31"

__changelog__ = {
"unreleased": """
- Fix showing correct PS Plus monthly games in Galaxy Subscription tab
""",
"0.31": """
- Fix losing authentication as side effect of shutdown while refreshing credentials
- Add cache invalidation for title-communication_ids map every 7 days; fixes not showing updated games without reconnection
Expand Down
Loading

0 comments on commit 00c87de

Please sign in to comment.