Skip to content

Commit

Permalink
feat(message): support One-Time Notification (#551)
Browse files Browse the repository at this point in the history
  • Loading branch information
chentsulin committed Apr 6, 2020
1 parent 5adcf9a commit 347a1a3
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 15 deletions.
14 changes: 14 additions & 0 deletions packages/messaging-api-messenger/src/Messenger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,19 @@ function createAirlineUpdateTemplate(
);
}

function createOneTimeNotifReqTemplate(
attrs: Types.OneTimeNotifReqAttributes,
options?: { quickReplies?: Types.QuickReply[] }
): Types.Message {
return createTemplate(
{
templateType: 'one_time_notif_req',
...attrs,
},
options
);
}

const Messenger = {
createMessage,
createText,
Expand All @@ -362,6 +375,7 @@ const Messenger = {
createAirlineCheckinTemplate,
createAirlineItineraryTemplate,
createAirlineUpdateTemplate,
createOneTimeNotifReqTemplate,
};

export default Messenger;
39 changes: 26 additions & 13 deletions packages/messaging-api-messenger/src/MessengerBatch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -241,13 +241,25 @@ function sendAirlineUpdateTemplate(
);
}

function sendOneTimeNotifReqTemplate(
psidOrRecipient: Types.PsidOrRecipient,
attrs: Types.OneTimeNotifReqAttributes,
options?: Types.SendOption & Types.BatchRequestOptions
): Types.BatchItem {
return sendMessage(
psidOrRecipient,
Messenger.createOneTimeNotifReqTemplate(attrs, options),
options
);
}

