Skip to content

Commit

Permalink
refactor(webhook): apply simpler postback handler signatures
Browse files Browse the repository at this point in the history
  • Loading branch information
MrOrz committed Nov 5, 2023
1 parent 6c1af7a commit 2433f47
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 55 deletions.
43 changes: 18 additions & 25 deletions src/webhook/handlePostback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,70 +7,65 @@ import defaultState from './handlers/defaultState';
import { ManipulationError } from './handlers/utils';
import tutorial from './handlers/tutorial';
import {
ChatbotEvent,
ChatbotState,
ChatbotStateHandlerParams,
ChatbotPostbackHandlerParams,
ChatbotStateHandlerReturnType,
Context,
PostbackActionData,
} from 'src/types/chatbotState';
import { Message } from '@line/bot-sdk';

/**
* Given input event and context, outputs the new context and the reply to emit.
*
* @param context The current context of the bot
* @param state The input state
* @param postbackData The input postback data extracted from event
* @param event The input event
* @param userId LINE user ID that does the input
*/
export default async function handlePostback(
{ data = {} },
data: Context,
postbackData: PostbackActionData<unknown>,
event: ChatbotEvent,
userId: string
) {
let replies: Message[] = [];

let params: ChatbotStateHandlerParams | ChatbotStateHandlerReturnType = {
const params: ChatbotPostbackHandlerParams = {
data,
state: postbackData.state,
event,
postbackData,
userId,
replies,
};

let result: ChatbotStateHandlerReturnType;

// Sets data and replies
//
try {
switch (params.state) {
switch (params.postbackData.state) {
case 'CHOOSING_ARTICLE': {
params = await choosingArticle(params);
result = await choosingArticle(params);
break;
}
case 'CHOOSING_REPLY': {
params = await choosingReply(params);
result = await choosingReply(params);
break;
}
case 'TUTORIAL': {
params = tutorial(params);
result = tutorial(params);
break;
}
case 'ASKING_ARTICLE_SOURCE': {
params = await askingArticleSource(params);
result = await askingArticleSource(params);
break;
}
case 'ASKING_ARTICLE_SUBMISSION_CONSENT': {
params = await askingArticleSubmissionConsent(params);
result = await askingArticleSubmissionConsent(params);
break;
}
default: {
params = defaultState(params);
result = defaultState(params);
break;
}
}
} catch (e) {
if (e instanceof ManipulationError) {
params = {
result = {
...params,
replies: [
{
Expand Down Expand Up @@ -115,10 +110,8 @@ export default async function handlePostback(
}
}

({ data, replies } = params);

return {
context: { data },
replies,
context: { data: result.data },
replies: result.replies,
};
}
37 changes: 18 additions & 19 deletions src/webhook/handlers/choosingArticle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import {

import UserArticleLink from '../../database/models/userArticleLink';
import choosingReply from './choosingReply';
import { ChatbotStateHandler } from 'src/types/chatbotState';
import { ChatbotPostbackHandler } from 'src/types/chatbotState';
import { FlexBubble, Message } from '@line/bot-sdk';

/**
Expand Down Expand Up @@ -57,17 +57,19 @@ function reorderArticleReplies(

// https://developers.line.biz/en/reference/messaging-api/#template-messages

const choosingArticle: ChatbotStateHandler = async (params) => {
const { data, state, event, userId } = params;
let { replies } = params;
const choosingArticle: ChatbotPostbackHandler = async (params) => {
const {
data,
userId,
postbackData: { input, state, sessionId },
} = params;

if (event.type !== 'postback' && event.type !== 'server_choose') {
// Input should be article ID, which is a string
if (typeof input !== 'string') {
throw new ManipulationError(t`Please choose from provided options.`);
}

const input = event.type === 'postback' ? event.postback.data : event.input;

if (input === POSTBACK_NO_ARTICLE_FOUND && data.searchedText) {
if (input === POSTBACK_NO_ARTICLE_FOUND && 'searchedText' in data) {
const visitor = ga(userId, state, data.searchedText);
visitor.event({
ec: 'UserInput',
Expand All @@ -76,11 +78,9 @@ const choosingArticle: ChatbotStateHandler = async (params) => {
});
visitor.send();

const inputSummary = ellipsis(data?.searchedText, 12);
const inputSummary = ellipsis(data.searchedText, 12);
return {
data,
event,
userId,
replies: [
createTextMessage({
text:
Expand All @@ -93,7 +93,7 @@ const choosingArticle: ChatbotStateHandler = async (params) => {
};
}

if (input === POSTBACK_NO_ARTICLE_FOUND && data.messageId) {
if (input === POSTBACK_NO_ARTICLE_FOUND && 'messageId' in data) {
const visitor = ga(userId, state, data.messageId);
visitor.event({
ec: 'UserInput',
Expand All @@ -104,8 +104,6 @@ const choosingArticle: ChatbotStateHandler = async (params) => {

return {
data,
event,
userId,
replies: [
createTextMessage({
text:
Expand Down Expand Up @@ -176,16 +174,17 @@ const choosingArticle: ChatbotStateHandler = async (params) => {
// choose reply for user
return await choosingReply({
data,
state: 'CHOOSING_REPLY',
event: {
type: 'server_choose',
postbackData: {
sessionId,
state: 'CHOOSING_REPLY',
input: articleReplies[0].reply?.id ?? '',
},
userId,
replies: [],
});
}

let replies: Message[] = [];

if (articleReplies.length !== 0) {
const countOfType: Record<ReplyTypeEnum, number> = {
RUMOR: 0,
Expand Down Expand Up @@ -456,7 +455,7 @@ Don’t trust the message just yet!`,

visitor.send();

return { data, event, userId, replies };
return { data, replies };
};

export default choosingArticle;
21 changes: 11 additions & 10 deletions src/webhook/handlers/choosingReply.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import {
import { getArticleURL, createTypeWords } from 'src/lib/sharedUtils';
import ga from 'src/lib/ga';
import UserSettings from 'src/database/models/userSettings';
import { FlexBubble } from '@line/bot-sdk';
import { ChatbotStateHandler } from 'src/types/chatbotState';
import { FlexBubble, Message } from '@line/bot-sdk';
import { ChatbotPostbackHandler } from 'src/types/chatbotState';
import {
GetReplyRelatedDataQuery,
GetReplyRelatedDataQueryVariables,
Expand Down Expand Up @@ -130,15 +130,16 @@ function createShareBubble(
};
}

const choosingReply: ChatbotStateHandler = async (params) => {
const { data, state, event, userId } = params;
let { replies } = params;

if (event.type !== 'postback' && event.type !== 'server_choose') {
const choosingReply: ChatbotPostbackHandler = async ({
data,
userId,
postbackData: { input, state },
}) => {
if (typeof input !== 'string') {
throw new ManipulationError(t`Please choose from provided options.`);
}

const selectedReplyId = event.input;
const selectedReplyId = input;

const { data: getReplyData, errors } = await gql`
query GetReplyRelatedData($id: String!, $articleId: String!) {
Expand Down Expand Up @@ -175,7 +176,7 @@ const choosingReply: ChatbotStateHandler = async (params) => {
userId
);

replies = [
const replies: Message[] = [
...createReplyMessages(GetReply, GetArticle, data.selectedArticleId ?? ''),
{
type: 'flex',
Expand Down Expand Up @@ -210,7 +211,7 @@ const choosingReply: ChatbotStateHandler = async (params) => {
visitor.event({ ec: 'Reply', ea: 'Type', el: GetReply.type, ni: true });
visitor.send();

return { data, event, userId, replies };
return { data, replies };
};

export default choosingReply;
2 changes: 1 addition & 1 deletion src/webhook/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ const singleUserHandler = async (
return;
}

result = await handlePostback(context, postbackData, webhookEvent, userId);
result = await handlePostback(context, postbackData, userId);
}

if (isReplied) {
Expand Down

0 comments on commit 2433f47

Please sign in to comment.