Skip to content

Commit

Permalink
chore: move example chat bot from packages to apps directory
Browse files Browse the repository at this point in the history
Signed-off-by: sarthakjdev <jsarthak448@gmail.com>
  • Loading branch information
sarthakjdev committed Jul 14, 2024
1 parent 0297832 commit f366e32
Show file tree
Hide file tree
Showing 14 changed files with 321 additions and 0 deletions.
4 changes: 4 additions & 0 deletions apps/example-chat-bot/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
WHATSAPP_API_ACCESS_TOKEN=
WHATSAPP_PHONE_NUMBER_ID=
WHATSAPP_BUSINESS_ACCOUNT_ID=
WHATSAPP_WEBHOOK_SECRET=
2 changes: 2 additions & 0 deletions apps/example-chat-bot/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
dist
.eslintrc.js
4 changes: 4 additions & 0 deletions apps/example-chat-bot/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/** @type {import("eslint").Linter.Config} */
module.exports = {
extends: ['@wapijs/eslint-config/config.node.js']
}
1 change: 1 addition & 0 deletions apps/example-chat-bot/.prettierrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('@wapijs/prettier-config/config.node')
63 changes: 63 additions & 0 deletions apps/example-chat-bot/build.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/* eslint-disable no-console */
import { nodeExternalsPlugin } from 'esbuild-node-externals'
import esbuildPluginTsc from 'esbuild-plugin-tsc'
import { context, build } from 'esbuild'
import { TsconfigPathsPlugin } from '@esbuild-plugins/tsconfig-paths'

// Define common options for both development and production builds
const commonOptions = {
entryPoints: ['./src/index.ts'],
target: 'es6',
format: "cjs",
splitting: false,
outdir: './dist',
platform: 'node',
bundle: true,
plugins: [
nodeExternalsPlugin(),
TsconfigPathsPlugin({ tsconfig: './tsconfig.json' }),
esbuildPluginTsc({
tsconfigPath: './tsconfig.json',
force: true
})
]
}

// Development Build
async function buildDevCode() {
const devOptions = {
...commonOptions,
minify: false // Don't minify in development
}

const buildContext = await context(devOptions)

// Add watch mode for development
await buildContext.watch()
}

// Production Build
async function buildProdCode() {
const prodOptions = {
...commonOptions,
minify: true // Minify in production
}

await build(prodOptions)
}

async function buildCode() {
if (process.argv.includes('--watch')) {
// If '--watch' argument is provided, run development build
await buildDevCode()
console.log('Built code in development watch mode.')
} else {
// Otherwise, run production build
await buildProdCode()
console.log('Production Build Ready!')
}
}

buildCode().catch(() => {
process.exit(1)
})
Empty file.
10 changes: 10 additions & 0 deletions apps/example-chat-bot/nodemon.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"watch": [
"./dist/src/index.js"
],
"ignore": [
"node_modules/*.*"
],
"ext": "js",
"exec": "sleep 2 && NODE_ENV=development node -r dotenv/config ./dist/index.js dotenv_config_path=./.env.dev"
}
48 changes: 48 additions & 0 deletions apps/example-chat-bot/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
"name": "@wapijs/example-chat-bot",
"description": "example whatsapp cloud api chatbot",
"private": true,
"main": "./dist/index.js",
"scripts": {
"watch": "pnpm tsc --watch",
"dev": "concurrently 'pnpm build:dev' 'nodemon -L'",
"build:dev": "node build.mjs --watch",
"build:prod": "NODE_ENV=production node ./build.mjs",
"lint": "pnpm eslint .",
"pretty": "pnpm prettier --write \"src/**/*.ts\"",
"clean-install": "rm -rf ./node_modules && pnpm install --frozen-lockfile"
},
"keywords": [
"whatsapp-cloud-api",
"whatsapp-chatbot",
"whatsapp-api",
"typescript",
"nodejs",
"@wapijs/wapi.js",
"wapi.js SDK"
],
"authors": [
"sarthak@softlancer.co"
],
"devDependencies": {
"@esbuild-plugins/tsconfig-paths": "^0.1.2",
"@types/node": "^20.10.2",
"@wapijs/eslint-config": "workspace:*",
"@wapijs/prettier-config": "workspace:*",
"@wapijs/typescript-config": "workspace:*",
"concurrently": "^8.2.1",
"esbuild": "^0.19.8",
"esbuild-node-externals": "^1.11.0",
"esbuild-plugin-tsc": "^0.4.0",
"nodemon": "^3.0.2",
"typescript": "5.4.5"
},
"packageManager": "pnpm@9.1.0",
"dependencies": {
"@wapijs/wapi.js": "workspace:*",
"dotenv": "^16.3.1"
},
"publishConfig": {
"access": "restricted"
}
}
4 changes: 4 additions & 0 deletions apps/example-chat-bot/src/constant.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const WHATSAPP_BUSINESS_ACCOUNT_ID = process.env.WHATSAPP_BUSINESS_ACCOUNT_ID
export const WHATSAPP_API_ACCESS_TOKEN = process.env.WHATSAPP_API_ACCESS_TOKEN
export const WHATSAPP_PHONE_NUMBER_ID = process.env.WHATSAPP_PHONE_NUMBER_ID
export const WHATSAPP_WEBHOOK_SECRET = process.env.WHATSAPP_WEBHOOK_SECRET
122 changes: 122 additions & 0 deletions apps/example-chat-bot/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import { whatsappClient } from './utils/client'
import { ListInteractionMessage, TextMessage } from '@wapijs/wapi.js'

