moons-ta-client 1.1.14 → 1.2.1

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.
@@ -4,12 +4,13 @@ import { v4 as uuidv4 } from "uuid";
4
4
  import { StateManager } from "./state-manager.js";
5
5
  import { Response_ResponseType, } from "./models/responses.js";
6
6
  import { Command_ModifyGameplay_Modifier } from "./models/commands.js";
7
- import { versionCode } from "./constants.js";
7
+ import { masterAddress, masterApiPort, versionCode } from "./constants.js";
8
8
  import WebSocket from "ws";
9
9
  // Created by Moon on 6/12/2022
10
10
  export * from "./scraper.js";
11
11
  export * from "./models/models.js";
12
12
  export class TAClient extends CustomEventEmitter {
13
+ _imageServer = `https://${masterAddress}:${masterApiPort}`;
13
14
  stateManager;
14
15
  uiVersion;
15
16
  client;
@@ -62,13 +63,8 @@ export class TAClient extends CustomEventEmitter {
62
63
  from: this.stateManager.getSelfGuid(),
63
64
  id: uuidv4(),
64
65
  packet: {
65
- oneofKind: "command",
66
- command: {
67
- type: {
68
- oneofKind: "heartbeat",
69
- heartbeat: true,
70
- },
71
- },
66
+ oneofKind: "heartbeat",
67
+ heartbeat: true,
72
68
  },
73
69
  });
74
70
  }, 10000);
@@ -104,31 +100,41 @@ export class TAClient extends CustomEventEmitter {
104
100
  this.token = token;
105
101
  this.client?.setToken(token);
106
102
  }
