diff --git a/src/webhook/handleInput.ts b/src/webhook/handleInput.ts index 0a5093d3..e41c37be 100644 --- a/src/webhook/handleInput.ts +++ b/src/webhook/handleInput.ts @@ -4,72 +4,70 @@ import { extractArticleId } from 'src/lib/sharedUtils'; import tutorial, { TUTORIAL_STEPS } from './handlers/tutorial'; import handlePostback from './handlePostback'; import { - ChatbotEvent, ChatbotState, ChatbotStateHandlerParams, ChatbotStateHandlerReturnType, } from 'src/types/chatbotState'; import { Result } from 'src/types/result'; -import { Message } from '@line/bot-sdk'; +import { Message, MessageEvent, TextEventMessage } from '@line/bot-sdk'; /** * Given input event and context, outputs the new context and the reply to emit. * - * @param {Object} context The current context of the bot - * @param {*} event The input event - * @param {*} userId LINE user ID that does the input + * @param context The current context of the bot + * @param event The input event + * @param userId LINE user ID that does the input */ export default async function handleInput( { data = {} }, - event: ChatbotEvent, + event: MessageEvent & { message: TextEventMessage }, userId: string ): Promise { let state: ChatbotState; let replies: Message[] = []; - if (event.input === undefined) { - throw new Error('input undefined'); - } - - if (event.type === 'message') { - // Trim input because these may come from other chatbot - // - const trimmedInput = event.input.trim(); - const articleId = extractArticleId(trimmedInput); - if (articleId) { - // Start new session, reroute to CHOOSING_ARTILCE and simulate "choose article" postback event - data = { - // Start a new session - sessionId: Date.now(), + // Trim input because these may come from other chatbot + // + const trimmedInput = event.message.text.trim(); + const articleId = extractArticleId(trimmedInput); + if (articleId) { + // Start new session, reroute to CHOOSING_ARTILCE and simulate "choose article" postback event + const sessionId = Date.now(); + return await handlePostback( + // Start a new session + { + sessionId, searchedText: '', - }; - event = { - type: 'postback', + }, + { + state: 'CHOOSING_ARTICLE', + sessionId, input: articleId, - }; - return await handlePostback({ data }, 'CHOOSING_ARTICLE', event, userId); - } else if (event.input === TUTORIAL_STEPS['RICH_MENU']) { - state = 'TUTORIAL'; - } else { - // The user forwarded us an new message. - // Create a new "search session". - // - data = { - // Used to determine button postbacks and GraphQL requests are from - // previous sessions - // - sessionId: Date.now(), - }; - state = '__INIT__'; - } + }, + userId + ); + } else if (event.message.text === TUTORIAL_STEPS['RICH_MENU']) { + state = 'TUTORIAL'; } else { - state = 'Error'; + // The user forwarded us an new message. + // Create a new "search session". + // + data = { + // Used to determine button postbacks and GraphQL requests are from + // previous sessions + // + sessionId: Date.now(), + }; + state = '__INIT__'; } - let params: ChatbotStateHandlerParams | ChatbotStateHandlerReturnType = { + const params: ChatbotStateHandlerParams = { data, state, - event, + event: { + ...event, + message: event.message, + }, userId, replies, }; diff --git a/src/webhook/index.ts b/src/webhook/index.ts index a6dc9153..700d42c5 100644 --- a/src/webhook/index.ts +++ b/src/webhook/index.ts @@ -18,13 +18,9 @@ import { import processMedia from './handlers/processMedia'; import UserSettings from '../database/models/userSettings'; import { Request } from 'koa'; -import { WebhookEvent } from '@line/bot-sdk'; +import { MessageEvent, TextEventMessage, WebhookEvent } from '@line/bot-sdk'; import { Result } from 'src/types/result'; -import { - ChatbotEvent, - Context, - PostbackActionData, -} from 'src/types/chatbotState'; +import { Context, PostbackActionData } from 'src/types/chatbotState'; const userIdBlacklist = (process.env.USERID_BLACKLIST || '').split(','); @@ -133,7 +129,13 @@ const singleUserHandler = async ( result = await processText( context, - { ...webhookEvent, input }, + // Make TS happy: + // Directly providing `webhookEvent` here can lead to type error + // because it cannot correctly narrow down webhookEvent.message to be TextEventMessage. + { + ...webhookEvent, + message: webhookEvent.message, + }, userId, req ); @@ -224,7 +226,7 @@ const singleUserHandler = async ( async function processText( context: { data: Partial }, - event: ChatbotEvent, + event: MessageEvent & { message: TextEventMessage }, userId: string, req: Request ): Promise {