Skip to content

Commit d853700

Browse files
author
fletcherist
committed
feat: implement timeout expired response
1 parent c9f778f commit d853700

File tree

5 files changed

+35
-9
lines changed

5 files changed

+35
-9
lines changed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
"scripts": {
77
"lint": "eslint src",
88
"test": "jest",
9-
"dev": "tsc -w",
10-
"build": "tsc",
9+
"dev": "tsc -w --declaration",
10+
"build": "rm -rf dist && tsc --declaration",
1111
"version": "npm run changelog && git add CHANGELOG.md",
1212
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0",
1313
"release": "conventional-github-releaser -p angular",

src/alice.ts

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
selectCommand,
1111
selectSessionId,
1212
isFunction,
13+
delay,
1314
} from './utils'
1415

1516
import {
@@ -19,13 +20,17 @@ import {
1920
import aliceStateMiddleware from './middlewares/aliceStateMiddleware'
2021
import { configInterface } from './types/alice'
2122
import { CommandInterface } from './types/command'
23+
import { CtxInterface } from './types/ctx'
2224
import { WebhookResponse, WebhookRequest } from 'webhook'
2325

2426
const DEFAULT_SESSIONS_LIMIT: number = 1000
27+
const DEFAULT_TIMEOUT_CALLBACK_MESSAGE = 'Извините, но я не успела найти ответ за отведенное время.'
28+
const DEFAULT_TIMEOUT_CALLBACK = 600
2529

2630
export default class Alice {
27-
private anyCallback: (ctx: Ctx) => void
28-
private welcomeCallback: (ctx: Ctx) => void
31+
private anyCallback: (ctx: CtxInterface) => void
32+
private welcomeCallback: (ctx: CtxInterface) => void
33+
private timeoutCallback: (ctx: CtxInterface) => void
2934
private commands: Commands
3035
private middlewares: any[]
3136
private scenes: Scene[]
@@ -40,6 +45,10 @@ export default class Alice {
4045
constructor(config: configInterface = {}) {
4146
this.anyCallback = null
4247
this.welcomeCallback = null
48+
this.timeoutCallback = async (ctx) => {
49+
await delay(DEFAULT_TIMEOUT_CALLBACK)
50+
ctx.reply(DEFAULT_TIMEOUT_CALLBACK_MESSAGE)
51+
}
4352
this.commands = new Commands(config.fuseOptions || null)
4453
this.middlewares = [aliceStateMiddleware()]
4554
this.scenes = []
@@ -240,18 +249,31 @@ export default class Alice {
240249
* При получении ответа от @handleRequestBody, результат
241250
* отправляется обратно.
242251
*/
243-
public async listen(callbackUrl = '/', port = 80, callback?: () => void) {
252+
public async listen(webhookPath = '/', port = 80, callback?: () => void) {
244253
return new Promise((resolve) => {
245254
const app = express()
246255
app.use(express.json())
247-
app.post(callbackUrl, async (req, res) => {
256+
app.post(webhookPath, async (req, res) => {
248257
if (this.config.oAuthToken) {
249258
res.setHeader('Authorization', this.config.oAuthToken)
250259
}
251260
res.setHeader('Content-type', 'application/json')
252-
const handleResponseCallback = (response) => res.send(response)
261+
262+
let responseAlreadySent = false
263+
const handleResponseCallback = (response) => {
264+
/* dont answer twice */
265+
if (responseAlreadySent) {
266+
return false
267+
}
268+
res.send(response)
269+
responseAlreadySent = true
270+
}
253271
try {
254-
return await this.handleRequestBody(req.body, handleResponseCallback)
272+
const executors = [
273+
this.handleRequestBody(req.body, handleResponseCallback),
274+
await this.timeoutCallback(new Ctx({ req: req.body, sendResponse: handleResponseCallback })),
275+
].filter(Boolean)
276+
return await Promise.race(executors)
255277
} catch (error) {
256278
throw new Error(error)
257279
}

src/ctx.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ export default class Ctx implements CtxInterface {
6666
return reversedInterpolation(this.command.name, requestText)
6767
}
6868

69-
public async reply(replyMessage) {
69+
public async reply(replyMessage: string | {}): Promise<WebhookResponse> {
7070
if (!replyMessage) {
7171
throw new Error('Reply message could not be empty!')
7272
}
@@ -103,4 +103,6 @@ export default class Ctx implements CtxInterface {
103103

104104
return replyMessage
105105
}
106+
107+
public getDefaultRespons
106108
}

src/types/ctx.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export interface CtxInterface {
1717
replyBuilder: ReplyBuilder
1818
buttonBuilder: ButtonBuilder
1919

20+
reply: (replyMessage: string | {}) => Promise<WebhookResponse>
2021
sendResponse: (response: WebhookResponse) => void
2122
enterScene: (sceneName: string) => void
2223
leaveScene: () => void

src/utils/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ export const selectSession = (req) => req.session
4747
export const selectSessionId = (req) => selectSession(req).session_id
4848
export const selectUserId = (req) => selectSession(req).user_id
4949
export const isFunction = (fn: () => void) => fn && typeof fn === 'function'
50+
export const delay = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms))
5051

5152
export default {
5253
getFiguresRegexp,

0 commit comments

Comments
 (0)