@smartico/public-api 0.0.4 → 0.0.5

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 (42) hide show
  1. package/README.md +23 -44
  2. package/dist/Core/GetLabelInfoRequest.d.ts +3 -0
  3. package/dist/Core/GetLabelInfoResponse.d.ts +7 -0
  4. package/dist/Core/GetTranslationsRequest.d.ts +7 -0
  5. package/dist/Core/GetTranslationsResponse.d.ts +7 -0
  6. package/dist/Core/PublicLabelSettings.d.ts +28 -0
  7. package/dist/Core/PublicProperties.d.ts +11 -0
  8. package/dist/Core/ResponseIdentify.d.ts +12 -0
  9. package/dist/Core/TranslationArea.d.ts +9 -0
  10. package/dist/Core/index.d.ts +8 -0
  11. package/dist/MiniGames/SAWAskForUsername.d.ts +4 -0
  12. package/dist/MiniGames/SAWDoSpinResponse.d.ts +1 -7
  13. package/dist/MiniGames/SAWSpinErrorCode.d.ts +7 -0
  14. package/dist/MiniGames/SAWTemplateUI.d.ts +2 -5
  15. package/dist/MiniGames/SAWUtils.d.ts +5 -0
  16. package/dist/MiniGames/index.d.ts +5 -2
  17. package/dist/OCache.d.ts +11 -0
  18. package/dist/SmarticoAPI.d.ts +14 -2
  19. package/dist/index.d.ts +1 -0
  20. package/dist/index.js +312 -36
  21. package/dist/index.js.map +1 -1
  22. package/dist/index.modern.mjs +217 -19
  23. package/dist/index.modern.mjs.map +1 -1
  24. package/package.json +9 -3
  25. package/src/Core/GetLabelInfoRequest.ts +5 -0
  26. package/src/Core/GetLabelInfoResponse.ts +6 -0
  27. package/src/Core/GetTranslationsRequest.ts +10 -0
  28. package/src/Core/GetTranslationsResponse.ts +8 -0
  29. package/src/Core/PublicLabelSettings.ts +34 -0
  30. package/src/Core/PublicProperties.ts +11 -0
  31. package/src/Core/ResponseIdentify.ts +14 -0
  32. package/src/Core/TranslationArea.ts +11 -0
  33. package/src/Core/index.ts +18 -0
  34. package/src/MiniGames/SAWAskForUsername.ts +5 -0
  35. package/src/MiniGames/SAWDoSpinResponse.ts +1 -8
  36. package/src/MiniGames/SAWSpinErrorCode.ts +8 -0
  37. package/src/MiniGames/SAWTemplateUI.ts +3 -5
  38. package/src/MiniGames/SAWUtils.ts +31 -0
  39. package/src/MiniGames/index.ts +8 -3
  40. package/src/OCache.ts +54 -0
  41. package/src/SmarticoAPI.ts +128 -9
  42. package/src/index.ts +1 -0
@@ -0,0 +1,5 @@
1
+
2
+ export enum SAWAskForUsername {
3
+ NOASK = "no-ask",
4
+ ONSUMBIT = "on-submit"
5
+ }
@@ -1,14 +1,7 @@
1
1
  import { ProtocolResponse } from "./../Base/ProtocolResponse";
2
+ import { SAWSpinErrorCode } from "./SAWSpinErrorCode";
2
3
 
3
4
 