function init() {
whatsappClient.on('Ready', () => {
console.log('Client is ready')
})

const faq = {
'What is wapijs': [
{
question: 'What is wapi.js?',
answer: 'wapi.js is a Tyepscript SDK for building WhatsApp chatbots.'
},
{
question: 'Main features of wapi.js?',
answer: 'Object-oriented design, single client, easy messaging, event handling, media upload.'
},
{
question: 'Can I build AI chatbots with wapi.js?',
answer: "wapi.js itself doesn't have AI, but you can integrate with NLU services."
}
],
'Getting Started': [
{
question: 'How do I get started with wapi.js?',
answer: 'Check out the docs at https://javascript.wapikit.com/ and use the "create-wapi-app" template.'
},
{
question: 'Is wapi.js easy to learn?',
answer: 'Yes, designed for all levels. Docs and examples help you get started quickly.'
}
],
Capabilities: [
{
question: 'What kind of chatbots can I build?',
answer: 'Customer support, marketing, notifications, and more! Leverage WhatsApp Business API.'
},
{
question: 'Can I integrate wapi.js with other systems?',
answer: 'Absolutely! Integrate with existing backend system.'
},
{
question: 'Are there examples of chatbots built with wapi.js?',
answer: "It's in beta, so not many yet. Be among the first to build and share yours!"
}
],
'Help & Support': [
{
question: 'Is wapi.js free and open-source?',
answer: "Yes, it's completely free and open-source under the AGPL 3.0 License."
},
{
question: 'Where can I get help or support for wapi.js?',
answer: 'Create an issue on our GitHub repository: https://github.com/sarthakjdev/wapi.js/issues.'
}
]
}

const listMessage = new ListInteractionMessage({
bodyText: 'Welcome to Wapi.js',
buttonText: 'Ask questions',
footerText: 'Beta version',
sections: Object.keys(faq).map((section, sectionIndex) => {
return {
// @ts-ignore
rows: faq[section].map((question, index) => {
return {
description: question.question,
id: `section-${sectionIndex + 1}-question-${index + 1}`,
title: `FAQ ${index + 1}`
}
}),
title: section
}
})
})

whatsappClient.on('Error', error => {
console.log('Error', error.message)
})

whatsappClient.on('TextMessage', async message => {
console.log('Text Message')
if (message.text.data.text.toLowerCase() === 'hello') {
const response = await message.client.message.send({
message: listMessage,
phoneNumber: message.context.from
})
console.log({ response })
} else {
await message.reply({
message: new TextMessage({
text: 'Please say "hello" to proceed.'
})
})
}
})

whatsappClient.on('ListInteraction', async message => {
console.log('List Interaction', message)

// it would be something like : section-1-question-1
const messageListId = message.listId

const sectionIndex = parseInt(messageListId.split('-')[1]) - 1
const questionIndex = parseInt(messageListId.split('-')[3]) - 1

// @ts-ignore
const answerToReply = faq[Object.keys(faq)[sectionIndex]][questionIndex].answer

await message.reply({
message: new TextMessage({
text: answerToReply
})
})
})

whatsappClient.initiate()
}

init()
Binary file added apps/example-chat-bot/src/media.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 25 additions & 0 deletions apps/example-chat-bot/src/utils/client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Client } from '@wapijs/wapi.js'
import {
WHATSAPP_API_ACCESS_TOKEN,
WHATSAPP_BUSINESS_ACCOUNT_ID,
WHATSAPP_PHONE_NUMBER_ID,
WHATSAPP_WEBHOOK_SECRET
} from '../constant'

if (
!WHATSAPP_API_ACCESS_TOKEN ||
!WHATSAPP_BUSINESS_ACCOUNT_ID ||
!WHATSAPP_PHONE_NUMBER_ID ||
!WHATSAPP_WEBHOOK_SECRET
) {
throw new Error('Configs not defined!')
}

export const whatsappClient = new Client({
apiAccessToken: WHATSAPP_API_ACCESS_TOKEN,
businessAccountId: WHATSAPP_BUSINESS_ACCOUNT_ID,
phoneNumberId: WHATSAPP_PHONE_NUMBER_ID,
port: 8080,
webhookEndpoint: '/webhook',
webhookSecret: WHATSAPP_WEBHOOK_SECRET
})
25 changes: 25 additions & 0 deletions apps/example-chat-bot/tsconfig.base.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"extends": "@wapijs/typescript-config/node.base.json",
"compilerOptions": {
"strictNullChecks": true,
"moduleResolution": "Node10",
"pretty": true,
"allowUnreachableCode": false,
"allowJs": true,
"strict": true,
"declaration": true,
"resolveJsonModule": true,
"declarationMap": false,
"newLine": "lf",
"outDir": "dist",
"removeComments": false,
"sourceMap": true,
"module": "CommonJS",
"target": "ESNext",
"types": ["node"],
"paths": {
"~/*": ["./src/*"],
"root/*": ["./*"]
}
}
}
13 changes: 13 additions & 0 deletions apps/example-chat-bot/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"extends": "./tsconfig.base.json",
"include": [
"**/*.ts",
"**/*.js",
"**/*.tsx",
"**/*.jsx",
"./.eslintrc.js",
"./build.mjs",
"./.prettier.js"
],
"exclude": ["node_modules", "dist/**"]
}

0 comments on commit f366e32

Please sign in to comment.