release:dev
release:dev
3
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"recommendations": ["xyc.vscode-mdx-preview"]
|
||||
}
|
||||
3
.vscode/settings.json
vendored
@@ -8,6 +8,7 @@
|
||||
"adapter",
|
||||
"ci",
|
||||
"starters",
|
||||
"conflict"
|
||||
"conflict",
|
||||
"contexts"
|
||||
]
|
||||
}
|
||||
|
||||
86
MIGRATION.md
@@ -2,9 +2,9 @@
|
||||
|
||||
#### Versión (legacy)
|
||||
|
||||
En la ***versión (legacy)*** se implementas los flujos de esta manera, en dos archivos independientes.
|
||||
En la ***versión (legacy)*** se implementaban los flujos de esta manera, en dos archivos independientes.
|
||||
|
||||
> __`initial.json`__ para establecer las palabras claves y el flujo a responder, por otro lado tambien se necesitaba implementar.
|
||||
> __`initial.json`__ para establecer las palabras claves y el flujo a responder, por otro lado tambien se necesitaba implementar
|
||||
> __`response.json`__ donde se escriben los mensajes a responder.
|
||||
|
||||
```json
|
||||
@@ -77,7 +77,7 @@ En la ***versión (legacy)*** se implementas los flujos de esta manera, en dos
|
||||
|
||||
#### Versión 2 (0.2.X)
|
||||
|
||||
En esta versión es mucho más sencillo abajo encontraras un ejemplo del mismo flujo anteriormente mostrado.
|
||||
En esta versión es mucho más sencillo, abajo encontraras un ejemplo del mismo flujo anteriormente mostrado.
|
||||
|
||||
```js
|
||||
//app.js
|
||||
@@ -126,6 +126,86 @@ const flowCatalogo = addKeyword(['imagen', 'foto'])
|
||||
}
|
||||
```
|
||||
|
||||
#### Flujos hijos
|
||||
|
||||
A continuación se muestra un ejemplo de flujos hijos, estos nos sirven para crear flujos que solo se disparan cuando el flujo anterior es el especificado, ejemplo:
|
||||
|
||||
> Menu Principal (Escoge zapatos o bolsos)
|
||||
> - SubMenu 1 (Elegiste bolsos, ahora escoge piel o tela)
|
||||
> - Submenu 1.1 (piel)
|
||||
> - Submenu 2 (Elegiste zapatos, ahora escoge piel o tela)
|
||||
> - Submenu 2.1 (piel)
|
||||
|
||||
El __submenu 1__ solo se va a disparar cuando el flujo anterior sea el __principal__, e igualmente el __submenu 1.1__, solo cuando el flujo anterior sea el __submenu 1__, ejemplo:
|
||||
|
||||
```js
|
||||
/**
|
||||
* Aqui declaramos los flujos hijos, los flujos se declaran de atras para adelante, es decir que si tienes un flujo de este tipo:
|
||||
*
|
||||
* Menu Principal
|
||||
* - SubMenu 1
|
||||
* - Submenu 1.1
|
||||
* - Submenu 2
|
||||
* - Submenu 2.1
|
||||
*
|
||||
* Primero declaras los submenus 1.1 y 2.1, luego el 1 y 2 y al final el principal.
|
||||
*/
|
||||
const flowBolsos2 = addKeyword(['bolsos2', '2'])
|
||||
.addAnswer('🤯 *MUCHOS* bolsos ...')
|
||||
.addAnswer('y mas bolsos... bla bla')
|
||||
|
||||
const flowZapatos2 = addKeyword(['zapatos2', '2'])
|
||||
.addAnswer('🤯 repito que tengo *MUCHOS* zapatos.')
|
||||
.addAnswer('y algunas otras cosas.')
|
||||
|
||||
const flowZapatos = addKeyword(['1', 'zapatos', 'ZAPATOS'])
|
||||
.addAnswer('🤯 Veo que elegiste zapatos')
|
||||
.addAnswer('Tengo muchos zapatos...bla bla')
|
||||
.addAnswer(
|
||||
['Manda:', '*(2) Zapatos2*', 'para mas información'],
|
||||
{ capture: true },
|
||||
(ctx) => {
|
||||
console.log('Aqui puedes ver más info del usuario...')
|
||||
console.log('Puedes enviar un mail, hook, etc..')
|
||||
console.log(ctx)
|
||||
},
|
||||
[...addChild(flowZapatos2)]
|
||||
)
|
||||
|
||||
const flowBolsos = addKeyword(['2', 'bolsos', 'BOLSOS'])
|
||||
.addAnswer('🙌 Veo que elegiste bolsos')
|
||||
.addAnswer('Tengo muchos bolsos...bla bla')
|
||||
.addAnswer(
|
||||
['Manda:', '*(2) Bolsos2*', 'para mas información.'],
|
||||
{ capture: true },
|
||||
(ctx) => {
|
||||
console.log('Aqui puedes ver más info del usuario...')
|
||||
console.log('Puedes enviar un mail, hook, etc..')
|
||||
console.log(ctx)
|
||||
},
|
||||
[...addChild(flowBolsos2)]
|
||||
)
|
||||
|
||||
/**
|
||||
* Declarando flujo principal
|
||||
*/
|
||||
|
||||
const flowPrincipal = addKeyword(['hola', 'ole', 'alo'])
|
||||
.addAnswer(['Hola, bienvenido a mi tienda', '¿Como puedo ayudarte?'])
|
||||
.addAnswer(['Tengo:', 'Zapatos', 'Bolsos', 'etc ...'])
|
||||
.addAnswer(
|
||||
['Para continuar escribe:', '*(1) Zapatos*', '*(2) Bolsos*'],
|
||||
{ capture: true },
|
||||
(ctx) => {
|
||||
console.log('Aqui puedes ver más info del usuario...')
|
||||
console.log('Puedes enviar un mail, hook, etc..')
|
||||
console.log(ctx)
|
||||
},
|
||||
[...addChild(flowBolsos), ...addChild(flowZapatos)]
|
||||
)
|
||||
```
|
||||
|
||||
|
||||
> Forma parte de este proyecto.
|
||||
|
||||
- [Discord](https://link.codigoencasa.com/DISCORD)
|
||||
|
||||
25
README.md
@@ -3,7 +3,7 @@
|
||||
--------
|
||||
🐤 Tablero de tareas : [https://github.com/users/leifermendez/projects/4/views/1](https://github.com/users/leifermendez/projects/4/views/1)
|
||||
|
||||
🦊 Documentación: [https://bot-whatsapp.pages.dev/](https://bot-whatsapp.pages.dev/)
|
||||
🦊 Documentación: [https://bot-whatsapp-codigoencasa.pages.dev/](https://bot-whatsapp-codigoencasa.pages.dev/)
|
||||
Video como hacer PR: https://youtu.be/Lxt8Acob6aU
|
||||
|
||||
🚀 __Roadmap:__ [https://github.com/users/leifermendez/projects/4/views/1](https://github.com/users/leifermendez/projects/4/views/1)
|
||||
@@ -42,8 +42,8 @@ Video como hacer PR: https://youtu.be/Lxt8Acob6aU
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/Gonzalito87">
|
||||
<img src="https://avatars.githubusercontent.com/u/100331586?v=4" width="50;" alt="Gonzalito87"/>
|
||||
<a href="https://github.com/HKong31">
|
||||
<img src="https://avatars.githubusercontent.com/u/113340082?v=4" width="50;" alt="HKong31"/>
|
||||
<br />
|
||||
<sub><b>Null</b></sub>
|
||||
</a>
|
||||
@@ -52,10 +52,17 @@ Video como hacer PR: https://youtu.be/Lxt8Acob6aU
|
||||
<a href="https://github.com/jzvi12">
|
||||
<img src="https://avatars.githubusercontent.com/u/10729787?v=4" width="50;" alt="jzvi12"/>
|
||||
<br />
|
||||
<sub><b>Null</b></sub>
|
||||
<sub><b>Zvi</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/Gonzalito87">
|
||||
<img src="https://avatars.githubusercontent.com/u/100331586?v=4" width="50;" alt="Gonzalito87"/>
|
||||
<br />
|
||||
<sub><b>Null</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/tonyvazgar">
|
||||
<img src="https://avatars.githubusercontent.com/u/21047090?v=4" width="50;" alt="tonyvazgar"/>
|
||||
@@ -83,15 +90,7 @@ Video como hacer PR: https://youtu.be/Lxt8Acob6aU
|
||||
<br />
|
||||
<sub><b>Yonathan Suarez</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/jlferrete">
|
||||
<img src="https://avatars.githubusercontent.com/u/36698913?v=4" width="50;" alt="jlferrete"/>
|
||||
<br />
|
||||
<sub><b>José Luis Ferrete</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</td></tr>
|
||||
</table>
|
||||
<!-- readme: collaborators,contributors -end -->
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ class CoreClass {
|
||||
this.databaseClass.save(ctxByNumber)
|
||||
}
|
||||
|
||||
// 📄 [options: fallback]: esta funcion se encarga de repetir el ultimo mensaje
|
||||
// 📄 [options: fallBack]: esta funcion se encarga de repetir el ultimo mensaje
|
||||
const fallBack = () => {
|
||||
fallBackFlag = true
|
||||
msgToSend = this.flowClass.find(refToContinue?.keyword, true) || []
|
||||
@@ -92,6 +92,27 @@ class CoreClass {
|
||||
return refToContinue
|
||||
}
|
||||
|
||||
// 📄 [options: flowDynamic]: esta funcion se encarga de responder un array de respuesta esta limitado a 5 mensajes
|
||||
// para evitar bloque de whatsapp
|
||||
const flowDynamic = (listMsg = [], optListMsg = { limit: 3 }) => {
|
||||
if (!Array.isArray(listMsg))
|
||||
throw new Error('Esto debe ser un ARRAY')
|
||||
|
||||
const parseListMsg = listMsg
|
||||
.map(({ body }, index) =>
|
||||
toCtx({
|
||||
body,
|
||||
from,
|
||||
keyword: null,
|
||||
index,
|
||||
})
|
||||
)
|
||||
.slice(0, optListMsg.limit)
|
||||
msgToSend = parseListMsg
|
||||
this.sendFlow(msgToSend, from)
|
||||
return
|
||||
}
|
||||
|
||||
// 📄 Se encarga de revisar si el contexto del mensaje tiene callback y ejecutarlo
|
||||
const cbEveryCtx = (inRef) => {
|
||||
const indexFlow = this.flowClass.findIndexByRef(inRef)
|
||||
@@ -99,6 +120,7 @@ class CoreClass {
|
||||
messageCtxInComming,
|
||||
{
|
||||
fallBack,
|
||||
flowDynamic,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -8,10 +8,7 @@ class FlowClass {
|
||||
if (!Array.isArray(_flow)) throw new Error('Esto debe ser un ARRAY')
|
||||
this.flowRaw = _flow
|
||||
|
||||
this.allCallbacks = _flow
|
||||
.map((cbIn) => cbIn.ctx.callbacks)
|
||||
.flat(2)
|
||||
.map((c, i) => ({ callback: c?.callback, index: i }))
|
||||
this.getAllCb(this.flowRaw)
|
||||
|
||||
const mergeToJsonSerialize = Object.keys(_flow)
|
||||
.map((indexObjectFlow) => _flow[indexObjectFlow].toJson())
|
||||
@@ -20,6 +17,17 @@ class FlowClass {
|
||||
this.flowSerialize = toSerialize(mergeToJsonSerialize)
|
||||
}
|
||||
|
||||
/**
|
||||
* Buscar y aplanar todos los callbacks
|
||||
* @param {*} inFlow
|
||||
*/
|
||||
getAllCb = (inFlow) => {
|
||||
this.allCallbacks = inFlow
|
||||
.map((cbIn) => cbIn.ctx.callbacks)
|
||||
.flat(2)
|
||||
.map((c, i) => ({ callback: c?.callback, index: i }))
|
||||
}
|
||||
|
||||
find = (keyOrWord, symbol = false, overFlow = null) => {
|
||||
keyOrWord = `${keyOrWord}`
|
||||
let capture = false
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bot-whatsapp/bot",
|
||||
"version": "0.0.25-alpha.0",
|
||||
"version": "0.0.26-alpha.0",
|
||||
"description": "",
|
||||
"main": "./lib/bundle.bot.cjs",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
const prompts = require('prompts')
|
||||
const { yellow, red, cyan, bgMagenta } = require('kleur')
|
||||
const { copyBaseApp } = require('../create-app')
|
||||
const { join } = require('path')
|
||||
const { yellow, red, cyan, bgMagenta } = require('kleur')
|
||||
const { existsSync } = require('fs')
|
||||
const { copyBaseApp } = require('../create-app')
|
||||
const { checkNodeVersion, checkOs } = require('../check')
|
||||
|
||||
const bannerDone = () => {
|
||||
@@ -48,9 +48,9 @@ const startInteractive = async () => {
|
||||
message: '¿Cuál base de datos quieres utilizar?',
|
||||
choices: [
|
||||
{ title: 'Memory', value: 'memory' },
|
||||
{ title: 'Json', value: 'json' },
|
||||
{ title: 'Mongo', value: 'mongo' },
|
||||
{ title: 'MySQL', value: 'mysql' },
|
||||
{ title: 'Json', value: 'json', disabled: true },
|
||||
],
|
||||
max: 1,
|
||||
hint: 'Espacio para seleccionar',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bot-whatsapp/cli",
|
||||
"version": "0.0.32-alpha.0",
|
||||
"version": "0.0.33-alpha.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"devDependencies": {
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
],
|
||||
"exports": {
|
||||
"./mock": "./lib/mock/index.cjs",
|
||||
"./dialogflow": "./lib/dialogflow/index.cjs"
|
||||
"./dialogflow": "./lib/dialogflow/index.cjs",
|
||||
"./dialogflowcx": "./lib/dialogflow-cx/index.cjs"
|
||||
},
|
||||
"dependencies": {
|
||||
"@bot-whatsapp/bot": "*"
|
||||
|
||||
@@ -21,4 +21,13 @@ module.exports = [
|
||||
},
|
||||
plugins: [commonjs()],
|
||||
},
|
||||
{
|
||||
input: join(__dirname, 'src', 'dialogflow-cx', 'index.js'),
|
||||
output: {
|
||||
banner: banner['banner.output'].join(''),
|
||||
file: join(__dirname, 'lib', 'dialogflow-cx', 'index.cjs'),
|
||||
format: 'cjs',
|
||||
},
|
||||
plugins: [commonjs()],
|
||||
},
|
||||
]
|
||||
|
||||
112
packages/contexts/src/dialogflow-cx/dialogflow-cx.class.js
Normal file
@@ -0,0 +1,112 @@
|
||||
const { CoreClass } = require('@bot-whatsapp/bot')
|
||||
const { SessionsClient } = require('@google-cloud/dialogflow-cx').v3beta1
|
||||
const { existsSync, readFileSync } = require('fs')
|
||||
const { join } = require('path')
|
||||
|
||||
/**
|
||||
* Necesita extender de core.class
|
||||
* handleMsg(messageInComming) // const { body, from } = messageInComming
|
||||
*/
|
||||
|
||||
const GOOGLE_ACCOUNT_PATH = join(process.cwd(), 'google-key.json')
|
||||
|
||||
class DialogFlowCXContext extends CoreClass {
|
||||
// Opciones del usuario
|
||||
optionsDX = {
|
||||
language: 'es',
|
||||
location: '',
|
||||
agentId: '',
|
||||
}
|
||||
projectId = null
|
||||
configuration = null
|
||||
sessionClient = null
|
||||
|
||||
constructor(_database, _provider, _optionsDX = {}) {
|
||||
super(null, _database, _provider)
|
||||
this.optionsDX = { ...this.optionsDX, ..._optionsDX }
|
||||
this.init()
|
||||
}
|
||||
|
||||
/**
|
||||
* Verificar conexión con servicio de DialogFlow
|
||||
*/
|
||||
init = () => {
|
||||
if (!existsSync(GOOGLE_ACCOUNT_PATH)) {
|
||||
console.log(`[ERROR]: No se encontro ${GOOGLE_ACCOUNT_PATH}`)
|
||||
/**
|
||||
* Emitir evento de error para que se mueste por consola dicinedo que no tiene el json
|
||||
* */
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
this.projectId = project_id
|
||||
|
||||
this.sessionClient = new SessionsClient({
|
||||
credentials: { private_key, client_email },
|
||||
apiEndpoint: `${this.optionsDX.location}-dialogflow.googleapis.com`,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* GLOSSARY.md
|
||||
* @param {*} messageCtxInComming
|
||||
* @returns
|
||||
*/
|
||||
handleMsg = async (messageCtxInComming) => {
|
||||
const languageCode = this.optionsDX.language
|
||||
const { from, body } = messageCtxInComming
|
||||
|
||||
/**
|
||||
* 📄 Creamos session de contexto basado en el numero de la persona
|
||||
* para evitar este problema.
|
||||
* https://github.com/codigoencasa/bot-whatsapp/pull/140
|
||||
*/
|
||||
|
||||
const session = this.sessionClient.projectLocationAgentSessionPath(
|
||||
this.projectId,
|
||||
this.optionsDX.location,
|
||||
this.optionsDX.agentId,
|
||||
from
|
||||
)
|
||||
|
||||
const reqDialog = {
|
||||
session,
|
||||
queryInput: {
|
||||
text: {
|
||||
text: body,
|
||||
},
|
||||
languageCode,
|
||||
},
|
||||
}
|
||||
|
||||
const [single] = (await this.sessionClient.detectIntent(reqDialog)) || [
|
||||
null,
|
||||
]
|
||||
|
||||
const listMessages = single.queryResult.responseMessages.map((res) => {
|
||||
if (res.message == 'text') {
|
||||
return { answer: res.text.text[0] }
|
||||
}
|
||||
|
||||
if (res.message == 'payload') {
|
||||
const { values } = res.payload.fields.buttons.listValue
|
||||
const buttonsArray = values.map((values) => {
|
||||
const { stringValue } = values.structValue.fields.body
|
||||
return { body: stringValue }
|
||||
})
|
||||
return { buttons: buttonsArray }
|
||||
}
|
||||
})
|
||||
|
||||
this.sendFlow(listMessages, from)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = DialogFlowCXContext
|
||||
14
packages/contexts/src/dialogflow-cx/index.js
Normal file
@@ -0,0 +1,14 @@
|
||||
const DialogCXFlowClass = require('./dialogflow-cx.class')
|
||||
|
||||
/**
|
||||
* Crear instancia de clase Bot
|
||||
* @param {*} args
|
||||
* @returns
|
||||
*/
|
||||
const createBotDialog = async ({ database, provider }, _options) =>
|
||||
new DialogCXFlowClass(database, provider, _options)
|
||||
|
||||
module.exports = {
|
||||
createBotDialog,
|
||||
DialogCXFlowClass,
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "create-bot-whatsapp",
|
||||
"version": "0.0.43-alpha.0",
|
||||
"version": "0.0.44-alpha.0",
|
||||
"description": "",
|
||||
"main": "./lib/bundle.create-bot-whatsapp.cjs",
|
||||
"files": [
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bot-whatsapp/database",
|
||||
"version": "0.0.24-alpha.0",
|
||||
"version": "0.0.25-alpha.0",
|
||||
"description": "Esto es el conector a mysql, pg, mongo",
|
||||
"main": "./lib/mock/index.cjs",
|
||||
"keywords": [],
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"build.server": "vite build -c adaptors/cloudflare-pages/vite.config.ts",
|
||||
"build.types": "tsc --incremental --noEmit",
|
||||
"deploy": "wrangler pages dev ./dist",
|
||||
"dev": "vite --mode ssr",
|
||||
"dev": "vite --host --mode ssr",
|
||||
"dev.debug": "node --inspect-brk ./node_modules/vite/bin/vite.js --mode ssr --force",
|
||||
"fmt": "prettier --write .",
|
||||
"fmt.check": "prettier --check .",
|
||||
@@ -24,6 +24,10 @@
|
||||
"@builder.io/qwik-city": "0.0.128",
|
||||
"@fontsource/inter": "^4.5.14",
|
||||
"@iconify-json/tabler": "^1.1.49",
|
||||
"@tailwindcss/aspect-ratio": "^0.4.0",
|
||||
"@tailwindcss/forms": "^0.5.3",
|
||||
"@tailwindcss/line-clamp": "^0.3.1",
|
||||
"@tailwindcss/typography": "^0.5.0",
|
||||
"@types/eslint": "8.4.10",
|
||||
"@types/node": "latest",
|
||||
"@typescript-eslint/eslint-plugin": "5.45.0",
|
||||
|
||||
BIN
packages/docs/public/favicon.ico
Normal file
|
After Width: | Height: | Size: 15 KiB |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 500 500"><g clip-path="url(#a)"><circle cx="250" cy="250" r="250" fill="#fff"/><path fill="#18B6F6" d="m367.87 418.45-61.17-61.18-.94.13v-.67L175.7 227.53l32.05-31.13L188.9 87.73 99.56 199.09c-15.22 15.42-18.03 40.51-7.08 59.03l55.83 93.11a46.82 46.82 0 0 0 40.73 22.81l27.65-.27 151.18 44.68Z"/><path fill="#AC7EF4" d="m401.25 196.94-12.29-22.81-6.41-11.67-2.54-4.56-.26.26-33.66-58.63a47.07 47.07 0 0 0-41.27-23.75l-29.51.8-88.01.28a47.07 47.07 0 0 0-40.33 23.34L93.4 207l95.76-119.54L314.7 226.19l-22.3 22.67 13.35 108.54.13-.26v.26h-.26l.26.27 10.42 10.2 50.62 49.78c2.13 2 5.6-.4 4.13-2.96l-31.25-61.85 54.5-101.3 1.73-2c.67-.81 1.33-1.62 1.87-2.42a46.8 46.8 0 0 0 3.34-50.18Z"/><path fill="#fff" d="M315.1 225.65 189.18 87.6l17.9 108.14L175 227l130.5 130.27-11.75-108.14 21.37-23.48Z"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h500v500H0z"/></clipPath></defs></svg>
|
||||
|
Before Width: | Height: | Size: 947 B |
BIN
packages/docs/src/assets/fonts/FiraCode-VF.woff
Normal file
BIN
packages/docs/src/assets/fonts/FiraCode-VF.woff2
Normal file
BIN
packages/docs/src/assets/fonts/IBMPlexMono-Regular.ttf
Normal file
BIN
packages/docs/src/assets/fonts/IBMPlexMono-SemiBold.ttf
Normal file
BIN
packages/docs/src/assets/fonts/Inter-italic-latin.var.woff2
Normal file
BIN
packages/docs/src/assets/fonts/Inter-roman-latin.var.woff2
Normal file
BIN
packages/docs/src/assets/fonts/Pally-Variable.ttf
Normal file
BIN
packages/docs/src/assets/fonts/SourceSansPro-Regular.otf
Normal file
BIN
packages/docs/src/assets/fonts/SourceSerifPro-Regular.ttf
Normal file
BIN
packages/docs/src/assets/fonts/Synonym-Variable.ttf
Normal file
BIN
packages/docs/src/assets/fonts/Ubuntu-Mono-bold.woff2
Normal file
@@ -0,0 +1,13 @@
|
||||
.font {
|
||||
font-family: IBMPlexMono-Regular;
|
||||
}
|
||||
|
||||
/* This file was automatically generated by GlyphHanger 4.0.1 */
|
||||
|
||||
@font-face {
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
.font {
|
||||
font-family: IBMPlexMono-SemiBold;
|
||||
}
|
||||
|
||||
/* This file was automatically generated by GlyphHanger 4.0.1 */
|
||||
|
||||
@font-face {
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
.font {
|
||||
font-family: Pally-Variable;
|
||||
}
|
||||
|
||||
/* This file was automatically generated by GlyphHanger 4.0.1 */
|
||||
|
||||
@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;
|
||||
font-weight: 400 700;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
.font {
|
||||
font-family: SourceSerifPro-Regular;
|
||||
}
|
||||
|
||||
/* This file was automatically generated by GlyphHanger 4.0.1 */
|
||||
|
||||
@font-face {
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
.font {
|
||||
font-family: Synonym-Variable;
|
||||
}
|
||||
|
||||
/* This file was automatically generated by GlyphHanger 4.0.1 */
|
||||
|
||||
@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;
|
||||
font-weight: 400 700;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
.font {
|
||||
font-family: TenorSans-Regular;
|
||||
}
|
||||
|
||||
/* This file was automatically generated by GlyphHanger 4.0.1 */
|
||||
|
||||
@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;
|
||||
}
|
||||
BIN
packages/docs/src/assets/images/chatbot-whatsapp.png
Normal file
|
After Width: | Height: | Size: 401 KiB |
BIN
packages/docs/src/assets/images/desahogo.png
Normal file
|
After Width: | Height: | Size: 670 KiB |
BIN
packages/docs/src/assets/images/eyes.png
Normal file
|
After Width: | Height: | Size: 423 KiB |
BIN
packages/docs/src/assets/images/leanga.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
packages/docs/src/assets/images/qwik.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
44
packages/docs/src/assets/styles/fonts.css
Normal file
@@ -0,0 +1,44 @@
|
||||
@font-face {
|
||||
font-family: 'Inter var';
|
||||
font-weight: 100 900;
|
||||
font-display: block;
|
||||
font-style: normal;
|
||||
font-named-instance: 'Regular';
|
||||
src: url('../fonts/Inter-roman-latin.var.woff2') format('woff2');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Inter var';
|
||||
font-weight: 100 900;
|
||||
font-display: block;
|
||||
font-style: italic;
|
||||
font-named-instance: 'Italic';
|
||||
src: url('../fonts/Inter-italic-latin.var.woff2') format('woff2');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Fira Code VF';
|
||||
font-weight: 300 700;
|
||||
font-style: normal;
|
||||
src: url('../fonts/FiraCode-VF.woff2') format('woff2-variations'),
|
||||
url('../fonts/FiraCode-VF.woff') format('woff-variations');
|
||||
}
|
||||
|
||||
.font-mono {
|
||||
font-variant-ligatures: none;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url('../fonts/SourceSansPro-Regular.otf') format('opentype');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Ubuntu Mono';
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
src: url('../fonts/Ubuntu-Mono-bold.woff2') format('woff2');
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
* the styles in here will be applied to the Document, without any sort of CSS scoping.
|
||||
*
|
||||
*/
|
||||
|
||||
@import 'prism.css';
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
@@ -24,31 +24,43 @@
|
||||
}
|
||||
|
||||
.slot h1 {
|
||||
@apply mb-2 font-semibold text-2xl;
|
||||
@apply my-2 font-semibold text-3xl;
|
||||
}
|
||||
|
||||
.slot h2 {
|
||||
@apply mb-2 font-semibold text-lg;
|
||||
@apply mt-4 font-semibold text-xl;
|
||||
}
|
||||
|
||||
.slot h3 {
|
||||
@apply mb-2 font-semibold text-base;
|
||||
@apply mt-4 font-semibold text-lg;
|
||||
}
|
||||
|
||||
.slot code {
|
||||
@apply bg-slate-100 dark:bg-slate-800 p-1 px-2 rounded w-full;
|
||||
.slot p code {
|
||||
@apply text-xs font-mono bg-stone-100 dark:bg-slate-600 dark:text-white text-red-500 p-1 rounded;
|
||||
}
|
||||
|
||||
.slot pre {
|
||||
@apply w-full flex my-2;
|
||||
}
|
||||
|
||||
.slot pre code {
|
||||
@apply p-3 rounded md:w-full max-w-screen-md overflow-x-auto w-fit bg-gray-800 dark:bg-slate-800 ease-in duration-75 text-gray-100 text-xs shadow-xl;
|
||||
}
|
||||
|
||||
.slot a {
|
||||
@apply text-sky-900 font-medium dark:text-sky-400;
|
||||
@apply text-sky-900 font-medium dark:text-sky-400 dark:hover:text-white;
|
||||
}
|
||||
|
||||
.slot hr {
|
||||
@apply my-5;
|
||||
@apply my-5 border-t-slate-100 dark:border-t-slate-800;
|
||||
}
|
||||
|
||||
.slot img {
|
||||
@apply rounded drop-shadow-2xl;
|
||||
}
|
||||
|
||||
.slot ul {
|
||||
@apply list-disc pl-5;
|
||||
}
|
||||
|
||||
[data-aw-toggle-menu] path {
|
||||
@@ -63,6 +75,10 @@
|
||||
@apply mt-2 text-sm text-slate-700 dark:text-slate-400;
|
||||
}
|
||||
|
||||
.coding p {
|
||||
@apply m-0;
|
||||
}
|
||||
|
||||
[data-aw-toggle-menu].expanded g > path:last-child {
|
||||
@apply rotate-45 translate-y-[-8px] translate-x-[14px];
|
||||
}
|
||||
|
||||
86
packages/docs/src/assets/styles/prism.css
Normal file
@@ -0,0 +1,86 @@
|
||||
.token.tag,
|
||||
.token.class-name,
|
||||
.token.selector,
|
||||
.token.selector .class,
|
||||
.token.selector.class,
|
||||
.token.function {
|
||||
@apply text-pink-400;
|
||||
}
|
||||
|
||||
.token.attr-name,
|
||||
.token.keyword,
|
||||
.token.rule,
|
||||
.token.pseudo-class,
|
||||
.token.important {
|
||||
@apply text-slate-300;
|
||||
}
|
||||
|
||||
.token.attr-value,
|
||||
.token.class,
|
||||
.token.string {
|
||||
@apply text-sky-300;
|
||||
}
|
||||
|
||||
.token.punctuation,
|
||||
.token.attr-equals {
|
||||
@apply text-slate-500;
|
||||
}
|
||||
|
||||
.token.attr-value * {
|
||||
@apply text-sky-300;
|
||||
}
|
||||
|
||||
.token.attr-value .attr-equals,
|
||||
.token.attr-value .attr-equals + .punctuation,
|
||||
.token.attr-value > .punctuation:last-child {
|
||||
@apply text-slate-500;
|
||||
}
|
||||
|
||||
.token.property {
|
||||
@apply text-sky-300;
|
||||
}
|
||||
|
||||
.token.unit {
|
||||
@apply text-teal-200;
|
||||
}
|
||||
|
||||
.language-shell .token:not(.comment),
|
||||
.token.atapply .token:not(.rule):not(.important):not(.punctuation) {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.language-css .token.function {
|
||||
@apply text-teal-200;
|
||||
}
|
||||
|
||||
.token.comment,
|
||||
.token.module,
|
||||
.token.operator,
|
||||
.token.combinator {
|
||||
@apply text-slate-400;
|
||||
}
|
||||
|
||||
.token.unchanged {
|
||||
@apply block;
|
||||
}
|
||||
|
||||
.token.deleted,
|
||||
.token.inserted {
|
||||
@apply block relative -mx-9 pl-8 pr-5 border-l-4 before:absolute before:top-0 before:left-4;
|
||||
}
|
||||
|
||||
.token.inserted {
|
||||
@apply bg-teal-400/[0.15] border-teal-400 before:content-['+'] before:text-teal-400;
|
||||
}
|
||||
|
||||
.token.deleted {
|
||||
@apply bg-rose-500/[0.15] border-rose-400 before:content-['-'] before:text-rose-400;
|
||||
}
|
||||
|
||||
pre[class^='language-diff-'] {
|
||||
@apply flex px-9;
|
||||
}
|
||||
|
||||
pre[class^='language-diff-'] > code {
|
||||
@apply flex-none min-w-full;
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import { component$ } from '@builder.io/qwik'
|
||||
|
||||
// @ts-ignore
|
||||
import logoSrc from '~/assets/images/logo.png?width=64&height=64&png'
|
||||
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">
|
||||
@@ -13,6 +13,6 @@ export default component$(() => (
|
||||
alt="Qwind Logo"
|
||||
loading="lazy"
|
||||
/>
|
||||
Qwind
|
||||
Chatbot
|
||||
</span>
|
||||
))
|
||||
|
||||
@@ -17,7 +17,7 @@ export const RouterHead = component$(() => {
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1.0"
|
||||
/>
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
|
||||
{head.meta.map((m) => (
|
||||
<meta {...m} />
|
||||
|
||||
14
packages/docs/src/components/icons/IconDiscord.tsx
Normal file
@@ -0,0 +1,14 @@
|
||||
export const IconDiscord = () => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 512 512"
|
||||
role="img"
|
||||
fill="currentColor"
|
||||
aria-label="Discord Logo"
|
||||
>
|
||||
<path d="M464 66.52A50 50 0 00414.12 17L97.64 16A49.65 49.65 0 0048 65.52V392c0 27.3 22.28 48 49.64 48H368l-13-44 109 100zM324.65 329.81s-8.72-10.39-16-19.32C340.39 301.55 352.5 282 352.5 282a139 139 0 01-27.85 14.25 173.31 173.31 0 01-35.11 10.39 170.05 170.05 0 01-62.72-.24 184.45 184.45 0 01-35.59-10.4 141.46 141.46 0 01-17.68-8.21c-.73-.48-1.45-.72-2.18-1.21-.49-.24-.73-.48-1-.48-4.36-2.42-6.78-4.11-6.78-4.11s11.62 19.09 42.38 28.26c-7.27 9.18-16.23 19.81-16.23 19.81-53.51-1.69-73.85-36.47-73.85-36.47 0-77.06 34.87-139.62 34.87-139.62 34.87-25.85 67.8-25.12 67.8-25.12l2.42 2.9c-43.59 12.32-63.44 31.4-63.44 31.4s5.32-2.9 14.28-6.77c25.91-11.35 46.5-14.25 55-15.21a24 24 0 014.12-.49 205.62 205.62 0 0148.91-.48 201.62 201.62 0 0172.89 22.95s-19.13-18.15-60.3-30.45l3.39-3.86s33.17-.73 67.81 25.16c0 0 34.87 62.56 34.87 139.62 0-.28-20.35 34.5-73.86 36.19z"></path>
|
||||
<path d="M212.05 218c-13.8 0-24.7 11.84-24.7 26.57s11.14 26.57 24.7 26.57c13.8 0 24.7-11.83 24.7-26.57.25-14.76-10.9-26.57-24.7-26.57zM300.43 218c-13.8 0-24.7 11.84-24.7 26.57s11.14 26.57 24.7 26.57c13.81 0 24.7-11.83 24.7-26.57S314 218 300.43 218z"></path>
|
||||
</svg>
|
||||
)
|
||||
14
packages/docs/src/components/widgets/Alert.tsx
Normal file
@@ -0,0 +1,14 @@
|
||||
import { component$, Slot } from '@builder.io/qwik'
|
||||
|
||||
export default component$(() => {
|
||||
return (
|
||||
<div
|
||||
class="p-4 border border-slate-200 rounded my-2 bg-gray-50 dark:border-gray-600 dark:bg-gray-700"
|
||||
role="alert"
|
||||
>
|
||||
<div class=" mb-2 text-md ">
|
||||
<Slot />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
@@ -5,31 +5,25 @@ export default component$(() => {
|
||||
<section class="relative">
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<div class="py-12 md:py-20">
|
||||
<div class="max-w-3xl mx-auto text-center p-6 rounded-md shadow-xl dark:shadow-none">
|
||||
<h2 class="text-4xl md:text-4xl font-bold leading-tighter tracking-tighter mb-4 font-heading">
|
||||
<span class="text-[#039de1]">Qwik</span> +{' '}
|
||||
<br class="block sm:hidden" />
|
||||
<span class="text-[#039de1] sm:whitespace-nowrap">
|
||||
Tailwind CSS
|
||||
</span>
|
||||
</h2>
|
||||
<p class="text-xl text-gray-600 dark:text-slate-400">
|
||||
Be very surprised by these huge fake numbers you are
|
||||
seeing on this page. <br class="hidden md:inline" />
|
||||
Don't waste more time!
|
||||
</p>
|
||||
<video
|
||||
style={'height:600px'}
|
||||
width="100%"
|
||||
height="400"
|
||||
autoPlay
|
||||
muted
|
||||
loop
|
||||
playsInline
|
||||
>
|
||||
<source
|
||||
src="https://leifer-landing-page.s3.us-east-2.amazonaws.com/xbmcc-kx99h.webm"
|
||||
type='video/mp4; codecs="hvc1"'
|
||||
/>
|
||||
|
||||
<div class="mt-6">
|
||||
<a
|
||||
class="btn btn-primary mb-4 sm:mb-0 w-full sm:w-auto"
|
||||
href="https://github.com/onwidget/qwind"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>
|
||||
Get template
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<source
|
||||
src="https://leifer-landing-page.s3.us-east-2.amazonaws.com/xbmcc-kx99h.webm"
|
||||
type="video/webm"
|
||||
/>
|
||||
</video>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
46
packages/docs/src/components/widgets/Collaborators.tsx
Normal file
@@ -0,0 +1,46 @@
|
||||
import { component$ } from '@builder.io/qwik'
|
||||
|
||||
export default component$(() => {
|
||||
return (
|
||||
<div class={'pt-4'}>
|
||||
<div class="flex items-center space-x-2 text-base">
|
||||
<h4 class="font-semibold text-slate-900">Contributors</h4>
|
||||
<span class="rounded-full bg-slate-100 px-2 py-1 text-xs font-semibold text-slate-700">
|
||||
204
|
||||
</span>
|
||||
</div>
|
||||
<div class="mt-3 flex -space-x-2 overflow-hidden">
|
||||
<img
|
||||
class="inline-block h-12 w-12 rounded-full ring-2 ring-white"
|
||||
src="https://images.unsplash.com/photo-1491528323818-fdd1faba62cc?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80"
|
||||
alt=""
|
||||
/>
|
||||
<img
|
||||
class="inline-block h-12 w-12 rounded-full ring-2 ring-white"
|
||||
src="https://images.unsplash.com/photo-1550525811-e5869dd03032?ixlib=rb-1.2.1&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80"
|
||||
alt=""
|
||||
/>
|
||||
<img
|
||||
class="inline-block h-12 w-12 rounded-full ring-2 ring-white"
|
||||
src="https://images.unsplash.com/photo-1500648767791-00dcc994a43e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2.25&w=256&h=256&q=80"
|
||||
alt=""
|
||||
/>
|
||||
<img
|
||||
class="inline-block h-12 w-12 rounded-full ring-2 ring-white"
|
||||
src="https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80"
|
||||
alt=""
|
||||
/>
|
||||
<img
|
||||
class="inline-block h-12 w-12 rounded-full ring-2 ring-white"
|
||||
src="https://images.unsplash.com/photo-1517365830460-955ce3ccd263?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80"
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
<div class="mt-3 text-sm font-medium">
|
||||
<a href="#" class="text-blue-500">
|
||||
+ 198 others
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
@@ -4,24 +4,22 @@ import { useLocation } from '@builder.io/qwik-city'
|
||||
/**
|
||||
* options = [] array con la lista de opciones de la documentacion
|
||||
*/
|
||||
export default component$(
|
||||
({
|
||||
options = [],
|
||||
}: {
|
||||
options: { link: string; name: string; class?: string }[]
|
||||
}) => {
|
||||
const { pathname } = useLocation()
|
||||
const editUrl = ` https://github.com/codigoencasa/bot-whatsapp/edit/dev/packages/docs/src/routes${pathname}index.mdx`
|
||||
return (
|
||||
<div>
|
||||
<ul>
|
||||
{options.map((opt) => (
|
||||
<li class={opt.class}>
|
||||
<a href={editUrl}>{opt.name}</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
)
|
||||
export default component$(() => {
|
||||
const { pathname } = useLocation()
|
||||
const editUrl = ` https://github.com/codigoencasa/bot-whatsapp/edit/dev/packages/docs/src/routes${pathname}index.mdx`
|
||||
return (
|
||||
<div class={'pb-3'}>
|
||||
<ul>
|
||||
<li>
|
||||
<a target={'_blank'} class={'font-semibold'} href={editUrl}>
|
||||
📄 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
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
||||
@@ -51,7 +51,7 @@ export default component$(() => {
|
||||
FAQs
|
||||
</p>
|
||||
<h2 class="max-w-lg mb-4 text-3xl font-bold leading-none tracking-tight sm:text-4xl md:mx-auto font-heading">
|
||||
Frequently Asked Questions
|
||||
Preguntas Frecuentes
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -5,41 +5,38 @@ export default component$(() => {
|
||||
const items = [
|
||||
[
|
||||
{
|
||||
title: 'Qwik + Tailwind CSS Integration',
|
||||
title: 'Atención al cliente rápida y eficiente',
|
||||
description:
|
||||
'A seamless integration between two great frameworks that offer high productivity, performance and versatility.',
|
||||
icon: 'tabler:brand-tailwind',
|
||||
'El chatbot puede ayudar a tus clientes a obtener respuestas a sus preguntas o solucionar problemas de manera rápida y sencilla, sin tener que esperar horas o incluso días por una respuesta.',
|
||||
},
|
||||
{
|
||||
title: 'Ready-to-use Components',
|
||||
title: 'Automatización de tareas repetitiva',
|
||||
description:
|
||||
'Widgets made with Tailwind CSS ready to be used in Marketing Websites, SaaS, Blogs, Personal Profiles, Small Business...',
|
||||
icon: 'tabler:components',
|
||||
'Se pueden automatizar tareas repetitivas y ahorrar tiempo y esfuerzo en tareas administrativas, como enviar recordatorios a tus clientes sobre pagos pendientes o para confirmar citas o reservas.',
|
||||
},
|
||||
{
|
||||
title: 'Best Practices',
|
||||
title: 'Experiencia personalizada para tus clientes',
|
||||
description:
|
||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi sagittis, quam nec venenatis lobortis, mi risus tempus nulla.',
|
||||
icon: 'tabler:list-check',
|
||||
'Podrás enviar mensajes automatizados con ofertas especiales o recomendaciones de productos basadas en el historial de compras de tus clientes, lo que significa que tus clientes pueden recibir una experiencia más personalizada.',
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
title: 'Excellent Page Speed',
|
||||
title: 'Análisis de datos y toma de decisiones informadas',
|
||||
description:
|
||||
'Having a good page speed impacts organic search ranking, improves user experience (UI/UX) and increase conversion rates.',
|
||||
'Te permite recopilar y analizar datos sobre tus clientes para ayudarte a entender mejor sus necesidades y preferencias, y ofrecerles un servicio aún más destacado.',
|
||||
icon: 'tabler:rocket',
|
||||
},
|
||||
{
|
||||
title: 'Search Engine Optimization (SEO)',
|
||||
title: 'Mejora de la eficiencia',
|
||||
description:
|
||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi sagittis, quam nec venenatis lobortis, mi risus tempus nulla.',
|
||||
'Te brinda la facilidad de manejar varias conversaciones al mismo tiempo, lo que significa que tus clientes no tendrán que esperar en una larga cola de mensajes para obtener atención. Esto puede ayudar a mejorar la eficiencia y la productividad en tu negocio.',
|
||||
icon: 'tabler:arrows-right-left',
|
||||
},
|
||||
{
|
||||
title: 'Open to new ideas and contributions',
|
||||
title: 'Personalización y adaptación',
|
||||
description:
|
||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi sagittis, quam nec venenatis lobortis, mi risus tempus nulla.',
|
||||
'Como proyecto open source, el chatbot de WhatsApp es totalmente personalizable y puede ser adaptado a las necesidades específicas de tu negocio o proyecto. Esto significa que puedes modificar el código fuente y adaptar el chatbot a tus necesidades exactas.',
|
||||
icon: 'tabler:bulb',
|
||||
},
|
||||
],
|
||||
@@ -50,16 +47,16 @@ export default component$(() => {
|
||||
<div class="px-4 py-16 mx-auto max-w-6xl lg:px-8 lg:py-20">
|
||||
<div class="mb-10 md:mx-auto sm:text-center md:mb-12 max-w-3xl">
|
||||
<p class="text-base text-primary-600 dark:text-purple-200 font-semibold tracking-wide uppercase">
|
||||
Features
|
||||
Caracteristicas
|
||||
</p>
|
||||
<h2 class="text-4xl md:text-5xl font-bold leading-tighter tracking-tighter mb-4 font-heading">
|
||||
What you get with{' '}
|
||||
<span class="whitespace-nowrap">Qwind</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">
|
||||
Sed ut perspiciatis unde omnis iste natus error sit
|
||||
voluptatem accusantium doloremque rem aperiam, eaque
|
||||
ipsa quae.
|
||||
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">
|
||||
@@ -68,7 +65,7 @@ export default component$(() => {
|
||||
{subitems.map(({ title, description }) => (
|
||||
<div class="flex flex-row max-w-md">
|
||||
<div class="mb-4 mr-4">
|
||||
<div class="text-white flex items-center justify-center w-12 h-12 rounded-full bg-secondary-500 dark:bg-secondary-700">
|
||||
<div class="text-white flex items-center justify-center w-12 h-12 rounded-full bg-primary-500 dark:bg-primary-500">
|
||||
<IconStar />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -50,18 +50,10 @@ export default component$(() => {
|
||||
]
|
||||
|
||||
return (
|
||||
<footer class="border-t border-gray-200 dark:border-slate-800">
|
||||
<footer class="">
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<div class="grid grid-cols-12 gap-4 gap-y-8 sm:gap-8 py-8 md:py-12">
|
||||
<div class="col-span-12 lg:col-span-4 pr-8">
|
||||
<div class="mb-2">
|
||||
<Link
|
||||
class="inline-block font-bold text-xl"
|
||||
href={'/'}
|
||||
>
|
||||
Qwind
|
||||
</Link>
|
||||
</div>
|
||||
<div class="text-sm text-gray-600 dark:text-gray-400">
|
||||
Nos sentimos muy afortunados de poder contribuir a
|
||||
este proyecto y esperamos poder seguir trabajando
|
||||
|
||||
@@ -1,27 +1,31 @@
|
||||
import { component$, useStore } from '@builder.io/qwik'
|
||||
import { component$, useContext, useStore } from '@builder.io/qwik'
|
||||
import Logo from '~/components/atoms/Logo'
|
||||
import { IconGithub } from '~/components/icons/IconGithub'
|
||||
import ToggleTheme from '~/components/core/ToggleTheme'
|
||||
import ToggleMenu from '~/components/core/ToggleMenu'
|
||||
import { IconDiscord } from '../icons/IconDiscord'
|
||||
import { GlobalStore } from '~/contexts'
|
||||
|
||||
export default component$(() => {
|
||||
const store = useStore({
|
||||
const storeScroll = useStore({
|
||||
isScrolling: false,
|
||||
})
|
||||
|
||||
const store = useContext(GlobalStore)
|
||||
|
||||
return (
|
||||
<header
|
||||
class={`sticky top-0 z-40 flex-none mx-auto w-full transition-all ${
|
||||
store.isScrolling
|
||||
class={`sticky top-0 z-40 flex-none mx-auto w-full transition-all border border-b-slate-100 dark:border-b-slate-800 border-x-0 border-t-0 ${
|
||||
storeScroll.isScrolling
|
||||
? ' md:bg-white/90 md:backdrop-blur-sm dark:md:bg-slate-900/90 bg-white dark:bg-slate-900'
|
||||
: ''
|
||||
}`}
|
||||
id="header"
|
||||
window:onScroll$={() => {
|
||||
if (!store.isScrolling && window.scrollY >= 10) {
|
||||
store.isScrolling = true
|
||||
} else if (store.isScrolling && window.scrollY < 10) {
|
||||
store.isScrolling = false
|
||||
if (!storeScroll.isScrolling && window.scrollY >= 10) {
|
||||
storeScroll.isScrolling = true
|
||||
} else if (storeScroll.isScrolling && window.scrollY < 10) {
|
||||
storeScroll.isScrolling = false
|
||||
}
|
||||
}}
|
||||
>
|
||||
@@ -42,44 +46,26 @@ export default component$(() => {
|
||||
<ul class="flex flex-col pt-8 md:pt-0 md:flex-row md:self-center w-full md:w-auto text-xl md:text-base">
|
||||
<li class="dropdown">
|
||||
<button class="font-medium hover:text-gray-900 dark:hover:text-white px-4 py-3 flex items-center transition duration-150 ease-in-out">
|
||||
Pages
|
||||
Documentación
|
||||
</button>
|
||||
<ul class="dropdown-menu rounded md:absolute pl-4 md:pl-0 md:hidden font-medium md:bg-white md:min-w-[200px] dark:md:bg-slate-800 drop-shadow-xl">
|
||||
<li>
|
||||
<a
|
||||
class="font-medium rounded-t md:hover:bg-gray-100 dark:hover:bg-gray-700 py-2 px-4 block whitespace-no-wrap"
|
||||
href="#"
|
||||
>
|
||||
Features
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
class="font-medium md:hover:bg-gray-100 dark:hover:bg-gray-700 py-2 px-4 block whitespace-no-wrap"
|
||||
href="#"
|
||||
>
|
||||
Profile
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
class="font-medium rounded-b md:hover:bg-gray-100 dark:hover:bg-gray-700 py-2 px-4 block whitespace-no-wrap"
|
||||
href="#"
|
||||
>
|
||||
Pricing
|
||||
</a>
|
||||
</li>
|
||||
{store.map((ctx) => {
|
||||
return ctx.list.map((listCtx) => {
|
||||
return (
|
||||
<li>
|
||||
<a
|
||||
class="font-medium rounded-t md:hover:bg-gray-100 dark:hover:bg-gray-700 py-2 px-4 block whitespace-no-wrap"
|
||||
href={listCtx.link}
|
||||
>
|
||||
{listCtx.name}
|
||||
</a>
|
||||
</li>
|
||||
)
|
||||
})
|
||||
})}
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
class="font-medium hover:text-gray-900 dark:hover:text-white px-4 py-3 flex items-center transition duration-150 ease-in-out"
|
||||
href={'/docs'}
|
||||
>
|
||||
Documentación
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
{/* <li>
|
||||
<a
|
||||
target={'_blank'}
|
||||
class="font-medium hover:text-gray-900 dark:hover:text-white px-4 py-3 flex items-center transition duration-150 ease-in-out"
|
||||
@@ -89,7 +75,7 @@ export default component$(() => {
|
||||
>
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
</li> */}
|
||||
<li class="md:hidden">
|
||||
<a
|
||||
target={'_blank'}
|
||||
@@ -104,6 +90,15 @@ export default component$(() => {
|
||||
<div class="hidden items-center md:flex">
|
||||
<ToggleTheme />
|
||||
<a
|
||||
target={'_blank'}
|
||||
href="https://link.codigoencasa.com/DISCORD"
|
||||
class="inline-block text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-2.5"
|
||||
aria-label="Qwind Github"
|
||||
>
|
||||
<IconDiscord />
|
||||
</a>
|
||||
<a
|
||||
target={'_blank'}
|
||||
href="https://github.com/codigoencasa/bot-whatsapp"
|
||||
class="inline-block text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-2.5"
|
||||
aria-label="Qwind Github"
|
||||
|
||||
@@ -1,63 +1,59 @@
|
||||
import { component$ } from '@builder.io/qwik'
|
||||
|
||||
// @ts-ignore
|
||||
import srcsetAvif from '~/assets/images/hero.jpg?w=400;900&avif&srcset'
|
||||
import srcsetAvif from '~/assets/images/chatbot-whatsapp.png?w=400;900&avif&srcset'
|
||||
// @ts-ignore
|
||||
import srcsetWebp from '~/assets/images/hero.jpg?w=400;900&webp&srcset'
|
||||
import srcsetWebp from '~/assets/images/chatbot-whatsapp.png?w=400;900&webp&srcset'
|
||||
// @ts-ignore
|
||||
import { src as placeholder } from '~/assets/images/hero.jpg?width=400&metadata'
|
||||
import { src as placeholder } from '~/assets/images/chatbot-whatsapp.png?width=400&metadata'
|
||||
|
||||
export default component$(() => {
|
||||
return (
|
||||
<section
|
||||
class={`bg-gradient-to-b md:bg-gradient-to-r from-white via-purple-50 to-sky-100 dark:bg-none mt-[-72px]`}
|
||||
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">
|
||||
Free template for <br class="hidden lg:block" />{' '}
|
||||
<span class="hidden lg:inline">
|
||||
create a website using{' '}
|
||||
</span>{' '}
|
||||
<span class="text-[#039de1]">Qwik</span> +{' '}
|
||||
<span class="sm:whitespace-nowrap text-[#039de1]">
|
||||
Tailwind CSS
|
||||
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 underline decoration-wavy decoration-1 decoration-secondary-600 underline-offset-2">
|
||||
Qwind
|
||||
</span>{' '}
|
||||
is a production ready template to start your
|
||||
new website using <em>Qwik</em> +{' '}
|
||||
<em>Tailwind CSS</em>. It has been designed
|
||||
following Best Practices, SEO,
|
||||
Accessibility,{' '}
|
||||
<span class="inline md:hidden">...</span>
|
||||
<span class="hidden md:inline">
|
||||
Dark Mode, Great Page Speed, image
|
||||
optimization, sitemap generation and
|
||||
more.
|
||||
Con esta libreria,{' '}
|
||||
</span>
|
||||
<span class="font-semibold underline decoration-wavy decoration-1 decoration-secondary-600 underline-offset-2">
|
||||
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.
|
||||
</p>
|
||||
<div class="max-w-xs sm:max-w-md flex flex-nowrap flex-col sm:flex-row gap-4 m-auto md:m-0 justify-center md:justify-start">
|
||||
|
||||
<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">
|
||||
<div class="flex w-full sm:w-auto">
|
||||
<a
|
||||
class="btn btn-primary sm:mb-0 w-full"
|
||||
href="https://github.com/onwidget/qwind"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>
|
||||
Get template
|
||||
</a>
|
||||
<code class="btn btn-primary sm:mb-0 w-full">
|
||||
npm create bot-whatsapp@latest
|
||||
</code>
|
||||
</div>
|
||||
<div class="flex w-full sm:w-auto">
|
||||
<button class="btn w-full bg-gray-50 dark:bg-transparent">
|
||||
Learn more
|
||||
</button>
|
||||
<a
|
||||
href="/docs"
|
||||
class="btn bg-gray-50 dark:bg-transparent"
|
||||
>
|
||||
Más información
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -72,7 +68,7 @@ export default component$(() => {
|
||||
src={placeholder}
|
||||
width={1000}
|
||||
height={1250}
|
||||
class="mx-auto w-full rounded-md md:h-full drop-shadow-2xl bg-gray-400 dark:bg-slate-700"
|
||||
class="mx-auto w-full rounded-md md:h-full drop-shadow-2xl"
|
||||
alt="Qwind Hero Image (Cool dog)"
|
||||
loading="eager"
|
||||
decoding="async"
|
||||
|
||||
@@ -1,32 +1,59 @@
|
||||
import { component$ } from '@builder.io/qwik'
|
||||
import { useLocation } from '@builder.io/qwik-city'
|
||||
import { Link, useLocation } from '@builder.io/qwik-city'
|
||||
import { DocumentationCtx } from '~/contexts'
|
||||
|
||||
/**
|
||||
* options = [] array con la lista de opciones de la documentacion
|
||||
*/
|
||||
export default component$(
|
||||
({ options = [] }: { options: { link: string; name: string }[] }) => {
|
||||
const location = useLocation()
|
||||
const currentPage = location.pathname
|
||||
({ options = [] }: { options: DocumentationCtx[] }) => {
|
||||
return (
|
||||
<div>
|
||||
<ul>
|
||||
{options.map((opt) => (
|
||||
<li>
|
||||
<a
|
||||
class={
|
||||
currentPage === `${opt.link}/`
|
||||
? 'font-semibold'
|
||||
: ''
|
||||
}
|
||||
href={opt.link}
|
||||
>
|
||||
{opt.name}
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
{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} />
|
||||
</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>
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
74
packages/docs/src/components/widgets/Navigation.tsx
Normal file
@@ -0,0 +1,74 @@
|
||||
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>
|
||||
)
|
||||
|
||||
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>
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
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>
|
||||
)
|
||||
}
|
||||
)
|
||||
52
packages/docs/src/components/widgets/SponsorBar.tsx
Normal file
@@ -0,0 +1,52 @@
|
||||
import { component$ } from '@builder.io/qwik'
|
||||
import { useLocation } from '@builder.io/qwik-city'
|
||||
|
||||
// @ts-ignore
|
||||
import { src as qwik } from '~/assets/images/qwik.png?width=100&metadata'
|
||||
// @ts-ignore
|
||||
import { src as leanga } from '~/assets/images/leanga.png?width=40&metadata'
|
||||
|
||||
/**
|
||||
* options = [] array con la lista de opciones de la documentacion
|
||||
*/
|
||||
export default component$(() => {
|
||||
const { pathname } = useLocation()
|
||||
const editUrl = ` https://github.com/codigoencasa/bot-whatsapp/edit/dev/packages/docs/src/routes${pathname}index.mdx`
|
||||
return (
|
||||
<div>
|
||||
<ul>
|
||||
<li>
|
||||
<a target={'_blank'} class={'font-semibold'} href={editUrl}>
|
||||
🙌 Sponsors
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a target={'_blank'} href="https://qwik.builder.io/">
|
||||
<picture>
|
||||
<img
|
||||
src={qwik}
|
||||
class="border border-slate-200 rounded my-2 p-1 bg-gray-50 dark:border-gray-600 dark:bg-gray-700"
|
||||
alt="Qwind Hero Image (Cool dog)"
|
||||
loading="eager"
|
||||
decoding="async"
|
||||
/>
|
||||
</picture>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a target={'_blank'} href="https://leangasoftware.es/">
|
||||
<picture>
|
||||
<img
|
||||
src={leanga}
|
||||
class="border border-slate-200 rounded my-2 p-1 bg-gray-50 dark:border-gray-600 dark:bg-gray-700"
|
||||
alt="Qwind Hero Image (Cool dog)"
|
||||
loading="eager"
|
||||
decoding="async"
|
||||
/>
|
||||
</picture>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
12
packages/docs/src/contexts/index.tsx
Normal file
@@ -0,0 +1,12 @@
|
||||
import { createContext } from '@builder.io/qwik'
|
||||
|
||||
export interface DocumentationCtx {
|
||||
title: string
|
||||
link?: string
|
||||
list: { link: string; name: string }[]
|
||||
}
|
||||
|
||||
export const GlobalStore =
|
||||
createContext<DocumentationCtx[]>('documentation-site')
|
||||
|
||||
export const AppSetting = createContext<{ repo: string }>('app-settings')
|
||||
@@ -1,4 +1,9 @@
|
||||
import { component$, useStyles$ } from '@builder.io/qwik'
|
||||
import {
|
||||
component$,
|
||||
useContextProvider,
|
||||
useStore,
|
||||
useStyles$,
|
||||
} from '@builder.io/qwik'
|
||||
import {
|
||||
QwikCityProvider,
|
||||
RouterOutlet,
|
||||
@@ -8,7 +13,9 @@ import {
|
||||
import { RouterHead } from '~/components/core/RouterHead'
|
||||
import { DarkThemeLauncher } from '~/components/core/DarkThemeLauncher'
|
||||
|
||||
import fontStyles from '~/assets/styles/fonts.css?inline'
|
||||
import globalStyles from '~/assets/styles/global.css?inline'
|
||||
import { DocumentationCtx, GlobalStore } from './contexts'
|
||||
|
||||
export default component$(() => {
|
||||
/**
|
||||
@@ -18,8 +25,46 @@ export default component$(() => {
|
||||
* Dont remove the `<head>` and `<body>` elements.
|
||||
*/
|
||||
|
||||
useStyles$(fontStyles)
|
||||
useStyles$(globalStyles)
|
||||
|
||||
const store = useStore<DocumentationCtx[]>([
|
||||
{
|
||||
title: 'Primeros pasos',
|
||||
list: [
|
||||
{ name: 'Vista rápida', link: '/docs' },
|
||||
{ name: 'Instalación', link: '/docs/install' },
|
||||
{ name: 'Pruebalo', link: '/docs/example' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Esenciales',
|
||||
list: [
|
||||
{ name: 'Conceptos', link: '/docs/essential' },
|
||||
{ name: 'Conversaciones', link: '/docs/flows' },
|
||||
{ name: 'Proveedores', link: '/docs/providers' },
|
||||
{ name: 'Base de datos', link: '/docs/database' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Avanzado',
|
||||
list: [
|
||||
{ name: 'Migración', link: '/docs/migration' },
|
||||
{ name: 'Extender funcionalidades', link: '/docs/custom' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Comunidad',
|
||||
list: [
|
||||
{ name: 'MasterClass', link: '/docs/masterclass' },
|
||||
{ name: 'Unirme al proyecto', link: '/docs/join' },
|
||||
{ name: 'Sponsors', link: '/docs/sponsors' },
|
||||
],
|
||||
},
|
||||
])
|
||||
|
||||
useContextProvider(GlobalStore, store)
|
||||
|
||||
return (
|
||||
<QwikCityProvider>
|
||||
<head>
|
||||
@@ -29,10 +74,7 @@ export default component$(() => {
|
||||
content="width=device-width, initial-scale=1"
|
||||
/>
|
||||
<link rel="manifest" href="/manifest.json" />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
|
||||
<RouterHead />
|
||||
<DarkThemeLauncher />
|
||||
</head>
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
import { component$ } from '@builder.io/qwik'
|
||||
import type { DocumentHead } from '@builder.io/qwik-city'
|
||||
|
||||
export default component$(() => {
|
||||
return (
|
||||
<>
|
||||
<section>
|
||||
<div class="max-w-6xl mx-auto py-6 px-4 sm:px-6 h-[60vh]">
|
||||
<h1 class="text-4xl font-bold leading-tighter tracking-tighter mb-8 font-heading">
|
||||
Blog
|
||||
</h1>
|
||||
<p class="text-xl">Coming soon ...</p>
|
||||
</div>
|
||||
</section>
|
||||
</>
|
||||
)
|
||||
})
|
||||
|
||||
export const head: DocumentHead = {
|
||||
title: 'Blog — Qwind',
|
||||
meta: [
|
||||
{
|
||||
name: 'description',
|
||||
content: 'Lorem ipsum lorem ...',
|
||||
},
|
||||
],
|
||||
}
|
||||
10
packages/docs/src/routes/docs/advanced/index.mdx
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
title: Overview
|
||||
contributors:
|
||||
- adamdbradley
|
||||
- steve8708
|
||||
- manucorporat
|
||||
- gabrielgrant
|
||||
---
|
||||
|
||||
# Avanzado
|
||||
1
packages/docs/src/routes/docs/buttons/index.mdx
Normal file
@@ -0,0 +1 @@
|
||||
# Botones
|
||||
1
packages/docs/src/routes/docs/contribuiting/index.mdx
Normal file
@@ -0,0 +1 @@
|
||||
# Personas que quieran unirse
|
||||
3
packages/docs/src/routes/docs/custom/index.mdx
Normal file
@@ -0,0 +1,3 @@
|
||||
# Extender Funcionalidades
|
||||
|
||||
...
|
||||
32
packages/docs/src/routes/docs/database/index.mdx
Normal file
@@ -0,0 +1,32 @@
|
||||
import Alert from '../../../components/widgets/Alert'
|
||||
|
||||
# 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
|
||||
</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
|
||||
|
||||
```js
|
||||
const MongoAdapter = require('@bot-whatsapp/database/mongo')
|
||||
....
|
||||
const adapterDB = new MongoAdapter({
|
||||
dbUri: 'mongodb://0.0.0.0:27017',
|
||||
dbName: 'db_bot',
|
||||
})
|
||||
```
|
||||
|
||||
Los conectores disponibles hasta el momento son los siguientes:
|
||||
|
||||
`require('@bot-whatsapp/database/mock')`
|
||||
|
||||
`require('@bot-whatsapp/database/mongo')`
|
||||
|
||||
`require('@bot-whatsapp/database/mysql')`
|
||||
|
||||
`require('@bot-whatsapp/database/json')`
|
||||
99
packages/docs/src/routes/docs/essential/index.mdx
Normal file
@@ -0,0 +1,99 @@
|
||||
import Alert from '../../../components/widgets/Alert'
|
||||
|
||||
# Conceptos
|
||||
|
||||
El desarrollo de la librería se base en tres (3) piezas claves para su correcto funcionamiento:
|
||||
|
||||
- **Flow:** Encargado de construir todo el contexto de la conversación, finalmente su objetivo es brindar una capa amigable al desarrollador.
|
||||
- **Provider:** Como si de un [conector](https://www.dignited.com/wp-content/uploads/2019/06/Plug-type-768x432.jpg) se tratara el objetivo es poder cambiar facilmente de proveedor de Whatsapp en minutos
|
||||
sin el riesgo de dañar otras partes del bot
|
||||
- **Database:** Siguiendo la linea de pensamiento de conectores, de igual manera que el provider nos brinda la capacidad de poder cambiar de capa de persistencia de datos (guardar datos) sin invertir tiempo en
|
||||
reescribir nuestro flujo.
|
||||
|
||||
---
|
||||
|
||||
## Flow (Flujos)
|
||||
|
||||
Los flujos hace referencia al hecho de construir un flujo de conversion. Esto es un flow podemos observar que estan presente dos metodos importantes **addKeyword** y el **addAnswer**.
|
||||
|
||||
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 flowPrincipal = addKeyword(['hola', 'alo'])
|
||||
.addAnswer(['Hola, bienvenido a mi tienda', '¿Como puedo ayudarte?'])
|
||||
.addAnswer(['Tengo:', 'Zapatos', 'Bolsos', 'etc ...'])
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 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
|
||||
</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
|
||||
|
||||
```js
|
||||
const WhatsappProvider = require('@bot-whatsapp/provider/web-whatsapp')
|
||||
....
|
||||
const adapterProvider = createProvider(WhatsappProvider)
|
||||
```
|
||||
|
||||
Los proveedores disponibles hasta el momento son los siguientes:
|
||||
|
||||
[whatsapp-web.js](https://github.com/pedroslopez/whatsapp-web.js) `require('@bot-whatsapp/provider/web-whatsapp')`
|
||||
|
||||
[Venom](https://github.com/orkestral/venom) `require('@bot-whatsapp/provider/venom')`
|
||||
|
||||
[Baileys](https://github.com/adiwajshing/Baileys) `require('@bot-whatsapp/provider/baileys')`
|
||||
|
||||
[Meta Official](https://developers.facebook.com/docs/whatsapp/cloud-api/reference/messages) `require('@bot-whatsapp/provider/meta')`
|
||||
|
||||
[Twilio Official](https://www.twilio.com/es-mx/messaging/whatsapp) `require('@bot-whatsapp/provider/twilio')`
|
||||
|
||||
---
|
||||
|
||||
## 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
|
||||
</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
|
||||
|
||||
```js
|
||||
const MongoAdapter = require('@bot-whatsapp/database/mongo')
|
||||
....
|
||||
const adapterDB = new MongoAdapter({
|
||||
dbUri: 'mongodb://0.0.0.0:27017',
|
||||
dbName: 'db_bot',
|
||||
})
|
||||
```
|
||||
|
||||
Los conectores disponibles hasta el momento son los siguientes:
|
||||
|
||||
`require('@bot-whatsapp/database/mock')`
|
||||
|
||||
`require('@bot-whatsapp/database/mongo')`
|
||||
|
||||
`require('@bot-whatsapp/database/mysql')`
|
||||
|
||||
`require('@bot-whatsapp/database/json')`
|
||||
68
packages/docs/src/routes/docs/example/index.mdx
Normal file
@@ -0,0 +1,68 @@
|
||||
# Ejemplo
|
||||
|
||||
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 WebWhatsappProvider = require('@bot-whatsapp/provider/web-whatsapp')
|
||||
const MockAdapter = require('@bot-whatsapp/database/mock')
|
||||
|
||||
const flowPrincipal = addKeyword(['hola', 'ole', 'alo'])
|
||||
.addAnswer(['Hola, bienvenido a mi tienda', '¿Como puedo ayudarte?'])
|
||||
.addAnswer(['Tengo:', 'Zapatos', 'Bolsos', 'etc ...'])
|
||||
|
||||
/**
|
||||
* Esta es la funcion importante es la que realmente inicia
|
||||
* el chatbot.
|
||||
*/
|
||||
const main = async () => {
|
||||
const adapterDB = new MockAdapter()
|
||||
const adapterFlow = createFlow([flowPrincipal])
|
||||
const adapterProvider = createProvider(WebWhatsappProvider)
|
||||
createBot({
|
||||
flow: adapterFlow,
|
||||
provider: adapterProvider,
|
||||
database: adapterDB,
|
||||
})
|
||||
}
|
||||
|
||||
main()
|
||||
```
|
||||
|
||||
## Explicando código
|
||||
|
||||
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 WebWhatsappProvider = require('@bot-whatsapp/provider/web-whatsapp')
|
||||
const MockAdapter = require('@bot-whatsapp/database/mock')
|
||||
```
|
||||
|
||||
La siguiente seccion te declaramos la palabras claves que disparan un flujo de conversación.
|
||||
|
||||
**Ejemplo**:
|
||||
|
||||
Si un usuario te escribe **👦hola** ó **👦alo** el bot respondera
|
||||
|
||||
**🤖Hola, bienvenido a mi tienda, ¿Como puedo ayudarte?**
|
||||
|
||||
**🤖Tengo: Zapatos, Bolsos, etc...**
|
||||
|
||||
```js
|
||||
const flowPrincipal = addKeyword(['hola', 'alo'])
|
||||
.addAnswer(['Hola, bienvenido a mi tienda', '¿Como puedo ayudarte?'])
|
||||
.addAnswer(['Tengo:', 'Zapatos', 'Bolsos', 'etc ...'])
|
||||
```
|
||||
20
packages/docs/src/routes/docs/flows/index.mdx
Normal file
@@ -0,0 +1,20 @@
|
||||
# Flow (Flujos)
|
||||
|
||||
Los flujos hace referencia al hecho de construir un flujo de conversion. Esto es un flow podemos observar que estan presente dos metodos importantes **addKeyword** y el **addAnswer**.
|
||||
|
||||
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 flowPrincipal = addKeyword(['hola', 'alo'])
|
||||
.addAnswer(['Hola, bienvenido a mi tienda', '¿Como puedo ayudarte?'])
|
||||
.addAnswer(['Tengo:', 'Zapatos', 'Bolsos', 'etc ...'])
|
||||
```
|
||||
@@ -1,19 +1,44 @@
|
||||
# Primeros Pasos
|
||||
import Alert from '../../components/widgets/Alert'
|
||||
|
||||
Los chatbots son una herramienta poderosa para que las empresas y
|
||||
organizaciones comuniquen de forma personalizada y automatizada con sus clientes.
|
||||
# Introducción
|
||||
|
||||
Está documentación te ayudará a instalar tu bot de whatsapp en simples pasos con el proposito de
|
||||
que tengas un chatbot funcional en solo minutos.
|
||||
<Alert>
|
||||
**Atención** estás leyendo la documentación de la **versión estable
|
||||
(0.2.x)** 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>
|
||||
|
||||
## ¿Que es esto?
|
||||
|
||||
**@bot-whatsapp** es una librería que te permitirá **crear chatbot para WhatsApp** en tan solo minutos de una manera ágil y rápida. A lo largo de esta documentación encontrarás ejemplos y material de ayuda.
|
||||
|
||||
Si eres una persona con **poco tiempo y gran capacidad** de comprensión con conocimientos, ejecutando proyectos en Node.js y manejo de terminal.
|
||||
Esta documentación te ayudará a instalar tu bot de WhatsApp en simples pasos con el propósito de que tengas un chatbot funcional **en solo minutos.**
|
||||
|
||||
---
|
||||
|
||||
### Ejecutar
|
||||
|
||||
Es muy sencillo solo deberas ejecutar el siguiente comando 🚀
|
||||
Ejecutar el siguiente comando y **seguir las instrucciones**
|
||||
|
||||
```shell
|
||||
npm create bot-whatsapp@latest
|
||||
```
|
||||
|
||||

|
||||
<div class="my-4 ">
|
||||
<video
|
||||
class="rounded drop-shadow-xl w-full md:w-full max-w-screen-md"
|
||||
height="100%"
|
||||
autoplay
|
||||
loop
|
||||
muted
|
||||
playsinline
|
||||
>
|
||||
<source
|
||||
src="https://leifer-landing-page.s3.us-east-2.amazonaws.com/console.webm"
|
||||
type="video/webm"
|
||||
/>
|
||||
</video>
|
||||
</div>
|
||||
|
||||
**¿Algun error?**
|
||||
Recuerda que debes de cumplir con los [requisitos minimos](/docs/install) del sistema
|
||||
|
||||
@@ -1,10 +1,41 @@
|
||||
---
|
||||
title: Overview
|
||||
contributors:
|
||||
- adamdbradley
|
||||
- steve8708
|
||||
- manucorporat
|
||||
- gabrielgrant
|
||||
---
|
||||
|
||||
# Instalación
|
||||
|
||||
A continuación se describen los puntos técnicos que debes de tener en cuenta antes de trabajar con esta herramienta
|
||||
|
||||
## Requerimientos
|
||||
|
||||
- Node v16 o superior **[descargar node](https://nodejs.org/es/download/)**
|
||||
|
||||
## ¿Como saber que tengo el Node?
|
||||
|
||||
Solo debes ejecutar el siguiente comando y esperar que la versión que te arroja sea superior a v16
|
||||
|
||||
```shell
|
||||
$ node -v
|
||||
v18.12.1
|
||||
```
|
||||
|
||||
## Opcionales
|
||||
|
||||
Dependiendo de las opciones de configuraciones que has marcado al momento de crear el bot **Command Line Interface (CLI)** puede que necesites instalar más cosas.
|
||||
|
||||
**Ejemplo**: Si elegiste _(MySQL)_ como proveedor de base de datos, lógicamente necesitaras tener un entorno de MySQL.
|
||||
|
||||
📄 Pronto se agregará más información y videos explicando esto a fondo.
|
||||
|
||||
<div class="my-4 w-full ">
|
||||
<video
|
||||
class="rounded drop-shadow-xl rounded "
|
||||
width="100%"
|
||||
height="100%"
|
||||
autoplay
|
||||
loop
|
||||
muted
|
||||
playsinline
|
||||
>
|
||||
<source
|
||||
src="https://leifer-landing-page.s3.us-east-2.amazonaws.com/console.webm"
|
||||
type="video/webm"
|
||||
/>
|
||||
</video>
|
||||
</div>
|
||||
|
||||
3
packages/docs/src/routes/docs/join/index.mdx
Normal file
@@ -0,0 +1,3 @@
|
||||
# Unirme
|
||||
|
||||
...
|
||||
@@ -1,55 +1,61 @@
|
||||
import { component$, Slot, useStore } from '@builder.io/qwik'
|
||||
import { component$, Slot, useContext } from '@builder.io/qwik'
|
||||
import type { DocumentHead } from '@builder.io/qwik-city'
|
||||
import ExtraBar from '~/components/widgets/ExtraBar'
|
||||
import Footer from '~/components/widgets/Footer'
|
||||
import Header from '~/components/widgets/Header'
|
||||
import NavBar from '~/components/widgets/NavBar'
|
||||
import ExtraBar from '~/components/widgets/ExtraBar'
|
||||
import SponsorBar from '~/components/widgets/SponsorBar'
|
||||
import { GlobalStore } from '~/contexts'
|
||||
// import Navigation from '~/components/widgets/Navigation'
|
||||
// import Collaborators from '~/components/widgets/Collaborators'
|
||||
// import ExtraBar from '~/components/widgets/ExtraBar'
|
||||
|
||||
export default component$(() => {
|
||||
const store = useStore({
|
||||
options: [
|
||||
{ name: 'Primeros pasos', link: '/docs' },
|
||||
{ name: 'Instalación', link: '/docs/install' },
|
||||
{ name: 'Configuración', link: '/docs/settings' },
|
||||
{ name: 'Migración', link: '/docs/migration' },
|
||||
],
|
||||
extraOptions: [
|
||||
{ name: 'Primeros pasos', link: '/docs', class: 'font-semibold' },
|
||||
{ name: 'Instalación', link: '/docs' },
|
||||
{ name: 'Configuración', link: '/docs' },
|
||||
{ name: 'Forma de pensar', link: '/docs' },
|
||||
],
|
||||
})
|
||||
const store = useContext(GlobalStore)
|
||||
|
||||
return (
|
||||
<>
|
||||
<Header />
|
||||
<main class="container mx-auto px-12 ">
|
||||
<div class={'grid grid-cols-5 gap-1 min-h-min'}>
|
||||
<div class={'px-3 col-span-1 '}>
|
||||
<NavBar options={store.options} />
|
||||
<main class={'overflow-hidden'}>
|
||||
<div class={'max-w-8xl'}>
|
||||
<div
|
||||
class={
|
||||
'hidden lg:block fixed z-20 inset-0 top-[4rem] left-[max(0px,calc(50%-48rem))] right-auto w-[14.5rem] py-5 px-8 overflow-y-auto'
|
||||
}
|
||||
>
|
||||
<NavBar options={store} />
|
||||
</div>
|
||||
<div class={'col-span-3 slot pb-5'}>
|
||||
<Slot />
|
||||
<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'
|
||||
}
|
||||
>
|
||||
<Slot />
|
||||
</div>
|
||||
</div>
|
||||
<div class={'px-3 col-span-1 '}>
|
||||
<ExtraBar options={store.extraOptions} />
|
||||
<div
|
||||
class={
|
||||
'hidden lg:block fixed z-20 inset-0 top-[4rem] right-[max(0px,calc(50%-48rem))] left-auto w-[14.5rem] py-5 px-8 overflow-y-auto'
|
||||
}
|
||||
>
|
||||
<ExtraBar />
|
||||
<SponsorBar />
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<Footer />
|
||||
</>
|
||||
)
|
||||
})
|
||||
|
||||
export const head: DocumentHead = {
|
||||
title: 'Qwind — Free template for starts a website using Qwik + Tailwind CSS',
|
||||
title: 'Crear chatbot WhatsApp en minutos — Servicio de chatbot para whatspp gratis proyecto OpenSource',
|
||||
meta: [
|
||||
{
|
||||
name: 'description',
|
||||
content:
|
||||
'Qwind is a free and ready to start template to make your website using Qwik and Tailwind CSS.',
|
||||
'Crear chatbot WhatsApp en minutos — Servicio de chatbot para whatspp gratis proyecto OpenSource',
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
1
packages/docs/src/routes/docs/lists/index.mdx
Normal file
@@ -0,0 +1 @@
|
||||
# Listas
|
||||
24
packages/docs/src/routes/docs/masterclass/index.md
Normal file
@@ -0,0 +1,24 @@
|
||||
[](https://hackmd.io/79xQyVSgRD6RsTpqtMPPdw)
|
||||
### Preguntas Frecuentes para Master Class BOT v2
|
||||
> Anota aqui las preguntas o dudas que tengas
|
||||
> Pronto estare publicando fecha y hora para la masterclass
|
||||
|
||||
1.- Si necesito correr dos bots al mismo tiempo ¿donde puedo cambiar el puerto?
|
||||
|
||||
2.- Si necesito agregar o modificar funciones del bot, ¿como puedo hacerlo?
|
||||
|
||||
3.- Si quiero mi bot con otra base de datos diferente a MySQL ¿como lo puedo hacer?
|
||||
|
||||
4.- Quiero conectarme a tal o cual API con JSON/XML/etc, ¿se puede hacer?
|
||||
|
||||
5.- ¿Como integrar listas?
|
||||
|
||||
6.- Preguntas y respuestas con el Bot
|
||||
|
||||
7.- Guardar conversaciones en Excel.
|
||||
|
||||
8.- ¿Puedo usar 2 o mas sesiones (códigos QR) al mismo tiempo?
|
||||
|
||||
9.- ¿Puede ser que al usar el provider bailey, al leer el qr.png, que sea desde una url en el navegador, y no desde visual studio? Gracias
|
||||
|
||||
10.- ¿Cómo tomo los datos que me envían en un mensaje para utilizarlo internamente en la búsqueda de datos propios y devolver la respuesta?
|
||||
@@ -1,10 +1,207 @@
|
||||
---
|
||||
title: Overview
|
||||
contributors:
|
||||
- adamdbradley
|
||||
- steve8708
|
||||
- manucorporat
|
||||
- gabrielgrant
|
||||
---
|
||||
# Migración
|
||||
|
||||
# Migracion
|
||||
#### Versión (legacy)
|
||||
|
||||
En la **_versión (legacy)_** se implementas los flujos de esta manera, en dos archivos independientes.
|
||||
|
||||
> **`initial.json`** para establecer las palabras claves y el flujo a responder, por otro lado tambien se necesitaba implementar.
|
||||
> **`response.json`** donde se escriben los mensajes a responder.
|
||||
|
||||
```json
|
||||
//initial.json
|
||||
[
|
||||
{
|
||||
"keywords": ["hola", "ola", "alo"],
|
||||
"key": "hola"
|
||||
},
|
||||
{
|
||||
"keywords": ["productos", "info"],
|
||||
"key": "productos"
|
||||
},
|
||||
{
|
||||
"keywords": ["adios", "bye"],
|
||||
"key": "adios"
|
||||
},
|
||||
{
|
||||
"keywords": ["imagen", "foto"],
|
||||
"key": "catalogo"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
```json
|
||||
//response.json
|
||||
{
|
||||
"hola": {
|
||||
"replyMessage": ["Gracias a ti! \n"],
|
||||
"media": null,
|
||||
"trigger": null
|
||||
},
|
||||
"adios": {
|
||||
"replyMessage": ["Que te vaya bien!!"]
|
||||
},
|
||||
"productos": {
|
||||
"replyMessage": ["Más productos aquí"],
|
||||
"trigger": null,
|
||||
"actions": {
|
||||
"title": "¿Que te interesa ver?",
|
||||
"message": "Abajo unos botons",
|
||||
"footer": "",
|
||||
"buttons": [
|
||||
{ "body": "Telefonos" },
|
||||
{ "body": "Computadoras" },
|
||||
{ "body": "Otros" }
|
||||
]
|
||||
}
|
||||
},
|
||||
"catalogo": {
|
||||
"replyMessage": ["Te envio una imagen"],
|
||||
"media": "https://media2.giphy.com/media/VQJu0IeULuAmCwf5SL/giphy.gif",
|
||||
"trigger": null
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Versión 2 (0.2.X)
|
||||
|
||||
En esta versión es mucho más sencillo, abajo encontrarás un ejemplo del mismo flujo anteriormente mostrado.
|
||||
|
||||
```js
|
||||
//app.js
|
||||
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 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 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 adapterProvider = createProvider(BaileysProvider)
|
||||
createBot({
|
||||
flow: adapterFlow,
|
||||
provider: adapterProvider,
|
||||
database: adapterDB,
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
#### Flujos hijos
|
||||
|
||||
A continuación se muestra un ejemplo de flujos hijos, estos nos sirven para crear flujos que solo se disparan cuando el flujo anterior es el especificado, ejemplo:
|
||||
|
||||
> Menu Principal (Escoge zapatos o bolsos)
|
||||
> - SubMenu 1 (Elegiste bolsos, ahora escoge piel o tela)
|
||||
> - Submenu 1.1 (piel)
|
||||
> - Submenu 2 (Elegiste zapatos, ahora escoge piel o tela)
|
||||
> - Submenu 2.1 (piel)
|
||||
|
||||
El `submenu 1` solo se va a disparar cuando el flujo anterior sea el `principal`, e igualmente el `submenu 1.1`, solo cuando el flujo anterior sea el `submenu 1`, ejemplo:
|
||||
|
||||
```js
|
||||
/**
|
||||
* Aqui declaramos los flujos hijos, los flujos se declaran de atras para adelante, es decir que si tienes un flujo de este tipo:
|
||||
*
|
||||
* Menu Principal
|
||||
* - SubMenu 1
|
||||
* - Submenu 1.1
|
||||
* - Submenu 2
|
||||
* - Submenu 2.1
|
||||
*
|
||||
* Primero declaras los submenus 1.1 y 2.1, luego el 1 y 2 y al final el principal.
|
||||
*/
|
||||
const flowBolsos2 = addKeyword(['bolsos2', '2'])
|
||||
.addAnswer('🤯 *MUCHOS* bolsos ...')
|
||||
.addAnswer('y mas bolsos... bla bla')
|
||||
|
||||
const flowZapatos2 = addKeyword(['zapatos2', '2'])
|
||||
.addAnswer('🤯 repito que tengo *MUCHOS* zapatos.')
|
||||
.addAnswer('y algunas otras cosas.')
|
||||
|
||||
const flowZapatos = addKeyword(['1', 'zapatos', 'ZAPATOS'])
|
||||
.addAnswer('🤯 Veo que elegiste zapatos')
|
||||
.addAnswer('Tengo muchos zapatos...bla bla')
|
||||
.addAnswer(
|
||||
['Manda:', '*(2) Zapatos2*', 'para mas información'],
|
||||
{ capture: true },
|
||||
(ctx) => {
|
||||
console.log('Aqui puedes ver más info del usuario...')
|
||||
console.log('Puedes enviar un mail, hook, etc..')
|
||||
console.log(ctx)
|
||||
},
|
||||
[...addChild(flowZapatos2)]
|
||||
)
|
||||
|
||||
const flowBolsos = addKeyword(['2', 'bolsos', 'BOLSOS'])
|
||||
.addAnswer('🙌 Veo que elegiste bolsos')
|
||||
.addAnswer('Tengo muchos bolsos...bla bla')
|
||||
.addAnswer(
|
||||
['Manda:', '*(2) Bolsos2*', 'para mas información.'],
|
||||
{ capture: true },
|
||||
(ctx) => {
|
||||
console.log('Aqui puedes ver más info del usuario...')
|
||||
console.log('Puedes enviar un mail, hook, etc..')
|
||||
console.log(ctx)
|
||||
},
|
||||
[...addChild(flowBolsos2)]
|
||||
)
|
||||
/**
|
||||
* Declarando flujo principal
|
||||
*/
|
||||
const flowPrincipal = addKeyword(['hola', 'ole', 'alo'])
|
||||
.addAnswer(['Hola, bienvenido a mi tienda', '¿Como puedo ayudarte?'])
|
||||
.addAnswer(['Tengo:', 'Zapatos', 'Bolsos', 'etc ...'])
|
||||
.addAnswer(
|
||||
['Para continuar escribe:', '*(1) Zapatos*', '*(2) Bolsos*'],
|
||||
{ capture: true },
|
||||
(ctx) => {
|
||||
console.log('Aqui puedes ver más info del usuario...')
|
||||
console.log('Puedes enviar un mail, hook, etc..')
|
||||
console.log(ctx)
|
||||
},
|
||||
[...addChild(flowBolsos), ...addChild(flowZapatos)]
|
||||
)
|
||||
```
|
||||
|
||||
> Forma parte de este proyecto.
|
||||
|
||||
- [Discord](https://link.codigoencasa.com/DISCORD)
|
||||
- [Twitter](https://twitter.com/leifermendez)
|
||||
- [Youtube](https://www.youtube.com/watch?v=5lEMCeWEJ8o&list=PL_WGMLcL4jzWPhdhcUyhbFU6bC0oJd2BR)
|
||||
- [Telegram](https://t.me/leifermendez)
|
||||
|
||||
31
packages/docs/src/routes/docs/providers/index.mdx
Normal file
@@ -0,0 +1,31 @@
|
||||
import Alert from '../../../components/widgets/Alert'
|
||||
|
||||
# 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
|
||||
</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
|
||||
|
||||
```js
|
||||
const WhatsappProvider = require('@bot-whatsapp/provider/web-whatsapp')
|
||||
....
|
||||
const adapterProvider = createProvider(WhatsappProvider)
|
||||
```
|
||||
|
||||
Los proveedores disponibles hasta el momento son los siguientes:
|
||||
|
||||
[whatsapp-web.js](https://github.com/pedroslopez/whatsapp-web.js) `require('@bot-whatsapp/provider/web-whatsapp')`
|
||||
|
||||
[Venom](https://github.com/orkestral/venom) `require('@bot-whatsapp/provider/venom')`
|
||||
|
||||
[Baileys](https://github.com/adiwajshing/Baileys) `require('@bot-whatsapp/provider/baileys')`
|
||||
|
||||
[Meta Official](https://developers.facebook.com/docs/whatsapp/cloud-api/reference/messages) `require('@bot-whatsapp/provider/meta')`
|
||||
|
||||
[Twilio Official](https://www.twilio.com/es-mx/messaging/whatsapp) `require('@bot-whatsapp/provider/twilio')`
|
||||
3
packages/docs/src/routes/docs/sponsors/index.mdx
Normal file
@@ -0,0 +1,3 @@
|
||||
# Sponsors
|
||||
|
||||
...
|
||||
@@ -4,7 +4,7 @@ import type { DocumentHead } from '@builder.io/qwik-city'
|
||||
import Hero from '~/components/widgets/Hero'
|
||||
import Features from '~/components/widgets/Features'
|
||||
import FAQs from '~/components/widgets/FAQs'
|
||||
import Stats from '~/components/widgets/Stats'
|
||||
// import Stats from '~/components/widgets/Stats'
|
||||
import CallToAction from '~/components/widgets/CallToAction'
|
||||
|
||||
export default component$(() => {
|
||||
@@ -12,20 +12,20 @@ export default component$(() => {
|
||||
<>
|
||||
<Hero />
|
||||
<Features />
|
||||
<FAQs />
|
||||
<Stats />
|
||||
<CallToAction />
|
||||
<FAQs />
|
||||
{/* <Stats /> */}
|
||||
</>
|
||||
)
|
||||
})
|
||||
|
||||
export const head: DocumentHead = {
|
||||
title: 'Qwind — Free template for starts a website using Qwik + Tailwind CSS',
|
||||
title: 'Crear chatbot WhatsApp en minutos — Servicio de chatbot para whatspp gratis proyecto OpenSource',
|
||||
meta: [
|
||||
{
|
||||
name: 'description',
|
||||
content:
|
||||
'Qwind is a free and ready to start template to make your website using Qwik and Tailwind CSS.',
|
||||
'Crear chatbot WhatsApp en minutos — Servicio de chatbot para whatspp gratis proyecto OpenSource',
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
@@ -8,14 +8,215 @@ module.exports = {
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
primary: colors.purple,
|
||||
primary: colors.green,
|
||||
secondary: colors.sky,
|
||||
},
|
||||
typography: (theme) => ({
|
||||
DEFAULT: {
|
||||
css: {
|
||||
maxWidth: 'none',
|
||||
color: theme('colors.slate.700'),
|
||||
hr: {
|
||||
borderColor: theme('colors.slate.100'),
|
||||
marginTop: '3em',
|
||||
marginBottom: '3em',
|
||||
},
|
||||
'h1, h2, h3': {
|
||||
letterSpacing: '-0.025em',
|
||||
},
|
||||
h2: {
|
||||
marginBottom: `${16 / 24}em`,
|
||||
},
|
||||
h3: {
|
||||
marginTop: '2.4em',
|
||||
lineHeight: '1.4',
|
||||
},
|
||||
h4: {
|
||||
marginTop: '2em',
|
||||
fontSize: '1.125em',
|
||||
},
|
||||
'h2 small, h3 small, h4 small': {
|
||||
fontFamily: theme('fontFamily.mono').join(', '),
|
||||
color: theme('colors.slate.500'),
|
||||
fontWeight: 500,
|
||||
},
|
||||
'h2 small': {
|
||||
fontSize: theme('fontSize.lg')[0],
|
||||
...theme('fontSize.lg')[1],
|
||||
},
|
||||
'h3 small': {
|
||||
fontSize: theme('fontSize.base')[0],
|
||||
...theme('fontSize.base')[1],
|
||||
},
|
||||
'h4 small': {
|
||||
fontSize: theme('fontSize.sm')[0],
|
||||
...theme('fontSize.sm')[1],
|
||||
},
|
||||
'h2, h3, h4': {
|
||||
'scroll-margin-top': 'var(--scroll-mt)',
|
||||
},
|
||||
ul: {
|
||||
listStyleType: 'none',
|
||||
paddingLeft: 0,
|
||||
},
|
||||
'ul > li': {
|
||||
position: 'relative',
|
||||
paddingLeft: '1.75em',
|
||||
},
|
||||
'ul > li::before': {
|
||||
content: '""',
|
||||
width: '0.75em',
|
||||
height: '0.125em',
|
||||
position: 'absolute',
|
||||
top: 'calc(0.875em - 0.0625em)',
|
||||
left: 0,
|
||||
borderRadius: '999px',
|
||||
backgroundColor: theme('colors.slate.300'),
|
||||
},
|
||||
a: {
|
||||
fontWeight: theme('fontWeight.semibold'),
|
||||
textDecoration: 'none',
|
||||
borderBottom: `1px solid ${theme(
|
||||
'colors.sky.300'
|
||||
)}`,
|
||||
},
|
||||
'a:hover': {
|
||||
borderBottomWidth: '2px',
|
||||
},
|
||||
'a code': {
|
||||
color: 'inherit',
|
||||
fontWeight: 'inherit',
|
||||
},
|
||||
strong: {
|
||||
color: theme('colors.slate.900'),
|
||||
fontWeight: theme('fontWeight.semibold'),
|
||||
},
|
||||
'a strong': {
|
||||
color: 'inherit',
|
||||
fontWeight: 'inherit',
|
||||
},
|
||||
kbd: {
|
||||
background: theme('colors.slate.100'),
|
||||
borderWidth: '1px',
|
||||
borderColor: theme('colors.slate.200'),
|
||||
padding: '0.125em 0.25em',
|
||||
color: theme('colors.slate.700'),
|
||||
fontWeight: 500,
|
||||
fontSize: '0.875em',
|
||||
fontVariantLigatures: 'none',
|
||||
borderRadius: '4px',
|
||||
margin: '0 1px',
|
||||
},
|
||||
code: {
|
||||
fontWeight: theme('fontWeight.medium'),
|
||||
fontVariantLigatures: 'none',
|
||||
},
|
||||
pre: {
|
||||
color: theme('colors.slate.50'),
|
||||
borderRadius: theme('borderRadius.xl'),
|
||||
padding: theme('padding.5'),
|
||||
boxShadow: theme('boxShadow.md'),
|
||||
display: 'flex',
|
||||
marginTop: `${20 / 14}em`,
|
||||
marginBottom: `${32 / 14}em`,
|
||||
},
|
||||
'p + pre': {
|
||||
marginTop: `${-4 / 14}em`,
|
||||
},
|
||||
'pre + pre': {
|
||||
marginTop: `${-16 / 14}em`,
|
||||
},
|
||||
'pre code': {
|
||||
flex: 'none',
|
||||
minWidth: '100%',
|
||||
},
|
||||
table: {
|
||||
fontSize: theme('fontSize.sm')[0],
|
||||
lineHeight: theme('fontSize.sm')[1].lineHeight,
|
||||
},
|
||||
thead: {
|
||||
color: theme('colors.slate.700'),
|
||||
borderBottomColor: theme('colors.slate.200'),
|
||||
},
|
||||
'thead th': {
|
||||
paddingTop: 0,
|
||||
fontWeight: theme('fontWeight.semibold'),
|
||||
},
|
||||
'tbody tr': {
|
||||
borderBottomColor: theme('colors.slate.100'),
|
||||
},
|
||||
'tbody tr:last-child': {
|
||||
borderBottomWidth: '1px',
|
||||
},
|
||||
'tbody code': {
|
||||
fontSize: theme('fontSize.xs')[0],
|
||||
},
|
||||
'figure figcaption': {
|
||||
textAlign: 'center',
|
||||
fontStyle: 'italic',
|
||||
},
|
||||
'figure > figcaption': {
|
||||
marginTop: `${12 / 14}em`,
|
||||
},
|
||||
},
|
||||
},
|
||||
dark: {
|
||||
css: {
|
||||
color: theme('colors.slate.400'),
|
||||
'h2, h3, h4, thead th': {
|
||||
color: theme('colors.slate.200'),
|
||||
},
|
||||
'h2 small, h3 small, h4 small': {
|
||||
color: theme('colors.slate.400'),
|
||||
},
|
||||
kbd: {
|
||||
background: theme('colors.slate.700'),
|
||||
borderColor: theme('colors.slate.600'),
|
||||
color: theme('colors.slate.200'),
|
||||
},
|
||||
code: {
|
||||
color: theme('colors.slate.200'),
|
||||
},
|
||||
hr: {
|
||||
borderColor: theme('colors.slate.200'),
|
||||
opacity: '0.05',
|
||||
},
|
||||
pre: {
|
||||
boxShadow: 'inset 0 0 0 1px rgb(255 255 255 / 0.1)',
|
||||
},
|
||||
a: {
|
||||
color: theme('colors.white'),
|
||||
borderBottomColor: theme('colors.sky.400'),
|
||||
},
|
||||
strong: {
|
||||
color: theme('colors.slate.200'),
|
||||
},
|
||||
thead: {
|
||||
color: theme('colors.slate.300'),
|
||||
borderBottomColor: 'rgb(148 163 184 / 0.2)',
|
||||
},
|
||||
'tbody tr': {
|
||||
borderBottomColor: 'rgb(148 163 184 / 0.1)',
|
||||
},
|
||||
blockQuote: {
|
||||
color: theme('colors.white'),
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
fontFamily: {
|
||||
sans: ["'Inter'", ...defaultTheme.fontFamily.sans],
|
||||
sans: ['Inter var', ...defaultTheme.fontFamily.sans],
|
||||
mono: ['Fira Code VF', ...defaultTheme.fontFamily.mono],
|
||||
source: ['Source Sans Pro', ...defaultTheme.fontFamily.sans],
|
||||
'ubuntu-mono': ['Ubuntu Mono', ...defaultTheme.fontFamily.mono],
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
darkMode: 'class',
|
||||
plugins: [
|
||||
require('@tailwindcss/line-clamp'),
|
||||
require('@tailwindcss/typography'),
|
||||
require('@tailwindcss/aspect-ratio'),
|
||||
require('@tailwindcss/forms')({ strategy: 'class' }),
|
||||
],
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bot-whatsapp/provider",
|
||||
"version": "0.0.30-alpha.0",
|
||||
"version": "0.0.31-alpha.0",
|
||||
"description": "Esto es el conector a Twilio, Meta, etc...",
|
||||
"main": "./lib/mock/index.cjs",
|
||||
"keywords": [],
|
||||
|
||||
@@ -14,6 +14,7 @@ const {
|
||||
baileyGenerateImage,
|
||||
baileyCleanNumber,
|
||||
baileyIsValidNumber,
|
||||
baileyDownloadMedia,
|
||||
} = require('./utils')
|
||||
|
||||
const logger = new Console({
|
||||
@@ -39,12 +40,43 @@ class BaileysProvider extends ProviderClass {
|
||||
initBailey = async () => {
|
||||
const { state, saveCreds } = await useMultiFileAuthState('sessions')
|
||||
this.saveCredsGlobal = saveCreds
|
||||
|
||||
try {
|
||||
this.vendor = makeWASocket({
|
||||
const sock = makeWASocket({
|
||||
printQRInTerminal: false,
|
||||
auth: state,
|
||||
logger: pino({ level: 'error' }),
|
||||
})
|
||||
|
||||
sock.ev.on('connection.update', async (update) => {
|
||||
const { connection, lastDisconnect, qr } = update
|
||||
|
||||
if (connection === 'close') {
|
||||
const shouldReconnect =
|
||||
lastDisconnect?.error?.output?.statusCode !==
|
||||
DisconnectReason.loggedOut
|
||||
|
||||
if (shouldReconnect) {
|
||||
await saveCreds()
|
||||
this.initBailey()
|
||||
}
|
||||
}
|
||||
|
||||
if (qr) {
|
||||
this.emit('require_action', {
|
||||
instructions: [
|
||||
`Debes escanear el QR Code para iniciar session reivsa qr.png`,
|
||||
`Recuerda que el QR se actualiza cada minuto `,
|
||||
`Necesitas ayuda: https://link.codigoencasa.com/DISCORD`,
|
||||
],
|
||||
})
|
||||
await baileyGenerateImage(qr)
|
||||
}
|
||||
|
||||
if (connection === 'open') this.emit('ready', true)
|
||||
})
|
||||
|
||||
this.vendor = sock
|
||||
} catch (e) {
|
||||
logger.log(e)
|
||||
this.emit('auth_failure', [
|
||||
@@ -64,25 +96,9 @@ class BaileysProvider extends ProviderClass {
|
||||
*/
|
||||
busEvents = () => [
|
||||
{
|
||||
event: 'connection.update',
|
||||
func: async ({ qr, connection, lastDisconnect }) => {
|
||||
const statusCode = lastDisconnect?.error?.output?.statusCode
|
||||
|
||||
if (statusCode && statusCode !== DisconnectReason.loggedOut)
|
||||
this.initBailey()
|
||||
|
||||
if (qr) {
|
||||
this.emit('require_action', {
|
||||
instructions: [
|
||||
`Debes escanear el QR Code para iniciar session reivsa qr.png`,
|
||||
`Recuerda que el QR se actualiza cada minuto `,
|
||||
`Necesitas ayuda: https://link.codigoencasa.com/DISCORD`,
|
||||
],
|
||||
})
|
||||
await baileyGenerateImage(qr)
|
||||
}
|
||||
|
||||
if (connection === 'open') this.emit('ready', true)
|
||||
event: 'creds.update',
|
||||
func: async () => {
|
||||
await this.saveCredsGlobal()
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -95,13 +111,20 @@ class BaileysProvider extends ProviderClass {
|
||||
body: messageCtx?.message?.conversation,
|
||||
from: messageCtx?.key?.remoteJid,
|
||||
}
|
||||
if (payload.from === 'status@broadcast') {
|
||||
return
|
||||
}
|
||||
if (payload.from === 'status@broadcast') return
|
||||
|
||||
if (payload?.key?.fromMe) return
|
||||
|
||||
if (!baileyIsValidNumber(payload.from)) {
|
||||
return
|
||||
}
|
||||
|
||||
const btnCtx =
|
||||
payload?.message?.templateButtonReplyMessage
|
||||
?.selectedDisplayText
|
||||
|
||||
if (btnCtx) payload.body = btnCtx
|
||||
|
||||
payload.from = baileyCleanNumber(payload.from, true)
|
||||
this.emit('message', payload)
|
||||
},
|
||||
@@ -124,8 +147,9 @@ class BaileysProvider extends ProviderClass {
|
||||
*/
|
||||
|
||||
sendMedia = async (number, imageUrl, text) => {
|
||||
await this.vendor.sendMessage(number, {
|
||||
image: { url: imageUrl },
|
||||
const fileDownloaded = await baileyDownloadMedia(imageUrl)
|
||||
return this.vendor.sendMessage(number, {
|
||||
image: { url: fileDownloaded },
|
||||
text,
|
||||
})
|
||||
}
|
||||
@@ -186,17 +210,21 @@ class BaileysProvider extends ProviderClass {
|
||||
* @example await sendMessage("+XXXXXXXXXXX", "Your Text", "Your Footer", [{"buttonId": "id", "buttonText": {"displayText": "Button"}, "type": 1}])
|
||||
*/
|
||||
|
||||
sendButtons = async (number, text, footer, buttons) => {
|
||||
sendButtons = async (number, text, buttons) => {
|
||||
const numberClean = number.replace('+', '')
|
||||
const templateButtons = buttons.map((btn, i) => ({
|
||||
index: `${i}`,
|
||||
quickReplyButton: {
|
||||
displayText: btn.body,
|
||||
id: `id-btn-${i}`,
|
||||
},
|
||||
}))
|
||||
|
||||
const buttonMessage = {
|
||||
text: text,
|
||||
footer: footer,
|
||||
buttons: buttons,
|
||||
headerType: 1,
|
||||
}
|
||||
|
||||
await this.vendor.sendMessage(`${numberClean}@c.us`, buttonMessage)
|
||||
return this.vendor.sendMessage(`${numberClean}@c.us`, {
|
||||
text,
|
||||
footer: '',
|
||||
templateButtons: templateButtons,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -209,8 +237,8 @@ class BaileysProvider extends ProviderClass {
|
||||
sendMessage = async (numberIn, message, { options }) => {
|
||||
const number = baileyCleanNumber(numberIn)
|
||||
|
||||
// if (options?.buttons?.length)
|
||||
// return this.sendButtons(number, message, options.buttons)
|
||||
if (options?.buttons?.length)
|
||||
return this.sendButtons(number, message, options.buttons)
|
||||
if (options?.media)
|
||||
return this.sendMedia(number, options.media, message)
|
||||
return this.sendText(number, message)
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
const { createWriteStream } = require('fs')
|
||||
const combineImage = require('combine-image')
|
||||
const qr = require('qr-image')
|
||||
const { tmpdir } = require('os')
|
||||
const http = require('http')
|
||||
const https = require('https')
|
||||
|
||||
const baileyCleanNumber = (number, full = false) => {
|
||||
number = number.replace('@s.whatsapp.net', '')
|
||||
@@ -38,4 +41,38 @@ const baileyIsValidNumber = (rawNumber) => {
|
||||
return !exist
|
||||
}
|
||||
|
||||
module.exports = { baileyCleanNumber, baileyGenerateImage, baileyIsValidNumber }
|
||||
/**
|
||||
* Incompleta
|
||||
* Descargar archivo multimedia para enviar
|
||||
* @param {*} url
|
||||
* @returns
|
||||
*/
|
||||
const baileyDownloadMedia = (url) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const ext = url.split('.').pop()
|
||||
const checkProtocol = url.includes('https:')
|
||||
const handleHttp = checkProtocol ? https : http
|
||||
const name = `tmp-${Date.now()}.${ext}`
|
||||
const fullPath = `${tmpdir()}/${name}`
|
||||
const file = createWriteStream(fullPath)
|
||||
handleHttp.get(url, function (response) {
|
||||
response.pipe(file)
|
||||
file.on('finish', function () {
|
||||
file.close()
|
||||
resolve(fullPath)
|
||||
})
|
||||
file.on('error', function () {
|
||||
console.log('errro')
|
||||
file.close()
|
||||
reject(null)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
baileyCleanNumber,
|
||||
baileyGenerateImage,
|
||||
baileyIsValidNumber,
|
||||
baileyDownloadMedia,
|
||||
}
|
||||
|
||||
@@ -105,6 +105,29 @@ class VenomProvider extends ProviderClass {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enviar botones
|
||||
* @private
|
||||
* @param {*} number
|
||||
* @param {*} message
|
||||
* @param {*} buttons []
|
||||
* @returns
|
||||
*/
|
||||
sendButtons = async (number, message, buttons = []) => {
|
||||
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`)
|
||||
return this.vendor.sendText(number, buttonToStr)
|
||||
// return this.vendor.sendButtons(number, "Title", buttons1, "Description");
|
||||
}
|
||||
|
||||
/**
|
||||
* Enviar imagen o multimedia
|
||||
* @param {*} number
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
},
|
||||
"keywords": [],
|
||||
"dependencies": {
|
||||
"whatsapp-web.js": "^1.18.3",
|
||||
"whatsapp-web.js": "^1.18.4",
|
||||
"@bot-whatsapp/bot": "latest",
|
||||
"@bot-whatsapp/cli": "latest",
|
||||
"@bot-whatsapp/database": "latest",
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
},
|
||||
"keywords": [],
|
||||
"dependencies": {
|
||||
"whatsapp-web.js": "^1.18.3",
|
||||
"whatsapp-web.js": "^1.18.4",
|
||||
"@bot-whatsapp/bot": "latest",
|
||||
"@bot-whatsapp/cli": "latest",
|
||||
"@bot-whatsapp/database": "latest",
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
},
|
||||
"keywords": [],
|
||||
"dependencies": {
|
||||
"whatsapp-web.js": "^1.18.3",
|
||||
"whatsapp-web.js": "^1.18.4",
|
||||
"@bot-whatsapp/bot": "latest",
|
||||
"@bot-whatsapp/cli": "latest",
|
||||
"@bot-whatsapp/database": "latest",
|
||||
|
||||
79
yarn.lock
@@ -916,11 +916,11 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"@babel/runtime@npm:^7.3.4":
|
||||
version: 7.20.6
|
||||
resolution: "@babel/runtime@npm:7.20.6"
|
||||
version: 7.20.7
|
||||
resolution: "@babel/runtime@npm:7.20.7"
|
||||
dependencies:
|
||||
regenerator-runtime: ^0.13.11
|
||||
checksum: 42a8504db21031b1859fbc0f52d698a3d2f5ada9519eb76c6f96a7e657d8d555732a18fe71ef428a67cc9fc81ca0d3562fb7afdc70549c5fec343190cbaa9b03
|
||||
checksum: 4629ce5c46f06cca9cfb9b7fc00d48003335a809888e2b91ec2069a2dcfbfef738480cff32ba81e0b7c290f8918e5c22ddcf2b710001464ee84ba62c7e32a3a3
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -1882,6 +1882,49 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@tailwindcss/aspect-ratio@npm:^0.4.0":
|
||||
version: 0.4.2
|
||||
resolution: "@tailwindcss/aspect-ratio@npm:0.4.2"
|
||||
peerDependencies:
|
||||
tailwindcss: ">=2.0.0 || >=3.0.0 || >=3.0.0-alpha.1"
|
||||
checksum: e998fcb0c1a55cae4e83c4510fed0d4d1cba845b7ed79a18451f55377d4a177050c2401af59222662a216aa9c407ef49c475c93db8e13246e0bb3f1ed42f78f8
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@tailwindcss/forms@npm:^0.5.3":
|
||||
version: 0.5.3
|
||||
resolution: "@tailwindcss/forms@npm:0.5.3"
|
||||
dependencies:
|
||||
mini-svg-data-uri: ^1.2.3
|
||||
peerDependencies:
|
||||
tailwindcss: ">=3.0.0 || >= 3.0.0-alpha.1"
|
||||
checksum: 9eddb4dbd06d01b1068138ff52a54ed0e35a28e7bfd3c72e226fc28658ecd92a9c078c4abe9c83db090984672040644d7ae2e035933fb619dd703df1d87aa275
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@tailwindcss/line-clamp@npm:^0.3.1":
|
||||
version: 0.3.1
|
||||
resolution: "@tailwindcss/line-clamp@npm:0.3.1"
|
||||
peerDependencies:
|
||||
tailwindcss: ">=2.0.0 || >=3.0.0 || >=3.0.0-alpha.1"
|
||||
checksum: 805322a6333f029d6d961e02f23099d16f55d31f4736511bc741efff4097a1ad1574a7dff0530b17dbc974e08138b3beb13766f809e0116ebc192b0edf38b737
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@tailwindcss/typography@npm:^0.5.0":
|
||||
version: 0.5.8
|
||||
resolution: "@tailwindcss/typography@npm:0.5.8"
|
||||
dependencies:
|
||||
lodash.castarray: ^4.4.0
|
||||
lodash.isplainobject: ^4.0.6
|
||||
lodash.merge: ^4.6.2
|
||||
postcss-selector-parser: 6.0.10
|
||||
peerDependencies:
|
||||
tailwindcss: "*"
|
||||
checksum: afe172c75ddf086f840b10f95e562bb210dde5612fccfcfd3c4cee688c57ca5b79569b3c2cb75687b34b1b7f9ad194b14e9fbb09a741cd69198bb92b5ac3838f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@tootallnate/once@npm:1":
|
||||
version: 1.1.2
|
||||
resolution: "@tootallnate/once@npm:1.1.2"
|
||||
@@ -7434,6 +7477,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"lodash.castarray@npm:^4.4.0":
|
||||
version: 4.4.0
|
||||
resolution: "lodash.castarray@npm:4.4.0"
|
||||
checksum: fca8c7047e0ae2738b0b2503fb00157ae0ff6d8a1b716f87ed715b22560e09de438c75b65e01a7e44ceb41c5b31dce2eb576e46db04beb9c699c498e03cbd00f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"lodash.clone@npm:^4.5.0":
|
||||
version: 4.5.0
|
||||
resolution: "lodash.clone@npm:4.5.0"
|
||||
@@ -8301,6 +8351,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"mini-svg-data-uri@npm:^1.2.3":
|
||||
version: 1.4.4
|
||||
resolution: "mini-svg-data-uri@npm:1.4.4"
|
||||
bin:
|
||||
mini-svg-data-uri: cli.js
|
||||
checksum: 997f1fbd8d59a70f03761e18626d335197a3479cb9d1ff75678e4b64b864d32a0b8fc18115eabde035e5299b8b4a354a78e57dd6ac10f9d604162a6170898d09
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"miniflare@npm:2.10.0":
|
||||
version: 2.10.0
|
||||
resolution: "miniflare@npm:2.10.0"
|
||||
@@ -9718,6 +9777,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"postcss-selector-parser@npm:6.0.10":
|
||||
version: 6.0.10
|
||||
resolution: "postcss-selector-parser@npm:6.0.10"
|
||||
dependencies:
|
||||
cssesc: ^3.0.0
|
||||
util-deprecate: ^1.0.2
|
||||
checksum: 46afaa60e3d1998bd7adf6caa374baf857cc58d3ff944e29459c9a9e4680a7fe41597bd5b755fc81d7c388357e9bf67c0251d047c640a09f148e13606b8a8608
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"postcss-selector-parser@npm:^6.0.10, postcss-selector-parser@npm:^6.0.4, postcss-selector-parser@npm:^6.0.5, postcss-selector-parser@npm:^6.0.9":
|
||||
version: 6.0.11
|
||||
resolution: "postcss-selector-parser@npm:6.0.11"
|
||||
@@ -10034,6 +10103,10 @@ __metadata:
|
||||
"@builder.io/qwik-city": 0.0.128
|
||||
"@fontsource/inter": ^4.5.14
|
||||
"@iconify-json/tabler": ^1.1.49
|
||||
"@tailwindcss/aspect-ratio": ^0.4.0
|
||||
"@tailwindcss/forms": ^0.5.3
|
||||
"@tailwindcss/line-clamp": ^0.3.1
|
||||
"@tailwindcss/typography": ^0.5.0
|
||||
"@types/eslint": 8.4.10
|
||||
"@types/node": latest
|
||||
"@typescript-eslint/eslint-plugin": 5.45.0
|
||||
|
||||