From bc3138596017c01eb4b7001dec07391a9fe1f55f Mon Sep 17 00:00:00 2001 From: leifermendez Date: Tue, 17 Sep 2024 10:30:53 +0200 Subject: [PATCH 1/2] fix: example fast --- src/pages/en/showcases/fast-entires.mdx | 26 ++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/pages/en/showcases/fast-entires.mdx b/src/pages/en/showcases/fast-entires.mdx index 3a48ec8..279e3f0 100644 --- a/src/pages/en/showcases/fast-entires.mdx +++ b/src/pages/en/showcases/fast-entires.mdx @@ -115,29 +115,29 @@ const queueConfig: QueueConfig = { gapSeconds: 3000 }; const enqueueMessage = createMessageQueue(queueConfig); const welcomeFlow = addKeyword(['hello', 'hi']) -.addAction(async (ctx, { flowDynamic }) => { - try { - enqueueMessage(ctx.body, async (body) => { - console.log('Processed messages:', body); - await flowDynamic(`Received messages: ${body}`); - }); - } catch (error) { - console.error('Error processing message:', error); - } -}); + .addAction(async (ctx, { flowDynamic }) => { + try { + enqueueMessage(ctx.body, async (body) => { + console.log('Processed messages:', body); + await flowDynamic(`Received messages: ${body}`); + }); + } catch (error) { + console.error('Error processing message:', error); + } + }); const main = async () => { const adapterDB = new MemoryDB() const adapterFlow = createFlow([welcomeFlow]) const adapterProvider = createProvider(BaileysProvider) - adapterProvider.initHttpServer(3000) - - await createBot({ + const bot = await createBot({ flow: adapterFlow, provider: adapterProvider, database: adapterDB, }) + + bot.httpServer(3000) } main() From 53ec55b466a319cd6a65dde855aeaedcd0a42170 Mon Sep 17 00:00:00 2001 From: leifermendez Date: Tue, 17 Sep 2024 11:17:40 +0200 Subject: [PATCH 2/2] fix: fast queue --- src/pages/en/showcases/fast-entires.mdx | 114 ++++++++++++++---------- 1 file changed, 67 insertions(+), 47 deletions(-) diff --git a/src/pages/en/showcases/fast-entires.mdx b/src/pages/en/showcases/fast-entires.mdx index 279e3f0..f24c447 100644 --- a/src/pages/en/showcases/fast-entires.mdx +++ b/src/pages/en/showcases/fast-entires.mdx @@ -34,71 +34,91 @@ In this example, we use __3000ms__ (equal to 3 seconds) as the default gap, but ```ts {{ title: 'fast-entires.ts' }} /** - * @file messageQueue.ts - * @description A functional implementation of a message queueing system with debounce functionality. + * @file multiUserMessageQueue.ts + * @description An improved functional implementation of a multi-user message queueing system with debounce functionality, + * ensuring separate conversation handling for each user. */ +import { BotContext } from "@builderbot/bot/dist/types"; + interface Message { text: string; timestamp: number; } interface QueueConfig { - gapSeconds: number; + gapMilliseconds: number; } -interface QueueState { - queue: Message[]; +interface UserQueue { + messages: Message[]; timer: NodeJS.Timeout | null; - callback: ((body: string) => void) | null; + callback: ((body: string, from: string) => void) | null; +} + +interface QueueState { + queues: Map; } function createInitialState(): QueueState { return { - queue: [], - timer: null, - callback: null + queues: new Map() }; } -function resetTimer(state: QueueState): QueueState { - if (state.timer) { - clearTimeout(state.timer); +function resetTimer(userQueue: UserQueue): UserQueue { + if (userQueue.timer) { + clearTimeout(userQueue.timer); } - return { ...state, timer: null }; + return { ...userQueue, timer: null }; } -function processQueue(state: QueueState): [string, QueueState] { - const result = state.queue.map(message => message.text).join(" "); +function processQueue(messages: Message[]): string { + const result = messages.map(message => message.text).join(" "); console.log('Accumulated messages:', result); - - const newState = { - ...state, - queue: [], - timer: null - }; - - return [result, newState]; + return result; } function createMessageQueue(config: QueueConfig) { - let state = createInitialState(); - - return function enqueueMessage(messageText: string, callback: (body: string) => void): void { - console.log('Enqueueing:', messageText); - - state = resetTimer(state); - state.queue.push({ text: messageText, timestamp: Date.now() }); - state.callback = callback; - - state.timer = setTimeout(() => { - const [result, newState] = processQueue(state); - state = newState; - if (state.callback) { - state.callback(result); - state.callback = null; - } - }, config.gapSeconds); + let state: QueueState = createInitialState(); + + return function enqueueMessage(ctx: BotContext, callback: (body: string, from: string) => void): void { + const from = ctx.from; + const messageBody = ctx.body; + + if (!from || !messageBody) { + console.error('Invalid message context:', ctx); + return; + } + + console.log('Enqueueing:', messageBody, 'from:', from); + + let userQueue = state.queues.get(from); + if (!userQueue) { + userQueue = { messages: [], timer: null, callback: null }; + state.queues.set(from, userQueue); + } + + userQueue = resetTimer(userQueue); + userQueue.messages.push({ text: messageBody, timestamp: Date.now() }); + userQueue.callback = callback; + + console.log('Messages for', from, ':', userQueue.messages); + + if (!userQueue.timer) { + userQueue.timer = setTimeout(() => { + const currentQueue = state.queues.get(from); + if (currentQueue) { + const result = processQueue(currentQueue.messages); + if (currentQueue.callback) { + currentQueue.callback(result, from); + } + state.queues.set(from, { ...currentQueue, messages: [], timer: null }); + } + }, config.gapMilliseconds); + } + + state.queues.set(from, userQueue); }; } @@ -106,19 +126,19 @@ export { createMessageQueue, QueueConfig }; ``` ```ts {{ title: 'app.ts' }} -import { createMessageQueue, QueueConfig } from './fast-entires' +import { createMessageQueue, QueueConfig } from './fast' -import { createBot, createProvider, createFlow, addKeyword, MemoryDB } from '@builderbot/bot' +import { createBot, createProvider, createFlow, addKeyword, MemoryDB, EVENTS } from '@builderbot/bot' import { BaileysProvider } from '@builderbot/provider-baileys' -const queueConfig: QueueConfig = { gapSeconds: 3000 }; +const queueConfig: QueueConfig = { gapMilliseconds: 3000 }; const enqueueMessage = createMessageQueue(queueConfig); -const welcomeFlow = addKeyword(['hello', 'hi']) +const welcomeFlow = addKeyword(EVENTS.WELCOME) .addAction(async (ctx, { flowDynamic }) => { try { - enqueueMessage(ctx.body, async (body) => { - console.log('Processed messages:', body); + enqueueMessage(ctx, async (body) => { + console.log('Processed messages:', body, ctx.from); await flowDynamic(`Received messages: ${body}`); }); } catch (error) { @@ -137,7 +157,7 @@ const main = async () => { database: adapterDB, }) - bot.httpServer(3000) + bot.httpServer(3005) } main()