4
- export enum SAWSpinErrorCode {
5
- SAW_OK = 0,
6
- SAW_NO_SPINS = 40001,
7
- SAW_PRIZE_POOL_EMPTY = 40002,
8
- SAW_NOT_ENOUGH_POINTS = 40003,
9
- SAW_FAILED_MAX_SPINS_REACHED = 40004,
10
- }
11
-
12
5
  export interface SAWDoSpinResponse extends ProtocolResponse {
13
6
  errCode: SAWSpinErrorCode;
14
7
  errMsg?: string;
@@ -0,0 +1,8 @@
1
+
2
+ export enum SAWSpinErrorCode {
3
+ SAW_OK = 0,
4
+ SAW_NO_SPINS = 40001,
5
+ SAW_PRIZE_POOL_EMPTY = 40002,
6
+ SAW_NOT_ENOUGH_POINTS = 40003,
7
+ SAW_FAILED_MAX_SPINS_REACHED = 40004,
8
+ }
@@ -1,7 +1,5 @@
1
- export enum AskForUsername {
2
- NOASK = "no-ask",
3
- ONSUMBIT = "on-submit"
4
- }
1
+ import { SAWAskForUsername } from "./SAWAskForUsername";
2
+
5
3
  export interface SAWTemplateUI {
6
4
  skin: string;
7
5
  name: string;
@@ -26,7 +24,7 @@ export interface SAWTemplateUI {
26
24
 
27
25
  promo_image?: string;
28
26
  promo_text?: string;
29
- ask_for_username?: AskForUsername;
27
+ ask_for_username?: SAWAskForUsername;
30
28
  show_prize_board?: boolean;
31
29
 
32
30
  max_spins_period_ms?: number;
@@ -0,0 +1,31 @@
1
+ import { SAWBuyInType } from "./SAWBuyInType";
2
+ import { SAWTemplate } from "./SAWTemplate";
3
+
4
+
5
+ class SAWUtils {
6
+
7
+ public static canPlay = (t: SAWTemplate, pointsBalance: number): boolean => {
8
+ if (t === null || t === undefined) {
9
+ return false;
10
+ }
11
+
12
+ switch (t.saw_buyin_type_id) {
13
+ case SAWBuyInType.Free: {
14
+ return true;
15
+ }
16
+ case SAWBuyInType.Spins: {
17
+ return t.spin_count !== null && t.spin_count > 0
18
+ }
19
+ case SAWBuyInType.Points: {
20
+ return t.buyin_cost_points <= pointsBalance;
21
+ }
22
+ default: {
23
+ console.error("MiniGamesUtils.canPlay: Unknwon SAW buyin type " + t.saw_buyin_type_id);
24
+ return false;
25
+ }
26
+ }
27
+ }
28
+
29
+ }
30
+
31
+ export { SAWUtils }
@@ -1,23 +1,26 @@
1
+ import { SAWUtils } from "./SAWUtils";
1
2
  import { SAWAcknowledgeType } from "./SAWAcknowledgeType";
3
+ import { SAWAskForUsername } from "./SAWAskForUsername";
2
4
  import { SAWBuyInType, SAWBuyInTypeName } from "./SAWBuyInType";
3
5
  import { SAWDoSpinRequest } from "./SAWDoSpinRequest";
4
- import { SAWDoSpinResponse, SAWSpinErrorCode } from "./SAWDoSpinResponse";
6
+ import { SAWDoSpinResponse } from "./SAWDoSpinResponse";
5
7
  import { SAWGameType, SAWGameTypeName } from "./SAWGameType";
6
8
  import { SAWGetTemplatesRequest } from "./SAWGetTemplatesRequest";
7
9
  import { SAWGetTemplatesResponse } from "./SAWGetTemplatesResponse";
8
10
  import { SAWPrize } from "./SAWPrize";
9
11
  import { SAWPrizeType } from "./SAWPrizeType";
10
12
  import { SAWPrizeUI } from "./SAWPrizeUI";
13
+ import { SAWSpinErrorCode } from "./SAWSpinErrorCode";
11
14
  import { SAWTemplate } from "./SAWTemplate";
12
15
  import { SAWTemplateUI } from "./SAWTemplateUI";
13
16
  import { SAWWinSoundType, SAWWinSoundFiles } from "./SAWWinSoundType";
14
17
 
15
18
  export {
19
+ SAWUtils,
16
20
  SAWAcknowledgeType,
17
21
  SAWBuyInType, SAWBuyInTypeName,
18
22
  SAWDoSpinRequest,
19
23
  SAWDoSpinResponse,
20
- SAWSpinErrorCode,
21
24
  SAWGameType, SAWGameTypeName,
22
25
  SAWGetTemplatesRequest,
23
26
  SAWGetTemplatesResponse,
@@ -26,5 +29,7 @@ export {
26
29
  SAWPrizeUI,
27
30
  SAWTemplate,
28
31
  SAWTemplateUI,
29
- SAWWinSoundType, SAWWinSoundFiles
32
+ SAWWinSoundType, SAWWinSoundFiles,
33
+ SAWAskForUsername,
34
+ SAWSpinErrorCode
30
35
  }
package/src/OCache.ts ADDED
@@ -0,0 +1,54 @@
1
+ import NodeCache from 'node-cache';
2
+
3
+ export enum ECacheContext {
4
+ Translations,
5
+ LabelInfo
6
+ }
7
+
8
+ const WITH_REF_CACHE = [
9
+ ECacheContext.Translations
10
+ ];
11
+
12
+ export class OCache {
13
+
14
+ private static cache: { [key: string] : NodeCache } = {}
15
+
16
+ public static get<T>(oKey: any, cacheContext: ECacheContext): T | undefined {
17
+
18
+ const key = cacheContext.toString() + '_' + JSON.stringify(oKey);
19
+
20
+ if (this.cache[cacheContext] === undefined) {
21
+ this.cache[cacheContext] = new NodeCache( { useClones: !WITH_REF_CACHE.includes(cacheContext) } );
22
+ }
23
+
24
+ return this.cache[cacheContext].get(key);
25
+ }
26
+
27
+ public static set(oKey: any, o: any, cacheContext: ECacheContext, ttlSeconds: number = 60) {
28
+
29
+ const key = cacheContext.toString() + '_' + JSON.stringify(oKey);
30
+
31
+ this.cache[cacheContext].set(key, o, ttlSeconds);
32
+ }
33
+
34
+ public static async use<T>(oKey: any, cacheContext: ECacheContext, f: () => Promise<T>, ttlSeconds: number = 60) {
35
+ if (ttlSeconds <= 0) {
36
+ return await f();
37
+ } else {
38
+ let o: T = OCache.get(oKey, cacheContext);
39
+
40
+ if (o === undefined) {
41
+ o = await f();
42
+ OCache.set(oKey, o, cacheContext, ttlSeconds);
43
+ }
44
+
45
+ return o;
46
+ }
47
+ }
48
+
49
+ public static async clear(cacheContext: ECacheContext) {
50
+ if (this.cache[cacheContext]) {
51
+ this.cache[cacheContext].flushAll();
52
+ }
53
+ }
54
+ }
@@ -7,9 +7,14 @@ import { SAWGetTemplatesRequest } from './MiniGames/SAWGetTemplatesRequest';
7
7
  import { SAWTemplate } from './MiniGames/SAWTemplate';
8
8
  import { IntUtils } from './IntUtils';
9
9
  import { ILogger } from './ILogger';
10
- import { SAWBuyInType, SAWBuyInTypeName, SAWGameType, SAWGameTypeName } from './MiniGames';
10
+ import { SAWBuyInType, SAWBuyInTypeName, SAWDoSpinRequest, SAWDoSpinResponse, SAWGameType, SAWGameTypeName, SAWSpinErrorCode, SAWUtils } from './MiniGames';
11
+ import { ECacheContext, OCache } from './OCache';
12
+ import { GetTranslationsRequest, GetTranslationsResponse, ResponseIdentify, TranslationArea } from './Core';
13
+ import { GetLabelInfoResponse } from './Core/GetLabelInfoResponse';
14
+ import { GetLabelInfoRequest } from './Core/GetLabelInfoRequest';
11
15
 
12
16
  const PUBLIC_API_URL = 'https://papi{ENV_ID}.smartico.ai/services/public';
17
+ const AVATAR_DOMAIN = 'https://img{ENV_ID}.smr.vc';
13
18
 
14
19
  interface IOptions {
15
20
  logger?: ILogger;
@@ -21,6 +26,9 @@ interface IOptions {
21
26
  class SmarticoAPI {
22
27
 
23
28
  private publicUrl: string;
29
+ private avatarDomain: string;
30
+
31
+
24
32
  private logger: ILogger;
25
33
  private logCIDs: ClassId[];
26
34
  private logHTTPTiming: boolean;
@@ -43,7 +51,8 @@ class SmarticoAPI {
43
51
  }
44
52
  label_api_key = label_api_key.substring(0, 36);
45
53
 
46
- this.publicUrl = PUBLIC_API_URL.replace('{ENV_ID}', ENV_ID);
54
+ this.publicUrl = PUBLIC_API_URL.replace('{ENV_ID}', ENV_ID);
55
+ this.avatarDomain = AVATAR_DOMAIN.replace('{ENV_ID}', ENV_ID);
47
56
  }
48
57
 
49
58
  private async send<T>(message: any, expectCID?: ClassId): Promise<T> {
@@ -59,6 +68,7 @@ class SmarticoAPI {
59
68
  try {
60
69
  const timeStart = new Date().getTime();
61
70
  const res = await superagent.post(this.publicUrl).send(message);
71
+ // const res = await superagent.post('http://channel01.int.smartico.ai:81/services/public').send(message);
62
72
  const timeEnd = new Date().getTime();
63
73
 
64
74
  if (this.logHTTPTiming) {
@@ -118,10 +128,94 @@ class SmarticoAPI {
118
128
  ...payload
119
129
  };
120
130
 
131
+ if (message.ext_user_id === undefined || message.ext_user_id === null) {
132
+ delete message.ext_user_id;
133
+ }
134
+
121
135
  return message as any
122
136
  }
123
137
 
124
- public async miniGamesGetTemplates(user_ext_id: string): Promise<SAWGetTemplatesResponse> {
138
+ public async coreReportCustomEvent(user_ext_id: string, eventType: string, payload: any = {}): Promise<any> {
139
+ const eventMessage = this.buildMessage<any, any>(user_ext_id, ClassId.EVENT, {
140
+ eventType,
141
+ payload
142
+ });
143
+
144
+ const eventResponse = await this.send<any>(eventMessage, ClassId.EVENT_RESPONSE);
145
+ return eventResponse;
146
+ }
147
+
148
+ public async coreGetTranslations(user_ext_id: string, lang_code: string, areas: TranslationArea[], cacheSec: number = 60): Promise<GetTranslationsResponse> {
149
+
150
+ const response = await OCache.use<GetTranslationsResponse>(`${lang_code}-${this.label_api_key}-${this.brand_api_key}`, ECacheContext.Translations, async () => {
151
+
152
+ const tsBaseRQ = this.buildMessage<GetTranslationsRequest, GetTranslationsResponse>(user_ext_id, ClassId.GET_TRANSLATIONS_REQUEST, {
153
+ lang_code: "EN",
154
+ hash_code: 0,
155
+ areas
156
+ });
157
+
158
+ const trBase = await this.send<GetTranslationsResponse>(tsBaseRQ);
159
+
160
+ if (lang_code !== "EN") {
161
+ const trUserRQ = this.buildMessage<GetTranslationsRequest, GetTranslationsResponse>(user_ext_id, ClassId.GET_TRANSLATIONS_REQUEST, {
162
+ lang_code,
163
+ hash_code: 0,
164
+ areas
165
+ });
166
+
167
+ const trUser = await this.send<GetTranslationsResponse>(trUserRQ);
168
+
169
+ Object.keys(trUser.translations).forEach( k => {
170
+ trBase.translations[k] = trUser.translations[k];
171
+ })
172
+ }
173
+
174
+ return trBase;
175
+
176
+ }, cacheSec );
177
+
178
+ return response;
179
+ }
180
+
181
+ public async coreIdentifyLabel(user_ext_id: string, cacheSec: number = 60): Promise<GetLabelInfoResponse> {
182
+
183
+ return OCache.use<GetLabelInfoResponse>(`${this.label_api_key} - ${this.brand_api_key}`, ECacheContext.LabelInfo, async () => {
184
+
185
+ const message = this.buildMessage<GetLabelInfoResponse, GetLabelInfoRequest>(user_ext_id, ClassId.GET_LABEL_INFO);
186
+
187
+ return this.send<GetLabelInfoResponse>(message, ClassId.GET_LABEL_INFO_RESPONSE)
188
+
189
+ }, cacheSec);
190
+
191
+ }
192
+
193
+ public async coreIdentifyUser(user_ext_id: string): Promise<ResponseIdentify> {
194
+
195
+ const message = this.buildMessage<any, ResponseIdentify>(user_ext_id, ClassId.IDENTIFY, {
196
+ request_id: IntUtils.uuid() // AA: do we need request_id?
197
+ });
198
+
199
+ const r = await this.send<ResponseIdentify>(message, ClassId.IDENTIFY_RESPONSE);
200
+
201
+ if (!(r.avatar_id && r.avatar_id.startsWith('http'))) {
202
+ r.avatar_id = AVATAR_DOMAIN + '/avatar/' + r.avatar_id
203
+ }
204
+
205
+ return r;
206
+ }
207
+
208
+ public async coreChangeUsername(user_ext_id: string, public_username_custom: string): Promise<{ public_username_custom: string }> {
209
+
210
+ const message = this.buildMessage<any, any>(user_ext_id, ClassId.CHANGE_USERNAME, {
211
+ public_username_custom
212
+ });
213
+
214
+ return this.send(message, ClassId.CHANGE_USERNAME_RESPONSE);
215
+ }
216
+
217
+
218
+ public async sawGetTemplates(user_ext_id: string): Promise<SAWGetTemplatesResponse> {
125
219
 
126
220
  const message = this.buildMessage<SAWGetTemplatesResponse, SAWGetTemplatesRequest>(user_ext_id, ClassId.SAW_GET_SPINS_REQUEST);
127
221
 
@@ -146,7 +240,7 @@ class SmarticoAPI {
146
240
 
147
241
  }
148
242
 
149
- public miniGamesFormatTemplatesForWidget(templates: SAWTemplate[], pointsBalance: number): any[] {
243
+ public async sawFormatTemplatesForWidget(templates: SAWTemplate[], pointsBalance: number): Promise<any[]> {
150
244
 
151
245
  return templates.filter( r => r.saw_template_id >= 1).map( r => (
152
246
  {
@@ -158,11 +252,7 @@ class SmarticoAPI {
158
252
  jackpot: r.jackpot_current,
159
253
  spin_count: r.spin_count,
160
254
  buyin_cost_points: r.buyin_cost_points,
161
- can_play: (
162
- r.saw_buyin_type_id === SAWBuyInType.Free
163
- || (r.saw_buyin_type_id === SAWBuyInType.Points && r.buyin_cost_points <= pointsBalance)
164
- || (r.saw_buyin_type_id === SAWBuyInType.Spins && r.spin_count > 0)
165
- ),
255
+ can_play: SAWUtils.canPlay(r, pointsBalance),
166
256
  icon:
167
257
  r.saw_skin_ui_definition?.skin_folder
168
258
  ? r.saw_skin_ui_definition?.skin_folder + '/ico.png'
@@ -172,6 +262,35 @@ class SmarticoAPI {
172
262
 
173
263
  }
174
264
 
265
+ public async sawSpinRequest(user_ext_id: string, saw_template_id: number, round_id: number): Promise<SAWDoSpinResponse> {
266
+
267
+ const message = this.buildMessage<SAWDoSpinRequest, SAWDoSpinResponse>(user_ext_id, ClassId.SAW_DO_SPIN_REQUEST, {
268
+ saw_template_id,
269
+ request_id: IntUtils.uuid()
270
+ });
271
+
272
+ const spinAttemptResponse = await this.send<SAWDoSpinResponse>(message, ClassId.SAW_DO_SPIN_RESPONSE);
273
+
274
+ // to simulate fail
275
+ // response.errCode = SAWSpinErrorCode.SAW_NO_SPINS;
276
+
277
+ const status: string = {
278
+ [SAWSpinErrorCode.SAW_OK]: 'OK',
279
+ [SAWSpinErrorCode.SAW_NO_SPINS]: 'NO SPINS AVAILABLE',
280
+ [SAWSpinErrorCode.SAW_PRIZE_POOL_EMPTY]: 'PRIZE POOL IS EMPTY',
281
+ [SAWSpinErrorCode.SAW_NOT_ENOUGH_POINTS]: 'NOT ENOUGH POINTS',
282
+ [SAWSpinErrorCode.SAW_FAILED_MAX_SPINS_REACHED]: 'MAX SPIN ATTEMPTS REACHED',
283
+ }[spinAttemptResponse.errCode] || 'OTHER';
284
+
285
+ await this.coreReportCustomEvent(user_ext_id, 'minigame_attempt', {
286
+ saw_template_id,
287
+ status,
288
+ round_id,
289
+ });
290
+
291
+ return spinAttemptResponse;
292
+ }
293
+
175
294
  }
176
295
 
177
296
  export { SmarticoAPI }
package/src/index.ts CHANGED
@@ -3,6 +3,7 @@ import { ILogger } from './ILogger';
3
3
  import { SmarticoAPI } from './SmarticoAPI'
4
4
 
5
5
  export * from './MiniGames';
6
+ export * from './Core';
6
7
 
7
8
  export {
8
9
  SmarticoAPI,