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

Parental Controls #12

Open
SolidTux opened this issue Apr 1, 2020 · 4 comments
Open

Parental Controls #12

SolidTux opened this issue Apr 1, 2020 · 4 comments

Comments

@SolidTux
Copy link

SolidTux commented Apr 1, 2020

Would be great to have more information about the parental control API to get a detailed playtime per game. I have a Wireshark recording, but I'll first have to figure out how to strip sensitive information from that before posting.

@frozenpandaman
Copy link

This would be cool to see!

@SolidTux
Copy link
Author

SolidTux commented Apr 2, 2020

My current problem is the session_code_verifier for the /connect/1.0.0/api/session_token. It is not the state like with the normal Switch app. In fact it doesn't appear in any form in the initial URL or the redirection URL.

@SolidTux
Copy link
Author

SolidTux commented Apr 6, 2020

Ok, I can now login, it works like here, but the rest doesn't really work yet as you apparently need to set special "X-Moon-*" headers.

Currently, the backend returns null pointer exceptions :-D

@SolidTux
Copy link
Author

SolidTux commented Apr 6, 2020

Ok, I got it to run and made an example to print play time per game (see here). As said before, the authentication works as expected up to the token API. After that you have an access_token and an id_token.

First we have to get the user id with

GET /2.0.0/users/me HTTP/1.1
Authorization: Bearer access_token
Host: api.accounts.nintendo.com

HTTP/1.1 200 OK
{
  "nickname": "nickname",
  "id": "user_id",
  ...a lot of other stuff...
}

