Skip to content

Commit

Permalink
fix: idle second version
Browse files Browse the repository at this point in the history
fix: idle second version
  • Loading branch information
leifermendez authored Jan 5, 2024
2 parents e122f67 + f47ef59 commit ea8d7b2
Show file tree
Hide file tree
Showing 8 changed files with 118 additions and 66 deletions.
8 changes: 4 additions & 4 deletions __test__/0.2.1-case.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,14 @@ suiteCase(`Enviar mensaje luego de inactividad (2seg)`, async ({ database, provi
assert.is(undefined, getHistory[2])
})

suiteCase.skip(`Enviar mensajes con ambos casos de idle`, async ({ database, provider }) => {
suiteCase(`Enviar mensajes con ambos casos de idle`, async ({ database, provider }) => {
const flujoFinal = addKeyword(EVENTS.ACTION)
.addAnswer('Se cancelo por inactividad')
.addAction(async (_, { flowDynamic }) => {
await flowDynamic(`Empezemos de nuevo.`)
await flowDynamic(`Cual es el numero de orden? tienes dos segundos para responder...`)
})
.addAction({ capture: true, idle: 2000, ref: '🙉🙉🙉🙉🙉🙉🙉🙉' }, async (ctx, { flowDynamic }) => {
.addAction({ capture: true, idle: 2100, ref: '🙉🙉🙉🙉🙉🙉🙉🙉' }, async (ctx, { flowDynamic }) => {
if (ctx?.idleFallBack) {
console.log(`[seundo desvio]`)
console.log(`[idleFallBack]:`, ctx)
Expand Down Expand Up @@ -126,10 +126,10 @@ suiteCase.skip(`Enviar mensajes con ambos casos de idle`, async ({ database, pro
body: 'el numero es 444',
})

await delay(10000)
await delay(15000)

const getHistory = database.listHistory.map((i) => i.answer)
assert.is('Hola tienes 2 segundos para responder si no te pedire de nuevo otro dato', getHistory)
assert.is('Hola tienes 2 segundos para responder si no te pedire de nuevo otro dato', getHistory[0])
assert.is('Se cancelo por inactividad', getHistory[1])
assert.is('__call_action__', getHistory[2])
assert.is('__capture_only_intended__', getHistory[3])
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"build": "pnpm run cli:rollup && pnpm run bot:rollup && pnpm run provider:rollup && pnpm run database:rollup && pnpm run contexts:rollup && pnpm run create-bot-whatsapp:rollup && pnpm run portal:rollup && pnpm run eslint-plugin:rollup",
"copy.lib": "node ./scripts/move.js",
"test.unit": "node ./node_modules/uvu/bin.js packages test",
"test.e2e": "node ./node_modules/uvu/bin.js __test__",
"test.e2e": "node ./node_modules/uvu/bin.js __test__ ",
"test.coverage": "node ./node_modules/c8/bin/c8.js npm run test.unit",
"test": "npm run test.coverage",
"cli": "node ./packages/cli/bin/cli.js",
Expand Down
17 changes: 17 additions & 0 deletions packages/bot/context/idleState.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ class IdleState {
indexCb = new Map()

setIdleTime = ({ from, inRef, timeInSeconds, cb }) => {
cb = cb ?? (() => {})
const startTime = new Date().getTime()
const endTime = startTime + timeInSeconds * 1000

Expand Down Expand Up @@ -30,6 +31,22 @@ class IdleState {
})
}

/**
*
* @param {*} param0
* @returns
*/
get = ({ from, inRef }) => {
try {
const queueCb = this.indexCb.get(from) ?? []
const isHas = queueCb.findIndex((i) => i.inRef !== inRef) !== -1
return isHas
} catch (err) {
console.error(`Error Get ctxInComming: `, err)
return null
}
}

stop = (ctxInComming) => {
try {
const queueCb = this.indexCb.get(ctxInComming.from) ?? []
Expand Down
97 changes: 60 additions & 37 deletions packages/bot/core/core.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -207,57 +207,80 @@ class CoreClass extends EventEmitter {
const sendFlow = async (messageToSend, numberOrId, options = {}) => {
options = { prev: prevMsg, forceQueue: false, ...options }

if (options.prev?.options?.capture && !options.prev?.options?.idle) {
await cbEveryCtx(options.prev?.ref)
const idleCtxQueue = idleForCallback.get({ from, inRef: prevMsg?.ref })

const { ref: prevRef, options: prevOptions } = options.prev || {}
const { capture, idle } = prevOptions || {}

if (messageCtxInComming?.ref && idleCtxQueue && messageToSend.length) {
return
}

if (capture && idle && messageToSend.length === 0) {
await cbEveryCtx(prevRef)
return
}

if (capture && !idle) {
await cbEveryCtx(prevRef)
}

for (const ctxMessage of messageToSend) {
if (endFlowFlag) {
return // Si endFlowFlag es verdadero, detener el flujo
break
}

const delayMs = ctxMessage?.options?.delay ?? this.generalArgs.delay ?? 0
await delay(delayMs)

//TODO el proceso de forzar cola de procsos
if (options?.forceQueue) {
const listIdsRefCallbacks = messageToSend.map((i) => i.ref)

const listProcessWait = this.queuePrincipal.getIdsCallback(from)
if (!listProcessWait.length) {
this.queuePrincipal.setIdsCallbacks(from, listIdsRefCallbacks)
} else {
const lastMessage = messageToSend[messageToSend.length - 1]
await this.databaseClass.save({ ...lastMessage, from: numberOrId })
if (listProcessWait.includes(lastMessage.ref)) {
this.queuePrincipal.clearQueue(from)
}
}
if (options.forceQueue) {
await handleForceQueue(ctxMessage, messageToSend, numberOrId, from)
}

try {
// this.queuePrincipal.clearQueue(from);
await this.queuePrincipal.enqueue(
from,
async () => {
// Usar async en la función pasada a enqueue
await this.sendProviderAndSave(numberOrId, ctxMessage).then(() =>
resolveCbEveryCtx(ctxMessage)
)
logger.log(`[QUEUE_SE_ENVIO]: `, ctxMessage)
// await resolveCbEveryCtx(ctxMessage)
},
ctxMessage.ref
)
} catch (error) {
logger.error(`Error al encolar (ID ${ctxMessage.ref}):`, error)
return Promise.reject()
// Puedes considerar manejar el error aquí o rechazar la promesa
// Pasada a resolveCbEveryCtx con el error correspondiente.
await enqueueMsg(numberOrId, ctxMessage, from)
}
}

// Se han extraído algunas funcionalidades en nuevas funciones para mejorar la legibilidad
const handleForceQueue = async (_, messageToSend, numberOrId, from) => {
const listIdsRefCallbacks = messageToSend.map((i) => i.ref)
const listProcessWait = this.queuePrincipal.getIdsCallback(from)

if (!listProcessWait.length) {
this.queuePrincipal.setIdsCallbacks(from, listIdsRefCallbacks)
} else {
const lastMessage = messageToSend[messageToSend.length - 1]
await this.databaseClass.save({ ...lastMessage, from: numberOrId })

if (listProcessWait.includes(lastMessage.ref)) {
this.queuePrincipal.clearQueue(from)
}
}
}

const enqueueMsg = async (numberOrId, ctxMessage, from) => {
try {
await this.queuePrincipal.enqueue(
from,
async () => {
await this.sendProviderAndSave(numberOrId, ctxMessage)
.then(() => resolveCbEveryCtx(ctxMessage))
.catch((error) => {
logger.error(`Error en sendProviderAndSave (ID ${ctxMessage.ref}):`, error)
throw error
})

logger.log(`[QUEUE_SE_ENVIO]: `, ctxMessage)
},
ctxMessage.ref
)
} catch (error) {
logger.error(`Error al encolar (ID ${ctxMessage.ref}):`, error)
throw error
}
}

const continueFlow = async (initRef = undefined) => {
const currentPrev = await this.databaseClass.getPrevByNumber(from)
let nextFlow = (await this.flowClass.find(refToContinue?.ref, true)) ?? []
Expand All @@ -267,7 +290,6 @@ class CoreClass extends EventEmitter {

const filterNextFlow = nextFlow.filter((msg) => msg.refSerialize !== currentPrev?.refSerialize)
const isContinueFlow = filterNextFlow.map((i) => i.keyword).includes(currentPrev?.ref)
console.log('--------------->', isContinueFlow, initRef)

if (!isContinueFlow) {
const refToContinueChild = this.flowClass.getRefToContinueChild(currentPrev?.keyword)
Expand All @@ -280,7 +302,7 @@ class CoreClass extends EventEmitter {
return exportFunctionsSend(() => sendFlow(filterNextFlow, from, { prev: undefined }))
}

if (initRef) {
if (initRef && !initRef?.idleFallBack) {
return exportFunctionsSend(() => sendFlow(filterNextFlow, from, { prev: undefined }))
}
}
Expand Down Expand Up @@ -541,6 +563,7 @@ class CoreClass extends EventEmitter {
msgToSend = this.flowClass.find(this.generalArgs.listEvents.TEMPLATE) || []
}
}

return exportFunctionsSend(() => sendFlow(msgToSend, from, { forceQueue: true }))
}

Expand Down
6 changes: 3 additions & 3 deletions packages/bot/io/events/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const LIST_ALL = {
VOICE_NOTE: eventVoiceNote(),
ACTION: eventAction(),
ORDER: eventOrder(),
TEMPLATE: eventTemplate()
TEMPLATE: eventTemplate(),
}

const LIST_REGEX = {
Expand All @@ -24,7 +24,7 @@ const LIST_REGEX = {
REGEX_EVENT_MEDIA,
REGEX_EVENT_VOICE_NOTE,
REGEX_EVENT_ORDER,
REGEX_EVENT_TEMPLATE
REGEX_EVENT_TEMPLATE,
}

module.exports = { LIST_ALL, LIST_REGEX }
module.exports = { LIST_ALL, LIST_REGEX }
14 changes: 14 additions & 0 deletions packages/bot/tests/idleState.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
const { test } = require('uvu')
const assert = require('uvu/assert')
const IdleState = require('../context/idleState.class')

test(`[IdleState] Probando instanciamiento de clase`, async () => {
const idleState = new IdleState()

idleState.setIdleTime({ from: '000', inRef: 'ref1', timeInSeconds: 10 })
const queue = idleState.get({ from: '000' })
assert.is(idleState instanceof IdleState, true)
assert.is(queue, true)
})

test.run()
24 changes: 11 additions & 13 deletions packages/contexts/src/dialogflow-cx/dialogflow-cx.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,33 +23,31 @@ class DialogFlowCXContext extends CoreClass {
* Verificar conexión con servicio de DialogFlow
*/
init = () => {
let credentials;
const googleKeyFilePath = join(process.cwd(), 'google-key.json');
let credentials
const googleKeyFilePath = join(process.cwd(), 'google-key.json')

if (existsSync(googleKeyFilePath)) {
const rawJson = readFileSync(googleKeyFilePath, 'utf-8');
credentials = JSON.parse(rawJson);
const rawJson = readFileSync(googleKeyFilePath, 'utf-8')
credentials = JSON.parse(rawJson)
} else if (process.env.GOOGLE_KEY_JSON) {
credentials = JSON.parse(process.env.GOOGLE_KEY_JSON);
credentials = JSON.parse(process.env.GOOGLE_KEY_JSON)
} else {
throw new Error('Google key configuration not found');
throw new Error('Google key configuration not found')
}

if (!this.optionsDX.location.length) throw new Error('LOCATION_NO_ENCONTRADO');
if (!this.optionsDX.agentId.length) throw new Error('AGENTID_NO_ENCONTRADO');
if (!this.optionsDX.location.length) throw new Error('LOCATION_NO_ENCONTRADO')
if (!this.optionsDX.agentId.length) throw new Error('AGENTID_NO_ENCONTRADO')

const { project_id, private_key, client_email } = credentials;
const { project_id, private_key, client_email } = credentials

this.projectId = project_id;
this.projectId = project_id

this.sessionClient = new SessionsClient({
credentials: { private_key, client_email },
apiEndpoint: `${this.optionsDX.location}-dialogflow.googleapis.com`,
});
})
}



/**
* GLOSSARY.md
* @param {*} messageCtxInComming
Expand Down
16 changes: 8 additions & 8 deletions packages/database/src/mysql/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,24 +26,24 @@ class MyslAdapter {
}

getPrevByNumber = async (from) => {
if (this.db._closing) await this.init()
if (this.db._closing) await this.init()
return await new Promise((resolve, reject) => {
const sql = `SELECT * FROM history WHERE phone='${from}' ORDER BY id DESC`;
const sql = `SELECT * FROM history WHERE phone='${from}' ORDER BY id DESC`
this.db.query(sql, (error, rows) => {
if (error) {
reject(error);
reject(error)
}

if (rows.length) {
const [row] = rows;
row.options = JSON.parse(row.options);
resolve(row);
const [row] = rows
row.options = JSON.parse(row.options)
resolve(row)
}

if (!rows.length) {
resolve(null);
resolve(null)
}
});
})
})
}

Expand Down

0 comments on commit ea8d7b2

Please sign in to comment.