function getUserProfile(
userId: string,
options: {
fields?: Types.UserProfileField[];
accessToken?: string;
} & Types.BatchRequestOptions = {}
) {
): Types.BatchItem {
const batchRequestOptions = pick(options, ['name', 'dependsOn']);

const fields = options.fields || [
Expand All @@ -271,7 +283,7 @@ function sendSenderAction(
psidOrRecipient: Types.PsidOrRecipient,
senderAction: Types.SenderAction,
options: Types.SendOption & Types.BatchRequestOptions = {}
) {
): Types.BatchItem {
const recipient =
typeof psidOrRecipient === 'string'
? {
Expand All @@ -294,21 +306,21 @@ function sendSenderAction(
function typingOn(
idOrRecipient: Types.PsidOrRecipient,
options?: Types.SendOption & Types.BatchRequestOptions
) {
): Types.BatchItem {
return sendSenderAction(idOrRecipient, 'typing_on', options);
}

function typingOff(
idOrRecipient: Types.PsidOrRecipient,
options?: Types.SendOption & Types.BatchRequestOptions
) {
): Types.BatchItem {
return sendSenderAction(idOrRecipient, 'typing_off', options);
}

function markSeen(
idOrRecipient: Types.PsidOrRecipient,
options?: Types.SendOption & Types.BatchRequestOptions
) {
): Types.BatchItem {
return sendSenderAction(idOrRecipient, 'mark_seen', options);
}

Expand All @@ -317,7 +329,7 @@ function passThreadControl(
targetAppId: number,
metadata: string,
options: { accessToken?: string } & Types.BatchRequestOptions = {}
) {
): Types.BatchItem {
const batchRequestOptions = pick(options, ['name', 'dependsOn']);

return {
Expand All @@ -337,15 +349,15 @@ function passThreadControlToPageInbox(
recipientId: string,
metadata: string,
options: { accessToken?: string } = {}
) {
): Types.BatchItem {
return passThreadControl(recipientId, 263902037430900, metadata, options);
}

function takeThreadControl(
recipientId: string,
metadata: string,
options: { accessToken?: string } & Types.BatchRequestOptions = {}
) {
): Types.BatchItem {
const batchRequestOptions = pick(options, ['name', 'dependsOn']);

return {
Expand All @@ -364,7 +376,7 @@ function requestThreadControl(
recipientId: string,
metadata: string,
options: { accessToken?: string } & Types.BatchRequestOptions = {}
) {
): Types.BatchItem {
const batchRequestOptions = pick(options, ['name', 'dependsOn']);

return {
Expand All @@ -382,7 +394,7 @@ function requestThreadControl(
function getThreadOwner(
recipientId: string,
options: { accessToken?: string } & Types.BatchRequestOptions = {}
) {
): Types.BatchItem {
const batchRequestOptions = pick(options, ['name', 'dependsOn']);

return {
Expand All @@ -399,7 +411,7 @@ function associateLabel(
userId: string,
labelId: number,
options: { accessToken?: string } & Types.BatchRequestOptions = {}
) {
): Types.BatchItem {
const batchRequestOptions = pick(options, ['name', 'dependsOn']);

return {
Expand All @@ -417,7 +429,7 @@ function dissociateLabel(
userId: string,
labelId: number,
options: { accessToken?: string } & Types.BatchRequestOptions = {}
): object {
): Types.BatchItem {
const batchRequestOptions = pick(options, ['name', 'dependsOn']);

return {
Expand All @@ -434,7 +446,7 @@ function dissociateLabel(
function getAssociatedLabels(
userId: string,
options: { accessToken?: string } & Types.BatchRequestOptions = {}
): object {
): Types.BatchItem {
const batchRequestOptions = pick(options, ['name', 'dependsOn']);

return {
Expand Down Expand Up @@ -464,6 +476,7 @@ const MessengerBatch = {
sendAirlineCheckinTemplate,
sendAirlineItineraryTemplate,
sendAirlineUpdateTemplate,
sendOneTimeNotifReqTemplate,

getUserProfile,

Expand Down
13 changes: 13 additions & 0 deletions packages/messaging-api-messenger/src/MessengerClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1058,6 +1058,19 @@ export default class MessengerClient {
);
}

// https://developers.facebook.com/docs/messenger-platform/send-messages/one-time-notification/#one-time-notif
sendOneTimeNotifReqTemplate(
psidOrRecipient: Types.PsidOrRecipient,
attrs: Types.OneTimeNotifReqAttributes,
options?: Types.SendOption
): Promise<Types.SendMessageSuccessResponse> {
return this.sendMessage(
psidOrRecipient,
Messenger.createOneTimeNotifReqTemplate(attrs, options),
options
);
}

/**
* Typing
*
Expand Down
18 changes: 16 additions & 2 deletions packages/messaging-api-messenger/src/MessengerTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ export type RecipientWithCommentId = {
commentId: string;
};

/**
* Used for the Messenger Platform's One-Time Notification API.
*/
export type RecipientWithOneTimeNotifToken = {
oneTimeNotifToken: string;
};

/**
* Description of the message recipient. All requests must include one to identify the recipient.
*/
Expand All @@ -56,7 +63,8 @@ export type Recipient =
| RecipientWithPhoneNumber
| RecipientWithUserRef
| RecipientWithPostId
| RecipientWithCommentId;
| RecipientWithCommentId
| RecipientWithOneTimeNotifToken;

/**
* Description of the message recipient. If a string is provided, it will be recognized as a psid.
Expand Down Expand Up @@ -106,7 +114,8 @@ export type TemplateAttachmentPayload = {
| 'airline_boardingpass'
| 'airline_checkin'
| 'airline_itinerary'
| 'airline_update';
| 'airline_update'
| 'one_time_notif_req';
[key: string]: any; // FIXME: list all of templates
};

Expand Down Expand Up @@ -380,6 +389,11 @@ export type AirlineUpdateAttributes = {
updateFlightInfo: UpdateFlightInfo;
};

export type OneTimeNotifReqAttributes = {
title: string;
payload: string;
};

export type SenderAction = 'mark_seen' | 'typing_on' | 'typing_off';

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1060,6 +1060,36 @@ describe('sendAirlineUpdateTemplate', () => {
});
});

describe('sendOneTimeNotifReqTemplate', () => {
it('should create send one time notif req template request', () => {
expect(
MessengerBatch.sendOneTimeNotifReqTemplate(RECIPIENT_ID, {
title: '<TITLE_TEXT>',
payload: '<USER_DEFINED_PAYLOAD>',
})
).toEqual({
method: 'POST',
relativeUrl: 'me/messages',
body: {
messagingType: 'UPDATE',
message: {
attachment: {
type: 'template',
payload: {
templateType: 'one_time_notif_req',
title: '<TITLE_TEXT>',
payload: '<USER_DEFINED_PAYLOAD>',
},
},
},
recipient: {
id: RECIPIENT_ID,
},
},
});
});
});

describe('getUserProfile', () => {
it('should create get user profile request', () => {
expect(MessengerBatch.getUserProfile(RECIPIENT_ID)).toEqual({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1298,3 +1298,52 @@ describe('#sendAirlineUpdateTemplate', () => {
});
});
});

describe('#sendOneTimeNotifReqTemplate', () => {
it('should call messages api with one time notif req template', async () => {
const { client, mock } = createMock();

const reply = {
recipient_id: USER_ID,
message_id: 'mid.1489394984387:3dd22de509',
};

let url;
let data;
mock.onPost().reply(config => {
url = config.url;
data = config.data;
return [200, reply];
});

const res = await client.sendOneTimeNotifReqTemplate(USER_ID, {
title: '<TITLE_TEXT>',
payload: '<USER_DEFINED_PAYLOAD>',
});

expect(url).toEqual(
`https://graph.facebook.com/v4.0/me/messages?access_token=${ACCESS_TOKEN}`
);
expect(JSON.parse(data)).toEqual({
messaging_type: 'UPDATE',
recipient: {
id: USER_ID,
},
message: {
attachment: {
type: 'template',
payload: {
template_type: 'one_time_notif_req',
title: '<TITLE_TEXT>',
payload: '<USER_DEFINED_PAYLOAD>',
},
},
},
});

expect(res).toEqual({
recipientId: USER_ID,
messageId: 'mid.1489394984387:3dd22de509',
});
});
});

0 comments on commit 347a1a3

Please sign in to comment.