Now the next step is to register the device with the online service. From now on the following headers probably have to be present (I didn't test which you can remove, but the device id should probably be required):

Authorization: Bearer access_token
X-Moon-App-Id: com.nintendo.znma
X-Moon-Os: ANDROID
X-Moon-Os-Version: 28
X-Moon-Model: some model
X-Moon-TimeZone: Europe/Berlin
X-Moon-Os-Language: de-DE
X-Moon-App-Language: de-DE
X-Moon-App-Display-Version: 1.11.0
X-Moon-App-Internal-Version: 229
X-Moon-Smart-Device-Id: device_id
User-Agent: moon_ANDROID/1.11.0 (com.nintendo.znma; build:229; ANDROID 28)

device_id can be chosen. The device is registered using

POST /moon/v1/users/user_id/smart_devices HTTP/1.1
Host: api-lp1.pctl.srv.nintendo.net
{
  "appLanguage": "de-DE",
  "appVersion": {
    "displayedVersion": "1.11.0",
    "internalVersion": "229"
  },
  "bundleId": "com.nintendo.znma",
  "id": "device_id",
  "modelName": some model name,
  "os": "ANDROID",
  "osLanguage": "de-DE",
  "osVersion": "28",
  "timeZone": "Europe/Berlin"
}

HTTP/1.1 201 Created
{
  "id": device_id,
  "nintendoAccountId": account_id,
  "bundleId": "com.nintendo.znma",
  "os": "ANDROID",
  "osVersion": "28",
  "modelName": some model name,
  "timeZone": "Europe/Berlin",
  "appVersion": {
    "displayedVersion": "1.11.0",
    "internalVersion": 229
  },
  "osLanguage": "de-DE",
  "appLanguage": "de-DE",
  "notificationToken": null,
  "updateRequired": false,
  "createdAt": timestamp,
  "updatedAt": timestamp
}

The registration is only needed once. This allows us now to get the ids of the registered devices

GET /moon/v1/users/user_id/devices?filter.device.activated.$eq=true HTTP/1.1
Host: api-lp1.pctl.srv.nintendo.net

HTTP/1.1 200 OK
{
  "count": 1,
  "items": [
    {
      "deviceId": "device_id",
      "device": {
        "id": "device_id",
        ...more information...
      },
      ...more information...
    },
    ...
  ]
}

For each device we can get the daily summaries

GET /moon/v1/devices/device_id/daily_summaries HTTP/1.1
Host: api-lp1.pctl.srv.nintendo.net

HTTP/1.1 200 OK
{
  "count": 31,
  "items": [
    {
      "deviceId": "device_id",
      "date": "2020-04-06",
      "result": "CALCULATING" or "ARCHIEVED",
      "playingTime": seconds,
      "exceededTime": null,
      "disabledTime": 0,
      "miscTime": 0,
      "importantInfos": [],
      "notices": [],
      "observations": [],
      "playedApps": [
        {
          "applicationId": "application id",
          "title": "title",
          ...
        },
        ...
      ],
      "anonymousPlayer": null,
      "devicePlayers": [
        {
          "playerId": "player_id",
          "nickname": "nickname",
          "imageUri": "image",
          "playingTime": seconds,
          "playedApps": [
            {
              "applicationId": "app_id",
              "firstPlayDate": date,
              "playingTime": seconds
            },
            ...
          ]
        }
      ],
      "timeZoneUtcOffsetSeconds": 7200,
      "lastPlayedAt": time stamp,
      "createdAt": time stamp,
      "updatedAt": time stamp
    },
    ...
  ],
  "updatedRecently": true
}

or a list of available monthly summaries

GET /moon/v1/devices/device_id/monthly_summaries HTTP/1.1
Host: api-lp1.pctl.srv.nintendo.net

HTTP/1.1 200 OK
{
  "count": 11,
  "indexes": [
    "2020-03",
    ...
  ],
  "items": [
    {
      "deviceId": "device_id",
      "month": "2020-03"
    },
    ...
  ]
}

Each montly summary can be obtained with

GET /moon/v1/devices/device_id/monthly_summaries/2020-03 HTTP/1.1
Host: api-lp1.pctl.srv.nintendo.net

HTTP/1.1 200 OK
{
  "deviceId": "device_id",
  "month": "2020-03",
  "dailySummaries": {
    "2020-03-11": {
      "date": "2020-03-11",
      "result": "ACHIEVED",
      "playingTime": seconds
    },
    ...
  },
  "playingDays": 31,
  "playedApps": [
    {
      "applicationId": "application id",
      "title": "title",
      ...
    },
    ...
  ],
  "insights": {
    "thisMonth": {
      "averagePlayingTime": seconds,
      "playingDays": days,
      "playingTime": seconds
    },
    "previousMonth": {
      "averagePlayingTime": second,
      "playingDays": days,
      "playingTime": seconds
    },
    "rankings": {
      "byDay": [
        {
          "applicationId": "application id",
          "units": days,
          "position": "UP"/"DOWN"/"STAY",
          "ratio": ratio
        },
        ...
      ],
      "byTime": [
        {
          "applicationId": "application id",
          "units": seconds,
          "position": "UP"/"DOWN"/"STAY",
          "ratio": ratio
        },
        ...
      ]
    }
  },
  "devicePlayers": [
    {
      "playerId": "player_id",
      "nickname": "nickname",
      "imageUri": "image",
      "dailySummaries": {
        "2020-03-11": {
          "date": "2020-03-11",
          "result": "ACHIEVED",
          "playingTime": seconds
        },
        ...
      },
      "insights": {
        "thisMonth": {
          "averagePlayingTime": seconds,
          "playingDays": days,
          "playingTime": seconds
        },
        "previousMonth": {
          "averagePlayingTime": seconds,
          "playingDays": days,
          "playingTime": seconds
        },
        "rankings": {
          "byDay": [
            {
              "applicationId": "application id",
              "units": days,
              "position": "UP"/"DOWN"/"STAY",
              "ratio": ratio
            },
            ...
          ],
          "byTime": [
            {
              "applicationId": "application id",
              "units": seconds,
              "position": "UP"/"DOWN"/"STAY",
              "ratio": ratio
            },
            ...
          ]
        }
      }
    },
    ...
  ],
  "includedMajorVersions": [
    9
  ],
  "createdAt": timestamp,
  "updatedAt": timestamp
}

There are a lot or more endpoints, e.g. for the parental control setting, but I haven't looked at them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants