yolkbot 1.4.7 → 1.5.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.
Files changed (129) hide show
  1. package/README.md +1 -1
  2. package/browser/build/global.js +1 -1
  3. package/browser/build/module.js +1 -1
  4. package/dist/api.d.ts +34 -16
  5. package/dist/api.js +164 -121
  6. package/dist/bot/GamePlayer.d.ts +2 -2
  7. package/dist/bot/GamePlayer.js +15 -5
  8. package/dist/bot.d.ts +121 -83
  9. package/dist/bot.js +624 -1077
  10. package/dist/comm/CommIn.js +14 -17
  11. package/dist/comm/CommOut.js +15 -15
  12. package/dist/constants/CommCode.js +1 -1
  13. package/dist/constants/findItemById.js +2 -1
  14. package/dist/constants/guns.d.ts +16 -41
  15. package/dist/constants/guns.js +137 -259
  16. package/dist/constants/index.d.ts +7 -9
  17. package/dist/constants/index.js +15 -13
  18. package/dist/dispatches/BanPlayerDispatch.d.ts +3 -1
  19. package/dist/dispatches/BootPlayerDispatch.d.ts +3 -1
  20. package/dist/dispatches/ChatDispatch.d.ts +3 -1
  21. package/dist/dispatches/ChatDispatch.js +3 -3
  22. package/dist/dispatches/FireDispatch.d.ts +3 -1
  23. package/dist/dispatches/GameOptionsDispatch.d.ts +3 -1
  24. package/dist/dispatches/GoToAmmoDispatch.d.ts +2 -0
  25. package/dist/dispatches/GoToAmmoDispatch.js +15 -16
  26. package/dist/dispatches/GoToCoopDispatch.d.ts +2 -0
  27. package/dist/dispatches/GoToCoopDispatch.js +19 -20
  28. package/dist/dispatches/GoToGrenadeDispatch.d.ts +2 -0
  29. package/dist/dispatches/GoToGrenadeDispatch.js +15 -16
  30. package/dist/dispatches/GoToPlayerDispatch.d.ts +3 -1
  31. package/dist/dispatches/GoToPlayerDispatch.js +16 -21
  32. package/dist/dispatches/GoToSpatulaDispatch.d.ts +2 -0
  33. package/dist/dispatches/GoToSpatulaDispatch.js +11 -14
  34. package/dist/dispatches/LookAtDispatch.d.ts +3 -1
  35. package/dist/dispatches/LookAtDispatch.js +8 -6
  36. package/dist/dispatches/LookAtPosDispatch.d.ts +3 -1
  37. package/dist/dispatches/LookAtPosDispatch.js +1 -1
  38. package/dist/dispatches/MeleeDispatch.d.ts +2 -0
  39. package/dist/dispatches/MeleeDispatch.js +4 -4
  40. package/dist/dispatches/MovementDispatch.d.ts +3 -1
  41. package/dist/dispatches/MovementDispatch.js +1 -1
  42. package/dist/dispatches/PauseDispatch.d.ts +2 -0
  43. package/dist/dispatches/ReloadDispatch.d.ts +2 -0
  44. package/dist/dispatches/ReloadDispatch.js +17 -10
  45. package/dist/dispatches/ReportPlayerDispatch.d.ts +4 -2
  46. package/dist/dispatches/ReportPlayerDispatch.js +8 -6
  47. package/dist/dispatches/ResetGameDispatch.d.ts +2 -0
  48. package/dist/dispatches/SaveLoadoutDispatch.d.ts +4 -2
  49. package/dist/dispatches/SaveLoadoutDispatch.js +9 -8
  50. package/dist/dispatches/SpawnDispatch.d.ts +2 -0
  51. package/dist/dispatches/SpawnDispatch.js +5 -1
  52. package/dist/dispatches/SwapWeaponDispatch.d.ts +3 -1
  53. package/dist/dispatches/SwapWeaponDispatch.js +1 -1
  54. package/dist/dispatches/SwitchTeamDispatch.d.ts +2 -0
  55. package/dist/dispatches/SwitchTeamDispatch.js +2 -1
  56. package/dist/dispatches/ThrowGrenadeDispatch.d.ts +3 -1
  57. package/dist/dispatches/index.d.ts +105 -182
  58. package/dist/dispatches/index.js +24 -25
  59. package/dist/enums.d.ts +154 -0
  60. package/dist/enums.js +114 -0
  61. package/dist/env/fetch.d.ts +15 -0
  62. package/dist/env/fetch.js +113 -79
  63. package/dist/env/globals.d.ts +9 -0
  64. package/dist/env/globals.js +11 -9
  65. package/dist/index.d.ts +31 -0
  66. package/dist/index.js +24 -14
  67. package/dist/packets/addPlayer.js +63 -0
  68. package/dist/packets/beginShellStreak.js +44 -0
  69. package/dist/packets/challengeCompleted.js +16 -0
  70. package/dist/packets/changeCharacter.js +46 -0
  71. package/dist/packets/chat.js +10 -0
  72. package/dist/packets/collectItem.js +26 -0
  73. package/dist/packets/die.js +40 -0
  74. package/dist/packets/endShellStreak.js +21 -0
  75. package/dist/packets/eventModifier.js +8 -0
  76. package/dist/packets/explode.js +19 -0
  77. package/dist/packets/fire.js +21 -0
  78. package/dist/packets/gameAction.js +33 -0
  79. package/dist/packets/gameJoined.js +64 -0
  80. package/dist/packets/gameOptions.js +27 -0
  81. package/dist/packets/hitMe.js +12 -0
  82. package/dist/packets/hitMeHardBoiled.js +18 -0
  83. package/dist/packets/hitThem.js +12 -0
  84. package/dist/packets/melee.js +8 -0
  85. package/dist/packets/metaGameState.js +62 -0
  86. package/dist/packets/pause.js +17 -0
  87. package/dist/packets/ping.js +19 -0
  88. package/dist/packets/playerInfo.js +15 -0
  89. package/dist/packets/reload.js +17 -0
  90. package/dist/packets/removePlayer.js +10 -0
  91. package/dist/packets/respawn.js +31 -0
  92. package/dist/packets/socketReady.js +16 -0
  93. package/dist/packets/spawnItem.js +11 -0
  94. package/dist/packets/swapWeapon.js +11 -0
  95. package/dist/packets/switchTeam.js +13 -0
  96. package/dist/packets/syncMe.js +25 -0
  97. package/dist/packets/syncThem.js +63 -0
  98. package/dist/packets/throwGrenade.js +17 -0
  99. package/dist/packets/updateBalance.js +8 -0
  100. package/dist/pathing/astar.js +33 -20
  101. package/dist/pathing/mapnode.d.ts +3 -1
  102. package/dist/pathing/mapnode.js +170 -65
  103. package/dist/socket.d.ts +21 -6
  104. package/dist/socket.js +48 -38
  105. package/dist/util.d.ts +4 -1
  106. package/dist/util.js +105 -45
  107. package/dist/wasm/bytes.d.ts +1 -1
  108. package/dist/wasm/bytes.js +1 -1
  109. package/dist/wasm/direct.d.ts +1 -1
  110. package/dist/wasm/direct.js +13 -13
  111. package/dist/wasm/legacy.d.ts +7 -6
  112. package/dist/wasm/legacy.js +14 -8
  113. package/package.json +43 -30
  114. package/dist/comm/index.d.ts +0 -12
  115. package/dist/comm/index.js +0 -11
  116. package/dist/constants/changelog.d.ts +0 -7
  117. package/dist/constants/housePromo.d.ts +0 -40
  118. package/dist/constants/language.d.ts +0 -3
  119. package/dist/constants/notices.d.ts +0 -4
  120. package/dist/constants/shellNews.d.ts +0 -12
  121. package/dist/constants/shellYoutube.d.ts +0 -12
  122. package/dist/constants/shopItems.d.ts +0 -15
  123. package/dist/constants/sounds.d.ts +0 -10
  124. package/dist/matchmaker.d.ts +0 -50
  125. package/dist/matchmaker.js +0 -141
  126. package/dist/pathing/binaryheap.d.ts +0 -18
  127. package/dist/pathing/binaryheap.js +0 -79
  128. package/dist/wasm/util.d.ts +0 -9
  129. package/dist/wasm/util.js +0 -19
package/dist/api.d.ts CHANGED
@@ -1,43 +1,61 @@
1
+ import { APIErrorEnum } from './enums';
2
+
3
+ export interface RawFirebase {
4
+ kind: string;
5
+ idToken: string;
6
+ refreshToken: string;
7
+ expiresIn: string; // in seconds
8
+ localId: string;
9
+ }
10
+
1
11
  export interface QueryRequest {
2
12
  cmd: string;
3
13
  [key: string]: any;
4
14
  }
5
15
 
6
16
  export interface QueryResponse {
17
+ ok: true;
7
18
  [key: string]: any;
8
19
  }
9
20
 
21
+ export interface AuthResponse extends QueryResponse {
22
+ firebase: RawFirebase;
23
+ }
24
+
25
+ export interface EmailResponse {
26
+ ok: true;
27
+ email: string;
28
+ }
29
+
10
30
  interface APIParams {
11
31
  proxy?: string;
12
32
  protocol?: string;
13
33
  instance?: string;
14
- maxRetries?: number;
15
- suppressErrors?: boolean;
34
+ customKey?: string | null;
16
35
  connectionTimeout?: number;
36
+ errorLogger?: (...args: any[]) => void;
17
37
  }
18
38
 
19
- export type QueryServicesError = 'websocket_connect_fail' | 'bad_json' | 'unknown_socket_error' | 'services_closed_early';
20
- export type AnonError = 'firebase_network_failed' | 'firebase_no_token';
21
- export type LoginError = AnonError | 'firebase_no_credentials' | 'firebase_bad_request' | 'firebase_unknown_error';
22
- export type EmailVerifyError = 'no_idtoken_passed' | 'firebase_invalid_response';
23
- export type OobCodeError = 'no_oob_code_passed' | 'firebase_unknown_error';
39
+ type ReturnError = { ok: false; error: APIErrorEnum };
40
+
41
+ type AnyObject = { [key: string]: any };
24
42
 
25
43
  export class API {
26
44
  proxy?: string;
27
45
  protocol: string;
28
46
  instance: string;
29
- maxRetries: number;
30
- suppressErrors: boolean;
47
+ customKey?: string | null;
31
48
  connectionTimeout: number;
32
49
 
33
50
  constructor(params?: APIParams);
34
51
 
35
- queryServices(request: QueryRequest): Promise<QueryResponse | QueryServicesError>;
52
+ queryServices(request: QueryRequest): Promise<QueryResponse | ReturnError>;
53
+
54
+ createAccount(email: string, password: string, customServicesParams?: AnyObject): Promise<AuthResponse | ReturnError>;
55
+ loginWithCredentials(email: string, password: string, customServicesParams?: AnyObject): Promise<AuthResponse | ReturnError>;
56
+ loginWithRefreshToken(refreshToken: string, customServicesParams?: AnyObject): Promise<AuthResponse | ReturnError>;
57
+ loginAnonymously(customServicesParams?: AnyObject): Promise<AuthResponse | ReturnError>;
36
58
 
37
- loginWithCredentials(email: string, password: string): Promise<QueryResponse | LoginError>;
38
- loginWithRefreshToken(refreshToken: string): Promise<QueryResponse | LoginError>;
39
- loginAnonymously(): Promise<QueryResponse | AnonError>;
40
- createAccount(email: string, password: string): Promise<QueryResponse | LoginError>;
41
- sendEmailVerification(idToken?: string): Promise<{ email: string } | EmailVerifyError>;
42
- verifyOobCode(oobCode: string): Promise<QueryResponse | OobCodeError>;
59
+ sendEmailVerification(idToken?: string): Promise<EmailResponse | ReturnError>;
60
+ verifyOobCode(oobCode: string): Promise<EmailResponse | ReturnError>;
43
61
  }
package/dist/api.js CHANGED
@@ -1,61 +1,71 @@
1
1
  import globals from "./env/globals.js";
2
2
  import yolkws from "./socket.js";
