Skip to content
This repository was archived by the owner on Nov 6, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions CONTRIBUTING/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ Scan through our [existing issues](https://github.com/asetalias/amibot/issues) t

This describes the setup you need to test and run this application on your local computer.

#### [Node.JS](https://nodejs.org/en/download/)
#### [Bun.JS](https://bun.sh)

Amibot needs Node version 18+ -- use [`nvm`](https://github.com/nvm-sh/nvm) for easy setup.
Amibot needs Bun version 1.0.6+ -- use [`bun`](https://bun.sh) for easy setup.

#### WhatsApp Business Cloud API

Expand All @@ -61,6 +61,7 @@ Amibot uses the [WhatsApp Business Cloud API][wa-business-cloud-api] to send and
- [Setup a facebook developer account](https://developers.facebook.com/)
- [Get started with WhatsApp Business Cloud API][wa-business-cloud-api]
- Add a test number so you can interact with your local deployment of the bot.
- Authorize your actual phone number with the whatsapp test number.
- Setup a webhook for whatsapp events (once you start Amibot and ngrok).

#### [MongoDB](https://www.mongodb.com/)
Expand All @@ -74,6 +75,9 @@ or spin up an instance locally.

Make a `.env` file by copying `.env.sample` and populating the `WHATSAPP_TOKEN`, `VERIFY_TOKEN` (token used for facebook ) and other fields.

`VERIFY_TOKEN` is a keyword specified in your `.env` file which has to be matched with the `Callback Token` on the facebook developer website.

Populate the `DB_NAME` & `USER_COLLECTION_NAME` with any keyword of your choice, while the `MONGO_URL` should match with the cluster.
#### ngrok

We need to expose the local web server to the internet so we can set up a WhatsApp webhook for the Amibot instance. [ngrok][ngrok] is an easy-to-use service that lets us do just that!
Expand All @@ -85,10 +89,13 @@ Make a `.env` file by copying `.env.sample` and populating the `WHATSAPP_TOKEN`,
- Expose the local Amibot instance with `ngrok http 3000 --region us` (the region is important --
facebook currently blocks other ngrok regions.
- Use `<ngrok-url>/webhook` as the webhook URL on the Meta developer portal.
- Enable messages in the `webhook fields` section of the website.

### Project Setup -- Starting Amibot

`yarn dev` to start Amibot with live-reload (the bot will restart with each change you make to the code).
`bun dev` to start Amibot with live-reload (the bot will restart with each change you make to the code).

Simply initate chat with bot by sending `Start`

### Commit your update

Expand Down
Binary file added bun.lockb
Binary file not shown.
9 changes: 4 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,11 @@
"test": "test"
},
"scripts": {
"test": "npm run build:ts && tsc -p test/tsconfig.json && tap --ts \"test/**/*.test.ts\"",
"start": "npm run build:ts && fastify start -l info dist/app.js",
"test": "bun server.ts && tsc -p test/tsconfig.json && tap --ts \"test/**/*.test.ts\"",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"test": "bun server.ts && tsc -p test/tsconfig.json && tap --ts \"test/**/*.test.ts\"",
"test": "tsc -p test/tsconfig.json && tap --ts \"test/**/*.test.ts\"",

"start": "bun server.ts",
"build:ts": "tsc",
"watch:ts": "tsc -w",
"dev": "npm run build:ts && concurrently -k -p \"[{name}]\" -n \"TypeScript,App\" -c \"yellow.bold,cyan.bold\" \"npm:watch:ts\" \"npm:dev:start\"",
"dev:start": "fastify start --ignore-watch=.ts$ -w -l info -P dist/app.js",
"dev": "concurrently -k -p \"[{name}]\" -n \"App\" -c \"cyan.bold\" \"bun start --watch\"",
"lint": "eslint . --ext .js,.mjs,.ts --quiet",
"lint:fix": "eslint . --ext .js,.mjs,.ts --quiet --fix",
"fmt": "prettier \"./**/*.{js,mjs,ts}\" --write"
Expand All @@ -25,6 +24,7 @@
"author": "asetalias <asetalias1@gmail.com>",
"license": "MIT",
"dependencies": {
"bun-types": "^1.0.6",
"@fastify/autoload": "^5.0.0",
"@fastify/sensible": "^4.1.0",
"amizone_api": "^0.7.0",
Expand All @@ -37,7 +37,6 @@
"mongodb": "^4.7.0"
},
"devDependencies": {
"@types/node": "^18.0.0",
"@typescript-eslint/eslint-plugin": "^5.59.0",
"@typescript-eslint/parser": "^5.59.0",
"concurrently": "^8.0.1",
Expand Down
16 changes: 7 additions & 9 deletions prod.Dockerfile
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
FROM node:18-alpine as builder

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove builder build stage, instead:

  1. Start from oven/bun:alpine as before
  2. Copy first the manifest and lockfile
  3. Bun install like below
  4. Copy all assets
  5. ✔️

FROM oven/bun:alpine as builder

WORKDIR /app

COPY package.json yarn.lock ./
RUN yarn install --frozen-lockfile
COPY package.json bun.lockb ./
RUN bun install --frozen-lockfile
COPY . .
RUN yarn build:ts

FROM node:slim
FROM oven/bun:alpine

ENV NODE_ENV production
USER node

WORKDIR /app
COPY --from=builder /app/package.json /app/yarn.lock ./
RUN yarn install --frozen-lockfile --production
COPY --from=builder /app/package.json /app/bun.lockb ./
RUN bun install --frozen-lockfile --production
COPY --from=builder /app/dist ./dist

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy all files (COPY . .) since we're not building JS assets anymore


CMD ["yarn", "fastify", "start", "-a", "::", "-l", "info", "dist/app.js"]

CMD ["bun", "start"]
38 changes: 38 additions & 0 deletions server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Read the .env file.
import * as dotenv from "dotenv";
dotenv.config();

// Require the framework
import Fastify from "fastify";

// Require library to exit fastify process, gracefully (if possible)
//import closeWithGrace from "close-with-grace";

// Instantiate Fastify with some config
const app = Fastify({
logger: true,
});

// Register your application as a normal plugin.
app.register(import("./src/app"));

// delay is the number of milliseconds for the graceful close to finish

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean up commented out code

// const closeListeners = closeWithGrace({ delay: 500 }, async function ({ signal, err, manual }) {
// if (err) {
// app.log.error(err)
// }
// await app.close()
// } as closeWithGrace.CloseWithGraceAsyncCallback)

// app.addHook('onClose', async (instance, done) => {
// closeListeners.uninstall()
// done()
// })

// Start listening.
app.listen({ port: parseInt(process.env.PORT || "3000") }, (err: any) => {
if (err) {
app.log.error(err);
process.exit(1);
}
});
23 changes: 11 additions & 12 deletions src/app.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
import "dotenv/config";

import * as path from "path";
import { fastifyAutoload } from "@fastify/autoload";
import { fileURLToPath } from "url";
import * as database from "./database.js";
import { FastifyInstance } from "fastify";
import fastifySensible from "@fastify/sensible";
import root from "./routes/root.js";
import webhook from "./routes/webhook.js";

const __dirname = path.dirname(fileURLToPath(import.meta.url));

export default async function (fastify: FastifyInstance, opts: object) {
export default async function (fastify: FastifyInstance) {
// TODO: handle error and log
const [client, dbCollection] = await database.connect();

Expand All @@ -23,10 +20,12 @@ export default async function (fastify: FastifyInstance, opts: object) {
errorHandler: false,
});

// This loads all plugins defined in routes
// define your routes in one of these
fastify.register(fastifyAutoload, {
dir: path.join(__dirname, "routes"),
options: { db: dbCollection, ...opts },
//We are registering routes manually due to fastifyAutoLoad not being compatible with .ts

fastify.register(webhook, {
db: dbCollection
});
fastify.register(root, {
db: dbCollection
});
}
}
4 changes: 3 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
"moduleResolution": "nodenext",
"outDir": "dist",
"sourceMap": true,
"module": "ES2020"
"module": "NodeNext",
"types": ["bun-types"],
"lib": ["ESNext"]
},
"include": [
"src/**/*.ts"
Expand Down
Loading