mirror of
https://github.com/cheveguerra/bot-whatsapp.git
synced 2026-04-17 19:26:23 +00:00
chore: ⚡ pre-chore
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env sh
|
||||
. "$(dirname -- "$0")/_/husky.sh"
|
||||
|
||||
npx --no -- commitlint --edit
|
||||
npm run lint:fix && npx --no -- commitlint --edit
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
packages/**/lib
|
||||
packages/docs/*.json
|
||||
packages/docs/
|
||||
**/.git
|
||||
**/.svn
|
||||
**/.hg
|
||||
|
||||
@@ -8,8 +8,7 @@ const { addKeyword, addAnswer, addChild, toSerialize } = require('./io/methods')
|
||||
* @param {*} args
|
||||
* @returns
|
||||
*/
|
||||
const createBot = async ({ flow, database, provider }, args = {}) =>
|
||||
new CoreClass(flow, database, provider, args)
|
||||
const createBot = async ({ flow, database, provider }, args = {}) => new CoreClass(flow, database, provider, args)
|
||||
|
||||
/**
|
||||
* Crear instancia de clase Io (Flow)
|
||||
@@ -29,8 +28,7 @@ const createFlow = (args) => {
|
||||
*/
|
||||
const createProvider = (providerClass = class {}, args = null) => {
|
||||
const providerInstance = new providerClass(args)
|
||||
if (!providerClass.prototype instanceof ProviderClass)
|
||||
throw new Error('El provider no implementa ProviderClass')
|
||||
if (!providerClass.prototype instanceof ProviderClass) throw new Error('El provider no implementa ProviderClass')
|
||||
return providerInstance
|
||||
}
|
||||
|
||||
|
||||
@@ -17,15 +17,10 @@ const addAnswer =
|
||||
* @returns
|
||||
*/
|
||||
const getAnswerOptions = () => ({
|
||||
media:
|
||||
typeof options?.media === 'string' ? `${options?.media}` : null,
|
||||
media: typeof options?.media === 'string' ? `${options?.media}` : null,
|
||||
buttons: Array.isArray(options?.buttons) ? options.buttons : [],
|
||||
capture:
|
||||
typeof options?.capture === 'boolean'
|
||||
? options?.capture
|
||||
: false,
|
||||
child:
|
||||
typeof options?.child === 'string' ? `${options?.child}` : null,
|
||||
capture: typeof options?.capture === 'boolean' ? options?.capture : false,
|
||||
child: typeof options?.child === 'string' ? `${options?.child}` : null,
|
||||
delay: typeof options?.delay === 'number' ? options?.delay : 0,
|
||||
})
|
||||
|
||||
@@ -49,8 +44,7 @@ const addAnswer =
|
||||
* Esta funcion aplana y busca los callback anidados de los hijos
|
||||
* @returns
|
||||
*/
|
||||
const getCbFromNested = () =>
|
||||
flatObject(Array.isArray(nested) ? nested : [nested])
|
||||
const getCbFromNested = () => flatObject(Array.isArray(nested) ? nested : [nested])
|
||||
|
||||
const callback = typeof cb === 'function' ? cb : () => null
|
||||
|
||||
|
||||
@@ -20,8 +20,7 @@ class ProviderClass extends EventEmitter {
|
||||
*/
|
||||
|
||||
sendMessage = async (userId, message) => {
|
||||
if (NODE_ENV !== 'production')
|
||||
console.log('[sendMessage]', { userId, message })
|
||||
if (NODE_ENV !== 'production') console.log('[sendMessage]', { userId, message })
|
||||
return message
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,13 +2,7 @@ const { test } = require('uvu')
|
||||
const assert = require('uvu/assert')
|
||||
const FlowClass = require('../io/flow.class')
|
||||
const MockProvider = require('../../../__mocks__/mock.provider')
|
||||
const {
|
||||
createBot,
|
||||
CoreClass,
|
||||
createFlow,
|
||||
createProvider,
|
||||
ProviderClass,
|
||||
} = require('../index')
|
||||
const { createBot, CoreClass, createFlow, createProvider, ProviderClass } = require('../index')
|
||||
|
||||
class MockFlow {
|
||||
allCallbacks = { ref: () => 1 }
|
||||
@@ -100,20 +94,13 @@ test(`[Bot] Eventos 'require_action,ready,auth_failure,message '`, async () => {
|
||||
await createBot(setting)
|
||||
|
||||
/// Escuchamos eventos
|
||||
mockProvider.on(
|
||||
'require_action',
|
||||
(r) => (responseEvents['require_action'] = r)
|
||||
)
|
||||
mockProvider.on('require_action', (r) => (responseEvents['require_action'] = r))
|
||||
mockProvider.on('ready', (r) => (responseEvents['ready'] = r))
|
||||
mockProvider.on('auth_failure', (r) => (responseEvents['auth_failure'] = r))
|
||||
mockProvider.on('message', (r) => (responseEvents['message'] = r))
|
||||
|
||||
/// Emitimos eventos
|
||||
mockProvider.delaySendMessage(
|
||||
0,
|
||||
'require_action',
|
||||
MOCK_EVENTS.require_action
|
||||
)
|
||||
mockProvider.delaySendMessage(0, 'require_action', MOCK_EVENTS.require_action)
|
||||
mockProvider.delaySendMessage(0, 'ready', MOCK_EVENTS.ready)
|
||||
mockProvider.delaySendMessage(0, 'auth_failure', MOCK_EVENTS.auth_failure)
|
||||
mockProvider.delaySendMessage(0, 'message', MOCK_EVENTS.message)
|
||||
@@ -121,21 +108,12 @@ test(`[Bot] Eventos 'require_action,ready,auth_failure,message '`, async () => {
|
||||
await delay(0)
|
||||
|
||||
/// Testeamos eventos
|
||||
assert.is(
|
||||
JSON.stringify(responseEvents.require_action),
|
||||
JSON.stringify(MOCK_EVENTS.require_action)
|
||||
)
|
||||
assert.is(JSON.stringify(responseEvents.require_action), JSON.stringify(MOCK_EVENTS.require_action))
|
||||
assert.is(responseEvents.ready, MOCK_EVENTS.ready)
|
||||
|
||||
assert.is(
|
||||
JSON.stringify(responseEvents.auth_failure),
|
||||
JSON.stringify(MOCK_EVENTS.auth_failure)
|
||||
)
|
||||
assert.is(JSON.stringify(responseEvents.auth_failure), JSON.stringify(MOCK_EVENTS.auth_failure))
|
||||
|
||||
assert.is(
|
||||
JSON.stringify(responseEvents.message),
|
||||
JSON.stringify(MOCK_EVENTS.message)
|
||||
)
|
||||
assert.is(JSON.stringify(responseEvents.message), JSON.stringify(MOCK_EVENTS.message))
|
||||
})
|
||||
|
||||
test(`[Bot] Probando Flujos Internos`, async () => {
|
||||
@@ -166,20 +144,13 @@ test(`[Bot] Probando Flujos Internos`, async () => {
|
||||
await createBot(setting)
|
||||
|
||||
/// Escuchamos eventos
|
||||
mockProvider.on(
|
||||
'require_action',
|
||||
(r) => (responseEvents['require_action'] = r)
|
||||
)
|
||||
mockProvider.on('require_action', (r) => (responseEvents['require_action'] = r))
|
||||
mockProvider.on('ready', (r) => (responseEvents['ready'] = r))
|
||||
mockProvider.on('auth_failure', (r) => (responseEvents['auth_failure'] = r))
|
||||
mockProvider.on('message', (r) => (responseEvents['message'] = r))
|
||||
|
||||
/// Emitimos eventos
|
||||
mockProvider.delaySendMessage(
|
||||
0,
|
||||
'require_action',
|
||||
MOCK_EVENTS.require_action
|
||||
)
|
||||
mockProvider.delaySendMessage(0, 'require_action', MOCK_EVENTS.require_action)
|
||||
mockProvider.delaySendMessage(0, 'ready', MOCK_EVENTS.ready)
|
||||
mockProvider.delaySendMessage(0, 'auth_failure', MOCK_EVENTS.auth_failure)
|
||||
mockProvider.delaySendMessage(0, 'message', MOCK_EVENTS.message)
|
||||
@@ -187,21 +158,12 @@ test(`[Bot] Probando Flujos Internos`, async () => {
|
||||
await delay(0)
|
||||
|
||||
/// Testeamos eventos
|
||||
assert.is(
|
||||
JSON.stringify(responseEvents.require_action),
|
||||
JSON.stringify(MOCK_EVENTS.require_action)
|
||||
)
|
||||
assert.is(JSON.stringify(responseEvents.require_action), JSON.stringify(MOCK_EVENTS.require_action))
|
||||
assert.is(responseEvents.ready, MOCK_EVENTS.ready)
|
||||
|
||||
assert.is(
|
||||
JSON.stringify(responseEvents.auth_failure),
|
||||
JSON.stringify(MOCK_EVENTS.auth_failure)
|
||||
)
|
||||
assert.is(JSON.stringify(responseEvents.auth_failure), JSON.stringify(MOCK_EVENTS.auth_failure))
|
||||
|
||||
assert.is(
|
||||
JSON.stringify(responseEvents.message),
|
||||
JSON.stringify(MOCK_EVENTS.message)
|
||||
)
|
||||
assert.is(JSON.stringify(responseEvents.message), JSON.stringify(MOCK_EVENTS.message))
|
||||
})
|
||||
|
||||
test(`[Bot] Probando Flujos Nested`, async () => {
|
||||
@@ -234,20 +196,13 @@ test(`[Bot] Probando Flujos Nested`, async () => {
|
||||
botInstance.sendProviderAndSave('xxxxx', 'xxxxx')
|
||||
botInstance.continue('xxxxx', 'xxxxx')
|
||||
/// Escuchamos eventos
|
||||
mockProvider.on(
|
||||
'require_action',
|
||||
(r) => (responseEvents['require_action'] = r)
|
||||
)
|
||||
mockProvider.on('require_action', (r) => (responseEvents['require_action'] = r))
|
||||
mockProvider.on('ready', (r) => (responseEvents['ready'] = r))
|
||||
mockProvider.on('auth_failure', (r) => (responseEvents['auth_failure'] = r))
|
||||
mockProvider.on('message', (r) => (responseEvents['message'] = r))
|
||||
|
||||
/// Emitimos eventos
|
||||
mockProvider.delaySendMessage(
|
||||
0,
|
||||
'require_action',
|
||||
MOCK_EVENTS.require_action
|
||||
)
|
||||
mockProvider.delaySendMessage(0, 'require_action', MOCK_EVENTS.require_action)
|
||||
mockProvider.delaySendMessage(0, 'ready', MOCK_EVENTS.ready)
|
||||
mockProvider.delaySendMessage(0, 'auth_failure', MOCK_EVENTS.auth_failure)
|
||||
mockProvider.delaySendMessage(0, 'message', MOCK_EVENTS.message)
|
||||
@@ -255,21 +210,12 @@ test(`[Bot] Probando Flujos Nested`, async () => {
|
||||
await delay(0)
|
||||
|
||||
/// Testeamos eventos
|
||||
assert.is(
|
||||
JSON.stringify(responseEvents.require_action),
|
||||
JSON.stringify(MOCK_EVENTS.require_action)
|
||||
)
|
||||
assert.is(JSON.stringify(responseEvents.require_action), JSON.stringify(MOCK_EVENTS.require_action))
|
||||
assert.is(responseEvents.ready, MOCK_EVENTS.ready)
|
||||
|
||||
assert.is(
|
||||
JSON.stringify(responseEvents.auth_failure),
|
||||
JSON.stringify(MOCK_EVENTS.auth_failure)
|
||||
)
|
||||
assert.is(JSON.stringify(responseEvents.auth_failure), JSON.stringify(MOCK_EVENTS.auth_failure))
|
||||
|
||||
assert.is(
|
||||
JSON.stringify(responseEvents.message),
|
||||
JSON.stringify(MOCK_EVENTS.message)
|
||||
)
|
||||
assert.is(JSON.stringify(responseEvents.message), JSON.stringify(MOCK_EVENTS.message))
|
||||
})
|
||||
|
||||
test.run()
|
||||
|
||||
@@ -35,10 +35,7 @@ test('Debere probar toSerialize', () => {
|
||||
const ARRANGE = {
|
||||
keyword: ['hola!', 'ole'],
|
||||
}
|
||||
const MAIN_CTX = addKeyword(ARRANGE.keyword)
|
||||
.addAnswer('Segundo!')
|
||||
.addAnswer('Segundo!')
|
||||
.toJson()
|
||||
const MAIN_CTX = addKeyword(ARRANGE.keyword).addAnswer('Segundo!').addAnswer('Segundo!').toJson()
|
||||
|
||||
const [ANSWER_A] = MAIN_CTX
|
||||
|
||||
@@ -71,9 +68,7 @@ test('Debere probar la anidación', () => {
|
||||
answer_A: 'Bienvenido',
|
||||
answer_B: 'Continuar',
|
||||
}
|
||||
const MAIN_CTX = addKeyword(ARRANGE.keyword)
|
||||
.addAnswer(ARRANGE.answer_A)
|
||||
.addAnswer(ARRANGE.answer_B)
|
||||
const MAIN_CTX = addKeyword(ARRANGE.keyword).addAnswer(ARRANGE.answer_A).addAnswer(ARRANGE.answer_B)
|
||||
|
||||
assert.is(MAIN_CTX.ctx.answer, ARRANGE.answer_B)
|
||||
})
|
||||
@@ -107,10 +102,7 @@ test('Debere probar error las addAnswer', () => {
|
||||
})
|
||||
|
||||
test('Obtener toJson', () => {
|
||||
const [ctxA, ctxB, ctxC] = addKeyword('hola')
|
||||
.addAnswer('pera!')
|
||||
.addAnswer('chao')
|
||||
.toJson()
|
||||
const [ctxA, ctxB, ctxC] = addKeyword('hola').addAnswer('pera!').addAnswer('chao').toJson()
|
||||
|
||||
assert.is(ctxA.keyword, 'hola')
|
||||
assert.match(ctxA.ref, /^key_/)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
const delay = (miliseconds) =>
|
||||
new Promise((res) => setTimeout(res, miliseconds))
|
||||
const delay = (miliseconds) => new Promise((res) => setTimeout(res, miliseconds))
|
||||
|
||||
module.exports = { delay }
|
||||
|
||||
@@ -3,9 +3,7 @@ const flatObject = (listArray = []) => {
|
||||
|
||||
if (!listArray.length) return {}
|
||||
|
||||
const cbNestedObj = cbNestedList
|
||||
.map(({ ctx }) => ctx?.callbacks)
|
||||
.filter((i) => !!i)
|
||||
const cbNestedObj = cbNestedList.map(({ ctx }) => ctx?.callbacks).filter((i) => !!i)
|
||||
const queueCb = cbNestedObj.reduce((acc, current) => {
|
||||
const getKeys = Object.keys(current)
|
||||
const parse = getKeys.map((icb, i) => ({
|
||||
|
||||
@@ -16,9 +16,6 @@ const generateRef = (prefix = false) => {
|
||||
* @returns
|
||||
*/
|
||||
const generateRefSerialize = ({ index, answer, keyword }) =>
|
||||
crypto
|
||||
.createHash('md5')
|
||||
.update(JSON.stringify({ index, answer, keyword }))
|
||||
.digest('hex')
|
||||
crypto.createHash('md5').update(JSON.stringify({ index, answer, keyword })).digest('hex')
|
||||
|
||||
module.exports = { generateRef, generateRefSerialize }
|
||||
|
||||
@@ -4,9 +4,7 @@ const printer = (message, title) => {
|
||||
if (NODE_ENV !== 'test') {
|
||||
// console.clear()
|
||||
if (title) console.log(bgRed(`${title}`))
|
||||
console.log(
|
||||
yellow(Array.isArray(message) ? message.join('\n') : message)
|
||||
)
|
||||
console.log(yellow(Array.isArray(message) ? message.join('\n') : message))
|
||||
console.log(``)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,15 +5,9 @@ const checkNodeVersion = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
console.log(bgCyan('🚀 Revisando tu Node.js'))
|
||||
const version = process.version
|
||||
const majorVersion = parseInt(
|
||||
version.replace('v', '').split('.').shift()
|
||||
)
|
||||
const majorVersion = parseInt(version.replace('v', '').split('.').shift())
|
||||
if (majorVersion < 16) {
|
||||
console.error(
|
||||
red(
|
||||
`🔴 Se require Node.js 16 o superior. Actualmente esta ejecutando Node.js ${version}`
|
||||
)
|
||||
)
|
||||
console.error(red(`🔴 Se require Node.js 16 o superior. Actualmente esta ejecutando Node.js ${version}`))
|
||||
console.log(``)
|
||||
reject('ERROR_NODE')
|
||||
}
|
||||
|
||||
@@ -2,10 +2,7 @@ const rimraf = require('rimraf')
|
||||
const { yellow } = require('kleur')
|
||||
const { join } = require('path')
|
||||
|
||||
const PATH_WW = [
|
||||
join(process.cwd(), '.wwebjs_auth'),
|
||||
join(process.cwd(), 'session.json'),
|
||||
]
|
||||
const PATH_WW = [join(process.cwd(), '.wwebjs_auth'), join(process.cwd(), 'session.json')]
|
||||
|
||||
const cleanSession = () => {
|
||||
const queue = []
|
||||
|
||||
@@ -23,11 +23,7 @@ const JSON_TEMPLATE = {
|
||||
const PATH_CONFIG = join(process.cwd(), 'config.json')
|
||||
|
||||
const jsonConfig = () => {
|
||||
return writeFile(
|
||||
PATH_CONFIG,
|
||||
JSON.stringify(JSON_TEMPLATE, null, 2),
|
||||
'utf-8'
|
||||
)
|
||||
return writeFile(PATH_CONFIG, JSON.stringify(JSON_TEMPLATE, null, 2), 'utf-8')
|
||||
}
|
||||
|
||||
module.exports = { jsonConfig }
|
||||
|
||||
@@ -20,13 +20,9 @@ const installDeps = (pkgManager, packageList) => {
|
||||
const installSingle = (pkgInstall) => () => {
|
||||
new Promise((resolve) => {
|
||||
try {
|
||||
childProcess = spawn(
|
||||
pkgManager,
|
||||
[PKG_OPTION[pkgManager], pkgInstall],
|
||||
{
|
||||
stdio: 'inherit',
|
||||
}
|
||||
)
|
||||
childProcess = spawn(pkgManager, [PKG_OPTION[pkgManager], pkgInstall], {
|
||||
stdio: 'inherit',
|
||||
})
|
||||
|
||||
childProcess.on('error', (e) => {
|
||||
console.error(e)
|
||||
|
||||
@@ -30,9 +30,7 @@ const startInteractive = async () => {
|
||||
await nextSteps()
|
||||
} catch (e) {
|
||||
console.error(bgRed(`Ups! 🙄 algo no va bien.`))
|
||||
console.error(
|
||||
bgRed(`Revisa los requerimientos minimos en la documentacion`)
|
||||
)
|
||||
console.error(bgRed(`Revisa los requerimientos minimos en la documentacion`))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,8 +80,7 @@ const nextSteps = async () => {
|
||||
const { outDir = '', providerDb = [], providerWs = [] } = response
|
||||
|
||||
const createApp = async (templateName = null) => {
|
||||
if (!templateName)
|
||||
throw new Error('TEMPLATE_NAME_INVALID: ', templateName)
|
||||
if (!templateName) throw new Error('TEMPLATE_NAME_INVALID: ', templateName)
|
||||
|
||||
const possiblesPath = [
|
||||
join(__dirname, '..', '..', 'starters', 'apps', templateName),
|
||||
@@ -115,11 +112,7 @@ const nextSteps = async () => {
|
||||
const vendorProvider = async () => {
|
||||
const [answer] = providerWs
|
||||
if (!providerWs.length) {
|
||||
console.log(
|
||||
red(
|
||||
`Debes seleccionar un proveedor de whatsapp. Tecla [Space] para seleccionar`
|
||||
)
|
||||
)
|
||||
console.log(red(`Debes seleccionar un proveedor de whatsapp. Tecla [Space] para seleccionar`))
|
||||
process.exit(1)
|
||||
}
|
||||
return answer
|
||||
@@ -132,11 +125,7 @@ const nextSteps = async () => {
|
||||
const dbProvider = async () => {
|
||||
const [answer] = providerDb
|
||||
if (!providerDb.length) {
|
||||
console.log(
|
||||
red(
|
||||
`Debes seleccionar un proveedor de base de datos. Tecla [Space] para seleccionar`
|
||||
)
|
||||
)
|
||||
console.log(red(`Debes seleccionar un proveedor de base de datos. Tecla [Space] para seleccionar`))
|
||||
process.exit(1)
|
||||
}
|
||||
return answer
|
||||
|
||||
@@ -38,10 +38,8 @@ class DialogFlowCXContext extends CoreClass {
|
||||
* */
|
||||
}
|
||||
|
||||
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 rawJson = readFileSync(GOOGLE_ACCOUNT_PATH, 'utf-8')
|
||||
const { project_id, private_key, client_email } = JSON.parse(rawJson)
|
||||
@@ -86,9 +84,7 @@ class DialogFlowCXContext extends CoreClass {
|
||||
},
|
||||
}
|
||||
|
||||
const [single] = (await this.sessionClient.detectIntent(reqDialog)) || [
|
||||
null,
|
||||
]
|
||||
const [single] = (await this.sessionClient.detectIntent(reqDialog)) || [null]
|
||||
|
||||
const listMessages = single.queryResult.responseMessages.map((res) => {
|
||||
if (res.message == 'text') {
|
||||
@@ -96,17 +92,11 @@ class DialogFlowCXContext extends CoreClass {
|
||||
}
|
||||
|
||||
if (res.message == 'payload') {
|
||||
const {
|
||||
media = null,
|
||||
buttons = [],
|
||||
answer = '',
|
||||
} = res.payload.fields
|
||||
const buttonsArray = buttons?.listValue?.values?.map(
|
||||
(btnValue) => {
|
||||
const { stringValue } = btnValue.structValue.fields.body
|
||||
return { body: stringValue }
|
||||
}
|
||||
)
|
||||
const { media = null, buttons = [], answer = '' } = res.payload.fields
|
||||
const buttonsArray = buttons?.listValue?.values?.map((btnValue) => {
|
||||
const { stringValue } = btnValue.structValue.fields.body
|
||||
return { body: stringValue }
|
||||
})
|
||||
return {
|
||||
answer: answer?.stringValue,
|
||||
options: {
|
||||
|
||||
@@ -5,8 +5,7 @@ const DialogCXFlowClass = require('./dialogflow-cx.class')
|
||||
* @param {*} args
|
||||
* @returns
|
||||
*/
|
||||
const createBotDialog = async ({ database, provider }, _options) =>
|
||||
new DialogCXFlowClass(database, provider, _options)
|
||||
const createBotDialog = async ({ database, provider }, _options) => new DialogCXFlowClass(database, provider, _options)
|
||||
|
||||
module.exports = {
|
||||
createBotDialog,
|
||||
|
||||
@@ -65,10 +65,7 @@ class DialogFlowContext extends CoreClass {
|
||||
* para evitar este problema.
|
||||
* https://github.com/codigoencasa/bot-whatsapp/pull/140
|
||||
*/
|
||||
const session = this.sessionClient.projectAgentSessionPath(
|
||||
this.projectId,
|
||||
from
|
||||
)
|
||||
const session = this.sessionClient.projectAgentSessionPath(this.projectId, from)
|
||||
const reqDialog = {
|
||||
session,
|
||||
queryInput: {
|
||||
@@ -79,15 +76,11 @@ class DialogFlowContext extends CoreClass {
|
||||
},
|
||||
}
|
||||
|
||||
const [single] = (await this.sessionClient.detectIntent(reqDialog)) || [
|
||||
null,
|
||||
]
|
||||
const [single] = (await this.sessionClient.detectIntent(reqDialog)) || [null]
|
||||
|
||||
const { queryResult } = single
|
||||
|
||||
const msgPayload = queryResult?.fulfillmentMessages?.find(
|
||||
(a) => a.message === 'payload'
|
||||
)
|
||||
const msgPayload = queryResult?.fulfillmentMessages?.find((a) => a.message === 'payload')
|
||||
|
||||
// Revisamos si el dialogFlow tiene multimedia
|
||||
if (msgPayload && msgPayload?.payload) {
|
||||
|
||||
@@ -5,8 +5,7 @@ const DialogFlowClass = require('./dialogflow.class')
|
||||
* @param {*} args
|
||||
* @returns
|
||||
*/
|
||||
const createBotDialog = async ({ database, provider }) =>
|
||||
new DialogFlowClass(database, provider)
|
||||
const createBotDialog = async ({ database, provider }) => new DialogFlowClass(database, provider)
|
||||
|
||||
module.exports = {
|
||||
createBotDialog,
|
||||
|
||||
@@ -5,8 +5,7 @@ const MockClass = require('./mock.class')
|
||||
* @param {*} args
|
||||
* @returns
|
||||
*/
|
||||
const createBotMock = async ({ database, provider }) =>
|
||||
new MockClass(database, provider)
|
||||
const createBotMock = async ({ database, provider }) => new MockClass(database, provider)
|
||||
|
||||
module.exports = {
|
||||
createBotMock,
|
||||
|
||||
@@ -24,12 +24,7 @@ class MongoAdapter {
|
||||
}
|
||||
|
||||
getPrevByNumber = async (from) => {
|
||||
const result = await this.db
|
||||
.collection('history')
|
||||
.find({ from })
|
||||
.sort({ _id: -1 })
|
||||
.limit(1)
|
||||
.toArray()
|
||||
const result = await this.db.collection('history').find({ from }).sort({ _id: -1 }).limit(1).toArray()
|
||||
return result[0]
|
||||
}
|
||||
|
||||
|
||||
@@ -1,76 +1,66 @@
|
||||
const mysql = require("mysql2");
|
||||
const mysql = require('mysql2')
|
||||
|
||||
class MyslAdapter {
|
||||
db;
|
||||
listHistory = [];
|
||||
credentials = { host: null, user: null, database: null, password: null };
|
||||
db
|
||||
listHistory = []
|
||||
credentials = { host: null, user: null, database: null, password: null }
|
||||
|
||||
constructor(_credentials) {
|
||||
this.credentials = _credentials;
|
||||
this.init().then();
|
||||
}
|
||||
constructor(_credentials) {
|
||||
this.credentials = _credentials
|
||||
this.init().then()
|
||||
}
|
||||
|
||||
async init() {
|
||||
this.db = mysql.createConnection(this.credentials);
|
||||
async init() {
|
||||
this.db = mysql.createConnection(this.credentials)
|
||||
|
||||
await this.db.connect(async (error) => {
|
||||
if (!error) {
|
||||
console.log(`Solicitud de conexión a base de datos exitosa`);
|
||||
await this.checkTableExists();
|
||||
}
|
||||
await this.db.connect(async (error) => {
|
||||
if (!error) {
|
||||
console.log(`Solicitud de conexión a base de datos exitosa`)
|
||||
await this.checkTableExists()
|
||||
}
|
||||
|
||||
if (error) {
|
||||
console.log(`Solicitud de conexión fallida ${error.stack}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (error) {
|
||||
console.log(`Solicitud de conexión fallida ${error.stack}`)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
getPrevByNumber = (from) =>
|
||||
new Promise((resolve, reject) => {
|
||||
const sql = `SELECT * FROM history WHERE phone=${from} ORDER BY id DESC`;
|
||||
this.db.query(sql, (error, rows) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
}
|
||||
getPrevByNumber = (from) =>
|
||||
new Promise((resolve, reject) => {
|
||||
const sql = `SELECT * FROM history WHERE phone=${from} ORDER BY id DESC`
|
||||
this.db.query(sql, (error, rows) => {
|
||||
if (error) {
|
||||
reject(error)
|
||||
}
|
||||
|
||||
if (rows.length) {
|
||||
const [row] = rows;
|
||||
row.options = JSON.parse(row.options);
|
||||
resolve(row);
|
||||
}
|
||||
if (rows.length) {
|
||||
const [row] = rows
|
||||
row.options = JSON.parse(row.options)
|
||||
resolve(row)
|
||||
}
|
||||
|
||||
if (!rows.length) {
|
||||
resolve(null);
|
||||
}
|
||||
});
|
||||
});
|
||||
if (!rows.length) {
|
||||
resolve(null)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
save = (ctx) => {
|
||||
const values = [
|
||||
[
|
||||
ctx.ref,
|
||||
ctx.keyword,
|
||||
ctx.answer,
|
||||
ctx.refSerialize,
|
||||
ctx.from,
|
||||
JSON.stringify(ctx.options),
|
||||
],
|
||||
];
|
||||
const sql =
|
||||
"INSERT INTO history (ref, keyword, answer, refSerialize, phone, options ) values ?";
|
||||
save = (ctx) => {
|
||||
const values = [[ctx.ref, ctx.keyword, ctx.answer, ctx.refSerialize, ctx.from, JSON.stringify(ctx.options)]]
|
||||
const sql = 'INSERT INTO history (ref, keyword, answer, refSerialize, phone, options ) values ?'
|
||||
|
||||
this.db.query(sql, [values], (err) => {
|
||||
if (err) throw err;
|
||||
console.log("Guardado en DB...", values);
|
||||
});
|
||||
this.listHistory.push(ctx);
|
||||
};
|
||||
this.db.query(sql, [values], (err) => {
|
||||
if (err) throw err
|
||||
console.log('Guardado en DB...', values)
|
||||
})
|
||||
this.listHistory.push(ctx)
|
||||
}
|
||||
|
||||
createTable = () =>
|
||||
new Promise((resolve) => {
|
||||
const tableName = "history";
|
||||
createTable = () =>
|
||||
new Promise((resolve) => {
|
||||
const tableName = 'history'
|
||||
|
||||
const sql = `CREATE TABLE ${tableName}
|
||||
const sql = `CREATE TABLE ${tableName}
|
||||
(id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
ref varchar(255) NOT NULL,
|
||||
keyword varchar(255) NOT NULL,
|
||||
@@ -78,29 +68,29 @@ class MyslAdapter {
|
||||
refSerialize varchar(255) NOT NULL,
|
||||
phone varchar(255) NOT NULL,
|
||||
options longtext NOT NULL)
|
||||
CHARACTER SET utf8mb4 COLLATE utf8mb4_General_ci`;
|
||||
CHARACTER SET utf8mb4 COLLATE utf8mb4_General_ci`
|
||||
|
||||
this.db.query(sql, (err) => {
|
||||
if (err) throw err;
|
||||
console.log(`Tabla ${tableName} creada correctamente `);
|
||||
resolve(true);
|
||||
});
|
||||
});
|
||||
this.db.query(sql, (err) => {
|
||||
if (err) throw err
|
||||
console.log(`Tabla ${tableName} creada correctamente `)
|
||||
resolve(true)
|
||||
})
|
||||
})
|
||||
|
||||
checkTableExists = () =>
|
||||
new Promise((resolve) => {
|
||||
const sql = "SHOW TABLES LIKE 'history'";
|
||||
checkTableExists = () =>
|
||||
new Promise((resolve) => {
|
||||
const sql = "SHOW TABLES LIKE 'history'"
|
||||
|
||||
this.db.query(sql, (err, rows) => {
|
||||
if (err) throw err;
|
||||
this.db.query(sql, (err, rows) => {
|
||||
if (err) throw err
|
||||
|
||||
if (!rows.length) {
|
||||
this.createTable();
|
||||
}
|
||||
if (!rows.length) {
|
||||
this.createTable()
|
||||
}
|
||||
|
||||
resolve(!!rows.length);
|
||||
});
|
||||
});
|
||||
resolve(!!rows.length)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = MyslAdapter;
|
||||
module.exports = MyslAdapter
|
||||
|
||||
@@ -8,6 +8,5 @@
|
||||
font-family: IBMPlexMono-Regular;
|
||||
src: url(IBMPlexMono-Regular-subset.woff2) format('woff2'),
|
||||
url(IBMPlexMono-Regular-subset.zopfli.woff) format('woff');
|
||||
unicode-range: U+20, U+2C, U+2E, U+41-43, U+46, U+49, U+4B-4F, U+53-55, U+58,
|
||||
U+61-65, U+67-69, U+6C-76;
|
||||
unicode-range: U+20, U+2C, U+2E, U+41-43, U+46, U+49, U+4B-4F, U+53-55, U+58, U+61-65, U+67-69, U+6C-76;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,6 @@
|
||||
font-family: IBMPlexMono-SemiBold;
|
||||
src: url(IBMPlexMono-SemiBold-subset.woff2) format('woff2'),
|
||||
url(IBMPlexMono-SemiBold-subset.zopfli.woff) format('woff');
|
||||
unicode-range: U+20, U+24, U+2E, U+30, U+38, U+39, U+41, U+42, U+44, U+47,
|
||||
U+4E, U+4F, U+52-55, U+57, U+59, U+65, U+68, U+6F, U+72, U+74;
|
||||
unicode-range: U+20, U+24, U+2E, U+30, U+38, U+39, U+41, U+42, U+44, U+47, U+4E, U+4F, U+52-55, U+57, U+59, U+65,
|
||||
U+68, U+6F, U+72, U+74;
|
||||
}
|
||||
|
||||
@@ -6,9 +6,8 @@
|
||||
|
||||
@font-face {
|
||||
font-family: Pally-Variable;
|
||||
src: url(Pally-Variable-subset.woff2) format('woff2'),
|
||||
url(Pally-Variable-subset.zopfli.woff) format('woff');
|
||||
unicode-range: U+20, U+24, U+2C, U+2E, U+30, U+33, U+39, U+41-43, U+46,
|
||||
U+49-4D, U+53, U+55, U+58, U+61-65, U+67-69, U+6B-77, U+79;
|
||||
src: url(Pally-Variable-subset.woff2) format('woff2'), url(Pally-Variable-subset.zopfli.woff) format('woff');
|
||||
unicode-range: U+20, U+24, U+2C, U+2E, U+30, U+33, U+39, U+41-43, U+46, U+49-4D, U+53, U+55, U+58, U+61-65, U+67-69,
|
||||
U+6B-77, U+79;
|
||||
font-weight: 400 700;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,5 @@
|
||||
font-family: SourceSerifPro-Regular;
|
||||
src: url(SourceSerifPro-Regular-subset.woff2) format('woff2'),
|
||||
url(SourceSerifPro-Regular-subset.zopfli.woff) format('woff');
|
||||
unicode-range: U+20, U+2C, U+2E, U+41-44, U+49, U+4A, U+4C, U+53, U+55,
|
||||
U+61-65, U+67-69, U+6B-76, U+79;
|
||||
unicode-range: U+20, U+2C, U+2E, U+41-44, U+49, U+4A, U+4C, U+53, U+55, U+61-65, U+67-69, U+6B-76, U+79;
|
||||
}
|
||||
|
||||
@@ -6,9 +6,8 @@
|
||||
|
||||
@font-face {
|
||||
font-family: Synonym-Variable;
|
||||
src: url(Synonym-Variable-subset.woff2) format('woff2'),
|
||||
url(Synonym-Variable-subset.zopfli.woff) format('woff');
|
||||
unicode-range: U+20, U+24, U+2C, U+2E, U+30, U+33, U+35, U+41-44, U+46, U+47,
|
||||
U+49, U+4B-4F, U+53-55, U+57-59, U+61, U+63-65, U+67-69, U+6C-76;
|
||||
src: url(Synonym-Variable-subset.woff2) format('woff2'), url(Synonym-Variable-subset.zopfli.woff) format('woff');
|
||||
unicode-range: U+20, U+24, U+2C, U+2E, U+30, U+33, U+35, U+41-44, U+46, U+47, U+49, U+4B-4F, U+53-55, U+57-59, U+61,
|
||||
U+63-65, U+67-69, U+6C-76;
|
||||
font-weight: 400 700;
|
||||
}
|
||||
|
||||
@@ -6,8 +6,7 @@
|
||||
|
||||
@font-face {
|
||||
font-family: TenorSans-Regular;
|
||||
src: url(TenorSans-Regular-subset.woff2) format('woff2'),
|
||||
url(TenorSans-Regular-subset.zopfli.woff) format('woff');
|
||||
unicode-range: U+20, U+24, U+2E, U+30, U+36, U+46, U+49, U+4A, U+53, U+54,
|
||||
U+61, U+63, U+65, U+69, U+6B, U+6E, U+6F, U+72-75, U+79;
|
||||
src: url(TenorSans-Regular-subset.woff2) format('woff2'), url(TenorSans-Regular-subset.zopfli.woff) format('woff');
|
||||
unicode-range: U+20, U+24, U+2E, U+30, U+36, U+46, U+49, U+4A, U+53, U+54, U+61, U+63, U+65, U+69, U+6B, U+6E, U+6F,
|
||||
U+72-75, U+79;
|
||||
}
|
||||
|
||||
@@ -56,10 +56,7 @@ export const DigitalOcean = () => (
|
||||
h-3.1V2h3.2V14.9z M361.9,21.1v1.1c0,4.4,2.6,6.6,6.2,6.6c3.7,0,6.5-2.5,6.5-7.2c0-4.6-2.8-7.1-6.5-7.1
|
||||
C364.5,14.5,361.9,16.8,361.9,21.1z"
|
||||
/>
|
||||
<path
|
||||
class="st0"
|
||||
d="M386.3,40.9l4.6-10.7L383.2,12h3.6l5.8,14.5l5.8-14.5h3.6l-12.2,28.9H386.3z"
|
||||
/>
|
||||
<path class="st0" d="M386.3,40.9l4.6-10.7L383.2,12h3.6l5.8,14.5l5.8-14.5h3.6l-12.2,28.9H386.3z" />
|
||||
</g>
|
||||
</g>
|
||||
<g id="XMLID_2369_">
|
||||
@@ -111,14 +108,7 @@ export const DigitalOcean = () => (
|
||||
c1.2,1.2,2.6,1.8,4.3,1.8c1.7,0,3.1-0.6,4.3-1.8c1.2-1.2,1.8-2.6,1.8-4.3c0-1.7-0.6-3.1-1.8-4.2
|
||||
C225.7,46.5,224.3,45.9,222.6,45.9z"
|
||||
/>
|
||||
<rect
|
||||
id="XMLID_276_"
|
||||
x="217.6"
|
||||
y="63"
|
||||
class="st0"
|
||||
width="9.8"
|
||||
height="39.1"
|
||||
/>
|
||||
<rect id="XMLID_276_" x="217.6" y="63" class="st0" width="9.8" height="39.1" />
|
||||
<path
|
||||
id="XMLID_273_"
|
||||
class="st0"
|
||||
@@ -128,14 +118,7 @@ export const DigitalOcean = () => (
|
||||
c3.5-3.6,5.3-8.4,5.3-14.2V63h-9.7V66.3z M260.6,89.4c-1.7,2-3.9,2.9-6.8,2.9c-2.8,0-5-0.9-6.7-2.9c-1.7-1.9-2.5-4.5-2.5-7.7
|
||||
c0-3.2,0.9-5.8,2.5-7.7c1.7-1.9,3.9-2.9,6.7-2.9c2.8,0,5,1,6.8,2.9c1.7,2,2.6,4.6,2.6,7.7C263.2,84.9,262.3,87.5,260.6,89.4z"
|
||||
/>
|
||||
<rect
|
||||
id="XMLID_272_"
|
||||
x="281.3"
|
||||
y="63"
|
||||
class="st0"
|
||||
width="9.8"
|
||||
height="39.1"
|
||||
/>
|
||||
<rect id="XMLID_272_" x="281.3" y="63" class="st0" width="9.8" height="39.1" />
|
||||
<path
|
||||
id="XMLID_271_"
|
||||
class="st0"
|
||||
@@ -149,14 +132,7 @@ export const DigitalOcean = () => (
|
||||
d="M312.7,52.5H303V63h-5.6v9h5.6v16.2c0,5.1,1,8.7,3,10.8c2,2.1,5.6,3.2,10.6,3.2
|
||||
c1.6,0,3.2-0.1,4.8-0.2l0.4,0v-9l-3.4,0.2c-2.3,0-3.9-0.4-4.7-1.2c-0.8-0.8-1.1-2.6-1.1-5.2V72h9.2v-9h-9.2V52.5z"
|
||||
/>
|
||||
<rect
|
||||
id="XMLID_269_"
|
||||
x="368"
|
||||
y="46.6"
|
||||
class="st0"
|
||||
width="9.8"
|
||||
height="55.5"
|
||||
/>
|
||||
<rect id="XMLID_269_" x="368" y="46.6" class="st0" width="9.8" height="55.5" />
|
||||
<path
|
||||
id="XMLID_268_"
|
||||
class="st0"
|
||||
|
||||
@@ -5,14 +5,7 @@ import logoSrc from '~/assets/images/chatbot-whatsapp.png?width=64&height=64&png
|
||||
|
||||
export default component$(() => (
|
||||
<span class="self-center ml-2 text-2xl md:text-xl font-bold text-gray-900 whitespace-nowrap dark:text-white flex items-center">
|
||||
<img
|
||||
src={logoSrc}
|
||||
class="inline-block mr-1"
|
||||
width={32}
|
||||
height={32}
|
||||
alt="Qwind Logo"
|
||||
loading="lazy"
|
||||
/>
|
||||
<img src={logoSrc} class="inline-block mr-1" width={32} height={32} alt="Qwind Logo" loading="lazy" />
|
||||
Chatbot
|
||||
</span>
|
||||
))
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
export const Netlify = () => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width={147}
|
||||
height={40}
|
||||
role="img"
|
||||
fill="currentColor"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width={147} height={40} role="img" fill="currentColor">
|
||||
<g fill-rule="evenodd">
|
||||
<path d="M53.37 12.978l.123 2.198c1.403-1.7 3.245-2.55 5.525-2.55 3.951 0 5.962 2.268 6.032 6.804v12.568H60.79V19.676c0-1.207-.26-2.1-.78-2.681-.52-.58-1.371-.87-2.552-.87-1.719 0-3 .78-3.84 2.338v13.535h-4.262v-19.02h4.016zM77.748 32.35c-2.7 0-4.89-.852-6.567-2.557-1.678-1.705-2.517-3.976-2.517-6.812v-.527c0-1.898.365-3.595 1.096-5.089.73-1.494 1.757-2.657 3.078-3.49 1.321-.831 2.794-1.247 4.42-1.247 2.583 0 4.58.826 5.988 2.478 1.41 1.653 2.114 3.99 2.114 7.014v1.723h-12.4c.13 1.57.652 2.812 1.57 3.726.918.914 2.073 1.371 3.464 1.371 1.952 0 3.542-.79 4.77-2.373l2.297 2.198c-.76 1.136-1.774 2.018-3.042 2.645-1.269.627-2.692.94-4.27.94zm-.508-16.294c-1.17 0-2.113.41-2.832 1.23-.72.82-1.178 1.963-1.377 3.428h8.12v-.317c-.094-1.43-.474-2.51-1.14-3.243-.667-.732-1.59-1.098-2.771-1.098zm16.765-7.7v4.623h3.35v3.164h-3.35V26.76c0 .726.144 1.25.43 1.573.286.322.798.483 1.535.483a6.55 6.55 0 0 0 1.49-.176v3.305c-.97.27-1.905.404-2.806.404-3.273 0-4.91-1.81-4.91-5.431V16.142H86.62v-3.164h3.122V8.355h4.261zm11.137 23.643h-4.262v-27h4.262v27zm9.172 0h-4.262v-19.02h4.262v19.02zm-4.525-23.96c0-.655.207-1.2.622-1.634.416-.433 1.009-.65 1.78-.65.772 0 1.368.217 1.79.65.42.434.63.979.63 1.635 0 .644-.21 1.18-.63 1.608-.422.428-1.018.642-1.79.642-.771 0-1.364-.214-1.78-.642-.415-.427-.622-.964-.622-1.608zm10.663 23.96V16.142h-2.894v-3.164h2.894v-1.74c0-2.11.584-3.738 1.753-4.887 1.17-1.148 2.806-1.722 4.91-1.722.749 0 1.544.105 2.386.316l-.105 3.34a8.375 8.375 0 0 0-1.631-.14c-2.035 0-3.052 1.048-3.052 3.146v1.687h3.858v3.164h-3.858v15.856h-4.261zm17.87-6.117l3.858-12.903h4.542l-7.54 21.903c-1.158 3.199-3.122 4.799-5.893 4.799-.62 0-1.304-.106-2.052-.317v-3.305l.807.053c1.075 0 1.885-.196 2.429-.589.543-.392.973-1.051 1.289-1.977l.613-1.635-6.664-18.932h4.595l4.016 12.903z" />
|
||||
<path
|
||||
|
||||
@@ -13,10 +13,7 @@ export const RouterHead = component$(() => {
|
||||
<title>{head.title}</title>
|
||||
|
||||
<link rel="canonical" href={loc.href} />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1.0"
|
||||
/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
|
||||
{head.meta.map((m) => (
|
||||
|
||||
@@ -34,14 +34,8 @@ export const Social = () => {
|
||||
content="https://campaign.codigoencasa.com"
|
||||
/>
|
||||
<meta property="og:site_name" content="campaign.codigoencasa.com" /> */}
|
||||
<meta
|
||||
property="og:image"
|
||||
content="https://i.imgur.com/0HpzsEm.png"
|
||||
></meta>
|
||||
<meta
|
||||
property="og:image:secure_url"
|
||||
content="https://i.imgur.com/0HpzsEm.png"
|
||||
/>
|
||||
<meta property="og:image" content="https://i.imgur.com/0HpzsEm.png"></meta>
|
||||
<meta property="og:image:secure_url" content="https://i.imgur.com/0HpzsEm.png" />
|
||||
<meta property="og:image:type" content="image/png"></meta>
|
||||
<meta property="og:image:width" content="1200"></meta>
|
||||
<meta property="og:image:height" content="630"></meta>
|
||||
@@ -52,10 +46,7 @@ export const Social = () => {
|
||||
name="twitter:title"
|
||||
content="💻 Conviértete en un Programador Backend aprendiendo todo de Cloud y Nodejs"
|
||||
/>
|
||||
<meta
|
||||
name="twitter:image"
|
||||
content="https://i.imgur.com/0HpzsEm.png"
|
||||
/>
|
||||
<meta name="twitter:image" content="https://i.imgur.com/0HpzsEm.png" />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -27,9 +27,7 @@ export default component$((props: ItemProps) => {
|
||||
// TODO:
|
||||
document.body.classList.toggle('overflow-hidden')
|
||||
document.getElementById('header')?.classList.toggle('h-screen')
|
||||
document
|
||||
.querySelector('#header nav')
|
||||
?.classList.toggle('hidden')
|
||||
document.querySelector('#header nav')?.classList.toggle('hidden')
|
||||
}}
|
||||
>
|
||||
<IconMenu class={iconClass} />
|
||||
|
||||
@@ -10,16 +10,13 @@ interface ItemProps {
|
||||
export default component$((props: ItemProps) => {
|
||||
const { iconClass } = props
|
||||
const store = useStore({
|
||||
theme:
|
||||
(typeof window !== 'undefined' && window?.localStorage?.theme) ||
|
||||
undefined,
|
||||
theme: (typeof window !== 'undefined' && window?.localStorage?.theme) || undefined,
|
||||
})
|
||||
|
||||
useClientEffect$(() => {
|
||||
store.theme =
|
||||
window.localStorage.theme === 'dark' ||
|
||||
(!('theme' in window.localStorage) &&
|
||||
window.matchMedia('(prefers-color-scheme: dark)').matches)
|
||||
(!('theme' in window.localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)
|
||||
? 'dark'
|
||||
: 'light'
|
||||
})
|
||||
@@ -42,11 +39,7 @@ export default component$((props: ItemProps) => {
|
||||
}
|
||||
}}
|
||||
>
|
||||
{store.theme == 'dark' ? (
|
||||
<IconMoon class={iconClass} />
|
||||
) : (
|
||||
<IconSun class={iconClass} />
|
||||
)}
|
||||
{store.theme == 'dark' ? <IconMoon class={iconClass} /> : <IconSun class={iconClass} />}
|
||||
</button>
|
||||
)
|
||||
})
|
||||
|
||||
@@ -7,9 +7,7 @@ export const IconArrowDownRight = (props: ItemProps) => {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class={`icon icon-tabler icon-tabler-arrow-down-right ${
|
||||
className || 'w-5 h-5'
|
||||
}`}
|
||||
class={`icon icon-tabler icon-tabler-arrow-down-right ${className || 'w-5 h-5'}`}
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
|
||||
@@ -8,9 +8,7 @@ export const IconMenu = (props: ItemProps) => {
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
class={`icon icon-tabler icon-tabler-menu ${
|
||||
className || 'w-5 h-5'
|
||||
}`}
|
||||
class={`icon icon-tabler icon-tabler-menu ${className || 'w-5 h-5'}`}
|
||||
preserveAspectRatio="xMidYMid meet"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
|
||||
@@ -7,9 +7,7 @@ export const IconMoon = (props: ItemProps) => {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class={`icon icon-tabler icon-tabler-moon ${
|
||||
className || 'w-5 h-5'
|
||||
}`}
|
||||
class={`icon icon-tabler icon-tabler-moon ${className || 'w-5 h-5'}`}
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
|
||||
@@ -23,9 +23,7 @@ export default component$(
|
||||
|
||||
<div class="pt-2 space-y-4 justify-center flex">
|
||||
<figcaption class="text-sm">
|
||||
<div class={'font-semibold truncate'}>
|
||||
{props.user.login}
|
||||
</div>
|
||||
<div class={'font-semibold truncate'}>{props.user.login}</div>
|
||||
</figcaption>
|
||||
</div>
|
||||
</figure>
|
||||
|
||||
@@ -32,8 +32,7 @@ export default component$((props: { users: User[] }) => {
|
||||
Super estrellas
|
||||
</h2>
|
||||
<p class="max-w-3xl mx-auto sm:text-center text-xl text-gray-600 dark:text-slate-400">
|
||||
Todo es posible gracias a el mayor recursos de todos, el
|
||||
recurso humano. Tu tambien puedes{' '}
|
||||
Todo es posible gracias a el mayor recursos de todos, el recurso humano. Tu tambien puedes{' '}
|
||||
<a class={'font-semibold'} href="/docs/contributing">
|
||||
formar parte
|
||||
</a>
|
||||
|
||||
@@ -15,8 +15,8 @@ export default component$(() => {
|
||||
📄 Editar esta pagina
|
||||
</a>
|
||||
<p class={'text-xs'}>
|
||||
Forma parte de esta comunidad mejorando la documentación
|
||||
siente libre de poder agregar o editar lo que quieras
|
||||
Forma parte de esta comunidad mejorando la documentación siente libre de poder agregar o editar
|
||||
lo que quieras
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -56,13 +56,9 @@ export default component$(() => {
|
||||
<IconArrowDownRight class="w-7 h-7 text-primary-600 inline-block" />
|
||||
{question}
|
||||
</div>
|
||||
{answer
|
||||
.split('\n\n')
|
||||
.map((paragraph) => (
|
||||
<p class="text-gray-700 dark:text-gray-400 mb-2">
|
||||
{paragraph}
|
||||
</p>
|
||||
))}
|
||||
{answer.split('\n\n').map((paragraph) => (
|
||||
<p class="text-gray-700 dark:text-gray-400 mb-2">{paragraph}</p>
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -50,13 +50,11 @@ export default component$(() => {
|
||||
Caracteristicas
|
||||
</p>
|
||||
<h2 class="text-4xl md:text-5xl font-bold leading-tighter tracking-tighter mb-4 font-heading">
|
||||
Nuestras principales{' '}
|
||||
<span class="whitespace-nowrap">funciones</span>
|
||||
Nuestras principales <span class="whitespace-nowrap">funciones</span>
|
||||
</h2>
|
||||
<p class="max-w-3xl mx-auto sm:text-center text-xl text-gray-600 dark:text-slate-400">
|
||||
El secreto es mantener los procesos repetitivos en
|
||||
procesos automatizados simples, por eso te mostramos en
|
||||
que destacamos.
|
||||
El secreto es mantener los procesos repetitivos en procesos automatizados simples, por eso te
|
||||
mostramos en que destacamos.
|
||||
</p>
|
||||
</div>
|
||||
<div class="grid mx-auto space-y-6 md:grid-cols-2 md:space-y-0">
|
||||
@@ -70,12 +68,8 @@ export default component$(() => {
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="mb-3 text-xl font-bold">
|
||||
{title}
|
||||
</h3>
|
||||
<p class="text-gray-600 dark:text-slate-400">
|
||||
{description}
|
||||
</p>
|
||||
<h3 class="mb-3 text-xl font-bold">{title}</h3>
|
||||
<p class="text-gray-600 dark:text-slate-400">{description}</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
|
||||
@@ -9,36 +9,24 @@ import { src as placeholder } from '~/assets/images/chatbot-whatsapp.png?width=4
|
||||
|
||||
export default component$(() => {
|
||||
return (
|
||||
<section
|
||||
class={` from-white via-purple-50 to-sky-100 dark:bg-none mt-[-95px]`}
|
||||
>
|
||||
<section class={` from-white via-purple-50 to-sky-100 dark:bg-none mt-[-95px]`}>
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6 md:flex md:h-screen 2xl:h-auto pt-[72px]">
|
||||
<div class="py-12 md:py-12 lg:py-16 block md:flex text-center md:text-left">
|
||||
<div class="pb-12 md:pb-0 md:py-0 max-w-5xl mx-auto md:pr-16 flex items-center basis-[56%]">
|
||||
<div>
|
||||
<h1 class="text-5xl md:text-[3.48rem] font-bold leading-tighter tracking-tighter mb-4 font-heading px-4 md:px-0">
|
||||
Crear chatbot{' '}
|
||||
<span class="sm:whitespace-nowrap text-[#25b637]">
|
||||
WhatsApp
|
||||
</span>
|
||||
<br class="hidden lg:block" />{' '}
|
||||
<span class="lg:inline">en minutos</span>
|
||||
Crear chatbot <span class="sm:whitespace-nowrap text-[#25b637]">WhatsApp</span>
|
||||
<br class="hidden lg:block" /> <span class="lg:inline">en minutos</span>
|
||||
</h1>
|
||||
<div class="max-w-3xl mx-auto">
|
||||
<p class="text-xl text-gray-600 mb-8 dark:text-slate-400">
|
||||
<span class="font-semibold ">
|
||||
Con esta libreria,{' '}
|
||||
</span>
|
||||
<span class="font-semibold ">Con esta libreria, </span>
|
||||
<span class="font-semibold ">
|
||||
puedes configurar respuestas
|
||||
automatizadas para preguntas frecuentes
|
||||
puedes configurar respuestas automatizadas para preguntas frecuentes
|
||||
</span>{' '}
|
||||
, recibir y responder mensajes de manera
|
||||
automatizada, y hacer un seguimiento de las
|
||||
interacciones con los clientes. Además,
|
||||
nuestro Chatbot se integra fácilmente con
|
||||
otros sistemas y herramientas que ya esté
|
||||
utilizando en su negocio.
|
||||
, recibir y responder mensajes de manera automatizada, y hacer un seguimiento de las
|
||||
interacciones con los clientes. Además, nuestro Chatbot se integra fácilmente con
|
||||
otros sistemas y herramientas que ya esté utilizando en su negocio.
|
||||
</p>
|
||||
|
||||
<div class="max-w-xs sm:max-w-md flex flex-nowrap flex-col sm:flex-col gap-4 m-auto md:m-0 justify-center md:justify-start">
|
||||
@@ -48,10 +36,7 @@ export default component$(() => {
|
||||
</code>
|
||||
</div>
|
||||
<div class="flex w-full sm:w-auto gap-3">
|
||||
<a
|
||||
href="/docs"
|
||||
class="btn bg-gray-50 dark:bg-transparent"
|
||||
>
|
||||
<a href="/docs" class="btn bg-gray-50 dark:bg-transparent">
|
||||
Ver documentación
|
||||
</a>
|
||||
<a
|
||||
|
||||
@@ -32,14 +32,9 @@ export default component$((props: { users: User[] }) => {
|
||||
Miembros
|
||||
</h2>
|
||||
<p class="max-w-3xl mx-auto sm:text-center text-xl text-gray-600 dark:text-slate-400">
|
||||
Conviértete en un miembro destacado y forma parte del
|
||||
proyecto y disfruta de manera adelantada de las
|
||||
actualizaciones{' '}
|
||||
<a
|
||||
class={'font-semibold'}
|
||||
target={'_blank'}
|
||||
href="https://opencollective.com/bot-whatsapp"
|
||||
>
|
||||
Conviértete en un miembro destacado y forma parte del proyecto y disfruta de manera adelantada
|
||||
de las actualizaciones{' '}
|
||||
<a class={'font-semibold'} target={'_blank'} href="https://opencollective.com/bot-whatsapp">
|
||||
Únete
|
||||
</a>
|
||||
</p>
|
||||
|
||||
@@ -5,55 +5,45 @@ import { DocumentationCtx } from '~/contexts'
|
||||
/**
|
||||
* options = [] array con la lista de opciones de la documentacion
|
||||
*/
|
||||
export default component$(
|
||||
({ options = [] }: { options: DocumentationCtx[] }) => {
|
||||
return (
|
||||
<div>
|
||||
{options.map((item, i) => (
|
||||
<UlCompoent key={i} title={item.title} list={item.list} />
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
)
|
||||
export default component$(({ options = [] }: { options: DocumentationCtx[] }) => {
|
||||
return (
|
||||
<div>
|
||||
{options.map((item, i) => (
|
||||
<UlCompoent key={i} title={item.title} list={item.list} />
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
||||
export const UlCompoent = component$(
|
||||
(porps: { title: string; list: { link: string; name: string }[] }) => {
|
||||
return (
|
||||
<ul>
|
||||
<li class="mt-2 lg:mt-2">
|
||||
<h5 class="mb-8 lg:mb-3 font-semibold text-slate-900 dark:text-slate-200">
|
||||
{porps.title}
|
||||
</h5>
|
||||
<LiComponent list={porps.list} />
|
||||
export const UlCompoent = component$((porps: { title: string; list: { link: string; name: string }[] }) => {
|
||||
return (
|
||||
<ul>
|
||||
<li class="mt-2 lg:mt-2">
|
||||
<h5 class="mb-8 lg:mb-3 font-semibold text-slate-900 dark:text-slate-200">{porps.title}</h5>
|
||||
<LiComponent list={porps.list} />
|
||||
</li>
|
||||
</ul>
|
||||
)
|
||||
})
|
||||
|
||||
export const LiComponent = component$((porps: { list: { link: string; name: string }[] }) => {
|
||||
const location = useLocation()
|
||||
const currentPage = location.pathname
|
||||
return (
|
||||
<ul class="space-y-6 lg:space-y-2 border-l border-slate-100 dark:border-slate-800">
|
||||
{porps.list.map((opt) => (
|
||||
<li>
|
||||
<Link
|
||||
class={[
|
||||
currentPage === `${opt.link}/` ? 'font-semibold' : '',
|
||||
'block border-l pl-4 -ml-px border-transparent hover:border-slate-400 dark:hover:border-slate-500 text-slate-700 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-300 ',
|
||||
]}
|
||||
href={opt.link}
|
||||
>
|
||||
{opt.name}
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
export const LiComponent = component$(
|
||||
(porps: { list: { link: string; name: string }[] }) => {
|
||||
const location = useLocation()
|
||||
const currentPage = location.pathname
|
||||
return (
|
||||
<ul class="space-y-6 lg:space-y-2 border-l border-slate-100 dark:border-slate-800">
|
||||
{porps.list.map((opt) => (
|
||||
<li>
|
||||
<Link
|
||||
class={[
|
||||
currentPage === `${opt.link}/`
|
||||
? 'font-semibold'
|
||||
: '',
|
||||
'block border-l pl-4 -ml-px border-transparent hover:border-slate-400 dark:hover:border-slate-500 text-slate-700 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-300 ',
|
||||
]}
|
||||
href={opt.link}
|
||||
>
|
||||
{opt.name}
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)
|
||||
}
|
||||
)
|
||||
))}
|
||||
</ul>
|
||||
)
|
||||
})
|
||||
|
||||
@@ -1,74 +1,63 @@
|
||||
import { component$ } from '@builder.io/qwik'
|
||||
|
||||
export const ButtonLink = component$(
|
||||
(props: { name: string; link: string; direction: 'left' | 'right' }) => {
|
||||
const ArrowRight = () => (
|
||||
<svg
|
||||
viewBox="0 0 3 6"
|
||||
class="ml-3 w-auto h-1.5 text-slate-400 overflow-visible group-hover:text-slate-600 dark:group-hover:text-slate-300"
|
||||
>
|
||||
<path
|
||||
d="M0 0L3 3L0 6"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
></path>
|
||||
</svg>
|
||||
)
|
||||
export const ButtonLink = component$((props: { name: string; link: string; direction: 'left' | 'right' }) => {
|
||||
const ArrowRight = () => (
|
||||
<svg
|
||||
viewBox="0 0 3 6"
|
||||
class="ml-3 w-auto h-1.5 text-slate-400 overflow-visible group-hover:text-slate-600 dark:group-hover:text-slate-300"
|
||||
>
|
||||
<path
|
||||
d="M0 0L3 3L0 6"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
></path>
|
||||
</svg>
|
||||
)
|
||||
|
||||
const ArrowLeft = () => (
|
||||
<svg
|
||||
viewBox="0 0 3 6"
|
||||
class="mr-3 w-auto h-1.5 text-slate-400 overflow-visible group-hover:text-slate-600 dark:group-hover:text-slate-300"
|
||||
>
|
||||
<path
|
||||
d="M3 0L0 3L3 6"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
></path>
|
||||
</svg>
|
||||
)
|
||||
const ArrowLeft = () => (
|
||||
<svg
|
||||
viewBox="0 0 3 6"
|
||||
class="mr-3 w-auto h-1.5 text-slate-400 overflow-visible group-hover:text-slate-600 dark:group-hover:text-slate-300"
|
||||
>
|
||||
<path
|
||||
d="M3 0L0 3L3 6"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
></path>
|
||||
</svg>
|
||||
)
|
||||
|
||||
return (
|
||||
<a
|
||||
class="group flex items-center hover:text-slate-900 dark:hover:text-white"
|
||||
href={props.link}
|
||||
>
|
||||
{props.direction === 'left' ? (
|
||||
<>
|
||||
<ArrowLeft />
|
||||
{props.name}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
{props.name}
|
||||
<ArrowRight />
|
||||
</>
|
||||
)}
|
||||
</a>
|
||||
)
|
||||
}
|
||||
)
|
||||
return (
|
||||
<a class="group flex items-center hover:text-slate-900 dark:hover:text-white" href={props.link}>
|
||||
{props.direction === 'left' ? (
|
||||
<>
|
||||
<ArrowLeft />
|
||||
{props.name}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
{props.name}
|
||||
<ArrowRight />
|
||||
</>
|
||||
)}
|
||||
</a>
|
||||
)
|
||||
})
|
||||
|
||||
export default component$(
|
||||
(props: { pages: ({ name: string; link: string } | null)[] }) => {
|
||||
const { pages } = props
|
||||
return (
|
||||
<div class="text-sm leading-6 mt-12">
|
||||
<div class="mb-10 text-slate-700 font-semibold flex justify-between items-center dark:text-slate-200">
|
||||
{pages[0] ? (
|
||||
<ButtonLink direction="left" {...pages[0]} />
|
||||
) : null}
|
||||
{pages[1] ? (
|
||||
<ButtonLink direction="right" {...pages[1]} />
|
||||
) : null}
|
||||
</div>
|
||||
export default component$((props: { pages: ({ name: string; link: string } | null)[] }) => {
|
||||
const { pages } = props
|
||||
return (
|
||||
<div class="text-sm leading-6 mt-12">
|
||||
<div class="mb-10 text-slate-700 font-semibold flex justify-between items-center dark:text-slate-200">
|
||||
{pages[0] ? <ButtonLink direction="left" {...pages[0]} /> : null}
|
||||
{pages[1] ? <ButtonLink direction="right" {...pages[1]} /> : null}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
)
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
||||
@@ -5,33 +5,25 @@ export default component$(() => {
|
||||
<div class="px-4 py-8 md:py-16 sm:px-6 mx-auto md:px-24 lg:px-8 lg:py-20 max-w-6xl">
|
||||
<div class="grid grid-cols-2 row-gap-8 md:grid-cols-4">
|
||||
<div class="text-center md:border-r dark:md:border-slate-500 mb-10 md:mb-0">
|
||||
<div class="text-4xl font-bold lg:text-5xl xl:text-6xl text-[#039de1] font-heading">
|
||||
132K
|
||||
</div>
|
||||
<div class="text-4xl font-bold lg:text-5xl xl:text-6xl text-[#039de1] font-heading">132K</div>
|
||||
<p class="text-sm font-medium tracking-widest text-gray-800 dark:text-slate-400 uppercase lg:text-base">
|
||||
Downloads
|
||||
</p>
|
||||
</div>
|
||||
<div class="text-center md:border-r dark:md:border-slate-500 mb-10 md:mb-0">
|
||||
<div class="text-4xl font-bold lg:text-5xl xl:text-6xl text-[#039de1] font-heading">
|
||||
24.8K
|
||||
</div>
|
||||
<div class="text-4xl font-bold lg:text-5xl xl:text-6xl text-[#039de1] font-heading">24.8K</div>
|
||||
<p class="text-sm font-medium tracking-widest text-gray-800 dark:text-slate-400 uppercase lg:text-base">
|
||||
Stars
|
||||
</p>
|
||||
</div>
|
||||
<div class="text-center md:border-r dark:md:border-slate-500 font-heading">
|
||||
<div class="text-4xl font-bold lg:text-5xl xl:text-6xl text-[#039de1]">
|
||||
10.3K
|
||||
</div>
|
||||
<div class="text-4xl font-bold lg:text-5xl xl:text-6xl text-[#039de1]">10.3K</div>
|
||||
<p class="text-sm font-medium tracking-widest text-gray-800 dark:text-slate-400 uppercase lg:text-base">
|
||||
Forks
|
||||
</p>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<div class="text-4xl font-bold lg:text-5xl xl:text-6xl text-[#039de1] font-heading">
|
||||
48.4K
|
||||
</div>
|
||||
<div class="text-4xl font-bold lg:text-5xl xl:text-6xl text-[#039de1] font-heading">48.4K</div>
|
||||
<p class="text-sm font-medium tracking-widest text-gray-800 dark:text-slate-400 uppercase lg:text-base">
|
||||
Users
|
||||
</p>
|
||||
|
||||
@@ -13,5 +13,4 @@ export interface User {
|
||||
avatar_url: string
|
||||
}
|
||||
|
||||
export const GlobalStore =
|
||||
createContext<DocumentationCtx[]>('documentation-site')
|
||||
export const GlobalStore = createContext<DocumentationCtx[]>('documentation-site')
|
||||
|
||||
@@ -1,14 +1,5 @@
|
||||
import {
|
||||
component$,
|
||||
useContextProvider,
|
||||
useStore,
|
||||
useStyles$,
|
||||
} from '@builder.io/qwik'
|
||||
import {
|
||||
QwikCityProvider,
|
||||
RouterOutlet,
|
||||
ServiceWorkerRegister,
|
||||
} from '@builder.io/qwik-city'
|
||||
import { component$, useContextProvider, useStore, useStyles$ } from '@builder.io/qwik'
|
||||
import { QwikCityProvider, RouterOutlet, ServiceWorkerRegister } from '@builder.io/qwik-city'
|
||||
|
||||
import { RouterHead } from '~/components/core/RouterHead'
|
||||
import { DarkThemeLauncher } from '~/components/core/DarkThemeLauncher'
|
||||
@@ -78,10 +69,7 @@ export default component$(() => {
|
||||
<QwikCityProvider>
|
||||
<head>
|
||||
<meta charSet="utf-8" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1"
|
||||
/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="manifest" href="/manifest.json" />
|
||||
|
||||
<RouterHead />
|
||||
|
||||
@@ -4,11 +4,10 @@ import Navigation from '../../../components/widgets/Navigation'
|
||||
# DataBase (Base de datos)
|
||||
|
||||
<Alert>
|
||||
⚡ Dependiendo del tipo de conector que utlices puede que necesites pasar
|
||||
algunas configuracion adicional como **user, host, password** para esos
|
||||
casos te recomendamos guiarte de los
|
||||
**[starters](https://github.com/codigoencasa/bot-whatsapp/tree/dev/starters/apps)**
|
||||
o si gustas puedes editar esta documentación para ir agregando más info
|
||||
⚡ Dependiendo del tipo de conector que utlices puede que necesites pasar algunas configuracion adicional como
|
||||
**user, host, password** para esos casos te recomendamos guiarte de los
|
||||
**[starters](https://github.com/codigoencasa/bot-whatsapp/tree/dev/starters/apps)** o si gustas puedes editar esta
|
||||
documentación para ir agregando más info
|
||||
</Alert>
|
||||
|
||||
Es la pieza encargada de mantener el **"estado"** de una conversación, para mayor facilidad la libreria te proporcia diferentes conectores que se de adapten mejor a tu desarrollo
|
||||
|
||||
@@ -22,12 +22,7 @@ Tan sencillo como decir **palabra/s clave** y **mensaje a responder**
|
||||
Ambos metodos **[addKeyword](https://github.com/codigoencasa/bot-whatsapp/blob/dev/packages/bot/io/methods/addKeyword.js)** y el **[addAnswer](https://github.com/codigoencasa/bot-whatsapp/blob/dev/packages/bot/io/methods/addAnswer.js)** tienen una serie opciones disponibles
|
||||
|
||||
```js
|
||||
const {
|
||||
createBot,
|
||||
createProvider,
|
||||
createFlow,
|
||||
addKeyword,
|
||||
} = require('@bot-whatsapp/bot')
|
||||
const { createBot, createProvider, createFlow, addKeyword } = require('@bot-whatsapp/bot')
|
||||
|
||||
const flowPrincipal = addKeyword(['hola', 'alo'])
|
||||
.addAnswer(['Hola, bienvenido a mi tienda', '¿Como puedo ayudarte?'])
|
||||
@@ -39,11 +34,10 @@ const flowPrincipal = addKeyword(['hola', 'alo'])
|
||||
## Provider (Proveedor)
|
||||
|
||||
<Alert>
|
||||
⚡ Dependiendo del tipo de proveedor que utlices puede que necesites pasar
|
||||
algunas configuracion adicional como **token, api, etc.** para esos casos te
|
||||
recomendamos guiarte de los
|
||||
**[starters](https://github.com/codigoencasa/bot-whatsapp/tree/dev/starters/apps)**
|
||||
o si gustas puedes editar esta documentación para ir agregando más info
|
||||
⚡ Dependiendo del tipo de proveedor que utlices puede que necesites pasar algunas configuracion adicional como
|
||||
**token, api, etc.** para esos casos te recomendamos guiarte de los
|
||||
**[starters](https://github.com/codigoencasa/bot-whatsapp/tree/dev/starters/apps)** o si gustas puedes editar esta
|
||||
documentación para ir agregando más info
|
||||
</Alert>
|
||||
|
||||
Es la pieza que conectara tu flujo con Whatsapp. En este chatbot tenemos varios proveedores disponibles la mayoria gratis pero tambien tenemos integracion la api oficial de whatsapp o twilio
|
||||
@@ -71,11 +65,10 @@ Los proveedores disponibles hasta el momento son los siguientes:
|
||||
## DataBase (Base de datos)
|
||||
|
||||
<Alert>
|
||||
⚡ Dependiendo del tipo de conector que utlices puede que necesites pasar
|
||||
algunas configuracion adicional como **user, host, password** para esos
|
||||
casos te recomendamos guiarte de los
|
||||
**[starters](https://github.com/codigoencasa/bot-whatsapp/tree/dev/starters/apps)**
|
||||
o si gustas puedes editar esta documentación para ir agregando más info
|
||||
⚡ Dependiendo del tipo de conector que utlices puede que necesites pasar algunas configuracion adicional como
|
||||
**user, host, password** para esos casos te recomendamos guiarte de los
|
||||
**[starters](https://github.com/codigoencasa/bot-whatsapp/tree/dev/starters/apps)** o si gustas puedes editar esta
|
||||
documentación para ir agregando más info
|
||||
</Alert>
|
||||
|
||||
Es la pieza encargada de mantener el **"estado"** de una conversación, para mayor facilidad la libreria te proporcia diferentes conectores que se de adapten mejor a tu desarrollo
|
||||
|
||||
@@ -5,12 +5,7 @@ import Navigation from '../../../components/widgets/Navigation'
|
||||
Si copias y pegas este codigo y tu entorno de trabajo cumple con todos los requesitos te debe funcionar abajo explico muy por encima
|
||||
|
||||
```js
|
||||
const {
|
||||
createBot,
|
||||
createProvider,
|
||||
createFlow,
|
||||
addKeyword,
|
||||
} = require('@bot-whatsapp/bot')
|
||||
const { createBot, createProvider, createFlow, addKeyword } = require('@bot-whatsapp/bot')
|
||||
|
||||
const WebWhatsappProvider = require('@bot-whatsapp/provider/web-whatsapp')
|
||||
const MockAdapter = require('@bot-whatsapp/database/mock')
|
||||
@@ -42,12 +37,7 @@ main()
|
||||
En esta parte solo estamos declaramos las dependencias que vamos a utilizar. Si quieres saber a fondo cada una de las funciones te recomiendo pasarte por la seccion de **[conceptos](/docs/concepts)**
|
||||
|
||||
```js
|
||||
const {
|
||||
createBot,
|
||||
createProvider,
|
||||
createFlow,
|
||||
addKeyword,
|
||||
} = require('@bot-whatsapp/bot')
|
||||
const { createBot, createProvider, createFlow, addKeyword } = require('@bot-whatsapp/bot')
|
||||
|
||||
const WebWhatsappProvider = require('@bot-whatsapp/provider/web-whatsapp')
|
||||
const MockAdapter = require('@bot-whatsapp/database/mock')
|
||||
|
||||
@@ -9,12 +9,7 @@ Tan sencillo como decir **palabra/s clave** y **mensaje a responder**
|
||||
Ambos metodos **[addKeyword](https://github.com/codigoencasa/bot-whatsapp/blob/dev/packages/bot/io/methods/addKeyword.js)** y el **[addAnswer](https://github.com/codigoencasa/bot-whatsapp/blob/dev/packages/bot/io/methods/addAnswer.js)** tienen una serie opciones disponibles
|
||||
|
||||
```js
|
||||
const {
|
||||
createBot,
|
||||
createProvider,
|
||||
createFlow,
|
||||
addKeyword,
|
||||
} = require('@bot-whatsapp/bot')
|
||||
const { createBot, createProvider, createFlow, addKeyword } = require('@bot-whatsapp/bot')
|
||||
|
||||
const flowPrincipal = addKeyword(['hola', 'alo'])
|
||||
.addAnswer(['Hola, bienvenido a mi tienda', '¿Como puedo ayudarte?'])
|
||||
@@ -81,37 +76,21 @@ Esta funcion se utliza para responder un mensaje despues del `addKeyword()`
|
||||
```js
|
||||
const { addKeyword } = require('@bot-whatsapp/bot')
|
||||
|
||||
const flowString = addKeyword('hola').addAnswer(
|
||||
'Este mensaje se enviara 1 segundo despues',
|
||||
{
|
||||
delay: 1000,
|
||||
}
|
||||
)
|
||||
const flowString = addKeyword('hola').addAnswer('Este mensaje se enviara 1 segundo despues', {
|
||||
delay: 1000,
|
||||
})
|
||||
|
||||
const flowString = addKeyword('hola').addAnswer(
|
||||
'Este mensaje envia una imagen',
|
||||
{
|
||||
media: 'https://i.imgur.com/0HpzsEm.png',
|
||||
}
|
||||
)
|
||||
const flowString = addKeyword('hola').addAnswer('Este mensaje envia una imagen', {
|
||||
media: 'https://i.imgur.com/0HpzsEm.png',
|
||||
})
|
||||
|
||||
const flowString = addKeyword('hola').addAnswer(
|
||||
'Este mensaje envia tres botones',
|
||||
{
|
||||
buttons: [
|
||||
{ body: 'Boton 1' },
|
||||
{ body: 'Boton 2' },
|
||||
{ body: 'Boton 3' },
|
||||
],
|
||||
}
|
||||
)
|
||||
const flowString = addKeyword('hola').addAnswer('Este mensaje envia tres botones', {
|
||||
buttons: [{ body: 'Boton 1' }, { body: 'Boton 2' }, { body: 'Boton 3' }],
|
||||
})
|
||||
|
||||
const flowString = addKeyword('hola').addAnswer(
|
||||
'Este mensaje espera una respueta del usuario',
|
||||
{
|
||||
capture: true,
|
||||
}
|
||||
)
|
||||
const flowString = addKeyword('hola').addAnswer('Este mensaje espera una respueta del usuario', {
|
||||
capture: true,
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
@@ -123,13 +102,9 @@ Este argumento se utiliza para obtener el contexto de la conversación
|
||||
```js
|
||||
const { addKeyword } = require('@bot-whatsapp/bot')
|
||||
|
||||
const flowString = addKeyword('hola').addAnswer(
|
||||
'Indica cual es tu email',
|
||||
null,
|
||||
(ctx) => {
|
||||
console.log('👉 Informacion del contexto: ', ctx)
|
||||
}
|
||||
)
|
||||
const flowString = addKeyword('hola').addAnswer('Indica cual es tu email', null, (ctx) => {
|
||||
console.log('👉 Informacion del contexto: ', ctx)
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
@@ -143,13 +118,9 @@ se repetira el mensaje `Indica cual es tu email`
|
||||
```js
|
||||
const { addKeyword } = require('@bot-whatsapp/bot')
|
||||
|
||||
const flowString = addKeyword('hola').addAnswer(
|
||||
'Indica cual es tu email',
|
||||
null,
|
||||
(ctx, { fallBack }) => {
|
||||
if (!ctx.body.includes('@')) return fallBack()
|
||||
}
|
||||
)
|
||||
const flowString = addKeyword('hola').addAnswer('Indica cual es tu email', null, (ctx, { fallBack }) => {
|
||||
if (!ctx.body.includes('@')) return fallBack()
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -4,10 +4,9 @@ import Navigation from '../../components/widgets/Navigation'
|
||||
# Introducción
|
||||
|
||||
<Alert>
|
||||
**Atención** estás leyendo la documentación de la **versión v2** de esta
|
||||
librería, si vienes de la versión anterior te recomendamos pasarte por la
|
||||
sección de **[migración](/docs/migration/)** para que puedas disfrutar de
|
||||
las nuevas características.
|
||||
**Atención** estás leyendo la documentación de la **versión v2** de esta librería, si vienes de la versión anterior
|
||||
te recomendamos pasarte por la sección de **[migración](/docs/migration/)** para que puedas disfrutar de las nuevas
|
||||
características.
|
||||
</Alert>
|
||||
|
||||
## ¿Qué es esto?
|
||||
@@ -34,10 +33,7 @@ npm create bot-whatsapp@latest
|
||||
muted
|
||||
playsinline
|
||||
>
|
||||
<source
|
||||
src="https://leifer-landing-page.s3.us-east-2.amazonaws.com/console.webm"
|
||||
type="video/webm"
|
||||
/>
|
||||
<source src="https://leifer-landing-page.s3.us-east-2.amazonaws.com/console.webm" type="video/webm" />
|
||||
</video>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -28,10 +28,7 @@ El **CLI** te hace una revisión previa, de versión de Node y sistema operativo
|
||||
muted
|
||||
playsinline
|
||||
>
|
||||
<source
|
||||
src="https://leifer-landing-page.s3.us-east-2.amazonaws.com/console.webm"
|
||||
type="video/webm"
|
||||
/>
|
||||
<source src="https://leifer-landing-page.s3.us-east-2.amazonaws.com/console.webm" type="video/webm" />
|
||||
</video>
|
||||
</div>
|
||||
|
||||
@@ -54,10 +51,8 @@ Cada plantilla tiene sus dependencias necesarias basadas en tu previa selección
|
||||
```
|
||||
|
||||
<Alert>
|
||||
📄 Si deseas cambiar tu **proveedor o tu motor** de base de datos no es
|
||||
necesario volver ejecutar el CLI (lo puedes hacer sin problema) aunque
|
||||
tambien basta con solo modificar un par de lineas. [Ver
|
||||
explicación](/docs/essential)
|
||||
📄 Si deseas cambiar tu **proveedor o tu motor** de base de datos no es necesario volver ejecutar el CLI (lo puedes
|
||||
hacer sin problema) aunque tambien basta con solo modificar un par de lineas. [Ver explicación](/docs/essential)
|
||||
</Alert>
|
||||
|
||||
---
|
||||
|
||||
@@ -27,11 +27,7 @@ export default component$(() => {
|
||||
<NavBar options={store} />
|
||||
</div>
|
||||
<div class={'lg:pl-[14.5rem] lg:pr-[14.5rem]'}>
|
||||
<div
|
||||
class={
|
||||
'slot max-w-3xl mx-auto relative z-20 p-5 xl:max-w-none'
|
||||
}
|
||||
>
|
||||
<div class={'slot max-w-3xl mx-auto relative z-20 p-5 xl:max-w-none'}>
|
||||
<Slot />
|
||||
</div>
|
||||
</div>
|
||||
@@ -54,8 +50,7 @@ export const head: DocumentHead = {
|
||||
meta: [
|
||||
{
|
||||
name: 'description',
|
||||
content:
|
||||
'Crear chatbot WhatsApp en minutos — Servicio de chatbot para whatspp gratis proyecto OpenSource',
|
||||
content: 'Crear chatbot WhatsApp en minutos — Servicio de chatbot para whatspp gratis proyecto OpenSource',
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
@@ -49,11 +49,7 @@ En la **_versión (legacy)_** se implementas los flujos de esta manera, en dos a
|
||||
"title": "¿Que te interesa ver?",
|
||||
"message": "Abajo unos botons",
|
||||
"footer": "",
|
||||
"buttons": [
|
||||
{ "body": "Telefonos" },
|
||||
{ "body": "Computadoras" },
|
||||
{ "body": "Otros" }
|
||||
]
|
||||
"buttons": [{ "body": "Telefonos" }, { "body": "Computadoras" }, { "body": "Otros" }]
|
||||
}
|
||||
},
|
||||
"catalogo": {
|
||||
@@ -70,51 +66,28 @@ En esta versión es mucho más sencillo, abajo encontrarás un ejemplo del mismo
|
||||
|
||||
```js
|
||||
//app.js
|
||||
const {
|
||||
createBot,
|
||||
createProvider,
|
||||
createFlow,
|
||||
addKeyword,
|
||||
addChild,
|
||||
} = require('@bot-whatsapp/bot')
|
||||
const { createBot, createProvider, createFlow, addKeyword, addChild } = require('@bot-whatsapp/bot')
|
||||
|
||||
const BaileysProvider = require('@bot-whatsapp/provider/baileys') //Provider
|
||||
const MockAdapter = require('@bot-whatsapp/database/mock') //Base de datos
|
||||
/**
|
||||
* Declarando flujos principales.
|
||||
*/
|
||||
const flowHola = addKeyword(['hola', 'ola', 'alo']).addAnswer(
|
||||
'Bienvenido a tu tienda online!'
|
||||
)
|
||||
const flowHola = addKeyword(['hola', 'ola', 'alo']).addAnswer('Bienvenido a tu tienda online!')
|
||||
|
||||
const flowAdios = addKeyword(['adios', 'bye'])
|
||||
.addAnswer('Que te vaya bien!!')
|
||||
.addAnswer('Hasta luego!')
|
||||
const flowAdios = addKeyword(['adios', 'bye']).addAnswer('Que te vaya bien!!').addAnswer('Hasta luego!')
|
||||
|
||||
const flowProductos = addKeyword(['productos', 'info']).addAnswer(
|
||||
'Te envio una imagen',
|
||||
{
|
||||
buttons: [
|
||||
{ body: 'Telefonos' },
|
||||
{ body: 'Computadoras' },
|
||||
{ body: 'Otros' },
|
||||
],
|
||||
}
|
||||
)
|
||||
const flowProductos = addKeyword(['productos', 'info']).addAnswer('Te envio una imagen', {
|
||||
buttons: [{ body: 'Telefonos' }, { body: 'Computadoras' }, { body: 'Otros' }],
|
||||
})
|
||||
|
||||
const flowCatalogo = addKeyword(['imagen', 'foto']).addAnswer(
|
||||
'Te envio una imagen',
|
||||
{ media: 'https://media2.giphy.com/media/VQJu0IeULuAmCwf5SL/giphy.gif' }
|
||||
)
|
||||
const flowCatalogo = addKeyword(['imagen', 'foto']).addAnswer('Te envio una imagen', {
|
||||
media: 'https://media2.giphy.com/media/VQJu0IeULuAmCwf5SL/giphy.gif',
|
||||
})
|
||||
|
||||
const main = async () => {
|
||||
const adapterDB = new MockAdapter()
|
||||
const adapterFlow = createFlow([
|
||||
flowHola,
|
||||
flowAdios,
|
||||
flowProductos,
|
||||
flowCatalogo,
|
||||
]) //Se crean los flujos.
|
||||
const adapterFlow = createFlow([flowHola, flowAdios, flowProductos, flowCatalogo]) //Se crean los flujos.
|
||||
const adapterProvider = createProvider(BaileysProvider)
|
||||
createBot({
|
||||
flow: adapterFlow,
|
||||
|
||||
@@ -49,17 +49,15 @@ Qwik is a new kind of web framework that can deliver instant loading web applica
|
||||
<div class="card">
|
||||
<h3>Instant-on</h3>
|
||||
<p>
|
||||
Unlike other frameworks, Qwik is resumable which means Qwik
|
||||
applications require 0 hydration. This allows Qwik apps to have
|
||||
instant-on interactivity, regardless of size or complexity
|
||||
Unlike other frameworks, Qwik is resumable which means Qwik applications require 0 hydration. This allows
|
||||
Qwik apps to have instant-on interactivity, regardless of size or complexity
|
||||
</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>Optimized for speed</h3>
|
||||
<p>
|
||||
Qwik has unprecedented performance, offering sub-second full page
|
||||
loads even on mobile devices. Qwik achieves this by delivering pure
|
||||
HTML, and incrementally loading JS only as-needed.
|
||||
Qwik has unprecedented performance, offering sub-second full page loads even on mobile devices. Qwik
|
||||
achieves this by delivering pure HTML, and incrementally loading JS only as-needed.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,11 +4,10 @@ import Navigation from '../../../components/widgets/Navigation'
|
||||
# Proveedores
|
||||
|
||||
<Alert>
|
||||
⚡ Dependiendo del tipo de proveedor que utlices puede que necesites pasar
|
||||
algunas configuracion adicional como **token, api, etc.** para esos casos te
|
||||
recomendamos guiarte de los
|
||||
**[starters](https://github.com/codigoencasa/bot-whatsapp/tree/dev/starters/apps)**
|
||||
o si gustas puedes editar esta documentación para ir agregando más info
|
||||
⚡ Dependiendo del tipo de proveedor que utlices puede que necesites pasar algunas configuracion adicional como
|
||||
**token, api, etc.** para esos casos te recomendamos guiarte de los
|
||||
**[starters](https://github.com/codigoencasa/bot-whatsapp/tree/dev/starters/apps)** o si gustas puedes editar esta
|
||||
documentación para ir agregando más info
|
||||
</Alert>
|
||||
|
||||
Es la pieza que conectara tu flujo con Whatsapp. En este chatbot tenemos varios proveedores disponibles la mayoria gratis pero tambien tenemos integracion la api oficial de whatsapp o twilio
|
||||
|
||||
@@ -59,10 +59,7 @@ En el **archivo principal** del bot donde estás implementando la función del a
|
||||
- **jwtToken:** Lo puedes encontrar en la pagina anterior
|
||||
- **verifyToken:** Puedes escribir lo que quieras es como una palabra clave
|
||||
|
||||
<Alert>
|
||||
En el ejemplo de abajo puedes ver como una sugerencia de como puede ser
|
||||
utilizando variables de entorno
|
||||
</Alert>
|
||||
<Alert>En el ejemplo de abajo puedes ver como una sugerencia de como puede ser utilizando variables de entorno</Alert>
|
||||
|
||||
```js
|
||||
const main = async () => {
|
||||
|
||||
@@ -5,10 +5,7 @@ import Navigation from '../../../../components/widgets/Navigation'
|
||||
|
||||
Twilio es una plataforma de desarrollo que permite a los desarrolladores construir aplicaciones de comunicación en la nube y sistemas web. Las API de comunicaciones de Twilio permiten a las empresas proporcionar la experiencia de comunicación adecuada para sus clientes dentro de la web y las aplicaciones móviles. Al usar las API de Twilio, los desarrolladores pueden agregar rápidamente esta funcionalidad a una aplicación, como mensajes de voz, videollamadas, mensajes de texto y más.
|
||||
|
||||
<Alert>
|
||||
Twilio te proporciona una cuenta **Sandbox** para que puedas probar
|
||||
gratuitamente el servicio
|
||||
</Alert>
|
||||
<Alert>Twilio te proporciona una cuenta **Sandbox** para que puedas probar gratuitamente el servicio</Alert>
|
||||
|
||||
### Requerimientos
|
||||
|
||||
@@ -66,10 +63,7 @@ En el **archivo principal** del bot donde estás implementando la función del a
|
||||
- **ACC_VENDOR:** Es el numero de whatsapp (si ya tienes el plan de pago de Twilio usa el numero que compraste), si aun estas en modo
|
||||
sandbox utliza el numero proporcionado en el paso numero 2
|
||||
|
||||
<Alert>
|
||||
En el ejemplo de abajo puedes ver como una sugerencia de como puede ser
|
||||
utilizando variables de entorno
|
||||
</Alert>
|
||||
<Alert>En el ejemplo de abajo puedes ver como una sugerencia de como puede ser utilizando variables de entorno</Alert>
|
||||
|
||||
```js
|
||||
const main = async () => {
|
||||
|
||||
@@ -13,8 +13,7 @@ import { GITHUB_TOKEN } from './docs/constant'
|
||||
// import { SearchModal } from '~/components/widgets/SearchModal'
|
||||
|
||||
export const onGet: RequestHandlerNetlify = async ({ platform }) => {
|
||||
const CHECK_GITHUB_TOKEN =
|
||||
(platform as any)?.['GITHUB_TOKEN'] ?? GITHUB_TOKEN
|
||||
const CHECK_GITHUB_TOKEN = (platform as any)?.['GITHUB_TOKEN'] ?? GITHUB_TOKEN
|
||||
const dataGithub = await fetchGithub(CHECK_GITHUB_TOKEN)
|
||||
const dataOpenCollective = await fetchOpenCollective()
|
||||
return {
|
||||
@@ -52,8 +51,7 @@ export const head: DocumentHead = {
|
||||
meta: [
|
||||
{
|
||||
name: 'description',
|
||||
content:
|
||||
'Crear chatbot WhatsApp en minutos — Servicio de chatbot para whatspp gratis proyecto OpenSource',
|
||||
content: 'Crear chatbot WhatsApp en minutos — Servicio de chatbot para whatspp gratis proyecto OpenSource',
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
@@ -3,17 +3,14 @@
|
||||
* @returns
|
||||
*/
|
||||
export const fetchGithub = async (token: string) => {
|
||||
const data = await fetch(
|
||||
`https://api.github.com/repos/codigoencasa/bot-whatsapp/contributors`,
|
||||
{
|
||||
method: 'GET',
|
||||
headers: {
|
||||
Accept: 'application/vnd.github+json',
|
||||
'X-GitHub-Api-Version': '2022-11-28',
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
}
|
||||
)
|
||||
const data = await fetch(`https://api.github.com/repos/codigoencasa/bot-whatsapp/contributors`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
Accept: 'application/vnd.github+json',
|
||||
'X-GitHub-Api-Version': '2022-11-28',
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
})
|
||||
const listUsers = await data.json()
|
||||
return listUsers.map((u: any) => ({
|
||||
...u,
|
||||
|
||||
@@ -3,12 +3,9 @@
|
||||
* @returns
|
||||
*/
|
||||
export const fetchOpenCollective = async () => {
|
||||
const data = await fetch(
|
||||
`https://opencollective.com/bot-whatsapp/members/users.json?limit=22&offset=0`,
|
||||
{
|
||||
method: 'GET',
|
||||
}
|
||||
)
|
||||
const data = await fetch(`https://opencollective.com/bot-whatsapp/members/users.json?limit=22&offset=0`, {
|
||||
method: 'GET',
|
||||
})
|
||||
const listUsers = await data.json()
|
||||
return listUsers.map((u: any) => ({
|
||||
html_url: u.profile,
|
||||
|
||||
@@ -76,9 +76,7 @@ module.exports = {
|
||||
a: {
|
||||
fontWeight: theme('fontWeight.semibold'),
|
||||
textDecoration: 'none',
|
||||
borderBottom: `1px solid ${theme(
|
||||
'colors.sky.300'
|
||||
)}`,
|
||||
borderBottom: `1px solid ${theme('colors.sky.300')}`,
|
||||
},
|
||||
'a:hover': {
|
||||
borderBottomWidth: '2px',
|
||||
|
||||
@@ -3,11 +3,7 @@
|
||||
"scope": "javascriptreact,typescriptreact",
|
||||
"prefix": "q:onGet",
|
||||
"description": "onGet function for a route index",
|
||||
"body": [
|
||||
"export const onGet: RequestHandler = (request) => {",
|
||||
" $0",
|
||||
"};"
|
||||
]
|
||||
"body": ["export const onGet: RequestHandler = (request) => {", " $0", "};"]
|
||||
},
|
||||
"onGet (typed)": {
|
||||
"scope": "javascriptreact,typescriptreact",
|
||||
|
||||
15
packages/portal/.vscode/qwik.code-snippets
vendored
15
packages/portal/.vscode/qwik.code-snippets
vendored
@@ -56,24 +56,13 @@
|
||||
"scope": "javascriptreact,typescriptreact",
|
||||
"prefix": "q:useTask",
|
||||
"description": "useTask$() function hook",
|
||||
"body": [
|
||||
"useTask$(({ track }) => {",
|
||||
" track(() => $1);",
|
||||
" $0",
|
||||
"});",
|
||||
""
|
||||
]
|
||||
"body": ["useTask$(({ track }) => {", " track(() => $1);", " $0", "});", ""]
|
||||
},
|
||||
"useResource": {
|
||||
"scope": "javascriptreact,typescriptreact",
|
||||
"prefix": "q:useResource",
|
||||
"description": "useResource$() declaration",
|
||||
"body": [
|
||||
"const $1 = useResource$(({ track, cleanup }) => {",
|
||||
" $0",
|
||||
"});",
|
||||
""
|
||||
]
|
||||
"body": ["const $1 = useResource$(({ track, cleanup }) => {", " $0", "});", ""]
|
||||
},
|
||||
"useServerMount": {
|
||||
"scope": "javascriptreact,typescriptreact",
|
||||
|
||||
@@ -5,14 +5,9 @@ const polka = require('polka')
|
||||
|
||||
const HTTP_PORT = process.env.PORT || 3000
|
||||
const QR_FILE = process.env.QR_FILE ?? 'bot'
|
||||
const PUBLIC_URL =
|
||||
process.env.PUBLIC_URL ??
|
||||
process.env.RAILWAY_STATIC_URL ??
|
||||
'http://localhost'
|
||||
const PUBLIC_URL = process.env.PUBLIC_URL ?? process.env.RAILWAY_STATIC_URL ?? 'http://localhost'
|
||||
|
||||
const dir = [join(__dirname, 'dist'), join(__dirname, '..', 'dist')].find((i) =>
|
||||
existsSync(i)
|
||||
)
|
||||
const dir = [join(__dirname, 'dist'), join(__dirname, '..', 'dist')].find((i) => existsSync(i))
|
||||
const serve = require('serve-static')(dir)
|
||||
|
||||
/**
|
||||
@@ -32,14 +27,8 @@ const start = (args) => {
|
||||
console.log(``)
|
||||
console.log(bgYellow(`🚩 ESCANEAR QR 🚩`))
|
||||
console.log(cyan(`Existen varias maneras de escanear el QR code`))
|
||||
console.log(
|
||||
cyan(`- Tambien puedes visitar `),
|
||||
yellow(`${publicSite}:${port}`)
|
||||
)
|
||||
console.log(
|
||||
cyan(`- Se ha creado un archivo que finaliza `),
|
||||
yellow('qr.png')
|
||||
)
|
||||
console.log(cyan(`- Tambien puedes visitar `), yellow(`${publicSite}:${port}`))
|
||||
console.log(cyan(`- Se ha creado un archivo que finaliza `), yellow('qr.png'))
|
||||
console.log(``)
|
||||
}
|
||||
|
||||
|
||||
@@ -8,28 +8,18 @@ export default component$(() => {
|
||||
return (
|
||||
<header>
|
||||
<div class="logo">
|
||||
<a
|
||||
href="https://github.com/codigoencasa/bot-whatsapp"
|
||||
target="_blank"
|
||||
title="qwik"
|
||||
>
|
||||
<a href="https://github.com/codigoencasa/bot-whatsapp" target="_blank" title="qwik">
|
||||
<BotLogo />
|
||||
</a>
|
||||
</div>
|
||||
<ul>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/codigoencasa/bot-whatsapp"
|
||||
target="_blank"
|
||||
>
|
||||
<a href="https://github.com/codigoencasa/bot-whatsapp" target="_blank">
|
||||
Docs
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/codigoencasa/bot-whatsapp/tree/main/starters/apps"
|
||||
target="_blank"
|
||||
>
|
||||
<a href="https://github.com/codigoencasa/bot-whatsapp/tree/main/starters/apps" target="_blank">
|
||||
Examples
|
||||
</a>
|
||||
</li>
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
export const QwikLogo = () => (
|
||||
<svg
|
||||
width="100"
|
||||
height="35"
|
||||
viewBox="0 0 167 53"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<svg width="100" height="35" viewBox="0 0 167 53" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M81.9545 46.5859H75.5513V35.4045C73.4363 36.8579 71.0496 37.5749 68.4884 37.5749C65.0151 37.5749 62.4344 36.6253 60.8239 34.6487C59.2134 32.6915 58.3984 29.2034 58.3984 24.2231C58.3984 19.1266 59.3492 15.5997 61.2702 13.5456C63.23 11.4721 66.3734 10.4644 70.7004 10.4644C74.7946 10.4644 78.5201 11.0264 81.9545 12.131V46.5859ZM75.5513 16.278C74.096 15.8323 72.4661 15.6191 70.7004 15.6191C68.5272 15.6191 66.9749 16.1811 66.1017 17.3244C65.2479 18.4871 64.7823 20.6962 64.7823 23.9712C64.7823 27.0524 65.1897 29.1065 66.0435 30.2304C66.8973 31.335 68.3719 31.897 70.5452 31.897C73.3781 31.897 75.5513 30.7343 75.5513 29.2809V16.278Z"
|
||||
fill="black"
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
import {
|
||||
component$,
|
||||
useClientEffect$,
|
||||
useStore,
|
||||
useStylesScoped$,
|
||||
} from '@builder.io/qwik'
|
||||
import { component$, useClientEffect$, useStore, useStylesScoped$ } from '@builder.io/qwik'
|
||||
import style from './qr.css?inline'
|
||||
|
||||
export const QR = component$(() => {
|
||||
@@ -20,12 +15,7 @@ export const QR = component$(() => {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<img
|
||||
width={350}
|
||||
height={350}
|
||||
src={'qr.png?time=' + state.count}
|
||||
alt="QR"
|
||||
/>
|
||||
<img width={350} height={350} src={'qr.png?time=' + state.count} alt="QR" />
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
||||
@@ -10,10 +10,7 @@ export const RouterHead = component$(() => {
|
||||
<title>{head.title}</title>
|
||||
|
||||
<link rel="canonical" href={loc.href} />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1.0"
|
||||
/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
|
||||
{head.meta.map((m) => (
|
||||
|
||||
@@ -15,8 +15,7 @@
|
||||
|
||||
body {
|
||||
background-color: #fafafa;
|
||||
font-family: 'Inter', sans-serif, ui-sans-serif, system-ui, -apple-system,
|
||||
BlinkMacSystemFont, sans-serif;
|
||||
font-family: 'Inter', sans-serif, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
|
||||
padding: 20px 20px 40px 20px;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,8 +12,7 @@
|
||||
|
||||
.page .btn-link {
|
||||
background: white;
|
||||
box-shadow: rgb(0 0 0 / 16%) 0px 10px 36px 0px,
|
||||
rgb(0 0 0 / 6%) 0px 0px 0px 1px;
|
||||
box-shadow: rgb(0 0 0 / 16%) 0px 10px 36px 0px, rgb(0 0 0 / 6%) 0px 0px 0px 1px;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
font-weight: 600;
|
||||
|
||||
@@ -15,19 +15,13 @@ export default component$(() => {
|
||||
<div class={'qr-section intructions'}>
|
||||
<h1>Whatsapp QR</h1>
|
||||
<p>
|
||||
Con esta libreria, puedes configurar respuestas
|
||||
automatizadas para preguntas frecuentes, recibir y responder
|
||||
mensajes de manera automatizada, y hacer un seguimiento de
|
||||
las interacciones con los clientes. <br /> Además, nuestro
|
||||
Chatbot se integra fácilmente con otros sistemas y
|
||||
herramientas que ya esté utilizando en su negocio.
|
||||
Con esta libreria, puedes configurar respuestas automatizadas para preguntas frecuentes, recibir y
|
||||
responder mensajes de manera automatizada, y hacer un seguimiento de las interacciones con los
|
||||
clientes. <br /> Además, nuestro Chatbot se integra fácilmente con otros sistemas y herramientas que
|
||||
ya esté utilizando en su negocio.
|
||||
</p>
|
||||
<div class={'qr-section links'}>
|
||||
<a
|
||||
class={'btn-link '}
|
||||
target="_blank"
|
||||
href="https://bot-whatsapp.netlify.app/"
|
||||
>
|
||||
<a class={'btn-link '} target="_blank" href="https://bot-whatsapp.netlify.app/">
|
||||
Ver documentación
|
||||
</a>
|
||||
<a
|
||||
@@ -37,11 +31,7 @@ export default component$(() => {
|
||||
>
|
||||
Ver videos
|
||||
</a>
|
||||
<a
|
||||
class={'btn-link '}
|
||||
target="_blank"
|
||||
href="https://opencollective.com/bot-whatsapp"
|
||||
>
|
||||
<a class={'btn-link '} target="_blank" href="https://opencollective.com/bot-whatsapp">
|
||||
Comprar café
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -56,15 +56,11 @@ class MetaProvider extends ProviderClass {
|
||||
|
||||
sendMessageMeta = async (body) => {
|
||||
try {
|
||||
const response = await axios.post(
|
||||
`${URL}/${this.numberId}/messages`,
|
||||
body,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${this.jwtToken}`,
|
||||
},
|
||||
}
|
||||
)
|
||||
const response = await axios.post(`${URL}/${this.numberId}/messages`, body, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${this.jwtToken}`,
|
||||
},
|
||||
})
|
||||
return response.data
|
||||
} catch (error) {
|
||||
return Promise.resolve(error)
|
||||
@@ -106,8 +102,7 @@ class MetaProvider extends ProviderClass {
|
||||
*/
|
||||
sendMessage = async (number, message, { options }) => {
|
||||
if (options?.buttons?.length) return console.log('Envio de botones')
|
||||
if (options?.media)
|
||||
return this.sendMedia(number, message, options.media)
|
||||
if (options?.media) return this.sendMedia(number, message, options.media)
|
||||
|
||||
this.sendtext(number, message)
|
||||
}
|
||||
|
||||
@@ -81,9 +81,7 @@ class MetaWebHookServer extends EventEmitter {
|
||||
* @returns
|
||||
*/
|
||||
buildHTTPServer = () => {
|
||||
this.metaServer
|
||||
.use(urlencoded({ extended: true }))
|
||||
.get('/webhook', this.verifyToken)
|
||||
this.metaServer.use(urlencoded({ extended: true })).get('/webhook', this.verifyToken)
|
||||
|
||||
this.metaServer
|
||||
.use(urlencoded({ extended: true }))
|
||||
@@ -99,9 +97,7 @@ class MetaWebHookServer extends EventEmitter {
|
||||
this.metaServer.listen(this.metaPort, () => {
|
||||
console.log(``)
|
||||
console.log(`[meta]: Agregar esta url "WHEN A MESSAGE COMES IN"`)
|
||||
console.log(
|
||||
`[meta]: POST http://localhost:${this.metaPort}/webhook`
|
||||
)
|
||||
console.log(`[meta]: POST http://localhost:${this.metaPort}/webhook`)
|
||||
console.log(`[meta]: Más información en la documentacion`)
|
||||
console.log(``)
|
||||
})
|
||||
|
||||
@@ -86,12 +86,8 @@ class TwilioProvider extends ProviderClass {
|
||||
*/
|
||||
sendButtons = async () => {
|
||||
console.log(``)
|
||||
console.log(
|
||||
`[NOTA]: Actualmente enviar botons con Twilio esta en desarrollo`
|
||||
)
|
||||
console.log(
|
||||
`[NOTA]: https://www.twilio.com/es-mx/docs/whatsapp/buttons`
|
||||
)
|
||||
console.log(`[NOTA]: Actualmente enviar botons con Twilio esta en desarrollo`)
|
||||
console.log(`[NOTA]: https://www.twilio.com/es-mx/docs/whatsapp/buttons`)
|
||||
console.log(``)
|
||||
}
|
||||
|
||||
@@ -104,10 +100,8 @@ class TwilioProvider extends ProviderClass {
|
||||
*/
|
||||
sendMessage = async (number, message, { options }) => {
|
||||
number = parseNumber(number)
|
||||
if (options?.buttons?.length)
|
||||
this.sendButtons(number, message, options.buttons)
|
||||
if (options?.media)
|
||||
return this.sendMedia(number, message, options.media)
|
||||
if (options?.buttons?.length) this.sendButtons(number, message, options.buttons)
|
||||
if (options?.media) return this.sendMedia(number, message, options.media)
|
||||
return this.vendor.messages.create({
|
||||
body: message,
|
||||
from: `whatsapp:+${this.vendorNumber}`,
|
||||
|
||||
@@ -51,9 +51,7 @@ class TwilioWebHookServer extends EventEmitter {
|
||||
this.twilioServer.listen(this.twilioPort, () => {
|
||||
console.log(``)
|
||||
console.log(`[Twilio]: Agregar esta url "WHEN A MESSAGE COMES IN"`)
|
||||
console.log(
|
||||
`[Twilio]: POST http://localhost:${this.twilioPort}/twilio-hook`
|
||||
)
|
||||
console.log(`[Twilio]: POST http://localhost:${this.twilioPort}/twilio-hook`)
|
||||
console.log(`[Twilio]: Más información en la documentacion`)
|
||||
console.log(``)
|
||||
})
|
||||
|
||||
@@ -4,11 +4,7 @@ const { createWriteStream } = require('fs')
|
||||
const { Console } = require('console')
|
||||
const mime = require('mime-types')
|
||||
|
||||
const {
|
||||
venomCleanNumber,
|
||||
venomGenerateImage,
|
||||
venomisValidNumber,
|
||||
} = require('./utils')
|
||||
const { venomCleanNumber, venomGenerateImage, venomisValidNumber } = require('./utils')
|
||||
|
||||
const logger = new Console({
|
||||
stdout: createWriteStream(`${process.cwd()}/venom.log`),
|
||||
@@ -108,8 +104,7 @@ class VenomProvider extends ProviderClass {
|
||||
const listEvents = this.busEvents()
|
||||
|
||||
for (const { event, func } of listEvents) {
|
||||
if (this.vendor[event])
|
||||
this.vendor[event]((payload) => func(payload))
|
||||
if (this.vendor[event]) this.vendor[event]((payload) => func(payload))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,16 +117,13 @@ class VenomProvider extends ProviderClass {
|
||||
* @returns
|
||||
*/
|
||||
sendButtons = async (number, message, buttons = []) => {
|
||||
const NOTE_VENOM_BUTTON = [
|
||||
`Actualmente VENOM tiene problemas con la API`,
|
||||
`para el envio de Botones`,
|
||||
].join('\n')
|
||||
const NOTE_VENOM_BUTTON = [`Actualmente VENOM tiene problemas con la API`, `para el envio de Botones`].join(
|
||||
'\n'
|
||||
)
|
||||
|
||||
console.log(`[NOTA]: ${NOTE_VENOM_BUTTON}`)
|
||||
|
||||
const buttonToStr = [message]
|
||||
.concat(buttons.map((btn) => `${btn.body}`))
|
||||
.join(`\n`)
|
||||
const buttonToStr = [message].concat(buttons.map((btn) => `${btn.body}`)).join(`\n`)
|
||||
return this.vendor.sendText(number, buttonToStr)
|
||||
// return this.vendor.sendButtons(number, "Title", buttons1, "Description");
|
||||
}
|
||||
@@ -194,12 +186,9 @@ class VenomProvider extends ProviderClass {
|
||||
const fileDownloaded = await generalDownload(mediaUrl)
|
||||
const mimeType = mime.lookup(fileDownloaded)
|
||||
|
||||
if (mimeType.includes('image'))
|
||||
return this.sendImage(number, fileDownloaded, text)
|
||||
if (mimeType.includes('video'))
|
||||
return this.sendVideo(number, fileDownloaded, text)
|
||||
if (mimeType.includes('audio'))
|
||||
return this.sendAudio(number, fileDownloaded)
|
||||
if (mimeType.includes('image')) return this.sendImage(number, fileDownloaded, text)
|
||||
if (mimeType.includes('video')) return this.sendVideo(number, fileDownloaded, text)
|
||||
if (mimeType.includes('audio')) return this.sendAudio(number, fileDownloaded)
|
||||
|
||||
return this.sendFile(number, fileDownloaded, text)
|
||||
}
|
||||
@@ -213,10 +202,8 @@ class VenomProvider extends ProviderClass {
|
||||
*/
|
||||
sendMessage = async (userId, message, { options }) => {
|
||||
const number = venomCleanNumber(userId)
|
||||
if (options?.buttons?.length)
|
||||
return this.sendButtons(number, message, options.buttons)
|
||||
if (options?.media)
|
||||
return this.sendMedia(number, options.media, message)
|
||||
if (options?.buttons?.length) return this.sendButtons(number, message, options.buttons)
|
||||
if (options?.media) return this.sendMedia(number, options.media, message)
|
||||
return this.vendor.sendText(number, message)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user