Repository: Yoctol/bottender
Pull request #266 (2018-05-14 10:31:16)

Implement game_play event
clsoe #262 

codecov-io: # [Codecov](https://codecov.io/gh/Yoctol/bottender/pull/266?src=pr&el=h1) Report
> Merging [#266](https://codecov.io/gh/Yoctol/bottender/pull/266?src=pr&el=desc) into [master](https://codecov.io/gh/Yoctol/bottender/commit/15e40f8532a8c76db3e0b93c985b882234f147d5?src=pr&el=desc) will **increase** coverage by `<.01%`.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/Yoctol/bottender/pull/266/graphs/tree.svg?width=650&height=150&src=pr&token=JX3EGtxYH3)](https://codecov.io/gh/Yoctol/bottender/pull/266?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master     #266      +/-   ##
==========================================
+ Coverage   90.21%   90.22%   +<.01%     
==========================================
  Files         107      107              
  Lines        3199     3201       +2     
  Branches      763      764       +1     
==========================================
+ Hits         2886     2888       +2     
  Misses        275      275              
  Partials       38       38
```


| [Impacted Files](https://codecov.io/gh/Yoctol/bottender/pull/266?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [src/context/MessengerEvent.js](https://codecov.io/gh/Yoctol/bottender/pull/266/diff?src=pr&el=tree#diff-c3JjL2NvbnRleHQvTWVzc2VuZ2VyRXZlbnQuanM=) | `100% <100%> (ø)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/Yoctol/bottender/pull/266?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/Yoctol/bottender/pull/266?src=pr&el=footer). Last update [15e40f8...ebf5f7e](https://codecov.io/gh/Yoctol/bottender/pull/266?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

tw0517tw: As `payload` is JSON encoded data, would it be better if we do `JSON.parse()` here?
kpman: Good catch!
Already implemented it on this PR.

Patch:
diff --git a/src/context/MessengerEvent.js b/src/context/MessengerEvent.js
index 5cc806dd..48828f4d 100644
--- a/src/context/MessengerEvent.js
+++ b/src/context/MessengerEvent.js
@@ -77,6 +77,15 @@ export type Postback = {
   referral?: Referral,
 };
 
+export type GamePlay = {
+  game_id: string,
+  player_id: string,
+  context_type: 'SOLO' | 'THREAD' | 'GROUP',
+  context_id: string,
+  score: number,
+  payload: string,
+};
+
 export type Optin = {
   ref: string,
 };
@@ -157,6 +166,7 @@ export type MessengerRawEvent = {
   read?: Read,
   delivery?: Delivery,
   postback?: Postback,
+  game_play?: GamePlay,
   optin?: Optin,
   payment?: Payment,
   checkout_update?: CheckoutUpdate,
@@ -426,6 +436,40 @@ export default class MessengerEvent implements Event {
     return this._rawEvent.postback || null;
   }
 
+  /**
+   * Determine if the event is a game_play event.
+   *
+   */
+  get isGamePlay(): boolean {
+    return (
+      !!this._rawEvent.game_play && typeof this._rawEvent.game_play === 'object'
+    );
+  }
+
+  /**
+   * The game_play object from Messenger raw event.
+   *
+   */
+  get gamePlay(): ?GamePlay {
+    if (!this.isGamePlay) {
+      return null;
+    }
+
+    const rawGamePlay = (this._rawEvent: any).game_play;
+
+    let payload;
+    try {
+      payload = JSON.parse(rawGamePlay.payload);
+    } catch (e) {
+      payload = rawGamePlay.payload;
+    }
+
+    return {
+      ...rawGamePlay,
+      payload,
+    };
+  }
+
   /**
    * Determine if the event is an opt-in event.
    *


Test patch:
diff --git a/src/context/__tests__/MessengerEvent.spec.js b/src/context/__tests__/MessengerEvent.spec.js
index 59e82eef..82d357f4 100644
--- a/src/context/__tests__/MessengerEvent.spec.js
+++ b/src/context/__tests__/MessengerEvent.spec.js
@@ -298,6 +298,42 @@ const postback = {
   },
 };
 
+const gamePlay = {
+  sender: {
+    id: 'USER_ID',
+  },
+  recipient: {
+    id: 'PAGE_ID',
+  },
+  timestamp: 1469111400000,
+  game_play: {
+    game_id: 'GAME_ID',
+    player_id: 'PLAYER_ID',
+    context_type: 'SOLO',
+    context_id: 'CONTEXT_ID',
+    score: 99,
+    payload: '{"SOME_KEY":"SOME_VALUE"}',
+  },
+};
+
+const gamePlayWithNonValidPayload = {
+  sender: {
+    id: 'USER_ID',
+  },
+  recipient: {
+    id: 'PAGE_ID',
+  },
+  timestamp: 1469111400000,
+  game_play: {
+    game_id: 'GAME_ID',
+    player_id: 'PLAYER_ID',
+    context_type: 'SOLO',
+    context_id: 'CONTEXT_ID',
+    score: 99,
+    payload: 'SOME_STRING',
+  },
+};
+
 const optin = {
   sender: {
     id: 'USER_ID',
@@ -910,6 +946,46 @@ it('#postback', () => {
   expect(new MessengerEvent(textMessage).payload).toEqual(null);
 });
 
+it('#isGamePlay', () => {
+  expect(new MessengerEvent(textMessage).isGamePlay).toEqual(false);
+  expect(new MessengerEvent(imageMessage).isGamePlay).toEqual(false);
+  expect(new MessengerEvent(likeStickerMessage).isGamePlay).toEqual(false);
+  expect(new MessengerEvent(echoMessage).isGamePlay).toEqual(false);
+  expect(new MessengerEvent(quickReplyMessage).isGamePlay).toEqual(false);
+  expect(new MessengerEvent(postback).isGamePlay).toEqual(false);
+  expect(new MessengerEvent(gamePlay).isGamePlay).toEqual(true);
+  expect(new MessengerEvent(gamePlayWithNonValidPayload).isGamePlay).toEqual(
+    true
+  );
+});
+
+it('#gamePlay', () => {
+  expect(new MessengerEvent(textMessage).gamePlay).toEqual(null);
+  expect(new MessengerEvent(imageMessage).gamePlay).toEqual(null);
+  expect(new MessengerEvent(likeStickerMessage).gamePlay).toEqual(null);
+  expect(new MessengerEvent(echoMessage).gamePlay).toEqual(null);
+  expect(new MessengerEvent(quickReplyMessage).gamePlay).toEqual(null);
+  expect(new MessengerEvent(postback).gamePlay).toEqual(null);
+  expect(new MessengerEvent(gamePlay).gamePlay).toEqual({
+    game_id: 'GAME_ID',
+    player_id: 'PLAYER_ID',
+    context_type: 'SOLO',
+    context_id: 'CONTEXT_ID',
+    score: 99,
+    payload: {
+      SOME_KEY: 'SOME_VALUE',
+    },
+  });
+  expect(new MessengerEvent(gamePlayWithNonValidPayload).gamePlay).toEqual({
+    game_id: 'GAME_ID',
+    player_id: 'PLAYER_ID',
+    context_type: 'SOLO',
+    context_id: 'CONTEXT_ID',
+    score: 99,
+    payload: 'SOME_STRING',
+  });
+});
+
 it('#isOptin', () => {
   expect(new MessengerEvent(textMessage).isOptin).toEqual(false);
   expect(new MessengerEvent(imageMessage).isOptin).toEqual(false);