107
- forwardToUsers(packet, to) {
108
- this.client?.send({
109
- token: "",
110
- from: packet.from,
111
- id: packet.id,
112
- packet: {
113
- oneofKind: "forwardingPacket",
114
- forwardingPacket: {
115
- forwardTo: to,
116
- packet,
117
- },
103
+ async uploadImage(bytes) {
104
+ // If the image is one byte, assume we are uploading no image.
105
+ // This is related to the way I am forced to represent empty Uint8Arrays
106
+ if (bytes.length < 3) {
107
+ return "";
108
+ }
109
+ const blob = new Blob([bytes], { type: "image/png" });
110
+ const file = new File([blob], "dummy.png", {
111
+ type: "image/png",
112
+ });
113
+ const formData = new FormData();
114
+ formData.append("file", file);
115
+ const response = await fetch(`${this._imageServer}/api/file/upload`, {
116
+ method: "POST",
117
+ headers: {
118
+ Authorization: `Bearer ${this.token}`,
118
119
  },
120
+ body: formData,
119
121
  });
122
+ if (!response.ok) {
123
+ const error = await response.text();
124
+ throw new Error("Upload failed: " + error);
125
+ }
126
+ return await response.text();
120
127
  }
121
- sendCommand(command, to) {
122
- const packet = {
123
- token: this.token,
128
+ sendCommand(command) {
129
+ this.client?.send({
130
+ token: "",
124
131
  from: this.stateManager.getSelfGuid(),
125
132
  id: uuidv4(),
126
133
  packet: {
127
134
  oneofKind: "command",
128
135
  command,
129
136
  },
130
- };
131
- this.forwardToUsers(packet, to);
137
+ });
132
138
  }
133
139
  async sendRequest(request, to, timeout = 30000) {
134
140
  const packet = {
@@ -142,7 +148,7 @@ export class TAClient extends CustomEventEmitter {
142
148
  };
143
149
  const responseDictionary = [];
144
150
  // Create a promise that resolves when all responses are received
145
- const responsesPromise = new Promise((resolve) => {
151
+ const responsesPromise = new Promise((resolve, reject) => {
146
152
  const addListeners = () => {
147
153
  this.on("responseReceived", onResponseReceived);
148
154
  this.on("authorizationRequestedFromServer", onAuthorizationRequested);
@@ -209,20 +215,14 @@ export class TAClient extends CustomEventEmitter {
209
215
  // to provide a valid token, so we will combust
210
216
  const onAuthorizationRequested = () => {
211
217
  clearTimeout(timeoutTimer);
212
- throw "Authorization token invalid or not provided";
218
+ reject("Authorization token invalid or not provided");
213
219
  };
214
220
  addListeners();
215
221
  });
216
- // Assume forwardToUsers emits the 'responseReceived' event asynchronously
217
- if (to) {
218
- this.forwardToUsers(packet, to);
219
- }
220
- else {
221
- this.client?.send(packet, to);
222
- }
222
+ this.client?.send(packet);
223
223
  return responsesPromise;
224
224
  }
225
- async sendResponse(response, to) {
225
+ async sendResponse(response) {
226
226
  const packet = {
227
227
  token: this.token,
228
228
  from: this.stateManager.getSelfGuid(),
@@ -232,81 +232,110 @@ export class TAClient extends CustomEventEmitter {
232
232
  response,
233
233
  },
234
234
  };
235
- if (to) {
236
- this.forwardToUsers(packet, to);
237
- }
238
- else {
239
- this.client?.send(packet, to);
240
- }
235
+ this.client?.send(packet);
241
236
  }
242
237
  // --- Commands --- //
243
- playSong = (gameplayParameters, userIds) => {
238
+ playSong = (tournamentId, gameplayParameters, userIds) => {
244
239
  this.sendCommand({
240
+ tournamentId,
241
+ forwardTo: userIds,
245
242
  type: {
246
243
  oneofKind: "playSong",
247
244
  playSong: {
248
245
  gameplayParameters,
249
246
  },
250
247
  },
251
- }, userIds);
248
+ });
252
249
  };
253
- returnToMenu = (userIds) => {
250
+ returnToMenu = (tournamentId, userIds) => {
254
251
  this.sendCommand({
252
+ tournamentId,
253
+ forwardTo: userIds,
255
254
  type: {
256
255
  oneofKind: "returnToMenu",
257
256
  returnToMenu: true,
258
257
  },
259
- }, userIds);
258
+ });
260
259
  };
261
- flipColors = (userIds) => {
260
+ flipColors = (tournamentId, userIds) => {
262
261
  this.sendCommand({
262
+ tournamentId,
263
+ forwardTo: userIds,
263
264
  type: {
264
265
  oneofKind: "modifyGameplay",
265
266
  modifyGameplay: {
266
267
  modifier: Command_ModifyGameplay_Modifier.InvertColors,
267
268
  },
268
269
  },
269
- }, userIds);
270
+ });
270
271
  };
271
- flipHands = (userIds) => {
272
+ flipHands = (tournamentId, userIds) => {
272
273
  this.sendCommand({
274
+ tournamentId,
275
+ forwardTo: userIds,
273
276
  type: {
274
277
  oneofKind: "modifyGameplay",
275
278
  modifyGameplay: {
276
279
  modifier: Command_ModifyGameplay_Modifier.InvertHandedness,
277
280
  },
278
281
  },
279
- }, userIds);
282
+ });
283
+ };
284
+ disableBlueNotes = (tournamentId, userIds) => {
285
+ this.sendCommand({
286
+ tournamentId,
287
+ forwardTo: userIds,
288
+ type: {
289
+ oneofKind: "modifyGameplay",
290
+ modifyGameplay: {
291
+ modifier: Command_ModifyGameplay_Modifier.DisableBlueNotes,
292
+ },
293
+ },
294
+ });
280
295
  };
281
- showLoadedImage = (userIds, show = true) => {
296
+ disableRedNotes = (tournamentId, userIds) => {
282
297
  this.sendCommand({
298
+ tournamentId,
299
+ forwardTo: userIds,
300
+ type: {
301
+ oneofKind: "modifyGameplay",
302
+ modifyGameplay: {
303
+ modifier: Command_ModifyGameplay_Modifier.DisableRedNotes,
304
+ },
305
+ },
306
+ });
307
+ };
308
+ showLoadedImage = (tournamentId, userIds, show = true) => {
309
+ this.sendCommand({
310
+ tournamentId,
311
+ forwardTo: userIds,
283
312
  type: {
284
313
  oneofKind: "streamSyncShowImage",
285
314
  streamSyncShowImage: show,
286
315
  },
287
- }, userIds);
316
+ });
288
317
  };
289
- showColor = async (color, userIds) => {
290
- const response = await this.sendRequest({
318
+ showColor = (tournamentId, color, userIds) => {
319
+ this.sendCommand({
320
+ tournamentId,
321
+ forwardTo: userIds,
291
322
  type: {
292
323
  oneofKind: "showColorForStreamSync",
293
324
  showColorForStreamSync: {
294
325
  color,
295
326
  },
296
327
  },
297
- }, userIds);
298
- if (response.length <= 0) {
299
- throw new Error("Server timed out, or no users responded");
300
- }
301
- return response;
328
+ });
302
329
  };
303
- delayTestFinished = (userIds) => {
330
+ delayTestFinished = (tournamentId, userIds) => {
304
331
  this.sendCommand({
332
+ tournamentId,
333
+ forwardTo: userIds,
305
334
  type: {
306
335
  oneofKind: "delayTestFinish",
307
336
  delayTestFinish: true,
308
337
  },
309
- }, userIds);
338
+ });
310
339
  };
311
340
  // --- Requests --- //
312
341
  joinTournament = async (tournamentId) => {
@@ -341,11 +370,13 @@ export class TAClient extends CustomEventEmitter {
341
370
  }
342
371
  return response[0].response;
343
372
  };
344
- loadSong = async (levelId, userIds, timeout) => {
373
+ loadSong = async (tournamentId, levelId, userIds, timeout) => {
345
374
  const response = await this.sendRequest({
346
375
  type: {
347
376
  oneofKind: "loadSong",
348
377
  loadSong: {
378
+ tournamentId,
379
+ forwardTo: userIds,
349
380
  levelId,
350
381
  customHostUrl: "",
351
382
  },
@@ -356,11 +387,13 @@ export class TAClient extends CustomEventEmitter {
356
387
  }
357
388
  return response;
358
389
  };
359
- loadImage = async (bitmap, userIds) => {
390
+ loadImage = async (tournamentId, bitmap, userIds) => {
360
391
  const response = await this.sendRequest({
361
392
  type: {
362
393
  oneofKind: "preloadImageForStreamSync",
363
394
  preloadImageForStreamSync: {
395
+ tournamentId,
396
+ forwardTo: userIds,
364
397
  fileId: uuidv4(),
365
398
  data: bitmap,
366
399
  compressed: false,
@@ -372,11 +405,13 @@ export class TAClient extends CustomEventEmitter {
372
405
  }
373
406
  return response;
374
407
  };
375
- showPrompt = async (userIds, titleText, bodyText, canClose, options, timer) => {
408
+ showPrompt = async (tournamentId, userIds, titleText, bodyText, canClose, options, timer) => {
376
409
  const response = await this.sendRequest({
377
410
  type: {
378
411
  oneofKind: "showPrompt",
379
412
  showPrompt: {
413
+ tournamentId,
414
+ forwardTo: userIds,
380
415
  promptId: uuidv4(),
381
416
  messageTitle: titleText,
382
417
  messageText: bodyText,
@@ -696,13 +731,24 @@ export class TAClient extends CustomEventEmitter {
696
731
  }
697
732
  return response[0].response;
698
733
  };
699
- createQualifierEvent = async (tournamentId, event) => {
734
+ createQualifierEvent = async (tournamentId, name, infoChannelId, maps, flags, sort, qualifierImage) => {
700
735
  const response = await this.sendRequest({
701
736
  type: {
702
737
  oneofKind: "createQualifierEvent",
703
738
  createQualifierEvent: {
704
739
  tournamentId,
705
- event,
740
+ event: {
741
+ guid: "",
742
+ name,
743
+ infoChannel: {
744
+ id: infoChannelId,
745
+ name: "dummy",
746
+ },
747
+ qualifierMaps: maps,
748
+ flags,
749
+ sort,
750
+ image: await this.uploadImage(qualifierImage),
751
+ },
706
752
  },
707
753
  },
708
754
  });
@@ -734,7 +780,7 @@ export class TAClient extends CustomEventEmitter {
734
780
  setQualifierImage: {
735
781
  tournamentId,
736
782
  qualifierId,
737
- qualifierImage,
783
+ qualifierImage: await this.uploadImage(qualifierImage),
738
784
  },
739
785
  },
740
786
  });
@@ -854,14 +900,14 @@ export class TAClient extends CustomEventEmitter {
854
900
  }
855
901
  return response[0].response;
856
902
  };
857
- addAuthorizedUser = async (tournamentId, discordId, permissionFlags) => {
903
+ addAuthorizedUser = async (tournamentId, discordId, roleIds) => {
858
904
  const response = await this.sendRequest({
859
905
  type: {
860
906
  oneofKind: "addAuthorizedUser",
861
907
  addAuthorizedUser: {
862
908
  tournamentId,
863
909
  discordId,
864
- permissionFlags,
910
+ roleIds,
865
911
  },
866
912
  },
867
913
  });
@@ -956,12 +1002,38 @@ export class TAClient extends CustomEventEmitter {
956
1002
  }
957
1003
  return response[0].response;
958
1004
  };
959
- createTournament = async (tournament) => {
1005
+ createTournament = async (serverAddress, serverName, serverPort, serverWebsocketPort, name, tournamentImage = new Uint8Array([1]), enableTeams = false, enablePools = false, showTournamentButton = true, showQualifierButton = true, roles = [], teams = [], scoreUpdateFrequency = 30, bannedMods = [], pools = [], allowUnauthorizedView = false) => {
960
1006
  const response = await this.sendRequest({
961
1007
  type: {
962
1008
  oneofKind: "createTournament",
963
1009
  createTournament: {
964
- tournament,
1010
+ tournament: {
1011
+ guid: uuidv4(),
1012
+ users: [],
1013
+ matches: [],
1014
+ qualifiers: [],
1015
+ settings: {
1016
+ tournamentName: name,
1017
+ tournamentImage: await this.uploadImage(tournamentImage),
1018
+ enableTeams,
1019
+ enablePools,
1020
+ showTournamentButton,
1021
+ showQualifierButton,
1022
+ roles,
1023
+ teams,
1024
+ scoreUpdateFrequency,
1025
+ bannedMods,
1026
+ pools,
1027
+ allowUnauthorizedView,
1028
+ myPermissions: [],
1029
+ },
1030
+ server: {
1031
+ address: serverAddress,
1032
+ name: serverName,
1033
+ port: +serverPort,
1034
+ websocketPort: +serverWebsocketPort,
1035
+ },
1036
+ },
965
1037
  },
966
1038
  },
967
1039
  });
@@ -991,7 +1063,7 @@ export class TAClient extends CustomEventEmitter {
991
1063
  oneofKind: "setTournamentImage",
992
1064
  setTournamentImage: {
993
1065
  tournamentId,
994
- tournamentImage,
1066
+ tournamentImage: await this.uploadImage(tournamentImage),
995
1067
  },
996
1068
  },
997
1069
  });
@@ -1105,13 +1177,79 @@ export class TAClient extends CustomEventEmitter {
1105
1177
  }
1106
1178
  return response[0].response;
1107
1179
  };
1108
- addTournamentTeam = async (tournamentId, team) => {
1180
+ addTournamentRole = async (tournamentId, role) => {
1181
+ const response = await this.sendRequest({
1182
+ type: {
1183
+ oneofKind: "addTournamentRole",
1184
+ addTournamentRole: {
1185
+ tournamentId,
1186
+ role,
1187
+ },
1188
+ },
1189
+ });
1190
+ if (response.length <= 0) {
1191
+ throw new Error("Server timed out");
1192
+ }
1193
+ return response[0].response;
1194
+ };
1195
+ setTournamentRoleName = async (tournamentId, roleId, roleName) => {
1196
+ const response = await this.sendRequest({
1197
+ type: {
1198
+ oneofKind: "setTournamentRoleName",
1199
+ setTournamentRoleName: {
1200
+ tournamentId,
1201
+ roleId,
1202
+ roleName,
1203
+ },
1204
+ },
1205
+ });
1206
+ if (response.length <= 0) {
1207
+ throw new Error("Server timed out");
1208
+ }
1209
+ return response[0].response;
1210
+ };
1211
+ setTournamentRolePermissions = async (tournamentId, roleId, permissions) => {
1212
+ const response = await this.sendRequest({
1213
+ type: {
1214
+ oneofKind: "setTournamentRolePermissions",
1215
+ setTournamentRolePermissions: {
1216
+ tournamentId,
1217
+ roleId,
1218
+ permissions,
1219
+ },
1220
+ },
1221
+ });
1222
+ if (response.length <= 0) {
1223
+ throw new Error("Server timed out");
1224
+ }
1225
+ return response[0].response;
1226
+ };
1227
+ removeTournamentRole = async (tournamentId, roleId) => {
1228
+ const response = await this.sendRequest({
1229
+ type: {
1230
+ oneofKind: "removeTournamentRole",
1231
+ removeTournamentRole: {
1232
+ tournamentId,
1233
+ roleId,
1234
+ },
1235
+ },
1236
+ });
1237
+ if (response.length <= 0) {
1238
+ throw new Error("Server timed out");
1239
+ }
1240
+ return response[0].response;
1241
+ };
1242
+ addTournamentTeam = async (tournamentId, name, image) => {
1109
1243
  const response = await this.sendRequest({
1110
1244
  type: {
1111
1245
  oneofKind: "addTournamentTeam",
1112
1246
  addTournamentTeam: {
1113
1247
  tournamentId,
1114
- team,
1248
+ team: {
1249
+ guid: uuidv4(),
1250
+ name,
1251
+ image: await this.uploadImage(image),
1252
+ },
1115
1253
  },
1116
1254
  },
1117
1255
  });
@@ -1143,7 +1281,7 @@ export class TAClient extends CustomEventEmitter {
1143
1281
  setTournamentTeamImage: {
1144
1282
  tournamentId,
1145
1283
  teamId,
1146
- teamImage,
1284
+ teamImage: await this.uploadImage(teamImage),
1147
1285
  },
1148
1286
  },
1149
1287
  });
@@ -1167,13 +1305,18 @@ export class TAClient extends CustomEventEmitter {
1167
1305
  }
1168
1306
  return response[0].response;
1169
1307
  };
1170
- addTournamentPool = async (tournamentId, pool) => {
1308
+ addTournamentPool = async (tournamentId, name, image, maps) => {
1171
1309
  const response = await this.sendRequest({
1172
1310
  type: {
1173
1311
  oneofKind: "addTournamentPool",
1174
1312
  addTournamentPool: {
1175
1313
  tournamentId,
1176
- pool,
1314
+ pool: {
1315
+ guid: uuidv4(),
1316
+ name,
1317
+ image: await this.uploadImage(image),
1318
+ maps,
1319
+ },
1177
1320
  },
1178
1321
  },
1179
1322
  });
@@ -1198,6 +1341,22 @@ export class TAClient extends CustomEventEmitter {
1198
1341
  }
1199
1342
  return response[0].response;
1200
1343
  };
1344
+ setTournamentPoolImage = async (tournamentId, poolId, image) => {
1345
+ const response = await this.sendRequest({
1346
+ type: {
1347
+ oneofKind: "setTournamentPoolImage",
1348
+ setTournamentPoolImage: {
1349
+ tournamentId,
1350
+ poolId,
1351
+ poolImage: await this.uploadImage(image),
1352
+ },
1353
+ },
1354
+ });
1355
+ if (response.length <= 0) {
1356
+ throw new Error("Server timed out");
1357
+ }
1358
+ return response[0].response;
1359
+ };
1201
1360
  addTournamentPoolMaps = async (tournamentId, poolId, maps) => {
1202
1361
  const response = await this.sendRequest({
1203
1362
  type: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "moons-ta-client",
3
- "version": "1.1.14",
3
+ "version": "1.2.1",
4
4
  "type": "module",
5
5
  "main": "./dist/index.esm.js",
6
6
  "types": "./dist/index.d.ts",