halo-infinite-api 4.0.6 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/authentication/xbox-authentication-client.d.ts +3 -2
- package/dist/authentication/xbox-authentication-client.js +8 -7
- package/dist/authentication/xbox-authentication-client.js.map +1 -1
- package/dist/core/halo-infinite-client.d.ts +2 -1
- package/dist/core/halo-infinite-client.js +5 -2
- package/dist/core/halo-infinite-client.js.map +1 -1
- package/dist/core/token-providers/auto-token-provider.d.ts +13 -0
- package/dist/core/token-providers/auto-token-provider.js +34 -0
- package/dist/core/token-providers/auto-token-provider.js.map +1 -0
- package/dist/core/token-providers/spartan-token-providers/auto-xsts-spartan-token-provider.d.ts +11 -0
- package/dist/core/token-providers/spartan-token-providers/auto-xsts-spartan-token-provider.js +29 -0
- package/dist/core/token-providers/spartan-token-providers/auto-xsts-spartan-token-provider.js.map +1 -0
- package/dist/core/token-providers/spartan-token-providers/index.d.ts +3 -0
- package/dist/core/token-providers/spartan-token-providers/index.js +2 -0
- package/dist/core/token-providers/spartan-token-providers/index.js.map +1 -0
- package/dist/core/token-providers/spartan-token-providers/static-xsts-ticket-token-spartan-token-provider.d.ts +12 -0
- package/dist/core/token-providers/spartan-token-providers/static-xsts-ticket-token-spartan-token-provider.js +25 -0
- package/dist/core/token-providers/spartan-token-providers/static-xsts-ticket-token-spartan-token-provider.js.map +1 -0
- package/dist/core/token-providers/xbox-token-provider.d.ts +3 -0
- package/dist/core/token-providers/xbox-token-provider.js +2 -0
- package/dist/core/token-providers/xbox-token-provider.js.map +1 -0
- package/dist/core/xbox-client.d.ts +13 -0
- package/dist/core/xbox-client.js +28 -0
- package/dist/core/xbox-client.js.map +1 -0
- package/dist/index.d.ts +4 -3
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/models/halo-infinite/game-variant-category.d.ts +3 -1
- package/dist/models/halo-infinite/game-variant-category.js +2 -0
- package/dist/models/halo-infinite/game-variant-category.js.map +1 -1
- package/dist/models/halo-infinite/stats.d.ts +46 -4
- package/dist/util/keyed-expiry-token-cache.d.ts +13 -0
- package/dist/util/keyed-expiry-token-cache.js +74 -0
- package/dist/util/keyed-expiry-token-cache.js.map +1 -0
- package/package.json +1 -1
- package/src/authentication/xbox-authentication-client.ts +18 -12
- package/src/core/halo-infinite-client.ts +15 -3
- package/src/core/{spartan-token-providers/auto-xsts-spartan-token-provider.ts → token-providers/auto-token-provider.ts} +15 -3
- package/src/core/{spartan-token-providers → token-providers/spartan-token-providers}/static-xsts-ticket-token-spartan-token-provider.ts +3 -3
- package/src/core/token-providers/xbox-token-provider.ts +3 -0
- package/src/core/xbox-client.ts +48 -0
- package/src/index.ts +7 -3
- package/src/models/halo-infinite/game-variant-category.ts +2 -0
- package/src/models/halo-infinite/stats.ts +51 -4
- package/src/util/keyed-expiry-token-cache.ts +90 -0
- /package/src/core/{spartan-token-providers → token-providers/spartan-token-providers}/index.ts +0 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { DateTime } from "luxon";
|
|
2
2
|
import { TokenPersister } from "../core/token-persisters";
|
|
3
|
+
import { XboxTicket } from "../models/xbox-ticket";
|
|
3
4
|
export declare enum RelyingParty {
|
|
4
5
|
Xbox = "http://xboxlive.com",
|
|
5
6
|
Halo = "https://prod.xsts.halowaypoint.com/"
|
|
@@ -15,7 +16,7 @@ export declare class XboxAuthenticationClient {
|
|
|
15
16
|
private xstsTicketCache;
|
|
16
17
|
private readonly httpClient;
|
|
17
18
|
constructor(tokenPersister?: TokenPersister | undefined);
|
|
18
|
-
getXstsTicket(getOauth2AccessToken: () => Promise<string
|
|
19
|
+
getXstsTicket(getOauth2AccessToken: () => Promise<string>, relyingParty: RelyingParty): Promise<{
|
|
19
20
|
expiresAt: DateTime;
|
|
20
21
|
IssueInstant: string;
|
|
21
22
|
NotAfter: string;
|
|
@@ -32,5 +33,5 @@ export declare class XboxAuthenticationClient {
|
|
|
32
33
|
}];
|
|
33
34
|
};
|
|
34
35
|
}>;
|
|
35
|
-
getXboxLiveV3Token: (
|
|
36
|
+
getXboxLiveV3Token: (xboxTicket: XboxTicket) => string;
|
|
36
37
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import axios from "axios";
|
|
2
2
|
import { DateTime } from "luxon";
|
|
3
|
+
import { KeyedExpiryTokenCache } from "../util/keyed-expiry-token-cache";
|
|
3
4
|
import { ExpiryTokenCache } from "../util/expiry-token-cache";
|
|
4
5
|
export var RelyingParty;
|
|
5
6
|
(function (RelyingParty) {
|
|
@@ -31,7 +32,7 @@ export class XboxAuthenticationClient {
|
|
|
31
32
|
await this.tokenPersister?.save("xbox.userToken", result);
|
|
32
33
|
return result;
|
|
33
34
|
}, async () => (await this.tokenPersister?.load("xbox.userToken")) ?? null);
|
|
34
|
-
xstsTicketCache = new
|
|
35
|
+
xstsTicketCache = new KeyedExpiryTokenCache(async (relyingParty, userToken) => {
|
|
35
36
|
const response = await this.httpClient.post("https://xsts.auth.xboxlive.com/xsts/authorize", {
|
|
36
37
|
RelyingParty: relyingParty,
|
|
37
38
|
TokenType: "JWT",
|
|
@@ -50,16 +51,16 @@ export class XboxAuthenticationClient {
|
|
|
50
51
|
...response.data,
|
|
51
52
|
expiresAt: DateTime.fromISO(response.data.NotAfter),
|
|
52
53
|
};
|
|
53
|
-
await this.tokenPersister?.save("xbox.xstsTicket", result);
|
|
54
|
+
await this.tokenPersister?.save("xbox.xstsTicket." + relyingParty, result);
|
|
54
55
|
return result;
|
|
55
|
-
}, async () => (await this.tokenPersister?.load("xbox.xstsTicket")) ?? null);
|
|
56
|
+
}, async (relyingParty) => (await this.tokenPersister?.load("xbox.xstsTicket." + relyingParty)) ?? null);
|
|
56
57
|
httpClient;
|
|
57
58
|
constructor(tokenPersister) {
|
|
58
59
|
this.tokenPersister = tokenPersister;
|
|
59
60
|
this.httpClient = axios.create();
|
|
60
61
|
}
|
|
61
|
-
async getXstsTicket(getOauth2AccessToken) {
|
|
62
|
-
let xstsTicket = await this.xstsTicketCache.getExistingToken();
|
|
62
|
+
async getXstsTicket(getOauth2AccessToken, relyingParty) {
|
|
63
|
+
let xstsTicket = await this.xstsTicketCache.getExistingToken(relyingParty);
|
|
63
64
|
if (!xstsTicket) {
|
|
64
65
|
let userToken = await this.userTokenCache.getExistingToken();
|
|
65
66
|
if (!userToken) {
|
|
@@ -67,10 +68,10 @@ export class XboxAuthenticationClient {
|
|
|
67
68
|
// worrying if it is expired.
|
|
68
69
|
userToken = await this.userTokenCache.getToken(await getOauth2AccessToken());
|
|
69
70
|
}
|
|
70
|
-
xstsTicket = await this.xstsTicketCache.getToken(userToken.Token
|
|
71
|
+
xstsTicket = await this.xstsTicketCache.getToken(relyingParty, userToken.Token);
|
|
71
72
|
}
|
|
72
73
|
return xstsTicket;
|
|
73
74
|
}
|
|
74
|
-
getXboxLiveV3Token = (
|
|
75
|
+
getXboxLiveV3Token = (xboxTicket) => `XBL3.0 x=${xboxTicket.DisplayClaims.xui[0].uhs};${xboxTicket.Token}`;
|
|
75
76
|
}
|
|
76
77
|
//# sourceMappingURL=xbox-authentication-client.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"xbox-authentication-client.js","sourceRoot":"","sources":["../../src/authentication/xbox-authentication-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAwB,MAAM,OAAO,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"xbox-authentication-client.js","sourceRoot":"","sources":["../../src/authentication/xbox-authentication-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,7 +8,7 @@ import { Playlist } from "../models/halo-infinite/playlist";
|
|
|
8
8
|
import { PlaylistCsrContainer } from "../models/halo-infinite/playlist-csr-container";
|
|
9
9
|
import { ServiceRecord } from "../models/halo-infinite/service-record";
|
|
10
10
|
import { UserInfo } from "../models/halo-infinite/user-info";
|
|
11
|
-
import { SpartanTokenProvider } from "./spartan-token-providers";
|
|
11
|
+
import { SpartanTokenProvider } from "./token-providers/spartan-token-providers";
|
|
12
12
|
interface ResultContainer<TValue> {
|
|
13
13
|
Id: string;
|
|
14
14
|
ResultCode: 0 | 1;
|
|
@@ -47,6 +47,7 @@ export declare class HaloInfiniteClient {
|
|
|
47
47
|
*/
|
|
48
48
|
getPlaylist: (playlistId: string) => Promise<Playlist>;
|
|
49
49
|
getPlayerMatches: (playerXuid: string, type?: MatchType, count?: number, start?: number) => Promise<PlayerMatchHistory[]>;
|
|
50
|
+
getPlayerServiceRecord(playerXuid: string, type?: MatchType): Promise<ServiceRecord>;
|
|
50
51
|
getMatchStats: (matchId: string) => Promise<MatchStats<import("..").GameVariantCategory>>;
|
|
51
52
|
getMatchSkill: (matchId: string, playerIds: string[]) => Promise<ResultContainer<MatchSkill<0>>[]>;
|
|
52
53
|
/** Gets authoring metadata about a specific asset. */
|
|
@@ -9,7 +9,7 @@ const assetKindUrlMap = {
|
|
|
9
9
|
[AssetKind.Playlist]: "Playlists",
|
|
10
10
|
};
|
|
11
11
|
function wrapPlayerId(playerId) {
|
|
12
|
-
if (/^\w
|
|
12
|
+
if (/^\w+\(\d+\)/.test(playerId)) {
|
|
13
13
|
return playerId;
|
|
14
14
|
}
|
|
15
15
|
else {
|
|
@@ -92,8 +92,11 @@ export class HaloInfiniteClient {
|
|
|
92
92
|
if (type !== MatchType.All) {
|
|
93
93
|
params.type = type.toString();
|
|
94
94
|
}
|
|
95
|
-
return this.executePaginationRequest(count, start, params, `https://${HaloCoreEndpoints.StatsOrigin}.${HaloCoreEndpoints.ServiceDomain}/hi/players
|
|
95
|
+
return this.executePaginationRequest(count, start, params, `https://${HaloCoreEndpoints.StatsOrigin}.${HaloCoreEndpoints.ServiceDomain}/hi/players/${wrapPlayerId(playerXuid)}/matches`, "get");
|
|
96
96
|
};
|
|
97
|
+
getPlayerServiceRecord(playerXuid, type = MatchType.All) {
|
|
98
|
+
return this.executeRequest(`https://${HaloCoreEndpoints.StatsOrigin}.${HaloCoreEndpoints.ServiceDomain}/hi/players/${wrapPlayerId(playerXuid)}/Matchmade/servicerecord`, "get");
|
|
99
|
+
}
|
|
97
100
|
getMatchStats = (matchId) => this.executeRequest(`https://${HaloCoreEndpoints.StatsOrigin}.${HaloCoreEndpoints.ServiceDomain}/hi/matches/${matchId}/stats`, "get");
|
|
98
101
|
getMatchSkill = async (matchId, playerIds) => {
|
|
99
102
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"halo-infinite-client.js","sourceRoot":"","sources":["../../src/core/halo-infinite-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,UAAU,EAAE,YAAY,EAAU,MAAM,OAAO,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAMrE,OAAO,EAAE,SAAS,EAAE,MAAM,oCAAoC,CAAC;AAG/D,OAAO,EAAE,SAAS,EAAE,MAAM,oCAAoC,CAAC;AAM/D,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AA0B1D,MAAM,eAAe,GAAG;IACtB,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,MAAM;IACvB,CAAC,SAAS,CAAC,cAAc,CAAC,EAAE,iBAAiB;IAC7C,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,WAAW;CAGlC,CAAC;AAEF,SAAS,YAAY,CAAC,QAAgB;IACpC,IAAI,
|
|
1
|
+
{"version":3,"file":"halo-infinite-client.js","sourceRoot":"","sources":["../../src/core/halo-infinite-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { TokenPersister } from "../token-persisters";
|
|
2
|
+
import { SpartanTokenProvider } from "./spartan-token-providers";
|
|
3
|
+
import { XboxTokenProvider } from "./xbox-token-provider";
|
|
4
|
+
/**
|
|
5
|
+
* A SpartanTokenProvider that fetches both the Xbox and Halo tokens in the same
|
|
6
|
+
* process. This is useful for applications that do not need to contend with
|
|
7
|
+
* CORS restrictions.
|
|
8
|
+
*/
|
|
9
|
+
export declare class AutoTokenProvider implements SpartanTokenProvider, XboxTokenProvider {
|
|
10
|
+
readonly getSpartanToken: () => Promise<string>;
|
|
11
|
+
readonly getXboxLiveV3Token: () => Promise<string>;
|
|
12
|
+
constructor(getOauth2AccessToken: () => Promise<string>, tokenPersister?: TokenPersister);
|
|
13
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { RelyingParty, XboxAuthenticationClient, } from "../../authentication/xbox-authentication-client";
|
|
2
|
+
import { HaloAuthenticationClient } from "../../authentication/halo-authentication-client";
|
|
3
|
+
import { inMemoryTokenPersister } from "../token-persisters/in-memory-token-persister";
|
|
4
|
+
/**
|
|
5
|
+
* A SpartanTokenProvider that fetches both the Xbox and Halo tokens in the same
|
|
6
|
+
* process. This is useful for applications that do not need to contend with
|
|
7
|
+
* CORS restrictions.
|
|
8
|
+
*/
|
|
9
|
+
export class AutoTokenProvider {
|
|
10
|
+
getSpartanToken;
|
|
11
|
+
getXboxLiveV3Token;
|
|
12
|
+
constructor(getOauth2AccessToken, tokenPersister) {
|
|
13
|
+
let actualTokenPersister;
|
|
14
|
+
if (tokenPersister) {
|
|
15
|
+
actualTokenPersister = tokenPersister;
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
actualTokenPersister = inMemoryTokenPersister;
|
|
19
|
+
}
|
|
20
|
+
const xboxAuthClient = new XboxAuthenticationClient(tokenPersister);
|
|
21
|
+
const haloAuthClient = new HaloAuthenticationClient(async () => {
|
|
22
|
+
const xstsTicket = await xboxAuthClient.getXstsTicket(getOauth2AccessToken, RelyingParty.Halo);
|
|
23
|
+
return xstsTicket.Token;
|
|
24
|
+
}, async () => await actualTokenPersister.load("halo.authToken"), async (token) => {
|
|
25
|
+
await actualTokenPersister.save("halo.authToken", token);
|
|
26
|
+
});
|
|
27
|
+
this.getSpartanToken = () => haloAuthClient.getSpartanToken();
|
|
28
|
+
this.getXboxLiveV3Token = async () => {
|
|
29
|
+
const xstsTicket = await xboxAuthClient.getXstsTicket(getOauth2AccessToken, RelyingParty.Xbox);
|
|
30
|
+
return xboxAuthClient.getXboxLiveV3Token(xstsTicket);
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=auto-token-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-token-provider.js","sourceRoot":"","sources":["../../../src/core/token-providers/auto-token-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,wBAAwB,GACzB,MAAM,iDAAiD,CAAC;AAEzD,OAAO,EAAE,wBAAwB,EAAE,MAAM,iDAAiD,CAAC;AAE3F,OAAO,EAAE,sBAAsB,EAAE,MAAM,+CAA+C,CAAC;AAGvF;;;;GAIG;AACH,MAAM,OAAO,iBAAiB;IAGZ,eAAe,CAAwB;IACvC,kBAAkB,CAAwB;IAE1D,YACE,oBAA2C,EAC3C,cAA+B;QAE/B,IAAI,oBAAoC,CAAC;QACzC,IAAI,cAAc,EAAE;YAClB,oBAAoB,GAAG,cAAc,CAAC;SACvC;aAAM;YACL,oBAAoB,GAAG,sBAAsB,CAAC;SAC/C;QACD,MAAM,cAAc,GAAG,IAAI,wBAAwB,CAAC,cAAc,CAAC,CAAC;QACpE,MAAM,cAAc,GAAG,IAAI,wBAAwB,CACjD,KAAK,IAAI,EAAE;YACT,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,aAAa,CACnD,oBAAoB,EACpB,YAAY,CAAC,IAAI,CAClB,CAAC;YACF,OAAO,UAAU,CAAC,KAAK,CAAC;QAC1B,CAAC,EACD,KAAK,IAAI,EAAE,CAAC,MAAM,oBAAoB,CAAC,IAAI,CAAC,gBAAgB,CAAC,EAC7D,KAAK,EAAE,KAAK,EAAE,EAAE;YACd,MAAM,oBAAoB,CAAC,IAAI,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;QAC3D,CAAC,CACF,CAAC;QAEF,IAAI,CAAC,eAAe,GAAG,GAAG,EAAE,CAAC,cAAc,CAAC,eAAe,EAAE,CAAC;QAC9D,IAAI,CAAC,kBAAkB,GAAG,KAAK,IAAI,EAAE;YACnC,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,aAAa,CACnD,oBAAoB,EACpB,YAAY,CAAC,IAAI,CAClB,CAAC;YACF,OAAO,cAAc,CAAC,kBAAkB,CAAC,UAAU,CAAC,CAAC;QACvD,CAAC,CAAC;IACJ,CAAC;CACF"}
|
package/dist/core/token-providers/spartan-token-providers/auto-xsts-spartan-token-provider.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { TokenPersister } from "../../token-persisters";
|
|
2
|
+
import { SpartanTokenProvider } from ".";
|
|
3
|
+
/**
|
|
4
|
+
* A SpartanTokenProvider that fetches both the Xbox and Halo tokens in the same
|
|
5
|
+
* process. This is useful for applications that do not need to contend with
|
|
6
|
+
* CORS restrictions.
|
|
7
|
+
*/
|
|
8
|
+
export declare class AutoXstsSpartanTokenProvider implements SpartanTokenProvider {
|
|
9
|
+
readonly getSpartanToken: () => Promise<string>;
|
|
10
|
+
constructor(getOauth2AccessToken: () => Promise<string>, tokenPersister?: TokenPersister);
|
|
11
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { XboxAuthenticationClient, } from "../../../authentication/xbox-authentication-client";
|
|
2
|
+
import { HaloAuthenticationClient } from "../../../authentication/halo-authentication-client";
|
|
3
|
+
import { inMemoryTokenPersister } from "../../token-persisters/in-memory-token-persister";
|
|
4
|
+
/**
|
|
5
|
+
* A SpartanTokenProvider that fetches both the Xbox and Halo tokens in the same
|
|
6
|
+
* process. This is useful for applications that do not need to contend with
|
|
7
|
+
* CORS restrictions.
|
|
8
|
+
*/
|
|
9
|
+
export class AutoXstsSpartanTokenProvider {
|
|
10
|
+
getSpartanToken;
|
|
11
|
+
constructor(getOauth2AccessToken, tokenPersister) {
|
|
12
|
+
let actualTokenPersister;
|
|
13
|
+
if (tokenPersister) {
|
|
14
|
+
actualTokenPersister = tokenPersister;
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
actualTokenPersister = inMemoryTokenPersister;
|
|
18
|
+
}
|
|
19
|
+
const xboxAuthClient = new XboxAuthenticationClient(tokenPersister);
|
|
20
|
+
const haloAuthClient = new HaloAuthenticationClient(async () => {
|
|
21
|
+
const xstsTicket = await xboxAuthClient.getXstsTicket(getOauth2AccessToken);
|
|
22
|
+
return xstsTicket.Token;
|
|
23
|
+
}, async () => await actualTokenPersister.load("halo.authToken"), async (token) => {
|
|
24
|
+
await actualTokenPersister.save("halo.authToken", token);
|
|
25
|
+
});
|
|
26
|
+
this.getSpartanToken = () => haloAuthClient.getSpartanToken();
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=auto-xsts-spartan-token-provider.js.map
|
package/dist/core/token-providers/spartan-token-providers/auto-xsts-spartan-token-provider.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-xsts-spartan-token-provider.js","sourceRoot":"","sources":["../../../../src/core/token-providers/spartan-token-providers/auto-xsts-spartan-token-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,wBAAwB,GACzB,MAAM,oDAAoD,CAAC;AAE5D,OAAO,EAAE,wBAAwB,EAAE,MAAM,oDAAoD,CAAC;AAE9F,OAAO,EAAE,sBAAsB,EAAE,MAAM,kDAAkD,CAAC;AAE1F;;;;GAIG;AACH,MAAM,OAAO,4BAA4B;IACvB,eAAe,CAAwB;IAEvD,YACE,oBAA2C,EAC3C,cAA+B;QAE/B,IAAI,oBAAoC,CAAC;QACzC,IAAI,cAAc,EAAE;YAClB,oBAAoB,GAAG,cAAc,CAAC;SACvC;aAAM;YACL,oBAAoB,GAAG,sBAAsB,CAAC;SAC/C;QACD,MAAM,cAAc,GAAG,IAAI,wBAAwB,CAAC,cAAc,CAAC,CAAC;QACpE,MAAM,cAAc,GAAG,IAAI,wBAAwB,CACjD,KAAK,IAAI,EAAE;YACT,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,aAAa,CACnD,oBAAoB,CACrB,CAAC;YACF,OAAO,UAAU,CAAC,KAAK,CAAC;QAC1B,CAAC,EACD,KAAK,IAAI,EAAE,CAAC,MAAM,oBAAoB,CAAC,IAAI,CAAC,gBAAgB,CAAC,EAC7D,KAAK,EAAE,KAAK,EAAE,EAAE;YACd,MAAM,oBAAoB,CAAC,IAAI,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;QAC3D,CAAC,CACF,CAAC;QAEF,IAAI,CAAC,eAAe,GAAG,GAAG,EAAE,CAAC,cAAc,CAAC,eAAe,EAAE,CAAC;IAChE,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/core/token-providers/spartan-token-providers/index.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { TokenPersister } from "../../token-persisters";
|
|
2
|
+
import { SpartanTokenProvider } from ".";
|
|
3
|
+
/**
|
|
4
|
+
* A SpartanTokenProvider that fetches uses a pre-fetched XSTS ticket token.
|
|
5
|
+
* Since requests to the Halo API are subject to CORS restrictions a
|
|
6
|
+
* HaloAuthenticationClient can be instantitated with a pre-fetched XSTS ticket
|
|
7
|
+
* and run on a server (such as one provided by the user).
|
|
8
|
+
*/
|
|
9
|
+
export declare class StaticXstsTicketTokenSpartanTokenProvider implements SpartanTokenProvider {
|
|
10
|
+
readonly getSpartanToken: () => Promise<string>;
|
|
11
|
+
constructor(xstsTicketToken: string, tokenPersister?: TokenPersister);
|
|
12
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { HaloAuthenticationClient } from "../../../authentication/halo-authentication-client";
|
|
2
|
+
import { inMemoryTokenPersister } from "../../token-persisters/in-memory-token-persister";
|
|
3
|
+
/**
|
|
4
|
+
* A SpartanTokenProvider that fetches uses a pre-fetched XSTS ticket token.
|
|
5
|
+
* Since requests to the Halo API are subject to CORS restrictions a
|
|
6
|
+
* HaloAuthenticationClient can be instantitated with a pre-fetched XSTS ticket
|
|
7
|
+
* and run on a server (such as one provided by the user).
|
|
8
|
+
*/
|
|
9
|
+
export class StaticXstsTicketTokenSpartanTokenProvider {
|
|
10
|
+
getSpartanToken;
|
|
11
|
+
constructor(xstsTicketToken, tokenPersister) {
|
|
12
|
+
let actualTokenPersister;
|
|
13
|
+
if (tokenPersister) {
|
|
14
|
+
actualTokenPersister = tokenPersister;
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
actualTokenPersister = inMemoryTokenPersister;
|
|
18
|
+
}
|
|
19
|
+
const haloAuthClient = new HaloAuthenticationClient(() => xstsTicketToken, async () => await actualTokenPersister.load("halo.authToken"), async (token) => {
|
|
20
|
+
await actualTokenPersister.save("halo.authToken", token);
|
|
21
|
+
});
|
|
22
|
+
this.getSpartanToken = () => haloAuthClient.getSpartanToken();
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=static-xsts-ticket-token-spartan-token-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"static-xsts-ticket-token-spartan-token-provider.js","sourceRoot":"","sources":["../../../../src/core/token-providers/spartan-token-providers/static-xsts-ticket-token-spartan-token-provider.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,wBAAwB,EAAE,MAAM,oDAAoD,CAAC;AAE9F,OAAO,EAAE,sBAAsB,EAAE,MAAM,kDAAkD,CAAC;AAE1F;;;;;GAKG;AACH,MAAM,OAAO,yCAAyC;IAGpC,eAAe,CAAwB;IAEvD,YAAY,eAAuB,EAAE,cAA+B;QAClE,IAAI,oBAAoC,CAAC;QACzC,IAAI,cAAc,EAAE;YAClB,oBAAoB,GAAG,cAAc,CAAC;SACvC;aAAM;YACL,oBAAoB,GAAG,sBAAsB,CAAC;SAC/C;QAED,MAAM,cAAc,GAAG,IAAI,wBAAwB,CACjD,GAAG,EAAE,CAAC,eAAe,EACrB,KAAK,IAAI,EAAE,CAAC,MAAM,oBAAoB,CAAC,IAAI,CAAC,gBAAgB,CAAC,EAC7D,KAAK,EAAE,KAAK,EAAE,EAAE;YACd,MAAM,oBAAoB,CAAC,IAAI,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;QAC3D,CAAC,CACF,CAAC;QAEF,IAAI,CAAC,eAAe,GAAG,GAAG,EAAE,CAAC,cAAc,CAAC,eAAe,EAAE,CAAC;IAChE,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"xbox-token-provider.js","sourceRoot":"","sources":["../../../src/core/token-providers/xbox-token-provider.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { XboxTokenProvider } from "./token-providers/xbox-token-provider";
|
|
2
|
+
export declare class XboxClient {
|
|
3
|
+
private xboxTokenProvider;
|
|
4
|
+
constructor(xboxTokenProvider: XboxTokenProvider);
|
|
5
|
+
private executeRequest;
|
|
6
|
+
searchUsers(query: string): Promise<{
|
|
7
|
+
id: string;
|
|
8
|
+
gamertag: string;
|
|
9
|
+
displayPicUri: string;
|
|
10
|
+
score: 0.0;
|
|
11
|
+
}[]>;
|
|
12
|
+
recentPlayers(): Promise<unknown>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import axios, { AxiosHeaders } from "axios";
|
|
2
|
+
export class XboxClient {
|
|
3
|
+
xboxTokenProvider;
|
|
4
|
+
constructor(xboxTokenProvider) {
|
|
5
|
+
this.xboxTokenProvider = xboxTokenProvider;
|
|
6
|
+
}
|
|
7
|
+
async executeRequest(url, method) {
|
|
8
|
+
const headers = new AxiosHeaders({
|
|
9
|
+
Accept: "application/json",
|
|
10
|
+
Authorization: await this.xboxTokenProvider.getXboxLiveV3Token(),
|
|
11
|
+
"x-xbl-contract-version": "1",
|
|
12
|
+
});
|
|
13
|
+
const response = await axios.request({
|
|
14
|
+
url,
|
|
15
|
+
method,
|
|
16
|
+
headers,
|
|
17
|
+
});
|
|
18
|
+
return response.data;
|
|
19
|
+
}
|
|
20
|
+
async searchUsers(query) {
|
|
21
|
+
const { results } = await this.executeRequest(`https://usersearch.xboxlive.com/suggest?q=${encodeURIComponent(query)}`, "GET");
|
|
22
|
+
return results.map(({ result }) => result);
|
|
23
|
+
}
|
|
24
|
+
async recentPlayers() {
|
|
25
|
+
return await this.executeRequest("https://peoplehub.xboxlive.com/users/me/people/recentplayers", "GET");
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=xbox-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"xbox-client.js","sourceRoot":"","sources":["../../src/core/xbox-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,YAAY,EAAU,MAAM,OAAO,CAAC;AAGpD,MAAM,OAAO,UAAU;IACD;IAApB,YAAoB,iBAAoC;QAApC,sBAAiB,GAAjB,iBAAiB,CAAmB;IAAG,CAAC;IAEpD,KAAK,CAAC,cAAc,CAAI,GAAW,EAAE,MAAc;QACzD,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC;YAC/B,MAAM,EAAE,kBAAkB;YAC1B,aAAa,EAAE,MAAM,IAAI,CAAC,iBAAiB,CAAC,kBAAkB,EAAE;YAChE,wBAAwB,EAAE,GAAG;SAC9B,CAAC,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,OAAO,CAAI;YACtC,GAAG;YACH,MAAM;YACN,OAAO;SACR,CAAC,CAAC;QAEH,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAEM,KAAK,CAAC,WAAW,CAAC,KAAa;QACpC,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,IAAI,CAAC,cAAc,CAa3C,6CAA6C,kBAAkB,CAAC,KAAK,CAAC,EAAE,EACxE,KAAK,CACN,CAAC;QACF,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC;IAC7C,CAAC;IAEM,KAAK,CAAC,aAAa;QACxB,OAAO,MAAM,IAAI,CAAC,cAAc,CAC9B,8DAA8D,EAC9D,KAAK,CACN,CAAC;IACJ,CAAC;CACF"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { HaloInfiniteClient, AssetKindTypeMap, } from "./core/halo-infinite-client";
|
|
2
|
+
export { XboxClient } from "./core/xbox-client";
|
|
2
3
|
export { XboxAuthenticationClient, RelyingParty, } from "./authentication/xbox-authentication-client";
|
|
3
4
|
export { Playlist } from "./models/halo-infinite/playlist";
|
|
4
5
|
export { PlaylistCsrContainer } from "./models/halo-infinite/playlist-csr-container";
|
|
@@ -15,8 +16,8 @@ export { MatchOutcome } from "./models/halo-infinite/match-outcome";
|
|
|
15
16
|
export { MatchSkill } from "./models/halo-infinite/match-skill";
|
|
16
17
|
export { AssetVersionLink } from "./models/halo-infinite/asset-version-link";
|
|
17
18
|
export { MatchInfo } from "./models/halo-infinite/match-info";
|
|
18
|
-
export { SpartanTokenProvider } from "./core/spartan-token-providers";
|
|
19
|
-
export { AutoXstsSpartanTokenProvider } from "./core/
|
|
20
|
-
export { StaticXstsTicketTokenSpartanTokenProvider } from "./core/spartan-token-providers/static-xsts-ticket-token-spartan-token-provider";
|
|
19
|
+
export { SpartanTokenProvider } from "./core/token-providers/spartan-token-providers";
|
|
20
|
+
export { AutoTokenProvider, AutoTokenProvider as AutoXstsSpartanTokenProvider, } from "./core/token-providers/auto-token-provider";
|
|
21
|
+
export { StaticXstsTicketTokenSpartanTokenProvider } from "./core/token-providers/spartan-token-providers/static-xsts-ticket-token-spartan-token-provider";
|
|
21
22
|
export { TokenPersister } from "./core/token-persisters";
|
|
22
23
|
export { PlaylistExperience } from "./models/halo-infinite/playlist-experience";
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
export { HaloInfiniteClient, } from "./core/halo-infinite-client";
|
|
2
|
+
export { XboxClient } from "./core/xbox-client";
|
|
2
3
|
export { XboxAuthenticationClient, RelyingParty, } from "./authentication/xbox-authentication-client";
|
|
3
4
|
export { MatchType } from "./models/halo-infinite/match-type";
|
|
4
5
|
export { GameVariantCategory } from "./models/halo-infinite/game-variant-category";
|
|
5
6
|
export { AssetKind } from "./models/halo-infinite/asset-kind";
|
|
6
7
|
export { MatchOutcome } from "./models/halo-infinite/match-outcome";
|
|
7
|
-
export { AutoXstsSpartanTokenProvider } from "./core/
|
|
8
|
-
export { StaticXstsTicketTokenSpartanTokenProvider } from "./core/spartan-token-providers/static-xsts-ticket-token-spartan-token-provider";
|
|
8
|
+
export { AutoTokenProvider, AutoTokenProvider as AutoXstsSpartanTokenProvider, } from "./core/token-providers/auto-token-provider";
|
|
9
|
+
export { StaticXstsTicketTokenSpartanTokenProvider } from "./core/token-providers/spartan-token-providers/static-xsts-ticket-token-spartan-token-provider";
|
|
9
10
|
export { PlaylistExperience } from "./models/halo-infinite/playlist-experience";
|
|
10
11
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,GAEnB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,wBAAwB,EACxB,YAAY,GACb,MAAM,6CAA6C,CAAC;AAKrD,OAAO,EAAE,SAAS,EAAE,MAAM,mCAAmC,CAAC;AAC9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,8CAA8C,CAAC;AAKnF,OAAO,EAAE,SAAS,EAAE,MAAM,mCAAmC,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,sCAAsC,CAAC;AAKpE,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,GAEnB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EACL,wBAAwB,EACxB,YAAY,GACb,MAAM,6CAA6C,CAAC;AAKrD,OAAO,EAAE,SAAS,EAAE,MAAM,mCAAmC,CAAC;AAC9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,8CAA8C,CAAC;AAKnF,OAAO,EAAE,SAAS,EAAE,MAAM,mCAAmC,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,sCAAsC,CAAC;AAKpE,OAAO,EACL,iBAAiB,EACjB,iBAAiB,IAAI,4BAA4B,GAClD,MAAM,4CAA4C,CAAC;AACpD,OAAO,EAAE,yCAAyC,EAAE,MAAM,gGAAgG,CAAC;AAE3J,OAAO,EAAE,kBAAkB,EAAE,MAAM,4CAA4C,CAAC"}
|
|
@@ -7,8 +7,10 @@ export declare enum GameVariantCategory {
|
|
|
7
7
|
MultiplayerTotalControl = 14,
|
|
8
8
|
MultiplayerCtf = 15,
|
|
9
9
|
MultiplayerOddball = 18,
|
|
10
|
+
MultiplayerStockpile = 19,
|
|
10
11
|
MultiplayerInfection = 22,
|
|
11
12
|
MultiplayerGrifball = 25,
|
|
12
13
|
MultiplayerLandGrab = 39,
|
|
13
|
-
MultiplayerExtraction = 17
|
|
14
|
+
MultiplayerExtraction = 17,
|
|
15
|
+
MultiplayerFirefight = 42
|
|
14
16
|
}
|
|
@@ -8,9 +8,11 @@ export var GameVariantCategory;
|
|
|
8
8
|
GameVariantCategory[GameVariantCategory["MultiplayerTotalControl"] = 14] = "MultiplayerTotalControl";
|
|
9
9
|
GameVariantCategory[GameVariantCategory["MultiplayerCtf"] = 15] = "MultiplayerCtf";
|
|
10
10
|
GameVariantCategory[GameVariantCategory["MultiplayerOddball"] = 18] = "MultiplayerOddball";
|
|
11
|
+
GameVariantCategory[GameVariantCategory["MultiplayerStockpile"] = 19] = "MultiplayerStockpile";
|
|
11
12
|
GameVariantCategory[GameVariantCategory["MultiplayerInfection"] = 22] = "MultiplayerInfection";
|
|
12
13
|
GameVariantCategory[GameVariantCategory["MultiplayerGrifball"] = 25] = "MultiplayerGrifball";
|
|
13
14
|
GameVariantCategory[GameVariantCategory["MultiplayerLandGrab"] = 39] = "MultiplayerLandGrab";
|
|
14
15
|
GameVariantCategory[GameVariantCategory["MultiplayerExtraction"] = 17] = "MultiplayerExtraction";
|
|
16
|
+
GameVariantCategory[GameVariantCategory["MultiplayerFirefight"] = 42] = "MultiplayerFirefight";
|
|
15
17
|
})(GameVariantCategory || (GameVariantCategory = {}));
|
|
16
18
|
//# sourceMappingURL=game-variant-category.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"game-variant-category.js","sourceRoot":"","sources":["../../../src/models/halo-infinite/game-variant-category.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,
|
|
1
|
+
{"version":3,"file":"game-variant-category.js","sourceRoot":"","sources":["../../../src/models/halo-infinite/game-variant-category.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,mBAeX;AAfD,WAAY,mBAAmB;IAC7B,uFAAqB,CAAA;IACrB,6FAAwB,CAAA;IACxB,uFAAqB,CAAA;IACrB,kGAA2B,CAAA;IAC3B,sGAA6B,CAAA;IAC7B,oGAA4B,CAAA;IAC5B,kFAAmB,CAAA;IACnB,0FAAuB,CAAA;IACvB,8FAAyB,CAAA;IACzB,8FAAyB,CAAA;IACzB,4FAAwB,CAAA;IACxB,4FAAwB,CAAA;IACxB,gGAA0B,CAAA;IAC1B,8FAAyB,CAAA;AAC3B,CAAC,EAfW,mBAAmB,KAAnB,mBAAmB,QAe9B"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { GameVariantCategory } from "./game-variant-category";
|
|
2
|
-
interface OddballStats {
|
|
2
|
+
export interface OddballStats {
|
|
3
3
|
KillsAsSkullCarrier: number;
|
|
4
4
|
LongestTimeAsSkullCarrier: string;
|
|
5
5
|
SkullCarriersKilled: number;
|
|
@@ -7,7 +7,7 @@ interface OddballStats {
|
|
|
7
7
|
TimeAsSkullCarrier: string;
|
|
8
8
|
SkullScoringTicks: number;
|
|
9
9
|
}
|
|
10
|
-
interface ZonesStats {
|
|
10
|
+
export interface ZonesStats {
|
|
11
11
|
StrongholdCaptures: number;
|
|
12
12
|
StrongholdDefensiveKills: number;
|
|
13
13
|
StrongholdOffensiveKills: number;
|
|
@@ -15,7 +15,7 @@ interface ZonesStats {
|
|
|
15
15
|
StrongholdOccupationTime: string;
|
|
16
16
|
StrongholdScoringTicks: number;
|
|
17
17
|
}
|
|
18
|
-
interface CaptureTheFlagStats {
|
|
18
|
+
export interface CaptureTheFlagStats {
|
|
19
19
|
FlagCaptureAssists: number;
|
|
20
20
|
FlagCaptures: number;
|
|
21
21
|
FlagCarriersKilled: number;
|
|
@@ -28,13 +28,46 @@ interface CaptureTheFlagStats {
|
|
|
28
28
|
KillsAsFlagReturner: number;
|
|
29
29
|
TimeAsFlagCarrier: string;
|
|
30
30
|
}
|
|
31
|
-
interface ExtractionStats {
|
|
31
|
+
export interface ExtractionStats {
|
|
32
32
|
SuccessfulExtractions: number;
|
|
33
33
|
ExtractionConversionsDenied: number;
|
|
34
34
|
ExtractionConversionsCompleted: number;
|
|
35
35
|
ExtractionInitiationsDenied: number;
|
|
36
36
|
ExtractionInitiationsCompleted: number;
|
|
37
37
|
}
|
|
38
|
+
export interface EliminationStats {
|
|
39
|
+
AlliesRevived: number;
|
|
40
|
+
EliminationAssists: number;
|
|
41
|
+
Eliminations: number;
|
|
42
|
+
EnemyRevivesDenied: number;
|
|
43
|
+
Executions: number;
|
|
44
|
+
KillsAsLastPlayerStanding: number;
|
|
45
|
+
LastPlayersStandingKilled: number;
|
|
46
|
+
RoundsSurvived: number;
|
|
47
|
+
TimesRevivedByAlly: number;
|
|
48
|
+
}
|
|
49
|
+
export interface InfectionStats {
|
|
50
|
+
AlphasKilled: number;
|
|
51
|
+
SpartansInfected: number;
|
|
52
|
+
SpartansInfectedAsAlpha: number;
|
|
53
|
+
KillsAsLastSpartanStanding: number;
|
|
54
|
+
LastSpartansStandingInfected: number;
|
|
55
|
+
RoundsAsAlpha: number;
|
|
56
|
+
RoundsAsLastSpartanStanding: number;
|
|
57
|
+
RoundsFinishedAsInfected: number;
|
|
58
|
+
RoundsSurvivedAsSpartan: number;
|
|
59
|
+
RoundsSurvivedAsLastSpartanStanding: number;
|
|
60
|
+
TimeAsLastSpartanStanding: string;
|
|
61
|
+
InfectedKilled: number;
|
|
62
|
+
}
|
|
63
|
+
export interface StockpileStats {
|
|
64
|
+
KillsAsPowerSeedCarrier: number;
|
|
65
|
+
PowerSeedCarriersKilled: number;
|
|
66
|
+
PowerSeedsDeposited: number;
|
|
67
|
+
PowerSeedsStolen: number;
|
|
68
|
+
TimeAsPowerSeedCarrier: string;
|
|
69
|
+
TimeAsPowerSeedDriver: string;
|
|
70
|
+
}
|
|
38
71
|
type StatsMap = {
|
|
39
72
|
[GameVariantCategory.MultiplayerOddball]: {
|
|
40
73
|
OddballStats: OddballStats;
|
|
@@ -51,6 +84,15 @@ type StatsMap = {
|
|
|
51
84
|
[GameVariantCategory.MultiplayerExtraction]: {
|
|
52
85
|
ExtractionStats: ExtractionStats;
|
|
53
86
|
};
|
|
87
|
+
[GameVariantCategory.MultiplayerFirefight]: {
|
|
88
|
+
EliminationStats: EliminationStats;
|
|
89
|
+
};
|
|
90
|
+
[GameVariantCategory.MultiplayerInfection]: {
|
|
91
|
+
InfectionSTats: InfectionStats;
|
|
92
|
+
};
|
|
93
|
+
[GameVariantCategory.MultiplayerStockpile]: {
|
|
94
|
+
StockpileStats: StockpileStats;
|
|
95
|
+
};
|
|
54
96
|
};
|
|
55
97
|
export type Stats<TCategory extends GameVariantCategory = GameVariantCategory> = {
|
|
56
98
|
CoreStats: {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { DateTime } from "luxon";
|
|
2
|
+
export declare class KeyedExpiryTokenCache<TToken extends {
|
|
3
|
+
expiresAt: DateTime;
|
|
4
|
+
}, TKey extends string, TArgs extends any[]> {
|
|
5
|
+
private readonly generateNewToken;
|
|
6
|
+
private readonly existingTokenFetcher;
|
|
7
|
+
private readonly tokenFetchPromiseMap;
|
|
8
|
+
constructor(generateNewToken: (key: TKey, ...args: TArgs) => Promise<TToken>, existingTokenFetcher: (key: TKey) => Promise<(Omit<TToken, "expiresAt"> & {
|
|
9
|
+
expiresAt: unknown;
|
|
10
|
+
}) | null>);
|
|
11
|
+
getToken(key: TKey, ...args: TArgs): Promise<TToken>;
|
|
12
|
+
getExistingToken(key: TKey): Promise<TToken | null>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { DateTime } from "luxon";
|
|
2
|
+
import { ResolvablePromise } from "./resolvable-promise";
|
|
3
|
+
import { coalesceDateTime } from "./date-time";
|
|
4
|
+
export class KeyedExpiryTokenCache {
|
|
5
|
+
generateNewToken;
|
|
6
|
+
existingTokenFetcher;
|
|
7
|
+
tokenFetchPromiseMap = new Map();
|
|
8
|
+
constructor(generateNewToken, existingTokenFetcher) {
|
|
9
|
+
this.generateNewToken = generateNewToken;
|
|
10
|
+
this.existingTokenFetcher = existingTokenFetcher;
|
|
11
|
+
}
|
|
12
|
+
async getToken(key, ...args) {
|
|
13
|
+
let tokenFetchPromise = this.tokenFetchPromiseMap.get(key);
|
|
14
|
+
if (tokenFetchPromise) {
|
|
15
|
+
// Someone either already has a token or is in the process of getting one
|
|
16
|
+
// Wait for them to finish, then check for validity
|
|
17
|
+
const currentToken = await tokenFetchPromise;
|
|
18
|
+
if (currentToken.expiresAt > DateTime.now()) {
|
|
19
|
+
// Current token is valid, return it
|
|
20
|
+
return currentToken;
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
// Current token expired, start a new promise
|
|
24
|
+
tokenFetchPromise = new ResolvablePromise();
|
|
25
|
+
this.tokenFetchPromiseMap.set(key, tokenFetchPromise);
|
|
26
|
+
try {
|
|
27
|
+
const newToken = await this.generateNewToken(key, ...args);
|
|
28
|
+
tokenFetchPromise.resolve(newToken);
|
|
29
|
+
return newToken;
|
|
30
|
+
}
|
|
31
|
+
catch (e) {
|
|
32
|
+
tokenFetchPromise.reject(e);
|
|
33
|
+
tokenFetchPromise = undefined;
|
|
34
|
+
throw e;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
// No one has a token, start a new promise
|
|
40
|
+
tokenFetchPromise = new ResolvablePromise();
|
|
41
|
+
this.tokenFetchPromiseMap.set(key, tokenFetchPromise);
|
|
42
|
+
try {
|
|
43
|
+
const existingToken = await this.getExistingToken(key);
|
|
44
|
+
if (existingToken?.expiresAt) {
|
|
45
|
+
const expiresAt = coalesceDateTime(existingToken.expiresAt);
|
|
46
|
+
if (expiresAt && expiresAt > DateTime.now()) {
|
|
47
|
+
const newToken = { ...existingToken, expiresAt };
|
|
48
|
+
tokenFetchPromise.resolve(newToken);
|
|
49
|
+
return newToken;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const newToken = await this.generateNewToken(key, ...args);
|
|
53
|
+
tokenFetchPromise.resolve(newToken);
|
|
54
|
+
return newToken;
|
|
55
|
+
}
|
|
56
|
+
catch (e) {
|
|
57
|
+
tokenFetchPromise.reject(e);
|
|
58
|
+
tokenFetchPromise = undefined;
|
|
59
|
+
throw e;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async getExistingToken(key) {
|
|
64
|
+
const existingToken = await this.existingTokenFetcher(key);
|
|
65
|
+
if (existingToken?.expiresAt) {
|
|
66
|
+
const expiresAt = coalesceDateTime(existingToken.expiresAt);
|
|
67
|
+
if (expiresAt && expiresAt > DateTime.now()) {
|
|
68
|
+
return { ...existingToken, expiresAt };
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=keyed-expiry-token-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyed-expiry-token-cache.js","sourceRoot":"","sources":["../../src/util/keyed-expiry-token-cache.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@ import axios, { AxiosInstance } from "axios";
|
|
|
2
2
|
import { DateTime } from "luxon";
|
|
3
3
|
import { TokenPersister } from "../core/token-persisters";
|
|
4
4
|
import { XboxTicket } from "../models/xbox-ticket";
|
|
5
|
-
import {
|
|
5
|
+
import { KeyedExpiryTokenCache } from "../util/keyed-expiry-token-cache";
|
|
6
6
|
import { ExpiryTokenCache } from "../util/expiry-token-cache";
|
|
7
7
|
|
|
8
8
|
export enum RelyingParty {
|
|
@@ -51,8 +51,8 @@ export class XboxAuthenticationClient {
|
|
|
51
51
|
"xbox.userToken"
|
|
52
52
|
)) ?? null
|
|
53
53
|
);
|
|
54
|
-
private xstsTicketCache = new
|
|
55
|
-
async (
|
|
54
|
+
private xstsTicketCache = new KeyedExpiryTokenCache(
|
|
55
|
+
async (relyingParty: RelyingParty, userToken: string) => {
|
|
56
56
|
const response = await this.httpClient.post<XboxTicket>(
|
|
57
57
|
"https://xsts.auth.xboxlive.com/xsts/authorize",
|
|
58
58
|
{
|
|
@@ -76,12 +76,15 @@ export class XboxAuthenticationClient {
|
|
|
76
76
|
...response.data,
|
|
77
77
|
expiresAt: DateTime.fromISO(response.data.NotAfter),
|
|
78
78
|
};
|
|
79
|
-
await this.tokenPersister?.save(
|
|
79
|
+
await this.tokenPersister?.save(
|
|
80
|
+
"xbox.xstsTicket." + relyingParty,
|
|
81
|
+
result
|
|
82
|
+
);
|
|
80
83
|
return result;
|
|
81
84
|
},
|
|
82
|
-
async () =>
|
|
85
|
+
async (relyingParty) =>
|
|
83
86
|
(await this.tokenPersister?.load<XboxTicket & { expiresAt: unknown }>(
|
|
84
|
-
"xbox.xstsTicket"
|
|
87
|
+
"xbox.xstsTicket." + relyingParty
|
|
85
88
|
)) ?? null
|
|
86
89
|
);
|
|
87
90
|
|
|
@@ -91,8 +94,11 @@ export class XboxAuthenticationClient {
|
|
|
91
94
|
this.httpClient = axios.create();
|
|
92
95
|
}
|
|
93
96
|
|
|
94
|
-
public async getXstsTicket(
|
|
95
|
-
|
|
97
|
+
public async getXstsTicket(
|
|
98
|
+
getOauth2AccessToken: () => Promise<string>,
|
|
99
|
+
relyingParty: RelyingParty
|
|
100
|
+
) {
|
|
101
|
+
let xstsTicket = await this.xstsTicketCache.getExistingToken(relyingParty);
|
|
96
102
|
if (!xstsTicket) {
|
|
97
103
|
let userToken = await this.userTokenCache.getExistingToken();
|
|
98
104
|
if (!userToken) {
|
|
@@ -103,13 +109,13 @@ export class XboxAuthenticationClient {
|
|
|
103
109
|
);
|
|
104
110
|
}
|
|
105
111
|
xstsTicket = await this.xstsTicketCache.getToken(
|
|
106
|
-
|
|
107
|
-
|
|
112
|
+
relyingParty,
|
|
113
|
+
userToken.Token
|
|
108
114
|
);
|
|
109
115
|
}
|
|
110
116
|
return xstsTicket;
|
|
111
117
|
}
|
|
112
118
|
|
|
113
|
-
public getXboxLiveV3Token = (
|
|
114
|
-
`XBL3.0 x=${
|
|
119
|
+
public getXboxLiveV3Token = (xboxTicket: XboxTicket) =>
|
|
120
|
+
`XBL3.0 x=${xboxTicket.DisplayClaims.xui[0].uhs};${xboxTicket.Token}`;
|
|
115
121
|
}
|
|
@@ -15,7 +15,7 @@ import { PlaylistCsrContainer } from "../models/halo-infinite/playlist-csr-conta
|
|
|
15
15
|
import { ServiceRecord } from "../models/halo-infinite/service-record";
|
|
16
16
|
import { UserInfo } from "../models/halo-infinite/user-info";
|
|
17
17
|
import { GlobalConstants } from "../util/global-contants";
|
|
18
|
-
import { SpartanTokenProvider } from "./spartan-token-providers";
|
|
18
|
+
import { SpartanTokenProvider } from "./token-providers/spartan-token-providers";
|
|
19
19
|
|
|
20
20
|
interface ResultContainer<TValue> {
|
|
21
21
|
Id: string;
|
|
@@ -49,7 +49,7 @@ const assetKindUrlMap = {
|
|
|
49
49
|
};
|
|
50
50
|
|
|
51
51
|
function wrapPlayerId(playerId: string) {
|
|
52
|
-
if (/^\w
|
|
52
|
+
if (/^\w+\(\d+\)/.test(playerId)) {
|
|
53
53
|
return playerId;
|
|
54
54
|
} else {
|
|
55
55
|
// Assume xuid
|
|
@@ -197,11 +197,23 @@ export class HaloInfiniteClient {
|
|
|
197
197
|
params,
|
|
198
198
|
`https://${HaloCoreEndpoints.StatsOrigin}.${
|
|
199
199
|
HaloCoreEndpoints.ServiceDomain
|
|
200
|
-
}/hi/players
|
|
200
|
+
}/hi/players/${wrapPlayerId(playerXuid)}/matches`,
|
|
201
201
|
"get"
|
|
202
202
|
);
|
|
203
203
|
};
|
|
204
204
|
|
|
205
|
+
public getPlayerServiceRecord(
|
|
206
|
+
playerXuid: string,
|
|
207
|
+
type: MatchType = MatchType.All
|
|
208
|
+
) {
|
|
209
|
+
return this.executeRequest<ServiceRecord>(
|
|
210
|
+
`https://${HaloCoreEndpoints.StatsOrigin}.${
|
|
211
|
+
HaloCoreEndpoints.ServiceDomain
|
|
212
|
+
}/hi/players/${wrapPlayerId(playerXuid)}/Matchmade/servicerecord`,
|
|
213
|
+
"get"
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
|
|
205
217
|
public getMatchStats = (matchId: string) =>
|
|
206
218
|
this.executeRequest<MatchStats>(
|
|
207
219
|
`https://${HaloCoreEndpoints.StatsOrigin}.${HaloCoreEndpoints.ServiceDomain}/hi/matches/${matchId}/stats`,
|
|
@@ -4,16 +4,20 @@ import {
|
|
|
4
4
|
} from "../../authentication/xbox-authentication-client";
|
|
5
5
|
import { TokenPersister } from "../token-persisters";
|
|
6
6
|
import { HaloAuthenticationClient } from "../../authentication/halo-authentication-client";
|
|
7
|
-
import { SpartanTokenProvider } from "
|
|
7
|
+
import { SpartanTokenProvider } from "./spartan-token-providers";
|
|
8
8
|
import { inMemoryTokenPersister } from "../token-persisters/in-memory-token-persister";
|
|
9
|
+
import { XboxTokenProvider } from "./xbox-token-provider";
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* A SpartanTokenProvider that fetches both the Xbox and Halo tokens in the same
|
|
12
13
|
* process. This is useful for applications that do not need to contend with
|
|
13
14
|
* CORS restrictions.
|
|
14
15
|
*/
|
|
15
|
-
export class
|
|
16
|
+
export class AutoTokenProvider
|
|
17
|
+
implements SpartanTokenProvider, XboxTokenProvider
|
|
18
|
+
{
|
|
16
19
|
public readonly getSpartanToken: () => Promise<string>;
|
|
20
|
+
public readonly getXboxLiveV3Token: () => Promise<string>;
|
|
17
21
|
|
|
18
22
|
constructor(
|
|
19
23
|
getOauth2AccessToken: () => Promise<string>,
|
|
@@ -29,7 +33,8 @@ export class AutoXstsSpartanTokenProvider implements SpartanTokenProvider {
|
|
|
29
33
|
const haloAuthClient = new HaloAuthenticationClient(
|
|
30
34
|
async () => {
|
|
31
35
|
const xstsTicket = await xboxAuthClient.getXstsTicket(
|
|
32
|
-
getOauth2AccessToken
|
|
36
|
+
getOauth2AccessToken,
|
|
37
|
+
RelyingParty.Halo
|
|
33
38
|
);
|
|
34
39
|
return xstsTicket.Token;
|
|
35
40
|
},
|
|
@@ -40,5 +45,12 @@ export class AutoXstsSpartanTokenProvider implements SpartanTokenProvider {
|
|
|
40
45
|
);
|
|
41
46
|
|
|
42
47
|
this.getSpartanToken = () => haloAuthClient.getSpartanToken();
|
|
48
|
+
this.getXboxLiveV3Token = async () => {
|
|
49
|
+
const xstsTicket = await xboxAuthClient.getXstsTicket(
|
|
50
|
+
getOauth2AccessToken,
|
|
51
|
+
RelyingParty.Xbox
|
|
52
|
+
);
|
|
53
|
+
return xboxAuthClient.getXboxLiveV3Token(xstsTicket);
|
|
54
|
+
};
|
|
43
55
|
}
|
|
44
56
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { TokenPersister } from "
|
|
2
|
-
import { HaloAuthenticationClient } from "
|
|
1
|
+
import { TokenPersister } from "../../token-persisters";
|
|
2
|
+
import { HaloAuthenticationClient } from "../../../authentication/halo-authentication-client";
|
|
3
3
|
import { SpartanTokenProvider } from ".";
|
|
4
|
-
import { inMemoryTokenPersister } from "
|
|
4
|
+
import { inMemoryTokenPersister } from "../../token-persisters/in-memory-token-persister";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* A SpartanTokenProvider that fetches uses a pre-fetched XSTS ticket token.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import axios, { AxiosHeaders, Method } from "axios";
|
|
2
|
+
import { XboxTokenProvider } from "./token-providers/xbox-token-provider";
|
|
3
|
+
|
|
4
|
+
export class XboxClient {
|
|
5
|
+
constructor(private xboxTokenProvider: XboxTokenProvider) {}
|
|
6
|
+
|
|
7
|
+
private async executeRequest<T>(url: string, method: Method) {
|
|
8
|
+
const headers = new AxiosHeaders({
|
|
9
|
+
Accept: "application/json",
|
|
10
|
+
Authorization: await this.xboxTokenProvider.getXboxLiveV3Token(),
|
|
11
|
+
"x-xbl-contract-version": "1",
|
|
12
|
+
});
|
|
13
|
+
const response = await axios.request<T>({
|
|
14
|
+
url,
|
|
15
|
+
method,
|
|
16
|
+
headers,
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
return response.data;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
public async searchUsers(query: string) {
|
|
23
|
+
const { results } = await this.executeRequest<{
|
|
24
|
+
results: [
|
|
25
|
+
{
|
|
26
|
+
result: {
|
|
27
|
+
id: string;
|
|
28
|
+
gamertag: string;
|
|
29
|
+
displayPicUri: string;
|
|
30
|
+
score: 0.0;
|
|
31
|
+
};
|
|
32
|
+
text: string;
|
|
33
|
+
}
|
|
34
|
+
];
|
|
35
|
+
}>(
|
|
36
|
+
`https://usersearch.xboxlive.com/suggest?q=${encodeURIComponent(query)}`,
|
|
37
|
+
"GET"
|
|
38
|
+
);
|
|
39
|
+
return results.map(({ result }) => result);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public async recentPlayers() {
|
|
43
|
+
return await this.executeRequest<unknown>(
|
|
44
|
+
"https://peoplehub.xboxlive.com/users/me/people/recentplayers",
|
|
45
|
+
"GET"
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -2,6 +2,7 @@ export {
|
|
|
2
2
|
HaloInfiniteClient,
|
|
3
3
|
AssetKindTypeMap,
|
|
4
4
|
} from "./core/halo-infinite-client";
|
|
5
|
+
export { XboxClient } from "./core/xbox-client";
|
|
5
6
|
export {
|
|
6
7
|
XboxAuthenticationClient,
|
|
7
8
|
RelyingParty,
|
|
@@ -21,8 +22,11 @@ export { MatchOutcome } from "./models/halo-infinite/match-outcome";
|
|
|
21
22
|
export { MatchSkill } from "./models/halo-infinite/match-skill";
|
|
22
23
|
export { AssetVersionLink } from "./models/halo-infinite/asset-version-link";
|
|
23
24
|
export { MatchInfo } from "./models/halo-infinite/match-info";
|
|
24
|
-
export { SpartanTokenProvider } from "./core/spartan-token-providers";
|
|
25
|
-
export {
|
|
26
|
-
|
|
25
|
+
export { SpartanTokenProvider } from "./core/token-providers/spartan-token-providers";
|
|
26
|
+
export {
|
|
27
|
+
AutoTokenProvider,
|
|
28
|
+
AutoTokenProvider as AutoXstsSpartanTokenProvider,
|
|
29
|
+
} from "./core/token-providers/auto-token-provider";
|
|
30
|
+
export { StaticXstsTicketTokenSpartanTokenProvider } from "./core/token-providers/spartan-token-providers/static-xsts-ticket-token-spartan-token-provider";
|
|
27
31
|
export { TokenPersister } from "./core/token-persisters";
|
|
28
32
|
export { PlaylistExperience } from "./models/halo-infinite/playlist-experience";
|
|
@@ -7,8 +7,10 @@ export enum GameVariantCategory {
|
|
|
7
7
|
MultiplayerTotalControl = 14,
|
|
8
8
|
MultiplayerCtf = 15,
|
|
9
9
|
MultiplayerOddball = 18,
|
|
10
|
+
MultiplayerStockpile = 19,
|
|
10
11
|
MultiplayerInfection = 22,
|
|
11
12
|
MultiplayerGrifball = 25,
|
|
12
13
|
MultiplayerLandGrab = 39,
|
|
13
14
|
MultiplayerExtraction = 17,
|
|
15
|
+
MultiplayerFirefight = 42,
|
|
14
16
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { GameVariantCategory } from "./game-variant-category";
|
|
2
2
|
|
|
3
|
-
interface OddballStats {
|
|
3
|
+
export interface OddballStats {
|
|
4
4
|
KillsAsSkullCarrier: number;
|
|
5
5
|
LongestTimeAsSkullCarrier: string;
|
|
6
6
|
SkullCarriersKilled: number;
|
|
@@ -8,7 +8,8 @@ interface OddballStats {
|
|
|
8
8
|
TimeAsSkullCarrier: string;
|
|
9
9
|
SkullScoringTicks: number;
|
|
10
10
|
}
|
|
11
|
-
|
|
11
|
+
|
|
12
|
+
export interface ZonesStats {
|
|
12
13
|
StrongholdCaptures: number;
|
|
13
14
|
StrongholdDefensiveKills: number;
|
|
14
15
|
StrongholdOffensiveKills: number;
|
|
@@ -16,7 +17,8 @@ interface ZonesStats {
|
|
|
16
17
|
StrongholdOccupationTime: string;
|
|
17
18
|
StrongholdScoringTicks: number;
|
|
18
19
|
}
|
|
19
|
-
|
|
20
|
+
|
|
21
|
+
export interface CaptureTheFlagStats {
|
|
20
22
|
FlagCaptureAssists: number;
|
|
21
23
|
FlagCaptures: number;
|
|
22
24
|
FlagCarriersKilled: number;
|
|
@@ -30,7 +32,7 @@ interface CaptureTheFlagStats {
|
|
|
30
32
|
TimeAsFlagCarrier: string;
|
|
31
33
|
}
|
|
32
34
|
|
|
33
|
-
interface ExtractionStats {
|
|
35
|
+
export interface ExtractionStats {
|
|
34
36
|
SuccessfulExtractions: number;
|
|
35
37
|
ExtractionConversionsDenied: number;
|
|
36
38
|
ExtractionConversionsCompleted: number;
|
|
@@ -38,6 +40,42 @@ interface ExtractionStats {
|
|
|
38
40
|
ExtractionInitiationsCompleted: number;
|
|
39
41
|
}
|
|
40
42
|
|
|
43
|
+
export interface EliminationStats {
|
|
44
|
+
AlliesRevived: number;
|
|
45
|
+
EliminationAssists: number;
|
|
46
|
+
Eliminations: number;
|
|
47
|
+
EnemyRevivesDenied: number;
|
|
48
|
+
Executions: number;
|
|
49
|
+
KillsAsLastPlayerStanding: number;
|
|
50
|
+
LastPlayersStandingKilled: number;
|
|
51
|
+
RoundsSurvived: number;
|
|
52
|
+
TimesRevivedByAlly: number;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface InfectionStats {
|
|
56
|
+
AlphasKilled: number;
|
|
57
|
+
SpartansInfected: number;
|
|
58
|
+
SpartansInfectedAsAlpha: number;
|
|
59
|
+
KillsAsLastSpartanStanding: number;
|
|
60
|
+
LastSpartansStandingInfected: number;
|
|
61
|
+
RoundsAsAlpha: number;
|
|
62
|
+
RoundsAsLastSpartanStanding: number;
|
|
63
|
+
RoundsFinishedAsInfected: number;
|
|
64
|
+
RoundsSurvivedAsSpartan: number;
|
|
65
|
+
RoundsSurvivedAsLastSpartanStanding: number;
|
|
66
|
+
TimeAsLastSpartanStanding: string;
|
|
67
|
+
InfectedKilled: number;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface StockpileStats {
|
|
71
|
+
KillsAsPowerSeedCarrier: number;
|
|
72
|
+
PowerSeedCarriersKilled: number;
|
|
73
|
+
PowerSeedsDeposited: number;
|
|
74
|
+
PowerSeedsStolen: number;
|
|
75
|
+
TimeAsPowerSeedCarrier: string;
|
|
76
|
+
TimeAsPowerSeedDriver: string;
|
|
77
|
+
}
|
|
78
|
+
|
|
41
79
|
type StatsMap = {
|
|
42
80
|
[GameVariantCategory.MultiplayerOddball]: { OddballStats: OddballStats };
|
|
43
81
|
[GameVariantCategory.MultiplayerStrongholds]: { ZonesStats: ZonesStats };
|
|
@@ -48,6 +86,15 @@ type StatsMap = {
|
|
|
48
86
|
[GameVariantCategory.MultiplayerExtraction]: {
|
|
49
87
|
ExtractionStats: ExtractionStats;
|
|
50
88
|
};
|
|
89
|
+
[GameVariantCategory.MultiplayerFirefight]: {
|
|
90
|
+
EliminationStats: EliminationStats;
|
|
91
|
+
};
|
|
92
|
+
[GameVariantCategory.MultiplayerInfection]: {
|
|
93
|
+
InfectionSTats: InfectionStats;
|
|
94
|
+
};
|
|
95
|
+
[GameVariantCategory.MultiplayerStockpile]: {
|
|
96
|
+
StockpileStats: StockpileStats;
|
|
97
|
+
};
|
|
51
98
|
};
|
|
52
99
|
|
|
53
100
|
export type Stats<TCategory extends GameVariantCategory = GameVariantCategory> =
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { DateTime } from "luxon";
|
|
2
|
+
import { ResolvablePromise } from "./resolvable-promise";
|
|
3
|
+
import { coalesceDateTime } from "./date-time";
|
|
4
|
+
|
|
5
|
+
export class KeyedExpiryTokenCache<
|
|
6
|
+
TToken extends { expiresAt: DateTime },
|
|
7
|
+
TKey extends string,
|
|
8
|
+
TArgs extends any[]
|
|
9
|
+
> {
|
|
10
|
+
private readonly tokenFetchPromiseMap = new Map<
|
|
11
|
+
TKey,
|
|
12
|
+
ResolvablePromise<TToken>
|
|
13
|
+
>();
|
|
14
|
+
|
|
15
|
+
constructor(
|
|
16
|
+
private readonly generateNewToken: (
|
|
17
|
+
key: TKey,
|
|
18
|
+
...args: TArgs
|
|
19
|
+
) => Promise<TToken>,
|
|
20
|
+
private readonly existingTokenFetcher: (
|
|
21
|
+
key: TKey
|
|
22
|
+
) => Promise<(Omit<TToken, "expiresAt"> & { expiresAt: unknown }) | null>
|
|
23
|
+
) {}
|
|
24
|
+
|
|
25
|
+
async getToken(key: TKey, ...args: TArgs): Promise<TToken> {
|
|
26
|
+
let tokenFetchPromise = this.tokenFetchPromiseMap.get(key);
|
|
27
|
+
if (tokenFetchPromise) {
|
|
28
|
+
// Someone either already has a token or is in the process of getting one
|
|
29
|
+
// Wait for them to finish, then check for validity
|
|
30
|
+
const currentToken = await tokenFetchPromise;
|
|
31
|
+
|
|
32
|
+
if (currentToken.expiresAt > DateTime.now()) {
|
|
33
|
+
// Current token is valid, return it
|
|
34
|
+
return currentToken;
|
|
35
|
+
} else {
|
|
36
|
+
// Current token expired, start a new promise
|
|
37
|
+
tokenFetchPromise = new ResolvablePromise<TToken>();
|
|
38
|
+
this.tokenFetchPromiseMap.set(key, tokenFetchPromise);
|
|
39
|
+
|
|
40
|
+
try {
|
|
41
|
+
const newToken = await this.generateNewToken(key, ...args);
|
|
42
|
+
tokenFetchPromise.resolve(newToken);
|
|
43
|
+
return newToken;
|
|
44
|
+
} catch (e) {
|
|
45
|
+
tokenFetchPromise.reject(e);
|
|
46
|
+
tokenFetchPromise = undefined;
|
|
47
|
+
throw e;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
} else {
|
|
51
|
+
// No one has a token, start a new promise
|
|
52
|
+
tokenFetchPromise = new ResolvablePromise<TToken>();
|
|
53
|
+
this.tokenFetchPromiseMap.set(key, tokenFetchPromise);
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
const existingToken = await this.getExistingToken(key);
|
|
57
|
+
|
|
58
|
+
if (existingToken?.expiresAt) {
|
|
59
|
+
const expiresAt = coalesceDateTime(existingToken.expiresAt);
|
|
60
|
+
if (expiresAt && expiresAt > DateTime.now()) {
|
|
61
|
+
const newToken = { ...existingToken, expiresAt } as TToken;
|
|
62
|
+
tokenFetchPromise.resolve(newToken);
|
|
63
|
+
return newToken;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const newToken = await this.generateNewToken(key, ...args);
|
|
68
|
+
tokenFetchPromise.resolve(newToken);
|
|
69
|
+
return newToken;
|
|
70
|
+
} catch (e) {
|
|
71
|
+
tokenFetchPromise.reject(e);
|
|
72
|
+
tokenFetchPromise = undefined;
|
|
73
|
+
throw e;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async getExistingToken(key: TKey) {
|
|
79
|
+
const existingToken = await this.existingTokenFetcher(key);
|
|
80
|
+
|
|
81
|
+
if (existingToken?.expiresAt) {
|
|
82
|
+
const expiresAt = coalesceDateTime(existingToken.expiresAt);
|
|
83
|
+
if (expiresAt && expiresAt > DateTime.now()) {
|
|
84
|
+
return { ...existingToken, expiresAt } as TToken;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
}
|
/package/src/core/{spartan-token-providers → token-providers/spartan-token-providers}/index.ts
RENAMED
|
File without changes
|