├── .github
├── dependabot.yaml
└── workflows
│ ├── auto-merge.yml
│ ├── build-docs.yaml
│ ├── build.yaml
│ └── publish.yaml
├── .gitignore
├── LICENSE
├── README.md
├── docs
├── .eslintrc.json
├── README.md
├── api-build.mjs
├── app
│ ├── (home)
│ │ ├── layout.tsx
│ │ └── page.tsx
│ ├── docs
│ │ ├── [[...slug]]
│ │ │ └── page.tsx
│ │ └── layout.tsx
│ ├── global.css
│ ├── layout.config.tsx
│ └── layout.tsx
├── content
│ └── docs
│ │ ├── api
│ │ ├── lib.model.mdxmodel
│ │ └── provider
│ │ │ ├── achievements.model.mdxmodel
│ │ │ ├── catalog.model.mdxmodel
│ │ │ ├── gameclips.model.mdxmodel
│ │ │ ├── gamepass.model.mdxmodel
│ │ │ ├── messages.model.mdxmodel
│ │ │ ├── people.model.mdxmodel
│ │ │ ├── pins.model.mdxmodel
│ │ │ ├── profile.model.mdxmodel
│ │ │ ├── rest.model.mdxmodel
│ │ │ ├── screenshots.model.mdxmodel
│ │ │ ├── smartglass.model.mdxmodel
│ │ │ ├── social.model.mdxmodel
│ │ │ ├── titlehub.model.mdxmodel
│ │ │ ├── userpresence.model.mdxmodel
│ │ │ ├── usersearch.model.mdxmodel
│ │ │ ├── userstats.model.mdxmodel
│ │ │ └── xnotify.model.mdxmodel
│ │ ├── changelogs
│ │ ├── 2.0.0.mdx
│ │ └── meta.json
│ │ ├── cli.mdx
│ │ ├── index.mdx
│ │ ├── meta.json
│ │ └── pagination.mdx
├── lib
│ └── source.ts
├── next.config.mjs
├── package-lock.json
├── package.json
├── postcss.config.js
├── source.config.ts
└── tsconfig.json
├── package-lock.json
├── package.json
├── src
├── bin
│ └── cli.ts
├── lib.ts
├── lib
│ └── http.ts
├── provider
│ ├── achievements.ts
│ ├── base.ts
│ ├── catalog.ts
│ ├── gameclips.ts
│ ├── gamepass.ts
│ ├── messages.ts
│ ├── people.ts
│ ├── pins.ts
│ ├── profile.ts
│ ├── rest.ts
│ ├── screenshots.ts
│ ├── smartglass.ts
│ ├── social.ts
│ ├── titlehub.ts
│ ├── userpresence.ts
│ ├── usersearch.ts
│ ├── userstats.ts
│ └── xnotify.ts
└── types
│ ├── achievements
│ └── index.ts
│ ├── catalog
│ └── index.ts
│ ├── gameclips
│ └── index.ts
│ ├── gamepass
│ └── index.ts
│ ├── messages
│ └── index.ts
│ ├── paging.ts
│ ├── people
│ └── index.ts
│ ├── pins
│ └── index.ts
│ ├── profile
│ └── index.ts
│ ├── screenshots
│ └── index.ts
│ ├── smartglass
│ └── index.ts
│ ├── social
│ └── index.ts
│ ├── titlehub
│ └── index.ts
│ ├── userpresence
│ └── index.ts
│ ├── usersearch
│ └── index.ts
│ ├── userstats
│ └── index.ts
│ └── xnotify
│ └── index.ts
├── tests
└── lib.ts
└── tsconfig.json
/.github/dependabot.yaml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 |
4 | # Maintain dependencies for GitHub Actions
5 | - package-ecosystem: "github-actions"
6 | directory: "/"
7 | schedule:
8 | interval: "weekly"
9 | target-branch: "main"
10 | labels:
11 | - "github-actions dependencies"
12 |
13 | # Maintain dependencies for npm
14 | - package-ecosystem: "npm"
15 | directory: "/"
16 | schedule:
17 | interval: "weekly"
18 | target-branch: "main"
19 | labels:
20 | - "npm dependencies"
21 |
22 | - package-ecosystem: "npm"
23 | directory: "/"
24 | schedule:
25 | interval: "weekly"
26 | target-branch: "release/2.0.0"
27 | labels:
28 | - "npm dependencies"
29 |
30 | - package-ecosystem: "npm"
31 | directory: "docs/"
32 | schedule:
33 | interval: "weekly"
34 | target-branch: "release/2.0.0"
35 | labels:
36 | - "npm dependencies"
--------------------------------------------------------------------------------
/.github/workflows/auto-merge.yml:
--------------------------------------------------------------------------------
1 | name: Dependabot Automerge
2 | on: [pull_request_target]
3 |
4 | jobs:
5 | auto-merge:
6 | runs-on: ubuntu-latest
7 | if: github.actor == 'dependabot[bot]'
8 | steps:
9 | - uses: actions/checkout@v4
10 | - uses: ahmadnassri/action-dependabot-auto-merge@v2
11 | with:
12 | target: minor
13 | github-token: ${{ secrets.SECRET_GITHUB }}
--------------------------------------------------------------------------------
/.github/workflows/build-docs.yaml:
--------------------------------------------------------------------------------
1 | name: Build docs
2 |
3 | on:
4 | push:
5 | branches:
6 | - '*'
7 | - 'feature/*'
8 | - 'release/*'
9 | tags:
10 | - v*
11 | pull_request:
12 | branches:
13 | - main
14 | - release/2.0.0
15 |
16 | permissions:
17 | id-token: write
18 | pages: write
19 |
20 | # env:
21 | # DEBUG: '*'
22 |
23 | jobs:
24 | build:
25 | runs-on: ${{ matrix.os }}
26 |
27 | strategy:
28 | matrix:
29 | os: [ubuntu-latest]
30 |
31 | steps:
32 | - name: Checkout Git repository
33 | uses: actions/checkout@v4.2.2
34 | with:
35 | submodules: recursive
36 |
37 | - name: Setup Node.js
38 | uses: actions/setup-node@v4.2.0
39 | with:
40 | node-version: 22
41 |
42 | - name: Install npm dependencies
43 | working-directory: ./docs
44 | run: npm ci
45 |
46 | - name: Build project
47 | working-directory: ./docs
48 | run: npm run build
49 |
50 | - name: Upload static files as artifact
51 | id: deployment-pages
52 | uses: actions/upload-pages-artifact@v3
53 | with:
54 | path: docs/out/
55 |
56 | # Deployment job
57 | deploy:
58 | environment:
59 | name: github-pages
60 | url: ${{ steps.deployment.outputs.page_url }}
61 | runs-on: ubuntu-latest
62 | needs: build
63 | if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/release/2.0.0' || startsWith(github.ref, 'refs/tags/v')
64 | steps:
65 | - name: Deploy to GitHub Pages
66 | id: deployment-pages
67 | uses: actions/deploy-pages@v4
68 |
69 | - name: Info
70 | run: echo "Deployed to ${{ steps.deployment-pages.outputs.page_url }}"
--------------------------------------------------------------------------------
/.github/workflows/build.yaml:
--------------------------------------------------------------------------------
1 | name: Build/release
2 |
3 | on:
4 | push:
5 | branches:
6 | - '*'
7 | - 'feature/*'
8 | - 'release/*'
9 | tags:
10 | - v*
11 | pull_request:
12 | branches:
13 | - main
14 |
15 | # env:
16 | # DEBUG: '*'
17 |
18 | jobs:
19 | release:
20 | runs-on: ${{ matrix.os }}
21 |
22 | strategy:
23 | matrix:
24 | os: [macos-latest, ubuntu-latest, windows-latest]
25 |
26 | steps:
27 | - name: Checkout Git repository
28 | uses: actions/checkout@v4.2.2
29 | with:
30 | fetch-depth: 0
31 | submodules: recursive
32 |
33 | - name: Setup Node.js
34 | uses: actions/setup-node@v4.2.0
35 | with:
36 | node-version: 22
37 |
38 | - name: SonarQube Scan
39 | uses: SonarSource/sonarqube-scan-action@v4
40 | env:
41 | SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
42 | with:
43 | args: |
44 | -Dsonar.organization=unknownskl-github \
45 | -Dsonar.projectKey=unknownskl_xbox-webapi-node \
46 | -Dsonar.sources=./src
47 | if: matrix.os == 'ubuntu-latest' && github.event_name != 'pull_request'
48 |
49 | - name: Install npm dependencies
50 | run: npm ci
51 |
52 | - name: Build project
53 | run: npm run build
54 |
55 | - name: Run NodeJS Tests
56 | run: npm run test
57 |
58 | # - name: Set release version
59 | # run: python3 -c "import os; tag = os.environ['GITHUB_REF'].split('/')[-1]; f = open(os.environ['GITHUB_ENV'], 'a'); f.write('RELEASE_VERSION='+tag); f.close();"
--------------------------------------------------------------------------------
/.github/workflows/publish.yaml:
--------------------------------------------------------------------------------
1 | name: NPM Publish
2 |
3 | on:
4 | push:
5 | tags:
6 | - '*'
7 |
8 | jobs:
9 | build:
10 | runs-on: ubuntu-latest
11 |
12 | strategy:
13 | matrix:
14 | # the Node.js versions to build on
15 | node-version: [22.x]
16 |
17 | steps:
18 | - uses: actions/checkout@v4.2.2
19 | with:
20 | persist-credentials: false # otherwise, the token used is the GITHUB_TOKEN, instead of your personal token
21 | fetch-depth: 0 # otherwise, you will failed to push refs to dest repo
22 |
23 | - name: Get tag name
24 | id: tag_name
25 | run: |
26 | echo ::set-output name=SOURCE_TAG::${GITHUB_REF#refs/tags/}
27 |
28 | - name: Install dependencies
29 | run: npm ci
30 |
31 | - name: Build the project
32 | run: npm run build
33 |
34 | - name: Run NodeJS Tests
35 | run: npm run test
36 |
37 | - name: NPM publish beta package
38 | if: ${{ contains(steps.tag_name.outputs.SOURCE_TAG, 'beta') }}
39 | uses: JS-DevTools/npm-publish@v3
40 | with:
41 | token: ${{ secrets.NPM_TOKEN }}
42 | tag: beta
43 |
44 | - name: NPM publish package
45 | if: ${{ !contains(steps.tag_name.outputs.SOURCE_TAG, 'beta') }}
46 | uses: JS-DevTools/npm-publish@v3
47 | with:
48 | token: ${{ secrets.NPM_TOKEN }}
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | target
2 | index.node
3 | **/node_modules
4 | **/.DS_Store
5 | npm-debug.log*
6 | dist/
7 | .xbox.tokens.json
8 | .xbox.tokens*.json
9 |
10 | # generated content
11 | .contentlayer
12 | .content-collections
13 | .source
14 | out/
15 | docs/content/docs/api/*.mdx
16 | docs/content/docs/api/*/*.mdx
17 | !docs/content/docs/api/*.model.mdx
18 | !docs/content/docs/api/*/*.model.mdx
19 | .nyc_output/
20 |
21 | # test & build
22 | docs/coverage
23 | coverage/
24 | docs/.next/
25 | docs/out/
26 | docs/build
27 | *.tsbuildinfo
28 |
29 | # misc
30 | .DS_Store
31 | *.pem
32 | /.pnp
33 | .pnp.js
34 | npm-debug.log*
35 | yarn-debug.log*
36 | yarn-error.log*
37 |
38 | # others
39 | .env*.local
40 | .vercel
41 | next-env.d.ts
42 | notes.md
43 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2020 UnknownSKL (Jim Kroon)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Xbox-Webapi-Node
2 |
3 | **xbox-webapi-node:** Typescript implementation for Xbox WebAPI's
4 |
5 | [](https://sonarcloud.io/summary/new_code?id=unknownskl_xbox-webapi-node)
6 | [](https://sonarcloud.io/summary/new_code?id=unknownskl_xbox-webapi-node)
7 | [](https://sonarcloud.io/summary/new_code?id=unknownskl_xbox-webapi-node)
8 | [](https://sonarcloud.io/summary/new_code?id=unknownskl_xbox-webapi-node)
9 |
10 |
11 | 📚 Documentation: [https://unknownskl.github.io/xbox-webapi-node/](https://unknownskl.github.io/xbox-webapi-node/)
--------------------------------------------------------------------------------
/docs/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | // "extends": ["next/core-web-vitals", "next/typescript"]
3 | "extends": ["next/typescript"]
4 | }
5 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | # docs
2 |
3 | This is a Next.js application generated with
4 | [Create Fumadocs](https://github.com/fuma-nama/fumadocs).
5 |
6 | Run development server:
7 |
8 | ```bash
9 | npm run dev
10 | # or
11 | pnpm dev
12 | # or
13 | yarn dev
14 | ```
15 |
16 | Open http://localhost:3000 with your browser to see the result.
17 |
18 | ## Learn More
19 |
20 | To learn more about Next.js and Fumadocs, take a look at the following
21 | resources:
22 |
23 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js
24 | features and API.
25 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
26 | - [Fumadocs](https://fumadocs.vercel.app) - learn about Fumadocs
27 |
--------------------------------------------------------------------------------
/docs/api-build.mjs:
--------------------------------------------------------------------------------
1 | import { generateFiles, createGenerator } from 'fumadocs-typescript';
2 | import * as path from 'node:path';
3 |
4 | const generator = createGenerator()
5 |
6 | void generateFiles(generator, {
7 | input: ['./content/docs/**/*.model.mdxmodel'],
8 | // Rename x.model.mdx to x.mdx
9 | output: (file) =>
10 | path.resolve(
11 | path.dirname(file),
12 | `${path.basename(file).split('.')[0]}.mdx`,
13 | ),
14 | });
--------------------------------------------------------------------------------
/docs/app/(home)/layout.tsx:
--------------------------------------------------------------------------------
1 | // import type { ReactNode } from 'react';
2 | // import { HomeLayout } from 'fumadocs-ui/layouts/home';
3 | // import { baseOptions } from '@/app/layout.config';
4 |
5 | // export default function Layout({ children }: { children: ReactNode }) {
6 | // return {children};
7 | // }
8 |
9 |
10 | import { DocsLayout } from 'fumadocs-ui/layouts/docs';
11 | import type { ReactNode } from 'react';
12 | import { baseOptions } from '@/app/layout.config';
13 | import { source } from '@/lib/source';
14 |
15 | export default function Layout({ children }: { children: ReactNode }) {
16 | return (
17 |
18 | {children}
19 |
20 | );
21 | }
22 |
--------------------------------------------------------------------------------
/docs/app/(home)/page.tsx:
--------------------------------------------------------------------------------
1 | import Link from 'next/link';
2 |
3 | export default function HomePage() {
4 | return (
5 |
6 | Xbox-Webapi-Node Documentation
7 |
8 | Check out{' '}
9 |
13 | getting started
14 | {' '}
15 | to start using xbox-webapi-node.
16 |
17 |
18 | );
19 | }
20 |
--------------------------------------------------------------------------------
/docs/app/docs/[[...slug]]/page.tsx:
--------------------------------------------------------------------------------
1 | import { source } from '@/lib/source';
2 | import {
3 | DocsPage,
4 | DocsBody,
5 | DocsDescription,
6 | DocsTitle,
7 | } from 'fumadocs-ui/page';
8 | import { notFound } from 'next/navigation';
9 | import defaultMdxComponents from 'fumadocs-ui/mdx';
10 |
11 | export default async function Page(props: {
12 | params: Promise<{ slug?: string[] }>;
13 | }) {
14 | const params = await props.params;
15 | const page = source.getPage(params.slug);
16 | if (!page) notFound();
17 |
18 | const MDX = page.data.body;
19 |
20 | return (
21 |
22 | {page.data.title}
23 | {page.data.description}
24 |
25 |
26 |
27 |
28 | );
29 | }
30 |
31 | export async function generateStaticParams() {
32 | return source.generateParams();
33 | }
34 |
35 | export async function generateMetadata(props: {
36 | params: Promise<{ slug?: string[] }>;
37 | }) {
38 | const params = await props.params;
39 | const page = source.getPage(params.slug);
40 | if (!page) notFound();
41 |
42 | return {
43 | title: page.data.title,
44 | description: page.data.description,
45 | };
46 | }
47 |
--------------------------------------------------------------------------------
/docs/app/docs/layout.tsx:
--------------------------------------------------------------------------------
1 | import { DocsLayout } from 'fumadocs-ui/layouts/docs';
2 | import type { ReactNode } from 'react';
3 | import { baseOptions } from '@/app/layout.config';
4 | import { source } from '@/lib/source';
5 |
6 | export default function Layout({ children }: { children: ReactNode }) {
7 | return (
8 |
9 | {children}
10 |
11 | );
12 | }
13 |
--------------------------------------------------------------------------------
/docs/app/global.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
5 | @import 'tailwindcss';
6 | @import 'fumadocs-ui/css/neutral.css';
7 | @import 'fumadocs-ui/css/preset.css';
8 |
9 | /* relative to the CSS file, make sure it's correct for your app */
10 | @source '../node_modules/fumadocs-ui/dist/**/*.js';
--------------------------------------------------------------------------------
/docs/app/layout.config.tsx:
--------------------------------------------------------------------------------
1 | import type { BaseLayoutProps } from 'fumadocs-ui/layouts/shared';
2 |
3 | /**
4 | * Shared layout configurations
5 | *
6 | * you can configure layouts individually from:
7 | * Home Layout: app/(home)/layout.tsx
8 | * Docs Layout: app/docs/layout.tsx
9 | */
10 | export const baseOptions: BaseLayoutProps = {
11 | nav: {
12 | title: 'Xbox-Webapi-Node',
13 | url: '/docs'
14 | },
15 | githubUrl: 'https://github.com/unknownskl/xbox-webapi-node',
16 | links: [
17 | {
18 | text: 'Home',
19 | url: '/',
20 | active: 'nested-url',
21 | },
22 | {
23 | text: 'Documentation',
24 | url: '/docs',
25 | active: 'nested-url',
26 | },
27 | ],
28 | };
29 |
--------------------------------------------------------------------------------
/docs/app/layout.tsx:
--------------------------------------------------------------------------------
1 | import './global.css';
2 | import { RootProvider } from 'fumadocs-ui/provider';
3 | import { Inter } from 'next/font/google';
4 | import type { ReactNode } from 'react';
5 |
6 | const inter = Inter({
7 | subsets: ['latin'],
8 | });
9 |
10 | export default function Layout({ children }: { children: ReactNode }) {
11 | return (
12 |
13 |
14 | {children}
17 |
18 |
19 | );
20 | }
21 |
--------------------------------------------------------------------------------
/docs/content/docs/api/lib.model.mdxmodel:
--------------------------------------------------------------------------------
1 | ---
2 | title: XboxWebApi
3 | description: XboxWebApi Class
4 | ---
5 |
6 | ---type-table---
7 | ../../../../src/lib.ts
8 | ---end---
--------------------------------------------------------------------------------
/docs/content/docs/api/provider/achievements.model.mdxmodel:
--------------------------------------------------------------------------------
1 | ---
2 | title: AchievementsProvider
3 | description: AchievementsProvider Class
4 | ---
5 |
6 | ---type-table---
7 | ../../../../../src/provider/achievements.ts
8 | ---end---
--------------------------------------------------------------------------------
/docs/content/docs/api/provider/catalog.model.mdxmodel:
--------------------------------------------------------------------------------
1 | ---
2 | title: CatalogProvider
3 | description: CatalogProvider Class
4 | ---
5 |
6 | ---type-table---
7 | ../../../../../src/provider/catalog.ts
8 | ---end---
--------------------------------------------------------------------------------
/docs/content/docs/api/provider/gameclips.model.mdxmodel:
--------------------------------------------------------------------------------
1 | ---
2 | title: GameclipsProvider
3 | description: GameclipsProvider Class
4 | ---
5 |
6 | ---type-table---
7 | ../../../../../src/provider/gameclips.ts
8 | ---end---
--------------------------------------------------------------------------------
/docs/content/docs/api/provider/gamepass.model.mdxmodel:
--------------------------------------------------------------------------------
1 | ---
2 | title: GamepassProvider
3 | description: GamepassProvider Class
4 | ---
5 |
6 | ---type-table---
7 | ../../../../../src/provider/gamepass.ts
8 | ---end---
--------------------------------------------------------------------------------
/docs/content/docs/api/provider/messages.model.mdxmodel:
--------------------------------------------------------------------------------
1 | ---
2 | title: MessagesProvider
3 | description: MessagesProvider Class
4 | ---
5 |
6 | ---type-table---
7 | ../../../../../src/provider/messages.ts
8 | ---end---
--------------------------------------------------------------------------------
/docs/content/docs/api/provider/people.model.mdxmodel:
--------------------------------------------------------------------------------
1 | ---
2 | title: PeopleProvider
3 | description: PeopleProvider Class
4 | ---
5 |
6 | ---type-table---
7 | ../../../../../src/provider/people.ts
8 | ---end---
--------------------------------------------------------------------------------
/docs/content/docs/api/provider/pins.model.mdxmodel:
--------------------------------------------------------------------------------
1 | ---
2 | title: PinsProvider
3 | description: PinsProvider Class
4 | ---
5 |
6 | ---type-table---
7 | ../../../../../src/provider/pins.ts
8 | ---end---
--------------------------------------------------------------------------------
/docs/content/docs/api/provider/profile.model.mdxmodel:
--------------------------------------------------------------------------------
1 | ---
2 | title: ProfileProvider
3 | description: ProfileProvider Class
4 | ---
5 |
6 | ---type-table---
7 | ../../../../../src/provider/profile.ts
8 | ---end---
--------------------------------------------------------------------------------
/docs/content/docs/api/provider/rest.model.mdxmodel:
--------------------------------------------------------------------------------
1 | ---
2 | title: RestProvider
3 | description: RestProvider Class
4 | ---
5 |
6 | ## Example code
7 |
8 | ```ts
9 | // Retrieve achievements of a user
10 | const result = await api.providers.rest.getRequest('https://achievements.xboxlive.com/users/xuid()/history/titles')
11 |
12 | // The response has a continuationToken. We can call .next() to retrieve the next page
13 | const result2 = await result.next()
14 |
15 | // Print out page 2 of the achievements api call
16 | console.log(result2)
17 | ```
18 |
19 | ---type-table---
20 | ../../../../../src/provider/rest.ts
21 | ---end---
--------------------------------------------------------------------------------
/docs/content/docs/api/provider/screenshots.model.mdxmodel:
--------------------------------------------------------------------------------
1 | ---
2 | title: ScreenshotsProvider
3 | description: ScreenshotsProvider Class
4 | ---
5 |
6 |
7 | This api is outdated. The api still works but no results are returned.
8 |
9 |
10 | ---type-table---
11 | ../../../../../src/provider/screenshots.ts
12 | ---end---
--------------------------------------------------------------------------------
/docs/content/docs/api/provider/smartglass.model.mdxmodel:
--------------------------------------------------------------------------------
1 | ---
2 | title: SmartglassProvider
3 | description: SmartglassProvider Class
4 | ---
5 |
6 | ---type-table---
7 | ../../../../../src/provider/smartglass.ts
8 | ---end---
--------------------------------------------------------------------------------
/docs/content/docs/api/provider/social.model.mdxmodel:
--------------------------------------------------------------------------------
1 | ---
2 | title: SocialProvider
3 | description: SocialProvider Class
4 | ---
5 |
6 | ---type-table---
7 | ../../../../../src/provider/social.ts
8 | ---end---
--------------------------------------------------------------------------------
/docs/content/docs/api/provider/titlehub.model.mdxmodel:
--------------------------------------------------------------------------------
1 | ---
2 | title: TitlehubProvider
3 | description: TitlehubProvider Class
4 | ---
5 |
6 | ---type-table---
7 | ../../../../../src/provider/titlehub.ts
8 | ---end---
--------------------------------------------------------------------------------
/docs/content/docs/api/provider/userpresence.model.mdxmodel:
--------------------------------------------------------------------------------
1 | ---
2 | title: UserpresenceProvider
3 | description: UserpresenceProvider Class
4 | ---
5 |
6 | ---type-table---
7 | ../../../../../src/provider/userpresence.ts
8 | ---end---
--------------------------------------------------------------------------------
/docs/content/docs/api/provider/usersearch.model.mdxmodel:
--------------------------------------------------------------------------------
1 | ---
2 | title: UsersearchProvider
3 | description: UsersearchProvider Class
4 | ---
5 |
6 |
7 | This api is outdated. The api still works but returns null results.
8 |
9 |
10 | ---type-table---
11 | ../../../../../src/provider/usersearch.ts
12 | ---end---
--------------------------------------------------------------------------------
/docs/content/docs/api/provider/userstats.model.mdxmodel:
--------------------------------------------------------------------------------
1 | ---
2 | title: UserstatsProvider
3 | description: UserstatsProvider Class
4 | ---
5 |
6 | ---type-table---
7 | ../../../../../src/provider/userstats.ts
8 | ---end---
--------------------------------------------------------------------------------
/docs/content/docs/api/provider/xnotify.model.mdxmodel:
--------------------------------------------------------------------------------
1 | ---
2 | title: XnotifyProvider
3 | description: XnotifyProvider Class
4 | ---
5 |
6 | ---type-table---
7 | ../../../../../src/provider/xnotify.ts
8 | ---end---
--------------------------------------------------------------------------------
/docs/content/docs/changelogs/2.0.0.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: v2.0.0
3 | description: Changelogs for v2.0.0
4 | ---
5 |
6 | Changelog:
7 |
8 | - Rewrite of `xbox-webapi` package
--------------------------------------------------------------------------------
/docs/content/docs/changelogs/meta.json:
--------------------------------------------------------------------------------
1 | {
2 | "pages": [
3 | "2.0.0"
4 | ]
5 | }
--------------------------------------------------------------------------------
/docs/content/docs/cli.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: CLI
3 | description: Xbox-Webapi CLI
4 | ---
5 |
6 | Xbox-Webapi-Node also offers a CLI application so you can make api calls to the xbox api from your terminal.
7 |
8 | ### Install
9 |
10 | To install the CLI, use the following command:
11 |
12 | ```npm install -g xbox-webapi```
13 |
14 | Once the package is installed the application should be available using `xbox-webapi`.
15 |
16 | ### Available commands
17 |
18 | | Command | Description |
19 | |---------|-------------|
20 | | `xbox-webapi` | Shows help and commands |
21 |
22 | Example output:
23 |
24 | ```shell
25 | xbox-webapi [args]
26 |
27 | Commands:
28 | xbox-webapi achievements [command] achievements provider
29 | xbox-webapi messages [command] messages provider
30 | xbox-webapi userpresence [command] userpresence provider
31 | xbox-webapi smartglass [command] smartglass provider
32 | xbox-webapi catalog [command] catalog provider
33 | xbox-webapi gameclips [command] gameclips provider
34 | xbox-webapi screenshots [command] screenshots provider
35 | xbox-webapi people [command] people provider
36 | xbox-webapi pins [command] pins provider
37 | xbox-webapi profile [command] profile provider
38 | xbox-webapi social [command] social provider
39 | xbox-webapi titlehub [command] titlehub provider
40 | xbox-webapi usersearch [command] usersearch provider
41 | xbox-webapi userstats [command] userstats provider
42 | xbox-webapi xnotify [command] xnotify provider
43 |
44 | Options:
45 | --help Show help [boolean]
46 | --version Show version number [boolean]
47 | -v, --verbose Run with verbose logging [boolean]
48 | -o, --output Output
49 | [string] [choices: "table", "json", "jsonp"] [default: "table"]
50 | -c, --continuationToken Continuation token [number]
51 | -n, --maxItems Max items [number]
52 | -s, --skipItems Skip items [number]
53 | -m, --market Market [string] [default: "US"]
54 | -l, --language Language [string] [default: "en-US"]
55 |
56 | You need to specify a command. Use --help to see available commands.
57 | ```
58 |
59 | ### Render output
60 |
61 | The default output of the cli is using `console.table`. This will try to render the data, however in most cases this is useless.
62 |
63 | You can supply the `-o json` argument to change the output to json.
64 |
65 | You can also use `-o jsonp` to output pretty printed json.
--------------------------------------------------------------------------------
/docs/content/docs/index.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Getting Started
3 | description: Starting with Xbox-Webapi-Node
4 | ---
5 |
6 | ### Installing xbox-webapi
7 |
8 | You can install the project with any package manager you like. In the project directory, run:
9 |
10 | For NPM:
11 | ```sh
12 | $ npm install xbox-webapi
13 | ```
14 |
15 | For Yarn:
16 | ```sh
17 | $ yarn add xbox-webapi
18 | ```
19 |
20 | If you want to install xbox-webapi-node for cli purposes, run the following:
21 |
22 | For NPM:
23 | ```sh
24 | $ npm install -g xbox-webapi
25 | ```
--------------------------------------------------------------------------------
/docs/content/docs/meta.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "pages": [
4 | "--- Documentation ---",
5 | "index",
6 | "cli",
7 | "...",
8 |
9 | "--- API Definitions ---",
10 | "...api",
11 |
12 | "--- Changelogs ---",
13 | "...changelogs"
14 | ]
15 | }
--------------------------------------------------------------------------------
/docs/content/docs/pagination.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Pagination
3 | description: Pagination system
4 | ---
5 |
6 | The library offers an easy way to paginate through api calls. For example the achievements provider uses the continuationToken to navigate through multiple lists.
7 |
8 | To help the user to navigate this we can simply make a api call using the example code below:
9 |
10 | ```ts
11 | const achievements = await api.providers.achievements.getAchievements(xuid) // Retrieve achievements of the user
12 | console.log(achievements.data.titles) // Print out the first list of achievements
13 |
14 | const achievements2 = await achievements.next() // Load second list of achievements.
15 | console.log(achievements2.data.titles) // Print out the second list of achievements
16 |
17 | const achievements3 = await achievements2.next() // Load third list of achievements.
18 | console.log(achievements2.data.titles) // Print out the third list of achievements
19 | ```
20 |
21 | All the methods which response contains a continuationToken will support this way of navigating. (Including the `rest` provider)
--------------------------------------------------------------------------------
/docs/lib/source.ts:
--------------------------------------------------------------------------------
1 | import { docs, meta } from '@/.source';
2 | import { createMDXSource } from 'fumadocs-mdx';
3 | import { loader } from 'fumadocs-core/source';
4 |
5 | export const source = loader({
6 | baseUrl: '/docs',
7 | source: createMDXSource(docs, meta),
8 | });
9 |
--------------------------------------------------------------------------------
/docs/next.config.mjs:
--------------------------------------------------------------------------------
1 | import { createMDX } from 'fumadocs-mdx/next';
2 |
3 | const withMDX = createMDX();
4 |
5 | /** @type {import('next').NextConfig} */
6 | const config = {
7 | output: 'export',
8 | reactStrictMode: true,
9 | basePath: '/xbox-webapi-node',
10 | };
11 |
12 | export default withMDX(config);
13 |
--------------------------------------------------------------------------------
/docs/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "docs",
3 | "version": "0.0.0",
4 | "private": true,
5 | "scripts": {
6 | "build": "node api-build.mjs && next build",
7 | "dev": "node api-build.mjs && next dev",
8 | "start": "next start",
9 | "postinstall": "fumadocs-mdx"
10 | },
11 | "dependencies": {
12 | "fumadocs-core": "^15.5.0",
13 | "fumadocs-mdx": "^11.6.7",
14 | "fumadocs-typescript": "^4.0.5",
15 | "fumadocs-ui": "^15.5.1",
16 | "next": "^15.3.3",
17 | "react": "^19.0.0",
18 | "react-dom": "^19.1.0"
19 | },
20 | "devDependencies": {
21 | "@tailwindcss/postcss": "^4.1.7",
22 | "@types/mdx": "^2.0.13",
23 | "@types/node": "^22.15.30",
24 | "@types/react": "^19.1.7",
25 | "@types/react-dom": "^19.1.5",
26 | "autoprefixer": "^10.4.20",
27 | "eslint": "^9",
28 | "eslint-config-next": "^15.3.3",
29 | "postcss": "^8.5.4",
30 | "tailwindcss": "^4.1.8",
31 | "typescript": "^5.8.3"
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/docs/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | autoprefixer: {},
4 | "@tailwindcss/postcss": {},
5 | },
6 | };
7 |
--------------------------------------------------------------------------------
/docs/source.config.ts:
--------------------------------------------------------------------------------
1 | import { defineDocs, defineConfig } from 'fumadocs-mdx/config';
2 |
3 | export const { docs, meta } = defineDocs({
4 | dir: 'content/docs',
5 | });
6 |
7 | export default defineConfig();
8 |
--------------------------------------------------------------------------------
/docs/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "baseUrl": ".",
4 | "target": "ESNext",
5 | "lib": ["dom", "dom.iterable", "esnext"],
6 | "allowJs": true,
7 | "skipLibCheck": true,
8 | "strict": true,
9 | "forceConsistentCasingInFileNames": true,
10 | "noEmit": true,
11 | "esModuleInterop": true,
12 | "module": "esnext",
13 | "moduleResolution": "bundler",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "jsx": "preserve",
17 | "incremental": true,
18 | "paths": {
19 | "@/*": ["./*"]
20 | },
21 | "plugins": [
22 | {
23 | "name": "next"
24 | }
25 | ]
26 | },
27 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
28 | "exclude": ["node_modules"]
29 | }
30 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "xbox-webapi",
3 | "version": "2.0.0-beta3",
4 | "description": "Xbox Web API client in Node.JS that supports Smartglass commands to control the Xbox",
5 | "main": "dist/lib.js",
6 | "bin": {
7 | "xbox-webapi": "dist/bin/cli.js"
8 | },
9 | "scripts": {
10 | "build": "rm -rf dist/ && tsc && chmod +x dist/bin/cli.js",
11 | "test": "npm run build && nyc --require ts-node/register --reporter=html --reporter=lcov --reporter=text mocha tests/**.ts",
12 | "start": "npm run build && node dist/bin/cli.js",
13 | "start:test": "npm run build && node dist/bin/test.js",
14 | "auth": "xbox-auth auth --auth msal"
15 | },
16 | "author": "UnknownSKL ",
17 | "license": "MIT",
18 | "devDependencies": {
19 | "@types/chai": "^5",
20 | "@types/mocha": "^10",
21 | "@types/node": "^22.5.4",
22 | "chai": "^5.1.1",
23 | "mocha": "^11.1.0",
24 | "nyc": "^17.1.0",
25 | "ts-node": "^10.9.2",
26 | "typescript": "^5.3.3",
27 | "uuid4": "^2.0.3",
28 | "xal-node": "^1.1.0",
29 | "yargs": "^17.7.2"
30 | },
31 | "repository": {
32 | "type": "git",
33 | "url": "git+https://github.com/unknownskl/xbox-webapi-node.git"
34 | },
35 | "keywords": [
36 | "xbox",
37 | "webapi",
38 | "api"
39 | ],
40 | "bugs": {
41 | "url": "https://github.com/unknownskl/xbox-webapi-node/issues"
42 | },
43 | "homepage": "https://github.com/unknownskl/xbox-webapi-node#readme"
44 | }
45 |
--------------------------------------------------------------------------------
/src/bin/cli.ts:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | import yargs from 'yargs'
3 | import ownPackage from '../../package.json'
4 | import XboxWebApi from '../lib'
5 |
6 | import { Xal, Msal, TokenStore } from 'xal-node'
7 |
8 | class Cli {
9 | _yargs:yargs
10 | _tokenStore:TokenStore
11 | _xal:Xal|Msal
12 |
13 | constructor() {
14 |
15 | this._yargs = yargs
16 | .scriptName("xbox-webapi")
17 | .usage('$0 [args]')
18 | .version(ownPackage.version)
19 | .detectLocale(false)
20 | .wrap(yargs.terminalWidth())
21 | .demandCommand(1, 'You need to specify a command. Use --help to see available commands.');
22 |
23 | this._tokenStore = new TokenStore()
24 | this._tokenStore.load('./.xbox.tokens.json')
25 | this._tokenStore.getAuthenticationMethod()
26 | if(this._tokenStore.getAuthenticationMethod() === 'msal'){
27 | this._xal = new Msal(this._tokenStore)
28 | } else {
29 | this._xal = new Xal(this._tokenStore)
30 | }
31 |
32 | // Load providers and commands
33 | this._yargs = this._populateCommands(this._yargs)
34 |
35 | this._yargs.option('verbose', {
36 | alias: 'v',
37 | type: 'boolean',
38 | description: 'Run with verbose logging'
39 | })
40 |
41 | this._yargs.option('output', {
42 | alias: 'o',
43 | type: 'string',
44 | description: 'Output',
45 | default: 'table'
46 | }).choices('output', ['table', 'json', 'jsonp'])
47 |
48 | yargs.option('continuationToken', {
49 | alias: 'c',
50 | type: 'number',
51 | description: 'Continuation token',
52 | }).option('maxItems', {
53 | alias: 'n',
54 | type: 'number',
55 | description: 'Max items',
56 | }).option('skipItems', {
57 | alias: 's',
58 | type: 'number',
59 | description: 'Skip items',
60 | }).option('market', {
61 | alias: 'm',
62 | type: 'string',
63 | description: 'Market',
64 | default: 'US'
65 | }).option('language', {
66 | alias: 'l',
67 | type: 'string',
68 | description: 'Language',
69 | default: 'en-US'
70 | })
71 | }
72 |
73 | run() {
74 | this._yargs.argv
75 | }
76 |
77 | _getFunctionArgs(func) {
78 | const args = func.toString().match(/\(([^)]*)\)/);
79 | const args2 = args ? args[1].split(',').map(arg => arg.trim().split(' ')[0]).filter(arg => arg) : [];
80 | return args2
81 | }
82 |
83 | _populateCommands(yargs: yargs) {
84 | // Load providers and commands
85 |
86 | // Create dummy api and check ffor providers and commands in class
87 | const dummyApi = new XboxWebApi({
88 | uhs: 'dummy',
89 | token: 'dummy'
90 | });
91 |
92 | for(const provider in dummyApi.providers){
93 | const commands = this._getCommandsFromProvider(dummyApi.providers[provider])
94 |
95 | yargs.command(
96 | `${provider} [command]`,
97 | `${provider} provider`,
98 | (yargs) => {
99 |
100 | // Setup commands in providers
101 | for(const command in commands){
102 | const functionArgs = this._getFunctionArgs(dummyApi.providers[provider][commands[command]])
103 |
104 | const functionArgsFiltered = functionArgs.filter((arg) => {
105 | return arg !== 'continuationToken' &&
106 | arg !== 'maxItems' &&
107 | arg !== 'skipItems'
108 | })
109 |
110 | const commandStr = commands[command] + '' + (functionArgsFiltered.length > 0 ? ' [' + functionArgsFiltered.join('] [') + ']' : '')
111 | const descriptionStr = ''
112 |
113 | yargs.command(
114 | commandStr,
115 | descriptionStr,
116 | (yargs) => {
117 | for(const arg in functionArgs){
118 | yargs.positional(functionArgs[arg], {
119 | type: 'string',
120 | });
121 | }
122 | },
123 | (argv) => {
124 | this._xal.getWebToken().then((token) => {
125 |
126 | const api = new XboxWebApi({
127 | uhs: token.data.DisplayClaims.xui[0].uhs,
128 | token: token.data.Token,
129 | })
130 |
131 | const args = [];
132 | for(const arg in functionArgs){
133 | args.push(argv[functionArgs[arg]])
134 | }
135 |
136 | if(argv.verbose === true)
137 | console.log(`Running command: ${provider}::${commands[command]}(${args})`);
138 |
139 | api.providers[provider][commands[command]](...args).then((result) => {
140 |
141 | // Render output
142 | if(argv.output === 'json'){
143 | console.log(JSON.stringify(result.data))
144 |
145 | } else if(argv.output === 'jsonp'){
146 | console.log(JSON.stringify(result.data, null, 2))
147 |
148 | } else {
149 | console.table(result.data)
150 | }
151 |
152 | }).catch((error) => {
153 | console.log('Failed to execute command:', error)
154 | })
155 |
156 | }).catch((error) => {
157 | console.log('Failed to retrieve web token:', error)
158 | })
159 | }
160 | );
161 | }
162 |
163 | },
164 | (argv) => {
165 | yargs.showHelp()
166 | }
167 | );
168 | }
169 |
170 | return yargs
171 | }
172 |
173 | _getCommandsFromProvider(provider: any) {
174 | const cmds:string[] = []
175 | const commands = Object.getOwnPropertyNames(Object.getPrototypeOf(provider))
176 | for(const command in commands){
177 | if(commands[command] === 'constructor')
178 | continue;
179 |
180 | if(commands[command].startsWith('_'))
181 | continue;
182 |
183 | // console.log('command:', commands[command])
184 | cmds.push(commands[command])
185 | }
186 |
187 | return cmds
188 | }
189 | }
190 |
191 | const cli = new Cli();
192 | cli.run()
--------------------------------------------------------------------------------
/src/lib.ts:
--------------------------------------------------------------------------------
1 | import SmartglassProvider from './provider/smartglass'
2 | import MessagesProvider from './provider/messages'
3 | import AchievementsProvider from './provider/achievements'
4 | import UserpresenceProvider from './provider/userpresence'
5 | import CatalogProvider from './provider/catalog'
6 | import GameclipsProvider from './provider/gameclips'
7 | import ScreenshotsProvider from './provider/screenshots'
8 | import PeopleProvider from './provider/people'
9 | import PinsProvider from './provider/pins'
10 | import ProfileProvider from './provider/profile'
11 | import SocialProvider from './provider/social'
12 | import TitlehubProvider from './provider/titlehub'
13 | import UsersearchProvider from './provider/usersearch'
14 | import UserstatsProvider from './provider/userstats'
15 | import XnotifyProvider from './provider/xnotify'
16 | import GamepassProvider from './provider/gamepass'
17 | import RestProvider from './provider/rest'
18 |
19 | type XboxWebApiConfig = {
20 | uhs: string
21 | token: string
22 | market?: string
23 | }
24 |
25 | export default class XboxWebApi {
26 |
27 | private readonly _config:XboxWebApiConfig
28 |
29 | constructor(config:XboxWebApiConfig){
30 | this._config = {
31 | market: 'en-us',
32 | ...config
33 | }
34 | }
35 |
36 | providers = {
37 | 'achievements': new AchievementsProvider(this),
38 | 'messages': new MessagesProvider(this),
39 | 'userpresence': new UserpresenceProvider(this),
40 | 'smartglass': new SmartglassProvider(this),
41 | 'catalog': new CatalogProvider(this),
42 | 'gameclips': new GameclipsProvider(this),
43 | 'gamepass': new GamepassProvider(this),
44 | 'screenshots': new ScreenshotsProvider(this),
45 | 'people': new PeopleProvider(this),
46 | 'pins': new PinsProvider(this),
47 | 'profile': new ProfileProvider(this),
48 | 'social': new SocialProvider(this),
49 | 'titlehub': new TitlehubProvider(this),
50 | 'usersearch': new UsersearchProvider(this),
51 | 'userstats': new UserstatsProvider(this),
52 | 'xnotify': new XnotifyProvider(this),
53 | 'rest': new RestProvider(this),
54 | }
55 |
56 | getAuthorizationHeader(){
57 | return 'XBL3.0 x='+this._config.uhs+';'+this._config.token
58 | }
59 |
60 | }
--------------------------------------------------------------------------------
/src/lib/http.ts:
--------------------------------------------------------------------------------
1 | import { IncomingHttpHeaders } from 'http'
2 | import https from 'https'
3 | import { URL } from 'url'
4 |
5 | export default class Http {
6 |
7 | getRequest(host:string, path:string, headers:any, method = 'GET') {
8 | return new Promise((resolve, reject) => {
9 |
10 | const hostHeaders = {
11 | ...headers,
12 | }
13 |
14 | const options = {
15 | method: method,
16 | hostname: host,
17 | path: path,
18 | port: 443,
19 | headers: hostHeaders
20 | }
21 |
22 | const req = this.createRequest(options, resolve, reject)
23 |
24 | req.on('error', (error) => {
25 | reject(new Error('Unhandled error:'+ JSON.stringify(error)))
26 | })
27 |
28 | req.end()
29 |
30 | })
31 | }
32 |
33 | deleteRequest(host:string, path:string, headers:any) {
34 | return this.getRequest(host, path, headers, 'DELETE')
35 | }
36 |
37 | postRequest(host:string, path:string, headers:any, data:any, method = 'POST') {
38 | return new Promise((resolve, reject) => {
39 |
40 | const hostHeaders = {
41 | ...headers,
42 | }
43 |
44 | if(typeof data === 'object'){
45 | data = JSON.stringify(data)
46 | }
47 |
48 | const options = {
49 | method: method,
50 | hostname: host,
51 | path: path,
52 | port: 443,
53 | headers: hostHeaders
54 | }
55 |
56 | const req = this.createRequest(options, resolve, reject)
57 |
58 | req.on('error', (error) => {
59 | reject(new Error('Unhandled error:'+ JSON.stringify(error)))
60 | })
61 |
62 | req.write(data)
63 | req.end()
64 |
65 | })
66 | }
67 |
68 | putRequest(host:string, path:string, headers:any, data:any) {
69 | return this.postRequest(host, path, headers, data, 'PUT')
70 | }
71 |
72 | createRequest(options:any, resolve:any, reject:any){
73 | return https.request(options, (res) => {
74 | let responseData = ''
75 |
76 | res.on('data', (data) => {
77 | responseData += data
78 | })
79 |
80 | res.on('close', () => {
81 | if(res.statusCode == 200 || res.statusCode == 204){
82 | if(responseData.toString() === ''){
83 | resolve(new HttpResponse({}, res.headers, options))
84 | } else {
85 | resolve(new HttpResponse(JSON.parse(responseData.toString()), res.headers, options))
86 | }
87 | } else {
88 | reject(new Error('Error fetching '+options.hostname+options.path+'. Details: '+ JSON.stringify({
89 | statuscode: res.statusCode,
90 | headers: res.headers,
91 | body: responseData.toString(),
92 | message: 'Error fetching '+options.hostname+options.path
93 | }, null, 2)))
94 | }
95 | })
96 | })
97 | }
98 | }
99 |
100 |
101 | export class HttpResponse {
102 |
103 | data:T
104 | headers:IncomingHttpHeaders
105 | options:any
106 |
107 | constructor(data:any, headers:IncomingHttpHeaders, options:any){
108 | this.data = data
109 | this.headers = headers
110 | this.options = options
111 |
112 | // delete(this.options.headers['Authorization'])
113 | }
114 |
115 | header(){
116 | return this.headers
117 | }
118 |
119 | body(){
120 | return this.data
121 | }
122 |
123 | async next(){
124 | const parsedUrl = new URL(this.options.path, 'https://dummy-base')
125 | const maxItems = parsedUrl.searchParams.get('maxItems') ?? undefined
126 | const skipItems = parsedUrl.searchParams.get('skipItems') ?? undefined
127 |
128 | // @ts-expect-error We already acknowledge the null value
129 | const continuationToken = this.data.pagingInfo?.continuationToken
130 | if(continuationToken === undefined){
131 | throw new Error('No continuation token found in response')
132 | }
133 |
134 | const request = new Http()
135 | const path = parsedUrl.pathname + parsedUrl.search
136 | return (await request.getRequest(this.options.hostname, applyPagination(path, maxItems, skipItems, continuationToken), this.options.headers)) as HttpResponse
137 | }
138 | }
139 |
140 | export function applyPagination(path:string, maxItems, skipItems, continuationToken:undefined|string){
141 | const parsedUrl = new URL(path, 'https://dummy-base')
142 |
143 | if(maxItems !== undefined)
144 | parsedUrl.searchParams.set('maxItems', maxItems)
145 |
146 | if(skipItems !== undefined)
147 | parsedUrl.searchParams.set('skipItems', skipItems)
148 |
149 | if(continuationToken !== undefined)
150 | parsedUrl.searchParams.set('continuationToken', continuationToken)
151 |
152 | return parsedUrl.pathname + parsedUrl.search
153 | }
--------------------------------------------------------------------------------
/src/provider/achievements.ts:
--------------------------------------------------------------------------------
1 | import { HttpResponse } from '../lib/http'
2 | import { AchievementsResponse, AchievementsTitleResponse } from '../types/achievements'
3 |
4 | import BaseProvider from './base'
5 |
6 | export default class AchievementsProvider extends BaseProvider {
7 | _endpoint = 'achievements.xboxlive.com'
8 | _headers = {
9 | 'x-xbl-contract-version': '2'
10 | }
11 |
12 | async getAchievements(xuid:string, continuationToken:undefined|string = undefined, maxItems = undefined, skipItems = undefined): Promise> {
13 | return (await this.get(this.applyPagination('/users/xuid('+xuid+')/history/titles', maxItems, skipItems, continuationToken)))
14 | }
15 |
16 | async getTitleId(xuid:string, titleId:string, continuationToken:undefined|string = undefined, maxItems = undefined, skipItems = undefined): Promise> {
17 | return (await this.get(this.applyPagination('/users/xuid('+xuid+')/achievements?titleid='+titleId, maxItems, skipItems, continuationToken)))
18 | }
19 |
20 | async getItemDetail(xuid:string, serviceConfigId:string, achievementId:string, continuationToken:undefined|string = undefined, maxItems = undefined, skipItems = undefined): Promise> {
21 | return (await this.get(this.applyPagination('/users/xuid('+xuid+')/achievements/'+serviceConfigId+'/'+achievementId, maxItems, skipItems, continuationToken)))
22 | }
23 | }
--------------------------------------------------------------------------------
/src/provider/base.ts:
--------------------------------------------------------------------------------
1 | import XboxWebApi from '../lib'
2 | import Http, { applyPagination } from '../lib/http'
3 |
4 | export default class BaseProvider {
5 | private readonly _api: XboxWebApi;
6 | private _defaultHeaders
7 | private _disableAuthHeader = false
8 | _endpoint = 'xboxlive.com'
9 | _headers
10 |
11 | constructor(api:XboxWebApi){
12 | this._api = api
13 | this._defaultHeaders = {
14 | 'Accept-Language': 'en-US',
15 | 'Accept': 'application/json',
16 | 'x-xbl-contract-version': '2',
17 | 'Content-Type': 'application/json'
18 | }
19 | }
20 |
21 | getApi(){
22 | return this._api
23 | }
24 |
25 | resetDefaultHeaders(){
26 | this._defaultHeaders = {}
27 | this._disableAuthHeader = true
28 | return true
29 | }
30 |
31 | applyPagination = applyPagination
32 |
33 | async get(path, headers?){
34 | const _headers = {
35 | ...this._defaultHeaders,
36 | ...this._headers,
37 | ...headers,
38 | ...(this._disableAuthHeader === true) ? {} : { 'Authorization': this.getApi().getAuthorizationHeader() }
39 | }
40 |
41 | const response = await new Http().getRequest(this._endpoint, path, _headers)
42 | return response
43 | }
44 |
45 | async delete(path, data, headers?){
46 | const _headers = {
47 | ...this._defaultHeaders,
48 | ...this._headers,
49 | ...headers,
50 | ...(this._disableAuthHeader === true) ? {} : { 'Authorization': this.getApi().getAuthorizationHeader() }
51 | }
52 |
53 | const response = await new Http().deleteRequest(this._endpoint, path, _headers)
54 | return response
55 | }
56 |
57 | async post(path, data, headers?){
58 | const _headers = {
59 | ...this._defaultHeaders,
60 | ...this._headers,
61 | ...headers,
62 | ...(this._disableAuthHeader === true) ? {} : { 'Authorization': this.getApi().getAuthorizationHeader() }
63 | }
64 |
65 | const response = await new Http().postRequest(this._endpoint, path, _headers, data)
66 | return response
67 | }
68 |
69 | async put(path, data, headers?){
70 | const _headers = {
71 | ...this._defaultHeaders,
72 | ...this._headers,
73 | ...headers,
74 | ...(this._disableAuthHeader === true) ? {} : { 'Authorization': this.getApi().getAuthorizationHeader() }
75 | }
76 |
77 | const response = await new Http().putRequest(this._endpoint, path, _headers, data)
78 | return response
79 | }
80 | }
--------------------------------------------------------------------------------
/src/provider/catalog.ts:
--------------------------------------------------------------------------------
1 | import QueryString from 'node:querystring'
2 | import { CatalogSearchResponse } from '../types/catalog'
3 |
4 | import BaseProvider from './base'
5 | import { HttpResponse } from '../lib/http'
6 |
7 | export default class CatalogProvider extends BaseProvider {
8 | _endpoint = 'displaycatalog.mp.microsoft.com'
9 | _headers = {
10 | 'MS-CV': '1.0',
11 | }
12 |
13 | async searchTitle(query:string, market = 'us', language = 'en-us', continuationToken:undefined|string = undefined, maxItems = undefined, skipItems = undefined): Promise> {
14 | const searchParams = {
15 | "languages": language,
16 | "market": market,
17 | "platformdependencyname": 'windows.xbox',
18 | "productFamilyNames": "Games,Apps",
19 | "query": query,
20 | "topProducts": 25,
21 | }
22 |
23 | const queryParams = QueryString.stringify(searchParams)
24 | this.resetDefaultHeaders()
25 |
26 | return (await this.get(this.applyPagination('/v7.0/productFamilies/autosuggest?'+queryParams, maxItems, skipItems, continuationToken)))
27 | }
28 |
29 | async getProductId(query:string, market = 'us', language = 'en-us', continuationToken:undefined|string = undefined, maxItems = undefined, skipItems = undefined): Promise> {
30 | const searchParams = {
31 | "actionFilter": 'Browse',
32 | "bigIds": [query],
33 | "fieldsTemplate": 'details',
34 | "languages": language,
35 | "market": market,
36 | }
37 |
38 | const queryParams = QueryString.stringify(searchParams)
39 | this.resetDefaultHeaders()
40 |
41 | return (await this.get(this.applyPagination('/v7.0/productFamilies/autosuggest?'+queryParams, maxItems, skipItems, continuationToken)))
42 | }
43 |
44 | async getProductFromAlternateId(titleId:string, titleType:string, market = 'us', language = 'en-us', continuationToken:undefined|string = undefined, maxItems = undefined, skipItems = undefined): Promise> {
45 | const searchParams = {
46 | "top": 25,
47 | "alternateId": titleType,
48 | "fieldsTemplate": 'details',
49 | // "languages": 'en-US',
50 | // "market": 'US',
51 | "languages": language,
52 | "market": market,
53 | "value": titleId,
54 | }
55 |
56 | const queryParams = QueryString.stringify(searchParams)
57 | this.resetDefaultHeaders()
58 |
59 | return (await this.get(this.applyPagination('/v7.0/productFamilies/autosuggest?'+queryParams, maxItems, skipItems, continuationToken)))
60 | }
61 | }
--------------------------------------------------------------------------------
/src/provider/gameclips.ts:
--------------------------------------------------------------------------------
1 | import { HttpResponse } from '../lib/http'
2 | import { GameclipsResponse } from '../types/gameclips'
3 |
4 | import BaseProvider from './base'
5 |
6 | export default class GameclipsProvider extends BaseProvider {
7 | _endpoint = 'mediahub.xboxlive.com'
8 |
9 | _headers = {
10 | 'x-xbl-contract-version': '3'
11 | }
12 |
13 | async getGameclips(xuid:string, continuationToken:undefined|string = undefined, maxItems = undefined, skipItems = undefined): Promise> {
14 | return (await this.post(this.applyPagination('/gameclips/search', maxItems, skipItems, continuationToken),
15 | {
16 | query: "OwnerXuid eq "+xuid,
17 | max: maxItems,
18 | skip: skipItems
19 | }
20 | ))
21 | }
22 | }
--------------------------------------------------------------------------------
/src/provider/gamepass.ts:
--------------------------------------------------------------------------------
1 | import QueryString from 'node:querystring'
2 | import pkg from '../../package.json'
3 | import { SiglResponse, ProductsResponse } from '../types/gamepass'
4 |
5 | import BaseProvider from './base'
6 | import { HttpResponse } from '../lib/http'
7 |
8 | export default class GamepassProvider extends BaseProvider {
9 | _endpoint = 'catalog.gamepass.com'
10 | _headers = {
11 | 'MS-CV': '1.0',
12 | 'calling-app-name': 'github.com/unknownskl/xbox-webapi-node',
13 | 'calling-app-version': pkg.version,
14 | }
15 |
16 | async getSigl(siglId:string, market = 'us', language = 'en-us', continuationToken:undefined|string = undefined, maxItems = undefined, skipItems = undefined): Promise> {
17 | const searchParams = {
18 | "id": siglId,
19 | "market": market,
20 | "language": language,
21 | }
22 | const queryParams = QueryString.stringify(searchParams)
23 | return (await this.get('/sigls/v2?'+queryParams))
24 | }
25 |
26 | async getProducts(products:string[], market = 'us', language = 'en-us', continuationToken:undefined|string = undefined, maxItems = undefined, skipItems = undefined): Promise> {
27 | const searchParams = {
28 | "hydration": 'MobileLowAmber0',
29 | "market": market,
30 | "language": language,
31 | }
32 | const queryParams = QueryString.stringify(searchParams)
33 | return (await this.post('/v3/products?'+queryParams,{
34 | Products: products
35 | }))
36 | }
37 |
38 | async getProductsDetailed(products:string[], market = 'us', language = 'en-us', continuationToken:undefined|string = undefined, maxItems = undefined, skipItems = undefined): Promise> {
39 | if(products.length > 20){
40 | throw new Error('Maximum of 20 products can be requested at a time')
41 | }
42 |
43 | const searchParams = {
44 | "hydration": 'RemoteHighSapphire0',
45 | "market": market,
46 | "language": language,
47 | }
48 | const queryParams = QueryString.stringify(searchParams)
49 | return (await this.post('/v3/products?'+queryParams,{
50 | Products: products
51 | }))
52 | }
53 | }
--------------------------------------------------------------------------------
/src/provider/messages.ts:
--------------------------------------------------------------------------------
1 | import { HttpResponse } from '../lib/http'
2 | import { ConversationResponse, InboxResponse } from '../types/messages'
3 |
4 | import BaseProvider from './base'
5 |
6 | export default class MessagesProvider extends BaseProvider {
7 | _endpoint = 'xblmessaging.xboxlive.com'
8 |
9 | async getInbox(): Promise> {
10 | return (await this.get('/network/Xbox/users/me/inbox'))
11 | }
12 |
13 | async getConversation(xuid:string, continuationToken:undefined|string = undefined, maxItems = undefined, skipItems = undefined): Promise> {
14 | return (await this.get(this.applyPagination('/network/Xbox/users/me/conversations/users/xuid('+xuid+')', maxItems, skipItems, continuationToken)))
15 | }
16 | }
--------------------------------------------------------------------------------
/src/provider/people.ts:
--------------------------------------------------------------------------------
1 | import { HttpResponse } from '../lib/http'
2 | import { PeopleResponse } from '../types/people'
3 |
4 | import BaseProvider from './base'
5 |
6 | export default class PeopleProvider extends BaseProvider {
7 | _endpoint = 'peoplehub.xboxlive.com'
8 |
9 | async getFriends(): Promise> {
10 | const params = [
11 | 'preferredcolor',
12 | 'detail',
13 | 'multiplayersummary',
14 | 'presencedetail',
15 | ]
16 | return (await this.get('/users/me/people/social/decoration/'+params.join(',')))
17 | }
18 |
19 | async recentPlayers(continuationToken:undefined|string = undefined, maxItems = undefined, skipItems = undefined): Promise> {
20 | return (await this.get(this.applyPagination('/users/me/people/recentplayers', maxItems, skipItems, continuationToken)))
21 | }
22 | }
--------------------------------------------------------------------------------
/src/provider/pins.ts:
--------------------------------------------------------------------------------
1 | import { HttpResponse } from '../lib/http'
2 | import { PinsResponse } from '../types/pins'
3 |
4 | import BaseProvider from './base'
5 |
6 | export default class PinsProvider extends BaseProvider {
7 | _endpoint = 'eplists.xboxlive.com'
8 |
9 | async getPins(xuid:string, listname = 'XBLPins'): Promise> {
10 | return (await this.get('/users/xuid('+xuid+')/lists/PINS/'+listname))
11 | }
12 |
13 | async getSavedForLater(xuid:string): Promise> {
14 | return (await this.getPins(xuid, 'SaveForLater'))
15 | }
16 | }
--------------------------------------------------------------------------------
/src/provider/profile.ts:
--------------------------------------------------------------------------------
1 | import { HttpResponse } from '../lib/http'
2 | import { ProfileResponse } from '../types/profile'
3 |
4 | import BaseProvider from './base'
5 |
6 | export default class ProfileProvider extends BaseProvider {
7 | _endpoint = 'profile.xboxlive.com'
8 | _headers = {
9 | 'x-xbl-contract-version': 3
10 | }
11 |
12 | async getCurrentUser(): Promise> {
13 | return (await this.get('/users/me/profile/settings?settings=GameDisplayName,GameDisplayPicRaw,Gamerscore,Gamertag'))
14 | }
15 |
16 | async getUserProfile(xuid:string): Promise> {
17 | return (await this.get('/users/xuid('+xuid+')/profile/settings?settings=GameDisplayName,GameDisplayPicRaw,Gamerscore,Gamertag'))
18 | }
19 |
20 | async getByGamertag(gamertag:string): Promise> {
21 | return (await this.get('/users/gt('+gamertag+')/profile/settings?settings=GameDisplayName,GameDisplayPicRaw,Gamerscore,Gamertag'))
22 | }
23 | }
--------------------------------------------------------------------------------
/src/provider/rest.ts:
--------------------------------------------------------------------------------
1 | import { HttpResponse } from '../lib/http'
2 | import { URL } from 'url'
3 |
4 | import BaseProvider from './base'
5 |
6 | export default class RestProvider extends BaseProvider {
7 | _endpoint = 'xboxlive.com'
8 | _headers = {}
9 |
10 | async getRequest(url:string, xblContractVersion:undefined|number = undefined, continuationToken:undefined|string = undefined, maxItems = undefined, skipItems = undefined): Promise {
11 | if(! URL.canParse(url)){
12 | throw new Error('Invalid URL supplied')
13 | }
14 |
15 | const parsedUrl = new URL(url)
16 | this._endpoint = parsedUrl.hostname
17 |
18 | if(xblContractVersion !== undefined){
19 | this._headers['x-xbl-contract-version'] = xblContractVersion.toString()
20 | }
21 |
22 | return (await this.get(this.applyPagination(parsedUrl.pathname + parsedUrl.search, maxItems, skipItems, continuationToken)))
23 | }
24 | }
--------------------------------------------------------------------------------
/src/provider/screenshots.ts:
--------------------------------------------------------------------------------
1 | import { HttpResponse } from '../lib/http'
2 | import BaseProvider from './base'
3 | import { ScreenshotsResponse } from '../types/screenshots'
4 |
5 | export default class ScreenshotsProvider extends BaseProvider {
6 | _endpoint = 'mediahub.xboxlive.com'
7 |
8 | _headers = {
9 | 'x-xbl-contract-version': '3'
10 | }
11 |
12 | async getScreenshots(xuid:string, continuationToken:undefined|string = undefined, maxItems = undefined, skipItems = undefined): Promise> {
13 | return (await this.post(this.applyPagination('/screenshots/search', maxItems, skipItems, continuationToken),
14 | {
15 | query: "OwnerXuid eq "+xuid,
16 | max: maxItems,
17 | skip: skipItems
18 | }
19 | ))
20 | }
21 | }
--------------------------------------------------------------------------------
/src/provider/smartglass.ts:
--------------------------------------------------------------------------------
1 | import { HttpResponse } from '../lib/http'
2 | import { SmartglassResponse, Console, ConsoleStatus, App, StorageDevice } from '../types/smartglass'
3 |
4 | import BaseProvider from './base'
5 | import Uuid4 from 'uuid4'
6 |
7 | export default class SmartglassProvider extends BaseProvider {
8 | _endpoint = 'xccs.xboxlive.com'
9 | _headers = {
10 | 'x-xbl-contract-version': '4',
11 | 'skillplatform': 'RemoteManagement'
12 | }
13 |
14 | async getConsolesList(): Promise>> {
15 | return (await this.get('/lists/devices?queryCurrentDevice=false&includeStorageDevices=true'))
16 | }
17 |
18 | async getInstalledApps(consoleId:string): Promise>> {
19 | return (await this.get('/lists/installedApps?deviceId='+consoleId))
20 | }
21 |
22 | async getStorageDevices(consoleId:string): Promise>> {
23 | return (await this.get('/lists/storageDevices?deviceId='+consoleId))
24 | }
25 |
26 | async getConsoleStatus(consoleId:string): Promise> {
27 | return (await this.get('/consoles/'+consoleId))
28 | }
29 |
30 |
31 |
32 |
33 | async powerOn(consoleId?:string) {
34 | return this._sendCommand(consoleId, 'Power', 'WakeUp')
35 | }
36 |
37 | async powerOff(consoleId?:string) {
38 | return this._sendCommand(consoleId, 'Power', 'TurnOff')
39 | }
40 |
41 | async launchOneGuide(consoleId:string) {
42 | return this._sendCommand(consoleId, 'TV', 'ShowGuide')
43 | }
44 |
45 | _sendCommand(consoleId, commandType, command, params?){
46 | if(params == undefined){
47 | params = []
48 | }
49 |
50 | const session_id = Uuid4()
51 | // var session_id = '2c1f6eae-30f1-4b03-81bf-ff11f4e02079'
52 |
53 | const postParams = {
54 | "destination": "Xbox",
55 | "type": commandType,
56 | "command": command,
57 | "sessionId": session_id,
58 | "sourceId": "com.microsoft.smartglass",
59 | "parameters": params,
60 | "linkedXboxId": consoleId,
61 | }
62 |
63 | const postData = JSON.stringify(postParams)
64 |
65 | return this.post('/commands', postData)
66 | }
67 | }
--------------------------------------------------------------------------------
/src/provider/social.ts:
--------------------------------------------------------------------------------
1 | import { HttpResponse } from '../lib/http'
2 | import { SummaryResponse } from '../types/social'
3 |
4 | import BaseProvider from './base'
5 |
6 | export default class SocialProvider extends BaseProvider {
7 | _endpoint = 'social.xboxlive.com'
8 |
9 | async getSummary(): Promise> {
10 | return (await this.get('/users/me/summary'))
11 | }
12 |
13 | async getSummaryByXuid(xuid:string): Promise> {
14 | return (await this.get('/users/xuid('+xuid+')/summary'))
15 | }
16 |
17 | async getSummaryByGamertag(gamertag:string): Promise> {
18 | return (await this.get('/users/gt('+gamertag+')/summary'))
19 | }
20 | }
--------------------------------------------------------------------------------
/src/provider/titlehub.ts:
--------------------------------------------------------------------------------
1 | import { HttpResponse } from '../lib/http'
2 | import { TitleHistoryResponse } from '../types/titlehub'
3 |
4 | import BaseProvider from './base'
5 |
6 | export default class TitlehubProvider extends BaseProvider {
7 | _endpoint = 'titlehub.xboxlive.com'
8 |
9 | async getTitleHistory(xuid:string): Promise> {
10 | const params = [
11 | 'achievement',
12 | 'image',
13 | 'scid',
14 | ]
15 | return (await this.get('/users/xuid('+xuid+')/titles/titlehistory/decoration/'+params.join(',')))
16 | }
17 |
18 | async getTitleId(xuid:string, titleId:string): Promise> {
19 |
20 | const params = [
21 | 'achievement',
22 | 'image',
23 | 'detail',
24 | 'scid',
25 | 'alternateTitleId'
26 | ]
27 | return (await this.get('/users/xuid('+xuid+')/titles/titleid('+titleId+')/decoration/'+params.join(',')))
28 | }
29 | }
--------------------------------------------------------------------------------
/src/provider/userpresence.ts:
--------------------------------------------------------------------------------
1 | import { HttpResponse } from '../lib/http'
2 | import { UserResponse } from '../types/userpresence'
3 |
4 | import BaseProvider from './base'
5 |
6 | export default class UserpresenceProvider extends BaseProvider {
7 | _endpoint = 'userpresence.xboxlive.com'
8 | _headers = {
9 | 'x-xbl-contract-version': '3'
10 | }
11 |
12 | async getCurrentUser(): Promise> {
13 | return (await this.get('/users/me?level=all'))
14 | }
15 |
16 | async getFriends(): Promise> {
17 | return (await this.get('/users/me/groups/People?level=all'))
18 | }
19 |
20 | async getUser(xuid:string): Promise> {
21 | return (await this.get('/users/xuid('+xuid+')?level=all'))
22 | }
23 | }
--------------------------------------------------------------------------------
/src/provider/usersearch.ts:
--------------------------------------------------------------------------------
1 | import { HttpResponse } from '../lib/http'
2 | import { UsersearchResponse } from '../types/usersearch'
3 |
4 | import BaseProvider from './base'
5 |
6 | export default class UsersearchProvider extends BaseProvider {
7 | _endpoint = 'usersearch.xboxlive.com'
8 | _headers = {
9 | 'x-xbl-contract-version': '1'
10 | }
11 |
12 | async searchUsers(query:string): Promise> {
13 | return (await this.get('/suggest?q='+query))
14 | }
15 | }
--------------------------------------------------------------------------------
/src/provider/userstats.ts:
--------------------------------------------------------------------------------
1 | import { HttpResponse } from '../lib/http'
2 | import { UserstatResponse } from '../types/userstats'
3 |
4 | import BaseProvider from './base'
5 |
6 | export default class UserstatsProvider extends BaseProvider {
7 | _endpoint = 'userstats.xboxlive.com'
8 | _headers = {
9 | 'x-xbl-contract-version': '2'
10 | }
11 |
12 | async getUserTitleStats(xuid:string, titleId:string): Promise> {
13 | return (await this.post('/batch',
14 | {
15 | "arrangebyfield":"xuid",
16 | "xuids":[
17 | xuid
18 | ],
19 | "groups":[
20 | {
21 | "name":"Hero",
22 | "titleId": titleId
23 | }
24 | ],
25 | "stats":[
26 | {
27 | "name":"MinutesPlayed",
28 | "titleId": titleId
29 | }
30 | ]
31 | }
32 | ))
33 | }
34 | }
--------------------------------------------------------------------------------
/src/provider/xnotify.ts:
--------------------------------------------------------------------------------
1 | import { HttpResponse } from '../lib/http'
2 | import { StatusResponse } from '../types/xnotify'
3 |
4 | import BaseProvider from './base'
5 |
6 | export default class XnotifyProvider extends BaseProvider {
7 | _endpoint = 'xnotify.xboxlive.com'
8 |
9 | async getLiveStatus(): Promise> {
10 | return (await this.get('/servicestatusv6/GB/en-GB'))
11 | }
12 | }
--------------------------------------------------------------------------------
/src/types/achievements/index.ts:
--------------------------------------------------------------------------------
1 | import { PagingInfo } from '../paging'
2 |
3 | export interface AchievementsResponse {
4 | titles: Title[];
5 | pagingInfo: PagingInfo;
6 | }
7 |
8 | export interface Title {
9 | lastUnlock: Date;
10 | titleId: number;
11 | serviceConfigId: string;
12 | titleType: TitleType;
13 | platform: Platform;
14 | name: string;
15 | earnedAchievements: number;
16 | currentGamerscore: number;
17 | maxGamerscore: number;
18 | }
19 |
20 | export enum Platform {
21 | Durango = "Durango",
22 | WindowsOneCore = "WindowsOneCore",
23 | XboxOne = "XboxOne",
24 | }
25 |
26 | export enum TitleType {
27 | DGame = "DGame",
28 | Game = "Game",
29 | LiveApp = "LiveApp",
30 | }
31 |
32 | // TitleResponse
33 |
34 | export interface AchievementsTitleResponse {
35 | achievements: Achievement[];
36 | pagingInfo: PagingInfo;
37 | }
38 |
39 | export interface Achievement {
40 | id: string;
41 | serviceConfigId: string;
42 | name: string;
43 | titleAssociations: TitleAssociation[];
44 | progressState: ProgressState;
45 | progression: Progression;
46 | mediaAssets: MediaAsset[];
47 | platforms: Platform[];
48 | isSecret: boolean;
49 | description: string;
50 | lockedDescription: string;
51 | productId: string;
52 | achievementType: AchievementType;
53 | participationType: ParticipationType;
54 | timeWindow: null;
55 | rewards: Reward[];
56 | estimatedTime: string;
57 | deeplink: string;
58 | isRevoked: boolean;
59 | }
60 |
61 | export enum AchievementType {
62 | Persistent = "Persistent",
63 | }
64 |
65 | export interface MediaAsset {
66 | name: string;
67 | type: MediaAssetType;
68 | url: string;
69 | }
70 |
71 | export enum MediaAssetType {
72 | Icon = "Icon",
73 | }
74 |
75 | export enum ParticipationType {
76 | Individual = "Individual",
77 | }
78 |
79 | export enum ProgressState {
80 | NotStarted = "NotStarted",
81 | Achieved = "Achieved",
82 | }
83 |
84 | export interface Progression {
85 | requirements: Requirement[];
86 | timeUnlocked: Date;
87 | }
88 |
89 | export interface Requirement {
90 | id: string;
91 | current: null;
92 | target: string;
93 | operationType: OperationType;
94 | valueType: RequirementValueType;
95 | ruleParticipationType: ParticipationType;
96 | }
97 |
98 | export enum OperationType {
99 | Sum = "SUM",
100 | }
101 |
102 | export enum RequirementValueType {
103 | Integer = "Integer",
104 | }
105 |
106 | export interface Reward {
107 | name: null;
108 | description: null;
109 | value: string;
110 | type: RewardType;
111 | mediaAsset: null;
112 | valueType: RewardValueType;
113 | }
114 |
115 | export enum RewardType {
116 | Gamerscore = "Gamerscore",
117 | }
118 |
119 | export enum RewardValueType {
120 | Int = "Int",
121 | }
122 |
123 | export interface TitleAssociation {
124 | name: Name;
125 | id: number;
126 | }
127 |
128 | export enum Name {
129 | Cuphead = "Cuphead",
130 | }
--------------------------------------------------------------------------------
/src/types/catalog/index.ts:
--------------------------------------------------------------------------------
1 | export interface CatalogSearchResponse {
2 | Results: Result[];
3 | TotalResultCount: number;
4 | }
5 |
6 | export interface Result {
7 | ProductFamilyName: ProductFamilyName;
8 | Products: Product[];
9 | }
10 |
11 | export enum ProductFamilyName {
12 | Apps = "Apps",
13 | Games = "Games",
14 | }
15 |
16 | export interface Product {
17 | BackgroundColor: string;
18 | Height: number;
19 | ImageType: ImageType;
20 | Width: number;
21 | PlatformProperties: any[];
22 | Icon: string;
23 | ProductId: string;
24 | Type: Type;
25 | Title: string;
26 | }
27 |
28 | export enum ImageType {
29 | BoxArt = "BoxArt",
30 | Logo = "Logo",
31 | Tile = "Tile",
32 | }
33 |
34 | export enum Type {
35 | Application = "Application",
36 | Durable = "Durable",
37 | Game = "Game",
38 | }
39 |
--------------------------------------------------------------------------------
/src/types/gameclips/index.ts:
--------------------------------------------------------------------------------
1 | import { PagingInfo } from '../paging'
2 |
3 | export interface GameclipsResponse {
4 | values: Value[];
5 | }
6 |
7 | export interface Value {
8 | contentId: string;
9 | contentLocators: ContentLocator[];
10 | contentSegments: ContentSegment[];
11 | creationType: string;
12 | durationInSeconds: number;
13 | expirationDate: Date;
14 | frameRate: number;
15 | greatestMomentId: string;
16 | localId: string;
17 | ownerXuid: number;
18 | resolutionHeight: number;
19 | resolutionWidth: number;
20 | sandboxId: string;
21 | sharedTo: any[];
22 | titleData: string;
23 | titleId: number;
24 | titleName: string;
25 | uploadDate: Date;
26 | uploadLanguage: string;
27 | uploadRegion: string;
28 | uploadTitleId: number;
29 | uploadDeviceType: string;
30 | userCaption: string;
31 | commentCount: number;
32 | likeCount: number;
33 | shareCount: number;
34 | viewCount: number;
35 | contentState: string;
36 | enforcementState: string;
37 | safetyThreshold: string;
38 | sessions: any[];
39 | tournaments: any[];
40 | }
41 |
42 | export interface ContentLocator {
43 | expiration?: Date;
44 | fileSize?: number;
45 | locatorType: string;
46 | uri: string;
47 | }
48 |
49 | export interface ContentSegment {
50 | segmentId: number;
51 | creationType: string;
52 | creatorChannelId: null;
53 | creatorXuid: number;
54 | recordDate: Date;
55 | durationInSeconds: number;
56 | offset: number;
57 | secondaryTitleId: null;
58 | titleId: number;
59 | }
60 |
--------------------------------------------------------------------------------
/src/types/gamepass/index.ts:
--------------------------------------------------------------------------------
1 | export type SiglResponse = [SiglHeader, ...SiglProduct[]];
2 |
3 | export interface SiglHeader {
4 | siglId: string;
5 | title: string;
6 | description: string;
7 | requiresShuffling: string;
8 | imageUrl: string;
9 | }
10 |
11 | export interface SiglProduct {
12 | id: string;
13 | }
14 |
15 |
16 | export interface ProductsResponse {
17 | Products: { [key: string]: Product };
18 | InvalidIds: any[];
19 | }
20 |
21 | export interface Product {
22 | alternateIds: AlternateID[];
23 | productKind: ProductKind;
24 | name: string;
25 | developerName?: string;
26 | publisherName: string;
27 | tileImage: Image;
28 | posterImage: Image;
29 | heroImage?: Image;
30 | releaseDate: Date;
31 | consoleComingSoonDate?: Date;
32 | gamePassStandardComingSoonDate?: Date;
33 | isEAPlay: boolean;
34 | xCloudIsStreamable: boolean;
35 | xCloudSupportsTouch: boolean;
36 | xCloudPrograms?: XCloudProgram[];
37 | capabilities?: Capability[];
38 | categories: Category[];
39 | availablePlatforms: AvailablePlatform[];
40 | isBundle: boolean;
41 | StoreId: string;
42 | pcComingSoonDate?: Date;
43 | eaConsoleComingSoonDate?: Date;
44 | gamePassCoreComingSoonDate?: Date;
45 | consoleCrossGenSiblings?: string[];
46 | gameCatalogExtensionId?: string;
47 | }
48 |
49 | export interface AlternateID {
50 | idType: IDType;
51 | id: string[] | string;
52 | }
53 |
54 | export enum IDType {
55 | Childxboxtitleids = "CHILDXBOXTITLEIDS",
56 | Xboxtitleid = "XBOXTITLEID",
57 | Xcloudtitleid = "XCLOUDTITLEID",
58 | }
59 |
60 | export enum AvailablePlatform {
61 | Hub = "Hub",
62 | MobileDevice = "MobileDevice",
63 | PC = "PC",
64 | XCloud = "XCloud",
65 | XboxOne = "XboxOne",
66 | XboxSeriesX = "XboxSeriesX",
67 | }
68 |
69 | export interface Capability {
70 | id: IDEnum;
71 | name: string;
72 | applicablePlatforms?: ApplicablePlatform[];
73 | }
74 |
75 | export enum ApplicablePlatform {
76 | Desktop = "Desktop",
77 | Xbox = "Xbox",
78 | }
79 |
80 | export enum IDEnum {
81 | Capability4K = "Capability4k",
82 | CapabilityHDR = "CapabilityHDR",
83 | CapabilityVRR = "CapabilityVRR",
84 | CapabilityXboxEnhanced = "CapabilityXboxEnhanced",
85 | ConsoleCrossGen = "ConsoleCrossGen",
86 | ConsoleGen9Optimized = "ConsoleGen9Optimized",
87 | ConsoleKeyboardMouse = "ConsoleKeyboardMouse",
88 | CoopSupportLocal = "CoopSupportLocal",
89 | CoopSupportOnline = "CoopSupportOnline",
90 | DolbyAtmos = "DolbyAtmos",
91 | Dtsx = "DTSX",
92 | FPSBoostEnabledX = "FPSBoostEnabledX",
93 | FPSBoostEnabledXS = "FPSBoostEnabledXS",
94 | GameStreaming = "GameStreaming",
95 | LocalMultiplayer = "LocalMultiplayer",
96 | OnlineMultiplayerWithGold = "OnlineMultiplayerWithGold",
97 | PCGamePad = "PcGamePad",
98 | RayTracing = "RayTracing",
99 | SharedSplitScreen = "SharedSplitScreen",
100 | SinglePlayer = "SinglePlayer",
101 | SpatialSound = "SpatialSound",
102 | The120FPS = "120fps",
103 | The60FPS = "60fps",
104 | XblAchievements = "XblAchievements",
105 | XblCloudSaves = "XblCloudSaves",
106 | XblClubs = "XblClubs",
107 | XblCrossPlatformCoop = "XblCrossPlatformCoop",
108 | XblCrossPlatformMultiPlayer = "XblCrossPlatformMultiPlayer",
109 | XblLocalCoop = "XblLocalCoop",
110 | XblLocalMultiPlayer = "XblLocalMultiPlayer",
111 | XblOnlineCoop = "XblOnlineCoop",
112 | XblOnlineMultiPlayer = "XblOnlineMultiPlayer",
113 | XblPresence = "XblPresence",
114 | XboxLiveCrossGenMP = "XboxLiveCrossGenMP",
115 | Xpa = "XPA",
116 | }
117 |
118 | export enum Category {
119 | ActionAdventure = "Action & adventure",
120 | CardBoard = "Card & board",
121 | Classics = "Classics",
122 | FamilyKids = "Family & kids",
123 | Fighting = "Fighting",
124 | MultiPlayerOnlineBattleArena = "Multi-Player Online Battle Arena",
125 | Other = "Other",
126 | Platformer = "Platformer",
127 | PuzzleTrivia = "Puzzle & trivia",
128 | RacingFlying = "Racing & flying",
129 | RolePlaying = "Role playing",
130 | Shooter = "Shooter",
131 | Simulation = "Simulation",
132 | Sports = "Sports",
133 | Strategy = "Strategy",
134 | Word = "Word",
135 | }
136 |
137 | export interface Image {
138 | uri: string;
139 | height: number;
140 | width: number;
141 | }
142 |
143 | export enum ProductKind {
144 | Game = "GAME",
145 | }
146 |
147 | export enum XCloudProgram {
148 | Byog = "BYOG",
149 | Gpultimate = "GPULTIMATE",
150 | }
151 |
--------------------------------------------------------------------------------
/src/types/messages/index.ts:
--------------------------------------------------------------------------------
1 | // Inbox
2 | export interface InboxResponse {
3 | primary: Primary;
4 | folders: Primary[];
5 | safetySettings: SafetySettings;
6 | }
7 |
8 | export interface Primary {
9 | folder: string;
10 | totalCount: number;
11 | unreadCount: number;
12 | conversations?: Conversation[];
13 | }
14 |
15 | export interface Conversation {
16 | timestamp: Date;
17 | networkId: NetworkID;
18 | type: ConversationTypeEnum;
19 | conversationId: string;
20 | participants: string[];
21 | folder: Folder;
22 | readHorizon: string;
23 | deleteHorizon: string;
24 | lastMessage: LastMessage;
25 | notificationOptions: NotificationOptions;
26 | isRead: boolean;
27 | directMentionHorizon: string;
28 | }
29 |
30 | export enum Folder {
31 | Primary = "Primary",
32 | }
33 |
34 | export interface LastMessage {
35 | contentPayload: ContentPayload;
36 | timestamp: Date;
37 | lastUpdateTimestamp: Date;
38 | type: PurpleType;
39 | networkId: NetworkID;
40 | conversationType: ConversationTypeEnum;
41 | conversationId: string;
42 | owner?: number;
43 | sender: string;
44 | messageId: string;
45 | clock: string;
46 | isDeleted: boolean;
47 | isServerUpdated: boolean;
48 | }
49 |
50 | export interface ContentPayload {
51 | content: Content;
52 | }
53 |
54 | export interface Content {
55 | parts: Part[];
56 | }
57 |
58 | export interface Part {
59 | contentType: ContentType;
60 | version: number;
61 | text?: string;
62 | voiceAttachmentId?: string;
63 | duration?: number;
64 | }
65 |
66 | export enum NotificationOptions {
67 | Smart = "Smart",
68 | }
69 |
70 | export interface SafetySettings {
71 | version: number;
72 | primaryInboxMedia: string;
73 | primaryInboxText: string;
74 | primaryInboxUrl: string;
75 | secondaryInboxMedia: string;
76 | secondaryInboxText: string;
77 | secondaryInboxUrl: string;
78 | canUnobscure: boolean;
79 | }
80 |
81 |
82 |
83 | // Conversations
84 | export interface ConversationResponse {
85 | timestamp: Date;
86 | networkId: NetworkID;
87 | type: ConversationTypeEnum;
88 | conversationId: string;
89 | participants: string[];
90 | readHorizon: string;
91 | deleteHorizon: string;
92 | isRead: boolean;
93 | folder: string;
94 | notificationOptions: string;
95 | messages: Message[];
96 | continuationToken: null;
97 | directMentionHorizon: string;
98 | muted: boolean;
99 | voiceId: string;
100 | voiceRoster: any[];
101 | }
102 |
103 | export interface Message {
104 | contentPayload: ContentPayload;
105 | timestamp: Date;
106 | lastUpdateTimestamp: Date;
107 | type: PurpleType;
108 | networkId: NetworkID;
109 | conversationType: ConversationTypeEnum;
110 | conversationId: string;
111 | sender: string;
112 | messageId: string;
113 | clock: string;
114 | isDeleted: boolean;
115 | isServerUpdated: boolean;
116 | }
117 |
118 | export interface ContentPayload {
119 | content: Content;
120 | }
121 |
122 | export interface Content {
123 | parts: Part[];
124 | }
125 |
126 | export interface Part {
127 | contentType: ContentType;
128 | text?: string;
129 | version: number;
130 | buttonText?: string;
131 | appUri?: null | string;
132 | code?: string;
133 | webUri?: null | string;
134 | }
135 |
136 | export enum ContentType {
137 | Deeplink = "deeplink",
138 | Fivebyfive = "fivebyfive",
139 | Text = "text",
140 | Voice = "voice",
141 | }
142 |
143 | export enum ConversationTypeEnum {
144 | OneToOne = "OneToOne",
145 | }
146 |
147 | export enum NetworkID {
148 | Xbox = "Xbox",
149 | }
150 |
151 | export enum PurpleType {
152 | ContentMessage = "ContentMessage",
153 | }
154 |
--------------------------------------------------------------------------------
/src/types/paging.ts:
--------------------------------------------------------------------------------
1 | export interface PagingInfo {
2 | continuationToken: string;
3 | totalRecords: number;
4 | }
--------------------------------------------------------------------------------
/src/types/people/index.ts:
--------------------------------------------------------------------------------
1 | export interface PeopleResponse {
2 | people: Person[];
3 | recommendationSummary: null;
4 | friendFinderState: null;
5 | }
6 |
7 | export interface Person {
8 | xuid: string;
9 | isFavorite: boolean;
10 | isFollowingCaller: boolean;
11 | isFollowedByCaller: boolean;
12 | isIdentityShared: boolean;
13 | addedDateTimeUtc: Date;
14 | displayName: string;
15 | realName: string;
16 | displayPicRaw: string;
17 | showUserAsAvatar: string;
18 | gamertag: string;
19 | gamerScore: string;
20 | xboxOneRep: XboxOneRep;
21 | presenceState: PresenceState;
22 | presenceText: string;
23 | presenceDevices: null;
24 | isBroadcasting: boolean;
25 | isCloaked: null;
26 | isQuarantined: boolean;
27 | suggestion: null;
28 | recommendation: null;
29 | titleHistory: null;
30 | multiplayerSummary: MultiplayerSummary;
31 | recentPlayer: null;
32 | follower: null;
33 | preferredColor: PreferredColor;
34 | presenceDetails: PresenceDetail[];
35 | titlePresence: null;
36 | titleSummaries: null;
37 | presenceTitleIds: null;
38 | detail: Detail;
39 | communityManagerTitles: null;
40 | socialManager: null;
41 | broadcast: null;
42 | tournamentSummary: null;
43 | avatar: null;
44 | }
45 |
46 | export interface Detail {
47 | accountTier: AccountTier;
48 | bio: string;
49 | isVerified: boolean;
50 | location: string;
51 | tenure: string;
52 | watermarks: string[];
53 | blocked: boolean;
54 | mute: boolean;
55 | followerCount: number;
56 | followingCount: number;
57 | }
58 |
59 | export enum AccountTier {
60 | Gold = "Gold",
61 | Silver = "Silver",
62 | }
63 |
64 | export interface MultiplayerSummary {
65 | InMultiplayerSession: number;
66 | InParty: number;
67 | }
68 |
69 | export interface PreferredColor {
70 | primaryColor: string;
71 | secondaryColor: string;
72 | tertiaryColor: string;
73 | }
74 |
75 | export interface PresenceDetail {
76 | IsBroadcasting: boolean;
77 | Device: string;
78 | PresenceText: string;
79 | State: State;
80 | TitleId: string;
81 | TitleType: null;
82 | IsPrimary: boolean;
83 | IsGame: boolean;
84 | RichPresenceText: null | string;
85 | }
86 |
87 | export enum State {
88 | Active = "Active",
89 | LastSeen = "LastSeen",
90 | }
91 |
92 | export enum PresenceState {
93 | Offline = "Offline",
94 | Online = "Online",
95 | }
96 |
97 | export enum XboxOneRep {
98 | GoodPlayer = "GoodPlayer",
99 | }
100 |
--------------------------------------------------------------------------------
/src/types/pins/index.ts:
--------------------------------------------------------------------------------
1 | export interface PinsResponse {
2 | ImpressionId: string;
3 | ListItems: ListItem[];
4 | ListMetadata: ListMetadata;
5 | }
6 |
7 | export interface ListItem {
8 | DateAdded: string;
9 | DateModified: string;
10 | Index: number;
11 | KValue: number;
12 | Item: Item;
13 | }
14 |
15 | export interface Item {
16 | ContentType: ContentType;
17 | ItemId: string;
18 | Title: string;
19 | DeviceType: DeviceType;
20 | Provider: null;
21 | ProviderId: null;
22 | }
23 |
24 | export enum ContentType {
25 | DApp = "DApp",
26 | DGame = "DGame",
27 | }
28 |
29 | export enum DeviceType {
30 | XboxOne = "XboxOne",
31 | }
32 |
33 | export interface ListMetadata {
34 | ListTitle: string;
35 | ListVersion: number;
36 | ListCount: number;
37 | AllowDuplicates: boolean;
38 | MaxListSize: number;
39 | AccessSetting: string;
40 | }
41 |
--------------------------------------------------------------------------------
/src/types/profile/index.ts:
--------------------------------------------------------------------------------
1 | export interface ProfileResponse {
2 | profileUsers: ProfileUser[];
3 | }
4 |
5 | export interface ProfileUser {
6 | id: string;
7 | hostId: string;
8 | settings: Setting[];
9 | isSponsoredUser: boolean;
10 | }
11 |
12 | export interface Setting {
13 | id: string;
14 | value: string;
15 | }
16 |
--------------------------------------------------------------------------------
/src/types/screenshots/index.ts:
--------------------------------------------------------------------------------
1 | export interface ScreenshotsResponse {
2 | values: Value[];
3 | }
4 |
5 | export interface Value {
6 | captureDate: Date;
7 | contentId: string;
8 | contentLocators: ContentLocator[];
9 | CreationType: string;
10 | expirationDate: Date;
11 | localId: string;
12 | ownerXuid: number;
13 | resolutionHeight: number;
14 | resolutionWidth: number;
15 | sandboxId: string;
16 | sharedTo: any[];
17 | titleId: number;
18 | titleName: string;
19 | dateUploaded: Date;
20 | uploadLanguage: string;
21 | uploadRegion: string;
22 | uploadTitleId: number;
23 | uploadDeviceType: string;
24 | commentCount: number;
25 | likeCount: number;
26 | shareCount: number;
27 | viewCount: number;
28 | contentState: string;
29 | enforcementState: string;
30 | safetyThreshold: string;
31 | sessions: any[];
32 | tournaments: any[];
33 | }
34 |
35 | export interface ContentLocator {
36 | fileSize?: number;
37 | locatorType: string;
38 | uri: string;
39 | }
40 |
--------------------------------------------------------------------------------
/src/types/smartglass/index.ts:
--------------------------------------------------------------------------------
1 | export interface SmartglassResponse {
2 | status: Status;
3 | result: T[];
4 | agentUserId: null;
5 | }
6 |
7 | export interface Console {
8 | id: string;
9 | name: string;
10 | locale: string;
11 | region: string;
12 | consoleType: string;
13 | powerState: string;
14 | digitalAssistantRemoteControlEnabled: boolean;
15 | remoteManagementEnabled: boolean;
16 | consoleStreamingEnabled: boolean;
17 | wirelessWarning: boolean;
18 | outOfHomeWarning: boolean;
19 | storageDevices: StorageDevice[];
20 | }
21 |
22 | export interface App {
23 | oneStoreProductId: null | string;
24 | titleId: number;
25 | aumid: null | string;
26 | lastActiveTime: Date | null;
27 | isGame: boolean;
28 | name: string;
29 | contentType: ContentType;
30 | instanceId: string;
31 | storageDeviceId: string;
32 | uniqueId: string;
33 | legacyProductId: null | string;
34 | version: number;
35 | sizeInBytes: number;
36 | installTime: Date;
37 | updateTime: Date | null;
38 | parentId: string | null;
39 | }
40 |
41 | export interface StorageDevice {
42 | storageDeviceId: string;
43 | storageDeviceName: string;
44 | isDefault: boolean;
45 | freeSpaceBytes: number;
46 | totalSpaceBytes: number;
47 | isGen9Compatible: null;
48 | }
49 |
50 | export interface Status {
51 | errorCode: string;
52 | errorMessage: null;
53 | }
54 |
55 | export enum ContentType {
56 | App = "App",
57 | Dlc = "Dlc",
58 | Game = "Game",
59 | }
60 |
61 | export interface ConsoleStatus {
62 | status: Status;
63 | id: string;
64 | name: string;
65 | locale: string;
66 | region: string;
67 | consoleType: string;
68 | powerState: string;
69 | playbackState: string;
70 | loginState: null;
71 | focusAppAumid: string;
72 | isTvConfigured: boolean;
73 | digitalAssistantRemoteControlEnabled: boolean;
74 | consoleStreamingEnabled: boolean;
75 | remoteManagementEnabled: boolean;
76 | }
--------------------------------------------------------------------------------
/src/types/social/index.ts:
--------------------------------------------------------------------------------
1 | export interface SummaryResponse {
2 | targetFollowingCount: number;
3 | targetFollowerCount: number;
4 | isCallerFollowingTarget: boolean;
5 | isTargetFollowingCaller: boolean;
6 | hasCallerMarkedTargetAsFavorite: boolean;
7 | hasCallerMarkedTargetAsIdentityShared: boolean;
8 | hasCallerMarkedTargetAsKnown: boolean;
9 | legacyFriendStatus: string;
10 | availablePeopleSlots: number;
11 | isFriend: boolean;
12 | availableFollowingSlots: number;
13 | }
14 |
--------------------------------------------------------------------------------
/src/types/titlehub/index.ts:
--------------------------------------------------------------------------------
1 | export interface TitleHistoryResponse {
2 | xuid: string;
3 | titles: Title[];
4 | }
5 |
6 | export interface Title {
7 | titleId: string;
8 | pfn: null | string;
9 | bingId: null | string;
10 | serviceConfigId?: string;
11 | windowsPhoneProductId: null;
12 | name: string;
13 | type: TitleType;
14 | devices: Device[];
15 | displayImage: null | string;
16 | mediaItemType: MediaItemType;
17 | modernTitleId: null | string;
18 | isBundle: boolean;
19 | achievement: Achievement;
20 | stats: null;
21 | gamePass: null;
22 | images: Image[];
23 | titleHistory: TitleHistory;
24 | titleRecord: null;
25 | detail: null;
26 | friendsWhoPlayed: null;
27 | alternateTitleIds: null;
28 | contentBoards: null;
29 | xboxLiveTier: XboxLiveTier;
30 | isStreamable?: boolean;
31 | }
32 |
33 | export interface Achievement {
34 | currentAchievements: number;
35 | totalAchievements: number;
36 | currentGamerscore: number;
37 | totalGamerscore: number;
38 | progressPercentage: number;
39 | sourceVersion: number;
40 | }
41 |
42 | export enum Device {
43 | IOS = "iOS",
44 | Mobile = "Mobile",
45 | NintendoSwitch = "Nintendo Switch",
46 | PC = "PC",
47 | Win32 = "Win32",
48 | Xbox360 = "Xbox360",
49 | XboxOne = "XboxOne",
50 | XboxSeries = "XboxSeries",
51 | }
52 |
53 | export interface Image {
54 | url: string;
55 | type: ImageType;
56 | caption: null | string;
57 | }
58 |
59 | export enum ImageType {
60 | BoxArt = "BoxArt",
61 | BrandedKeyArt = "BrandedKeyArt",
62 | FeaturePromotionalSquareArt = "FeaturePromotionalSquareArt",
63 | Hero = "Hero",
64 | Image = "Image",
65 | ImageGallery = "ImageGallery",
66 | Logo = "Logo",
67 | Poster = "Poster",
68 | Screenshot = "Screenshot",
69 | SellImage = "SellImage",
70 | SuperHeroArt = "SuperHeroArt",
71 | Thumbnail = "Thumbnail",
72 | Tile = "Tile",
73 | TitledHeroArt = "TitledHeroArt",
74 | WideBackgroundImage = "WideBackgroundImage",
75 | }
76 |
77 | export enum MediaItemType {
78 | Application = "Application",
79 | Xbox360Game = "Xbox360Game",
80 | XboxArcadeGame = "XboxArcadeGame",
81 | XboxOriginalGame = "XboxOriginalGame",
82 | }
83 |
84 | export interface TitleHistory {
85 | lastTimePlayed: Date;
86 | visible: boolean;
87 | canHide: boolean;
88 | }
89 |
90 | export enum TitleType {
91 | Game = "Game",
92 | }
93 |
94 | export enum XboxLiveTier {
95 | Full = "Full",
96 | None = "None",
97 | Open = "Open",
98 | }
99 |
--------------------------------------------------------------------------------
/src/types/userpresence/index.ts:
--------------------------------------------------------------------------------
1 | export interface UserResponse {
2 | xuid: string;
3 | state: State;
4 | lastSeen?: LastSeen;
5 | devices?: Device[];
6 | }
7 |
8 | export interface Device {
9 | type: string;
10 | titles: Title[];
11 | }
12 |
13 | export interface Title {
14 | id: string;
15 | name: string;
16 | placement: string;
17 | state: string;
18 | lastModified: Date;
19 | activity?: Activity;
20 | }
21 |
22 | export interface Activity {
23 | richPresence: string;
24 | }
25 |
26 | export interface LastSeen {
27 | deviceType: string;
28 | titleId: string;
29 | titleName: string;
30 | timestamp: Date;
31 | }
32 |
33 | export enum State {
34 | Offline = "Offline",
35 | Online = "Online",
36 | }
37 |
--------------------------------------------------------------------------------
/src/types/usersearch/index.ts:
--------------------------------------------------------------------------------
1 | export interface UsersearchResponse {
2 | results: Result[];
3 | }
4 |
5 | export interface Result {
6 | text: null;
7 | result: null;
8 | }
9 |
--------------------------------------------------------------------------------
/src/types/userstats/index.ts:
--------------------------------------------------------------------------------
1 | export interface UserstatResponse {
2 | groups: Group[];
3 | statlistscollection: Userstat[];
4 | }
5 |
6 | export interface Group {
7 | name: string;
8 | titleid: string;
9 | statlistscollection: GroupStatlistscollection[];
10 | }
11 |
12 | export interface GroupStatlistscollection {
13 | arrangebyfield: string;
14 | arrangebyfieldid: string;
15 | stats: Userstat[];
16 | }
17 |
18 |
19 |
20 | export interface Userstat {
21 | groupproperties: Groupproperties;
22 | xuid: string;
23 | scid: string;
24 | titleid?: string;
25 | name: string;
26 | type: string;
27 | value: string;
28 | properties: Properties;
29 | }
30 |
31 | export interface Groupproperties {
32 | Ordinal?: string;
33 | SortOrder?: string;
34 | DisplayName?: string;
35 | DisplayFormat?: string;
36 | DisplaySemantic?: string;
37 | }
38 |
39 | export interface Properties {
40 | DisplayName?: string;
41 | }
--------------------------------------------------------------------------------
/src/types/xnotify/index.ts:
--------------------------------------------------------------------------------
1 | export interface StatusResponse {
2 | Status: StatusResponseStatus;
3 | CoreServices: CoreService[];
4 | Titles: CoreService[];
5 | }
6 |
7 | export interface CoreService {
8 | Id: number;
9 | Name: string;
10 | Status: Status;
11 | Scenarios: Scenario[];
12 | }
13 |
14 | export interface Scenario {
15 | Id: number;
16 | Status: Status;
17 | Name: string;
18 | Devices: Status[];
19 | Incidents: any[];
20 | Description: string;
21 | }
22 |
23 | export interface Status {
24 | Id: number;
25 | Name: State;
26 | }
27 |
28 | export enum State {
29 | AndroidDevices = "Android devices",
30 | AppleDevices = "Apple devices",
31 | BackwardCompatibility = "Backward compatibility",
32 | CloudGaming = "Cloud gaming",
33 | None = "None",
34 | SmartTV = "Smart TV",
35 | WebServices = "Web services",
36 | Xbox360 = "Xbox 360",
37 | XboxOnWindows = "Xbox on Windows",
38 | XboxOne = "Xbox One",
39 | XboxOneS = "Xbox One S",
40 | XboxOneX = "Xbox One X",
41 | XboxSeriesS = "Xbox Series S",
42 | XboxSeriesX = "Xbox Series X",
43 | }
44 |
45 | export interface StatusResponseStatus {
46 | Overall: Overall;
47 | SelectedScenarios: Overall;
48 | }
49 |
50 | export interface Overall {
51 | State: State;
52 | Id: number;
53 | LastUpdated: Date;
54 | }
55 |
--------------------------------------------------------------------------------
/tests/lib.ts:
--------------------------------------------------------------------------------
1 | import assert from 'assert'
2 | import XboxWebApi from '../src/lib'
3 |
4 | describe('XboxWebApi', function () {
5 | describe('#constructor()', function () {
6 | it('should be able to construct without error', function (done) {
7 | const client = new XboxWebApi({
8 | uhs: 'uhs',
9 | token: '',
10 | })
11 |
12 | assert.equal(client.constructor.name, 'XboxWebApi')
13 |
14 | done();
15 | });
16 | });
17 | });
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2021",
4 | "module": "commonjs",
5 | "lib": [
6 | "es2015",
7 | "es2016",
8 | "es2017",
9 | "es2018",
10 | "DOM"
11 | ],
12 | "declaration": true,
13 | "declarationMap": true,
14 | "sourceMap": true,
15 | "outDir": "./dist",
16 | "rootDir": "./src/",
17 | "strict": true,
18 | "esModuleInterop": true,
19 | "noImplicitAny": false,
20 | "resolveJsonModule": true
21 | },
22 | "include": [
23 | "src/"
24 | ],
25 | "exclude": [
26 | "**/*.spec.ts"
27 | ]
28 | }
--------------------------------------------------------------------------------