Skip to content

Commit

Permalink
Release 1.0.0-beta.2
Browse files Browse the repository at this point in the history
  • Loading branch information
webNeat committed Jun 27, 2021
1 parent 2c7f9af commit caee14d
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 23 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "messenger-chat",
"author": "Amine Ben hammou",
"version": "1.0.0-beta.1",
"version": "1.0.0-beta.2",
"license": "MIT",
"description": "A library to create chat bots for Messenger",
"module": "dist/messenger-chat.esm.js",
Expand Down
24 changes: 20 additions & 4 deletions src/bot/handle.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {EventEntry, WebhookEvent} from '../events/types'
import {Reply} from '../messages/types'
import {BotConfig} from './types'

export async function handle(config: BotConfig, event: WebhookEvent) {
Expand All @@ -11,19 +12,34 @@ export async function handle(config: BotConfig, event: WebhookEvent) {
async function handleEntry(config: BotConfig, entry: EventEntry) {
const messaging = entry.messaging[0]
const {recipient, sender} = messaging
const {accessToken, storage, send} = config
const {storage, initialContext} = config
const contextKey = `${sender.id}-${recipient.id}`
const context = (await storage.get(contextKey)) || config.initialContext
const context = (await storage.get(contextKey)) || initialContext
const setContext = (value: any) => storage.set(contextKey, value)
let response = config.handle({...messaging, context, setContext})
const getUserFields = () => loadUserFields(config, sender)
let response = config.handle({...messaging, context, setContext, getUserFields})
if (response instanceof Promise) {
response = await response
}
if (response) {
await send(accessToken, {
await sendReply(config, {
messaging_type: 'RESPONSE',
recipient: sender,
message: response,
})
}
}

async function sendReply({axiosInstance, accessToken}: BotConfig, reply: Reply) {
return axiosInstance.post(
`https://graph.facebook.com/v11.0/me/messages?access_token=${accessToken}`,
reply
)
}

async function loadUserFields({axiosInstance, accessToken}: BotConfig, sender: {id: string}) {
const res = await axiosInstance.get(
`https://graph.facebook.com/v11.0/${sender.id}?access_token=${accessToken}&fields=id,first_name,last_name,profile_pic`
)
return res.data
}
6 changes: 1 addition & 5 deletions src/bot/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,7 @@ export function bot(config: Partial<BotConfig>): Bot {
config = {
initialContext: {},
storage: memoryStorage(),
send: (token, data) =>
axiosInstance.post(
`https://graph.facebook.com/v11.0/me/messages?access_token=${token}`,
data
),
axiosInstance,
...config,
}

Expand Down
11 changes: 10 additions & 1 deletion src/bot/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {AxiosInstance} from 'axios'
import {Message} from '../messages/types'
import {ContextStorage} from '../storages/types'
import {WebhookEvent, MessagingItem} from '../events/types'
Expand All @@ -8,7 +9,7 @@ export type BotConfig = {
initialContext: any
storage: ContextStorage
handle: (entry: ChatEntry) => Message | undefined | Promise<Message | undefined>
send: (accessToken: string, data: any) => Promise<any>
axiosInstance: AxiosInstance
}

export interface Bot {
Expand All @@ -25,4 +26,12 @@ export type VerificationQuery = {
export type ChatEntry = MessagingItem & {
context: any
setContext: (value: Record<string, any>) => void
getUserFields: () => Promise<UserFields>
}

export type UserFields = {
id: string
first_name: string
last_name: string
profile_pic: string
}
27 changes: 15 additions & 12 deletions test/bot.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {BotConfig, ChatEntry} from '../src/types'
import {bot, event, text, textReply} from '../src'
import {AxiosInstance} from 'axios'

describe('bot', () => {
const evt = event()
Expand All @@ -14,17 +15,18 @@ describe('bot', () => {
})

test(`simple echo bot`, async () => {
const send = jest.fn()
const axiosMock = ({post: jest.fn()} as any) as AxiosInstance
const sendUrl = `https://graph.facebook.com/v11.0/me/messages?access_token=fake-access-token`
const handle = ({message}: ChatEntry) => {
if (message) {
return text(`You said: "${message.text}"`)
}
return text(`Send me a message and I will send it back to you!`)
}
const app = makeBot({send, handle})
const app = makeBot({axiosInstance: axiosMock, handle})

await app.handle(getStarted)
expect(send).toBeCalledWith('fake-access-token', {
expect(axiosMock.post).toBeCalledWith(sendUrl, {
messaging_type: 'RESPONSE',
recipient: {id: 'bob'},
message: {
Expand All @@ -34,15 +36,16 @@ describe('bot', () => {
})

await app.handle(evt.text('Yo').get())
expect(send).toBeCalledWith('fake-access-token', {
expect(axiosMock.post).toBeCalledWith(sendUrl, {
messaging_type: 'RESPONSE',
recipient: {id: 'bob'},
message: {text: 'You said: "Yo"', quick_replies: undefined},
})
})

test(`calculator bot`, async () => {
const send = jest.fn()
const axiosMock = ({post: jest.fn()} as any) as AxiosInstance
const sendUrl = `https://graph.facebook.com/v11.0/me/messages?access_token=fake-access-token`
const initialContext = {step: 'start'}
const handle = async ({context, setContext, message}: ChatEntry) => {
if (context.step === 'start') {
Expand Down Expand Up @@ -81,10 +84,10 @@ describe('bot', () => {
}
return undefined
}
const app = makeBot({send, handle, initialContext})
const app = makeBot({axiosInstance: axiosMock, handle, initialContext})

await app.handle(getStarted)
expect(send).toBeCalledWith('fake-access-token', {
expect(axiosMock.post).toBeCalledWith(sendUrl, {
messaging_type: 'RESPONSE',
recipient: {id: 'bob'},
message: {
Expand All @@ -99,35 +102,35 @@ describe('bot', () => {
})

await app.handle(evt.quickReply('+').get())
expect(send).toBeCalledWith('fake-access-token', {
expect(axiosMock.post).toBeCalledWith(sendUrl, {
messaging_type: 'RESPONSE',
recipient: {id: 'bob'},
message: {text: `Please enter the first argument for operation '+'`},
})

await app.handle(evt.text('bla bla').get())
expect(send).toBeCalledWith('fake-access-token', {
expect(axiosMock.post).toBeCalledWith(sendUrl, {
messaging_type: 'RESPONSE',
recipient: {id: 'bob'},
message: {text: `Your input is incorrect, try again`},
})

await app.handle(evt.text('11').get())
expect(send).toBeCalledWith('fake-access-token', {
expect(axiosMock.post).toBeCalledWith(sendUrl, {
messaging_type: 'RESPONSE',
recipient: {id: 'bob'},
message: {text: `Please enter the second argument for operation '+'`},
})

await app.handle(evt.text('4').get())
expect(send).toBeCalledWith('fake-access-token', {
expect(axiosMock.post).toBeCalledWith(sendUrl, {
messaging_type: 'RESPONSE',
recipient: {id: 'bob'},
message: {text: `The result is 15`},
})

await app.handle(evt.text('Thanks!').get())
expect(send).toBeCalledWith('fake-access-token', {
expect(axiosMock.post).toBeCalledWith(sendUrl, {
messaging_type: 'RESPONSE',
recipient: {id: 'bob'},
message: {
Expand Down

0 comments on commit caee14d

Please sign in to comment.