feat(psn): link PlayStation account and import played games
Build, Test & Push Core Service / quality-check (push) Successful in 1m22s
Build, Test & Push Core Service / docker (push) Successful in 1m27s

The NPSSO is used once to get a refresh token; only that token is
stored, sealed with AES-GCM (SecretBox, key APP_PSN_TOKEN_KEY; no key
= feature off). One-time import of played PS4/PS5 titles through the
import pipeline as source PSN. Unlink keeps the games. One PSN call
per user at a time. IGDB search now sends UTF-8, so non-ASCII names
like "Yōtei" match again.
This commit is contained in:
lobo committed 2026-10-07 13:30:48 +02:00
1 parent e87f40bba0
commit 7ac887ed5a
72 files changed
+2407 -78

No files matched your search

@@ -0,0 +1,17 @@
[
{
"id": 900003,
"name": "Mega Man Legacy Collection",
"first_release_date": 1451520000,
"cover": {
"image_id": "co1r7f"
},
"platforms": [
{
"name": "PlayStation 4",
"abbreviation": "PS4"
}
],
"total_rating_count": 300
}
]
@@ -0,0 +1,21 @@
[
{
"id": 900002,
"name": "Ghost of Tsushima",
"first_release_date": 1595548800,
"cover": {
"image_id": "co1r7f"
},
"platforms": [
{
"name": "PlayStation 4",
"abbreviation": "PS4"
},
{
"name": "PlayStation 5",
"abbreviation": "PS5"
}
],
"total_rating_count": 2000
}
]
@@ -0,0 +1,17 @@
[
{
"id": 900001,
"name": "Ghost of Yōtei",
"first_release_date": 1760054400,
"cover": {
"image_id": "co1r7f"
},
"platforms": [
{
"name": "PlayStation 5",
"abbreviation": "PS5"
}
],
"total_rating_count": 800
}
]
+81
View File
@@ -0,0 +1,81 @@
{
"titles": [
{
"titleId": "PPSA26344_00",
"name": "Ghost of Yōtei",
"category": "ps5_native_game",
"service": "none(purchased)",
"playCount": 31,
"playDuration": "PT65H9M15S",
"imageUrl": "https://image.api.playstation.com/local/ghost-of-yotei.png",
"firstPlayedDateTime": "2025-10-03T18:20:11.000Z",
"lastPlayedDateTime": "2026-10-01T20:41:07.000Z",
"concept": {
"id": 10003923,
"titleIds": ["PPSA26344_00"]
}
},
{
"titleId": "CUSA02521_00",
"name": "Mega Man Legacy Collection™",
"category": "ps4_game",
"service": "none(purchased)",
"playCount": 9,
"playDuration": "PT8H30M28S",
"imageUrl": "https://image.api.playstation.com/local/mega-man-legacy.png",
"firstPlayedDateTime": "2017-01-14T09:02:51.000Z",
"lastPlayedDateTime": "2024-03-02T16:10:30.000Z",
"concept": {
"id": 202697,
"titleIds": ["CUSA02521_00", "CUSA02522_00"]
}
},
{
"titleId": "PPSA03208_00",
"name": "Ghost of Tsushima DIRECTOR'S CUT (PS5)",
"category": "ps5_native_game",
"service": "none(purchased)",
"playCount": 22,
"playDuration": "PT64H3S",
"imageUrl": "https://image.api.playstation.com/local/ghost-of-tsushima.png",
"firstPlayedDateTime": "2021-08-20T19:44:02.000Z",
"lastPlayedDateTime": "2023-12-11T21:15:48.000Z",
"concept": {
"id": 235227,
"titleIds": ["PPSA03208_00", "CUSA17722_00", "CUSA17723_00"]
}
},
{
"titleId": "CUSA17722_00",
"name": "Ghost of Tsushima",
"category": "ps4_game",
"service": "none(purchased)",
"playCount": 3,
"playDuration": "PT1H30M",
"imageUrl": "https://image.api.playstation.com/local/ghost-of-tsushima.png",
"firstPlayedDateTime": "2020-07-17T10:00:00.000Z",
"lastPlayedDateTime": "2020-07-19T12:00:00.000Z",
"concept": {
"id": 235227,
"titleIds": ["PPSA03208_00", "CUSA17722_00", "CUSA17723_00"]
}
},
{
"titleId": "PPSA00000_00",
"name": "Monster Hunter Wilds",
"category": "ps5_native_game",
"service": "none(purchased)",
"playCount": 5,
"playDuration": "PT12H",
"imageUrl": "https://image.api.playstation.com/local/monster-hunter-wilds.png",
"firstPlayedDateTime": "2025-03-01T10:00:00.000Z",
"lastPlayedDateTime": "2025-03-09T22:00:00.000Z",
"concept": {
"id": 10000001,
"titleIds": ["PPSA00000_00"]
}
}
],
"totalItemCount": 5,
"nextOffset": null
}
+9
View File
@@ -0,0 +1,9 @@
{
"access_token": "local-access",
"token_type": "bearer",
"expires_in": 3599,
"scope": "psn:mobile.v2.core psn:clientapp",
"id_token": "local-id",
"refresh_token": "local-refresh",
"refresh_token_expires_in": 863999
}