3
+ import { APIError } from "./enums.js";
4
+ import { createError } from "./util.js";
3
5
  import { FirebaseKey, UserAgent } from "./constants/index.js";
4
6
  const baseHeaders = {
5
7
  origin: "https://shellshock.io",
6
- "user-agent": UserAgent,
8
+ "user-agent": typeof process === "undefined" ? null : UserAgent,
7
9
  "x-client-version": "Chrome/JsCore/9.17.2/FirebaseCore-web",
8
10
  "x-firebase-locale": "en"
9
11
  };
10
12
 
11
13
  export class API {
14
+ errorLogger = (...args) => console.error(...args);
12
15
  constructor(params = {}) {
13
16
  this.proxy = params.proxy;
14
17
  this.instance = params.instance || "shellshock.io";
15
18
  this.protocol = params.protocol || "wss";
16
- this.maxRetries = params.maxRetries || 5;
17
- this.suppressErrors = params.suppressErrors || false;
19
+ this.customKey = params.customKey || null;
18
20
  this.connectionTimeout = params.connectionTimeout || 5000;
21
+ if (typeof params.errorLogger === "function")
22
+ this.errorLogger = params.errorLogger;
19
23
  }
20
24
  queryServices = async (request) => {
21
- const ws = new yolkws(`${this.protocol}://${this.instance}/services/`, this.proxy);
25
+ const ws = new yolkws(`${this.protocol}://${this.instance}/services/`, { proxy: this.proxy, errorLogger: this.errorLogger });
22
26
  ws.connectionTimeout = this.connectionTimeout;
23
- const didConnect = await ws.tryConnect(-2);
27
+ const didConnect = await ws.tryConnect();
24
28
  if (!didConnect || ws.socket.readyState !== 1)
25
- return "websocket_connect_fail";
29
+ return createError(APIError.WebSocketConnectFail);
26
30
  return new Promise((resolve) => {
27
31
  let resolved = false;
28
32
  ws.onmessage = (mes) => {
29
33
  resolved = true;
30
34
  try {
31
35
  const resp = JSON.parse(mes.data);
32
- resolve(resp);
33
- } catch {
34
- if (!this.suppressErrors) {
35
- console.error("queryServices: Bad API JSON response with call:", request.cmd, "and data:", JSON.stringify(request));
36
- console.error("queryServices: Full data sent:", JSON.stringify(request));
37
- }
38
- resolve("bad_json");
36
+ resolve({ ok: true, ...resp });
37
+ } catch (e) {
38
+ this.errorLogger("queryServices: error! command:", request.cmd, "and data:", request, e);
39
+ resolve(createError(APIError.InternalError));
39
40
  }
40
41
  ws.close();
41
42
  };
42
- ws.onerror = () => !resolved && resolve("unknown_socket_error");
43
- ws.onclose = () => !resolved && resolve("services_closed_early");
43
+ ws.onerror = (error) => {
44
+ if (resolved)
45
+ return;
46
+ resolved = true;
47
+ this.errorLogger("queryServices: websocket error! command:", request.cmd, "and data:", request, "error:", error);
48
+ resolve(createError(APIError.InternalError));
49
+ };
50
+ ws.onclose = () => {
51
+ if (resolved)
52
+ return;
53
+ resolved = true;
54
+ this.errorLogger("queryServices: services closed before sending back message");
55
+ this.errorLogger("queryServices: command:", request.cmd, "and data:", request);
56
+ resolve(createError(APIError.ServicesClosedEarly));
57
+ };
44
58
  ws.send(JSON.stringify(request));
45
59
  });
46
60
  };
47
- #authWithEmailPass = async (email, password, endpoint) => {
61
+ #authWithEmailPass = async (email, password, customServicesParams, endpoint) => {
48
62
  if (!email || !password)
49
- return "firebase_no_credentials";
50
- let body, firebaseToken;
63
+ return createError(APIError.MissingParams);
64
+ let body;
51
65
  try {
52
- const request = await globals.fetch(`https://identitytoolkit.googleapis.com/v1/accounts:${endpoint}?key=${FirebaseKey}`, {
66
+ const request = await globals.fetch(`https://identitytoolkit.googleapis.com/v1/accounts:${endpoint}?key=${this.customKey || FirebaseKey}`, {
53
67
  method: "POST",
54
- body: JSON.stringify({
55
- email,
56
- password,
57
- returnSecureToken: true
58
- }),
68
+ body: JSON.stringify({ email, password, returnSecureToken: true }),
59
69
  headers: {
60
70
  ...baseHeaders,
61
71
  "content-type": "application/json"
@@ -63,47 +73,43 @@ export class API {
63
73
  proxy: this.proxy
64
74
  });
65
75
  body = await request.json();
66
- firebaseToken = body.idToken;
67
76
  } catch (error) {
68
- if (error.code === "auth/network-request-failed") {
69
- if (!this.suppressErrors)
70
- console.error("loginWithCredentials: Network req failed (auth/network-request-failed)");
71
- return "firebase_network_failed";
72
- } else if (error.code === "auth/missing-email") {
73
- return "firebase_no_credentials";
77
+ if (error.code === "auth/too-many-requests")
78
+ return createError(APIError.FirebaseRateLimited);
79
+ else if (error.code === "auth/network-request-failed") {
80
+ this.errorLogger("authWithEmailPass: network error", body || error);
81
+ return createError(APIError.NetworkFail);
74
82
  } else if (error.code === "ERR_BAD_REQUEST") {
75
- if (!this.suppressErrors)
76
- console.error("loginWithCredentials: Error:", email, password);
77
- if (!this.suppressErrors)
78
- console.error("loginWithCredentials: Error:", body || error);
79
- return "firebase_bad_request";
83
+ this.errorLogger("authWithEmailPass: bad request", body || error);
84
+ return createError(APIError.InternalError);
85
+ } else if (error.code === "ECONNREFUSED") {
86
+ this.errorLogger("authWithEmailPass: connection refused", body || error);
87
+ return createError(APIError.NetworkFail);
80
88
  }
81
- if (!this.suppressErrors)
82
- console.error("loginWithCredentials: Error:", email, password, error);
83
- return "firebase_unknown_error";
89
+ this.errorLogger("authWithEmailPass: unknown error:", email, error);
90
+ return createError(APIError.InternalError);
84
91
  }
85
- if (!firebaseToken) {
86
- if (!this.suppressErrors)
87
- console.error("loginWithCredentials: the game sent no idToken", body);
88
- return "firebase_no_token";
92
+ if (!body.idToken) {
93
+ this.errorLogger("authWithEmailPass: missing idToken", body);
94
+ return createError(APIError.InternalError);
89
95
  }
90
- this.idToken = firebaseToken;
91
- const servicesQuery = await this.queryServices({ cmd: "auth", firebaseToken });
92
- return typeof servicesQuery === "object" ? { firebase: body, ...servicesQuery } : servicesQuery;
96
+ this.idToken = body.idToken;
97
+ const servicesQuery = await this.queryServices({ cmd: "auth", firebaseToken: body.idToken, ...customServicesParams });
98
+ return servicesQuery.ok ? { firebase: body, ...servicesQuery } : servicesQuery;
93
99
  };
94
- createAccount = async (email, password) => await this.#authWithEmailPass(email, password, "signUp");
95
- loginWithCredentials = async (email, password) => await this.#authWithEmailPass(email, password, "signInWithPassword");
96
- loginWithRefreshToken = async (refreshToken) => {
100
+ createAccount = (email, password, customServicesParams) => this.#authWithEmailPass(email, password, customServicesParams, "signUp");
101
+ loginWithCredentials = (email, password, customServicesParams) => this.#authWithEmailPass(email, password, customServicesParams, "signInWithPassword");
102
+ loginWithRefreshToken = async (refreshToken, customServicesParams) => {
97
103
  if (!refreshToken)
98
- return "firebase_no_credentials";
104
+ return createError(APIError.MissingParams);
99
105
  const formData = new URLSearchParams;
100
106
  formData.append("grant_type", "refresh_token");
101
107
  formData.append("refresh_token", refreshToken);
102
- let body, token;
108
+ let body;
103
109
  try {
104
- const request = await globals.fetch(`https://securetoken.googleapis.com/v1/token?key=${FirebaseKey}`, {
110
+ const request = await globals.fetch(`https://securetoken.googleapis.com/v1/token?key=${this.customKey || FirebaseKey}`, {
105
111
  method: "POST",
106
- body: formData,
112
+ body: formData.toString(),
107
113
  headers: {
108
114
  ...baseHeaders,
109
115
  "content-type": "application/x-www-form-urlencoded"
@@ -111,90 +117,127 @@ export class API {
111
117
  proxy: this.proxy
112
118
  });
113
119
  body = await request.json();
114
- token = body.id_token;
115
120
  } catch (error) {
116
- if (error.code === "auth/network-request-failed") {
117
- if (!this.suppressErrors)
118
- console.error("loginWithRefreshToken: Network req failed (auth/network-request-failed)");
119
- return "firebase_network_failed";
120
- } else if (error.code === "auth/missing-email") {
121
- return "firebase_no_credentials";
121
+ if (error.code === "auth/too-many-requests")
122
+ return createError(APIError.FirebaseRateLimited);
123
+ else if (error.code === "auth/network-request-failed") {
124
+ this.errorLogger("loginWithRefreshToken: network error", body || error);
125
+ return createError(APIError.NetworkFail);
126
+ } else if (error.code === "ECONNREFUSED") {
127
+ this.errorLogger("loginWithRefreshToken: connection refused", body || error);
128
+ return createError(APIError.NetworkFail);
122
129
  }
123
- if (!this.suppressErrors)
124
- console.error("loginWithRefreshToken: Error:", error, refreshToken);
125
- return "firebase_unknown_error";
130
+ this.errorLogger("loginWithRefreshToken: unknown error:", body, error);
131
+ return createError(APIError.InternalError);
126
132
  }
127
- if (!token) {
128
- if (!this.suppressErrors)
129
- console.error("loginWithRefreshToken: the game sent no idToken", body);
130
- return "firebase_no_token";
133
+ if (!body.id_token) {
134
+ this.errorLogger("loginWithRefreshToken: missing idToken", body);
135
+ return createError(APIError.InternalError);
131
136
  }
132
- this.idToken = token;
133
- const response = await this.queryServices({ cmd: "auth", firebaseToken: token });
134
- return typeof response === "object" ? { firebase: body, ...response } : response;
137
+ this.idToken = body.id_token;
138
+ const response = await this.queryServices({ cmd: "auth", firebaseToken: body.id_token, ...customServicesParams });
139
+ return response.ok ? { firebase: body, ...response } : response;
135
140
  };
136
- loginAnonymously = async () => {
137
- const req = await globals.fetch(`https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=${FirebaseKey}`, {
138
- method: "POST",
139
- body: JSON.stringify({ returnSecureToken: true }),
140
- headers: {
141
- ...baseHeaders,
142
- "content-type": "application/json"
143
- },
144
- proxy: this.proxy
145
- });
146
- const body = await req.json();
147
- const firebaseToken = body.idToken;
148
- if (!firebaseToken) {
149
- if (!this.suppressErrors)
150
- console.error("loginAnonymously: the game sent no idToken", body);
151
- return "firebase_no_token";
141
+ loginAnonymously = async (customServicesParams) => {
142
+ let body;
143
+ try {
144
+ const req = await globals.fetch(`https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=${this.customKey || FirebaseKey}`, {
145
+ method: "POST",
146
+ body: JSON.stringify({ returnSecureToken: true }),
147
+ headers: {
148
+ ...baseHeaders,
149
+ "content-type": "application/json"
150
+ },
151
+ proxy: this.proxy
152
+ });
153
+ body = await req.json();
154
+ } catch (error) {
155
+ if (error.code === "auth/too-many-requests")
156
+ return createError(APIError.FirebaseRateLimited);
157
+ else if (error.code === "ECONNREFUSED") {
158
+ this.errorLogger("loginAnonymously: connection refused", body || error);
159
+ return createError(APIError.NetworkFail);
160
+ }
161
+ this.errorLogger("loginAnonymously: unknown error:", body, error);
162
+ return createError(APIError.InternalError);
152
163
  }
153
- this.idToken = firebaseToken;
154
- const query = await this.queryServices({ cmd: "auth", firebaseToken });
155
- return typeof query === "object" ? { firebase: body, ...query } : query;
164
+ if (!body.idToken) {
165
+ this.errorLogger("loginAnonymously: missing idToken", body);
166
+ return createError(APIError.InternalError);
167
+ }
168
+ this.idToken = body.idToken;
169
+ const query = await this.queryServices({ cmd: "auth", firebaseToken: body.idToken, ...customServicesParams });
170
+ return query.ok ? { firebase: body, ...query } : query;
156
171
  };
157
172
  sendEmailVerification = async (idToken = this.idToken) => {
158
173
  if (!idToken)
159
- return "no_idtoken_passed";
160
- const req = await globals.fetch(`https://identitytoolkit.googleapis.com/v1/accounts:sendOobCode?key=${FirebaseKey}`, {
161
- method: "POST",
162
- body: JSON.stringify({ requestType: "VERIFY_EMAIL", idToken }),
163
- headers: {
164
- ...baseHeaders,
165
- "content-type": "application/json"
166
- },
167
- proxy: this.proxy
168
- });
169
- const body = await req.json();
174
+ return createError(APIError.MissingParams);
175
+ let body;
176
+ try {
177
+ const req = await globals.fetch(`https://identitytoolkit.googleapis.com/v1/accounts:sendOobCode?key=${this.customKey || FirebaseKey}`, {
178
+ method: "POST",
179
+ body: JSON.stringify({ requestType: "VERIFY_EMAIL", idToken }),
180
+ headers: {
181
+ ...baseHeaders,
182
+ "content-type": "application/json"
183
+ },
184
+ proxy: this.proxy
185
+ });
186
+ body = await req.json();
187
+ } catch (error) {
188
+ if (error.code === "auth/too-many-requests")
189
+ return createError(APIError.FirebaseRateLimited);
190
+ else if (error.code === "auth/network-request-failed") {
191
+ this.errorLogger("sendEmailVerification: network error", body || error);
192
+ return createError(APIError.NetworkFail);
193
+ } else if (error.code === "ECONNREFUSED") {
194
+ this.errorLogger("sendEmailVerification: connection refused", body || error);
195
+ return createError(APIError.NetworkFail);
196
+ }
197
+ this.errorLogger("sendEmailVerification: unknown error:", idToken, error);
198
+ return createError(APIError.InternalError);
199
+ }
170
200
  if (body.kind !== "identitytoolkit#GetOobConfirmationCodeResponse") {
171
- if (!this.suppressErrors)
172
- console.error("sendEmailVerification: the game sent an invalid response", body);
173
- return "firebase_invalid_response";
201
+ this.errorLogger("sendEmailVerification: the game sent an invalid response", body);
202
+ return createError(APIError.InternalError);
174
203
  }
175
- return { email: body.email };
204
+ return { ok: true, email: body.email };
176
205
  };
177
206
  verifyOobCode = async (oobCode) => {
178
207
  if (!oobCode)
179
- return "no_oob_code_passed";
180
- const req = await globals.fetch(`https://www.googleapis.com/identitytoolkit/v3/relyingparty/setAccountInfo?key=${FirebaseKey}`, {
181
- method: "POST",
182
- body: JSON.stringify({ oobCode }),
183
- headers: {
184
- ...baseHeaders,
185
- "x-client-version": "Chrome/JsCore/3.7.5/FirebaseCore-web",
186
- referer: "https://shellshockio-181719.firebaseapp.com/",
187
- "content-type": "application/json"
188
- },
189
- proxy: this.proxy
190
- });
191
- const body = await req.json();
208
+ return createError(APIError.MissingParams);
209
+ let body;
210
+ try {
211
+ const req = await globals.fetch(`https://www.googleapis.com/identitytoolkit/v3/relyingparty/setAccountInfo?key=${this.customKey || FirebaseKey}`, {
212
+ method: "POST",
213
+ body: JSON.stringify({ oobCode }),
214
+ headers: {
215
+ ...baseHeaders,
216
+ "x-client-version": "Chrome/JsCore/3.7.5/FirebaseCore-web",
217
+ referer: "https://shellshockio-181719.firebaseapp.com/",
218
+ "content-type": "application/json"
219
+ },
220
+ proxy: this.proxy
221
+ });
222
+ body = await req.json();
223
+ } catch (error) {
224
+ if (error.code === "auth/too-many-requests")
225
+ return createError(APIError.FirebaseRateLimited);
226
+ else if (error.code === "auth/network-request-failed") {
227
+ this.errorLogger("verifyOobCode: network error", body || error);
228
+ return createError(APIError.NetworkFail);
229
+ } else if (error.code === "ECONNREFUSED") {
230
+ this.errorLogger("verifyOobCode: connection refused", body || error);
231
+ return createError(APIError.NetworkFail);
232
+ }
233
+ this.errorLogger("verifyOobCode: unknown error:", oobCode, error);
234
+ return createError(APIError.InternalError);
235
+ }
192
236
  if (!body.emailVerified) {
193
- if (!this.suppressErrors)
194
- console.error("verifyOobCode: the game sent an invalid response", body);
195
- return "firebase_invalid_response";
237
+ this.errorLogger("verifyOobCode: the game sent an invalid response", body);
238
+ return createError(APIError.InternalError);
196
239
  }
197
- return body.email;
240
+ return { ok: true, email: body.email };
198
241
  };
199
242
  }
200
243
  export default API;
@@ -1,4 +1,4 @@
1
- import { AnyGun, Cluck9mm } from '../constants/guns';
1
+ import { CreatedGun } from '../constants/guns';
2
2
  import { Item } from '../constants/items';
3
3
 
4
4
  export interface Position {
@@ -87,7 +87,7 @@ export interface Social {
87
87
  active: boolean;
88
88
  }
89
89
 
90
- export type PlayerWeapons = [AnyGun, Cluck9mm];
90
+ export type PlayerWeapons = [CreatedGun, CreatedGun];
91
91
 
92
92
  export interface PlayerAdminData {
93
93
  ip: string;
@@ -1,5 +1,6 @@
1
1
  import { GunList, Movement, ShellStreak, SocialMedia } from "../constants/index.js";
2
2
  import { Cluck9mm } from "../constants/guns.js";
3
+ import { createGun } from "../util.js";
3
4
  const RSocialMedia = Object.fromEntries(Object.entries(SocialMedia).map(([key, value]) => [value, key.toLowerCase()]));
4
5
 
5
6
  export class GamePlayer {
@@ -10,9 +11,18 @@ export class GamePlayer {
10
11
  this.safeName = playerData.safeName;
11
12
  this.team = playerData.team;
12
13
  this.playing = playerData.playing;
13
- this.socials = playerData.social && JSON.parse(playerData.social);
14
- if (this.socials)
15
- this.socials.forEach((social) => social.type = RSocialMedia[social.id]);
14
+ this.socials = [];
15
+ if (typeof playerData.social === "string" && playerData.social.length) {
16
+ try {
17
+ const parsed = JSON.parse(playerData.social);
18
+ if (Array.isArray(parsed))
19
+ this.socials = parsed;
20
+ } catch (e) {
21
+ console.error("Error parsing socials:", e);
22
+ console.error("Report this on Github!");
23
+ }
24
+ }
25
+ this.socials.forEach((social) => social.type = RSocialMedia[social.id]);
16
26
  this.isVip = playerData.upgradeProductId > 0;
17
27
  this.showBadge = !playerData.hideBadge || false;
18
28
  this.streak = playerData.score;
@@ -53,8 +63,8 @@ export class GamePlayer {
53
63
  this.selectedGun = playerData.charClass;
54
64
  this.weapons = [];
55
65
  if (this.character.primaryGun) {
56
- this.weapons[0] = new GunList[this.selectedGun];
57
- this.weapons[1] = new Cluck9mm;
66
+ this.weapons[0] = createGun(GunList[this.selectedGun]);
67
+ this.weapons[1] = createGun(Cluck9mm);
58
68
  }
59
69
  this.grenades = 1;
60
70
  this.hp = playerData.hp;