diff --git a/.github/commit_convention.md b/.github/commit_convention.md new file mode 100644 index 0000000..f796ab2 --- /dev/null +++ b/.github/commit_convention.md @@ -0,0 +1,93 @@ +# ๐Ÿ“˜ Commit and Branch Conventions + +At `wapi.js`, we follow a strict set of conventions for commit messages and branch names to ensure that our repository stays organized, and our commit history remains crystal clear. Here's a guide on our conventions: + +--- + +## ๐Ÿš€ Conventional Commits + +Conventional commits ensure our commit messages are clear and useful. + +๐Ÿ“‹ **Benefits**: +- ๐Ÿ“œ Automatic changelog generation +- ๐Ÿ”ข Simplified versioning +- ๐Ÿง Improved readability of commit messages + +### ๐Ÿ“„ Commit Message Format + +Each commit message should follow this format: + +``` +(): + + + + +``` + +- **``**: Describes the purpose of the commit: + - ๐Ÿ†• `feat`: Introduces a new feature + - ๐Ÿž `fix`: Addresses a bug + - ๐Ÿ“š `docs`: Updates documentation + - ๐ŸŽจ `style`: Code that relates to styling, not affecting logic + - ๐Ÿ”ง `refactor`: Refactoring existing code + - ๐Ÿš€ `perf`: Improving performance + - ๐Ÿงช `test`: All about tests + - ๐Ÿงฝ `chore`: Maintenance tasks + +- **``**: (Optional) Specifies which part of the codebase is affected. + +- **``**: A concise summary of the changes made. + +### ๐Ÿ“ Examples: + +1. Introducing a new feature: +``` +feat(auth): implement social login +``` + +2. Addressing a bug: +``` +fix(button): resolve alignment issue +``` + +--- + +## ๐ŸŒฒ Conventional Branching + +A standardized naming system for branches helps everyone quickly understand a branch's purpose. + +### ๐Ÿ“„ Branch Naming Format + +Branch names should adhere to: + +``` +/ +``` + +- **``**: Purpose of the branch, common ones being: + - ๐Ÿ†• `feature`: Developing a new feature. + - ๐Ÿž `fix`: Addressing a bug. + - ๐Ÿงฝ `chore`: Regular maintenance tasks. + - ๐Ÿ”ฅ `hotfix`: Immediate fixes, often tied to production issues. + - ๐Ÿ“š `docs`: Documentation enhancements. + +- **``**: A brief, kebab-cased (words separated by hyphens) description of the branch's objective. + +### ๐Ÿ“ Examples: + +1. Developing a new user dashboard: +``` +feature/user-dashboard +``` + +2. Resolving a login issue: +``` +fix/login-issue +``` + +--- + +๐Ÿ™Œ Thanks for contributing to `wapi.js`! By adhering to these conventions, we're making our repository a better place. If you're new, welcome aboard, and if you've been here, thanks for sticking around! + +--- \ No newline at end of file diff --git a/.github/label-actions.yaml b/.github/label-actions.yaml new file mode 100644 index 0000000..279419c --- /dev/null +++ b/.github/label-actions.yaml @@ -0,0 +1,5 @@ +bug: + comment: | + Thanks for pointing out this bug! + We'll take a look and see what's going on. + If you can, please give us a step-by-step on how it happens and any other info that could help. \ No newline at end of file diff --git a/.github/labels.yaml b/.github/labels.yaml new file mode 100644 index 0000000..8ca7242 --- /dev/null +++ b/.github/labels.yaml @@ -0,0 +1,12 @@ +- name: good-first-issue + color: '' +- name: level1-issue + color: '' +- name: level2-issue + color: '' +- name: level3-issue + color: '' +- name: feature + color: '' +- name: docs + color: '' \ No newline at end of file diff --git a/.github/workflows/auto-comment.yaml b/.github/workflows/auto-comment.yaml new file mode 100644 index 0000000..249f415 --- /dev/null +++ b/.github/workflows/auto-comment.yaml @@ -0,0 +1,18 @@ +name: Auto Comment on New Issue Label +# This workflow is triggered when a label is added to an issue. +on: + issues: + types: [labeled] + +jobs: + processLabelAction: + name: Process Label Action + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Process Label Action + uses: hramos/respond-to-issue-based-on-label@v2 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + configuration-path: '.github/label-actions.yml' \ No newline at end of file diff --git a/.github/workflows/staging.yml b/.github/workflows/build.yml similarity index 97% rename from .github/workflows/staging.yml rename to .github/workflows/build.yml index bca5a3b..1077129 100644 --- a/.github/workflows/staging.yml +++ b/.github/workflows/build.yml @@ -32,7 +32,7 @@ jobs: uses: actions/github-script@v5 with: script: | - const { pullRequestData: data } = await github.rest.repos.listPullRequestsAssociatedWithCommit({ + const { data: pullRequestData } = await github.rest.repos.listPullRequestsAssociatedWithCommit({ owner: context.repo.owner, repo: context.repo.repo, commit_sha: context.payload.after @@ -57,7 +57,7 @@ jobs: uses: actions/checkout@v3 - name: Install Dependencies - run: pnpm install --frozen-lockfile + run: pnpm install - name: Build the packages run: pnpm build diff --git a/.github/workflows/changelog.yaml b/.github/workflows/changelog.yaml new file mode 100644 index 0000000..c501a19 --- /dev/null +++ b/.github/workflows/changelog.yaml @@ -0,0 +1,26 @@ +name: Changelog + +on: + pull_request: + branches: + - master + +jobs: + changelog: + runs-on: ubuntu-latest + # skip this workflow if no-changelog label has been added to the pull request + if: ${{ contains( github.event.pull_request.labels.*.name, 'no-changelog') != true }} + + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Check Changelog Updated + uses: awharn/check_changelog_action@v1 + with: + header: '## Recent Changes' + file: 'CHANGELOG.md' + lerna: true + ignoreFiles: 'package.json|pnpm-lock.json|*.md' \ No newline at end of file diff --git a/.github/workflows/labeler.yaml b/.github/workflows/labeler.yaml new file mode 100644 index 0000000..e69de29 diff --git a/.github/workflows/master.yml b/.github/workflows/release.yaml similarity index 100% rename from .github/workflows/master.yml rename to .github/workflows/release.yaml diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml new file mode 100644 index 0000000..e69de29 diff --git a/.husky/commit-msg b/.husky/commit-msg index 21a2570..a18618a 100755 --- a/.husky/commit-msg +++ b/.husky/commit-msg @@ -2,7 +2,7 @@ . "$(dirname "$0")/_/husky.sh" # lint the commit as per the config defined in .commitlintrc.json -yarn commitlint --edit $1 +pnpm commitlint --edit $1 # If not a merge commit, require commit to be signed off if [ ! -e .git/MERGE_MSG ] && ! grep -q "^Signed-off-by: " "$1"; then diff --git a/.husky/pre-commit b/.husky/pre-commit index 5550854..1325c62 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -8,4 +8,4 @@ if [ "$branch" = "refs/heads/master" ]; then exit 1 fi -yarn lint-staged --quiet +pnpm lint-staged --quiet diff --git a/README.md b/README.md index 89720ce..5c45ff7 100644 --- a/README.md +++ b/README.md @@ -1,38 +1,45 @@ -
wapi.js
- - +--- -## About +## ๐Ÿ“Œ Status -Wapi.js is a javascript module written in typescript to interact with Whatsapp cloud API in a user-friendly way. +This library is currently in beta version and in work in progress state. Report issues [here](https://github.com/sarthakjdev/wapi.js/issues). -## Packages: +## ๐Ÿ“– About -- [wapi.js]('/packages/wapi.js'): A node library to interact with WhatsApp cloud API efficiently and in a user-friendly way. +Wapi.js is a JavaScript module, written in TypeScript, designed to interact with the WhatsApp cloud API in a user-friendly manner. -- [@wapijs/component-builder]('/packages/component-generator): A utility package to build WhatsApp cloud API payloads. +### Packages: -## Features : +- [**wapi.js**]('/packages/wapi.js'): Interact with WhatsApp cloud API efficiently. +- [**@wapijs/component-builder**]('/packages/component-generator): Utility to build WhatsApp cloud API payloads. -- Object- Oriented -- Single Client -- Registering phone number with WhatsApp Business account -- Send Messages -- Handle Notifications via event listeners -- Respond to notifications using event listeners +--- -


+## โœจ Features -## Installation +- Object-Oriented Architecture +- Single Client Model +- Phone number registration with WhatsApp Business +- Message Sending Capabilities +- Event Listener for Notifications +- Responding to notifications -Node.js 16 LTS version is required to use this library. +--- + +## ๐Ÿ’ป Installation + +Ensure you have Node.js 16 LTS version to use this library. ```sh npm install wapi.js @@ -40,110 +47,70 @@ yarn add wapi.js pnpm install wapi.js ``` -NOTE: This library doesn't hold any rights over the official Whatsapp Cloud API. It has been developed and will be maintained as an open-source project for the simplification of interaction with the WhatsApp cloud API, to build WhatsApp-based chat apps and for any other purpose cloud API serves. - -


- -## Usage : +> Note: This library is not affiliated with the official WhatsApp Cloud API. -Wanna start with your first WhatsApp application using Wapi.js library, check the [User Manual](./USER_MANUAL.md) +--- -


+## ๐Ÿš€ Usage -### Cloud API structures : +Kickstart your first WhatsApp application with Wapi.js. Check the [User Manual](./USER_MANUAL.md). -
+--- -For reference visit Whatsapp Docs [here](https://developers.facebook.com/docs/whatsapp/cloud-api/reference/messages) +## ๐Ÿ”— Cloud API References -
cloud API message structure
+- **Message Structures**: Refer to the WhatsApp Docs [here](https://developers.facebook.com/docs/whatsapp/cloud-api/reference/messages). -### Cloud API notification payload structure : +

+ cloud API message structure +

-
+- **Notification Payloads**: Details can be found [here](https://developers.facebook.com/docs/whatsapp/cloud-api/webhooks/components). -For reference visit WhatsApp Docs [here](https://developers.facebook.com/docs/whatsapp/cloud-api/webhooks/components) +

+ cloud-api notification structure +

-
cloud-api0notification-structure
+--- -


+## ๐Ÿงฐ Scripts -## Scripts: - -``` -pnpm run build : To build the project -pnpm run watch: To compile the project in watch mode or transpile the project -pnpm run clean-install : To clean install the modules removing the previous ones -pnpm run lint : TO check for the eslint errors -pnpm run lint:fix : To fix the fixable eslint errors +```sh +pnpm run build # Build the project +pnpm run watch # Compile in watch mode +pnpm run clean-install # Clean install modules +pnpm run lint # Check eslint errors +pnpm run lint:fix # Fix eslint errors ``` -


+--- -## Future Scopes : +## ๐ŸŒ Future Roadmap -This library is in its development and pre-release phase only. If you are using this library and facing any issues and bugs, please report us by creating an issue here, Also you can contribute to this project, by visiting [Contribution Guidelines](#contribution-guidelines) +This library is in early development. Please report bugs or issues [here](#). You're also welcome to contribute; see our [Contribution Guidelines](#contribution-guidelines). - +--- -


- -## Contribution Guidelines : - -Contributions are what makes the open-source community such an amazing place to learn, inspire, and create. Any contributions you make are **greatly appreciated**. +## ๐Ÿค Contribution Guidelines 1. Fork the Project 2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`) -3. Commit your changes (`git commit -m 'Add some AmazingFeature'`) +3. Commit changes (`git commit -m 'Add some AmazingFeature'`) 4. Push to the Branch (`git push origin feature/AmazingFeature`) 5. Open a Pull Request -Refer to this [Contributing.md](./CONTRIBUTING.md) if you have any difficulty in making a pull request - -


- -## Build the library from source : - -- After cloning the project in your local, run the following command to install the dependencies required by the project: - -```sh -pnpm install --frozen-lockfile -``` - -- Build the project using the following command: - -```sh -pnpm build -``` - -


- -## Installing Wapi.js from source for development purposes: - -1. cd to your node project where you wanna use the library. - -2. Run the following commands: - -```sh -pnpm install -pnpm link -``` - -NOTE: Make sure you have already built the library using `pnpm build` - -


+For detailed guidelines, check [Contributing.md](./CONTRIBUTING.md). -## License : +--- -Distributed under the MIT License. See [LICENSE](./LICENSE) for more information. +## ๐Ÿ“œ License -


+Distributed under the MIT License. View [LICENSE](./LICENSE). -## Contact Information: +--- -[Sarthak Jain](https://sarthakjdev.com)
-contact.sarthakjain@gmail.com
-[Twitter](https://twitter.com/sarthakjdev)
-[Linkedin](https://www.linkedin.com/in/sarthakjdev) +## ๐Ÿ“ž Contact -


+[Sarthak Jain](https://sarthakjdev.com) +Email: contact.sarthakjain@gmail.com +[Twitter](https://twitter.com/sarthakjdev) | [LinkedIn](https://www.linkedin.com/in/sarthakjdev) \ No newline at end of file diff --git a/lint-staged.config.js b/lint-staged.config.js index 6511ff3..75e083b 100644 --- a/lint-staged.config.js +++ b/lint-staged.config.js @@ -1,4 +1,4 @@ -const prettierWriteCommand = 'yarn prettier --write' +const prettierWriteCommand = 'pnpm prettier --write' // eslint-disable-next-line no-undef module.exports = { diff --git a/packages/wapi.js/CHANGELOG.md b/packages/wapi.js/CHANGELOG.md new file mode 100644 index 0000000..e69de29 diff --git a/packages/wapi.js/index.ts b/packages/wapi.js/index.ts index 030d849..312f974 100644 --- a/packages/wapi.js/index.ts +++ b/packages/wapi.js/index.ts @@ -1,8 +1,4 @@ export { Client } from './src/client/index' -export { BaseManager } from './src/manager/base' -export { BaseManagerInterface } from './src/manager/base/interface' -export { MediaManager } from './src/manager/media' -export { MediaManagerInterface } from './src/manager/media/interface' -export { PhoneNumberManagerInterface } from './src/manager/phone/interface' -export { PhoneNumberManager } from './src/manager/phone' export { Webhook } from './src/webhook' +export * from './src/manager' +export * from './src/structures' diff --git a/packages/wapi.js/src/client/index.ts b/packages/wapi.js/src/client/index.ts index deecbad..bb85c42 100644 --- a/packages/wapi.js/src/client/index.ts +++ b/packages/wapi.js/src/client/index.ts @@ -4,27 +4,31 @@ import { Webhook } from '../webhook' import { PhoneNumberManager } from '../manager/phone' import { MediaManager } from '../manager/media' import { RequestClient } from './request-client' -import { type ClientInterface } from './interface' +import { ClientStatusEnum, type ClientInterface } from './interface' +import { MessageManager } from '../manager/message' export class Client extends EventEmitter implements ClientInterface { + /** + * phone number manager to verify phone numbers for your + */ phone: PhoneNumberManager media: MediaManager webhook: Webhook requester: RequestClient - status: 'Ready' | 'Idle' | null = null + message: MessageManager + status: ClientStatusEnum | null = null readyAtTimeStamp: Date | null = null private static baseUrl = 'cloud.whatsapp.com' + private static apiVersion = 'v17.0' constructor(params: { webhookSecret: string webhookEndpoint: string apiAccessToken: string - apiVersion: string phoneNumberId: string businessAccountId: string port: number - userAgent: string }) { super() this.webhook = new Webhook({ @@ -33,22 +37,26 @@ export class Client extends EventEmitter implements ClientInterface { webhookEndpoint: params.webhookEndpoint, port: params.port }) - this.phone = new PhoneNumberManager({client: this}) + this.phone = new PhoneNumberManager({ client: this }) this.media = new MediaManager({ client: this }) + this.message = new MessageManager({ client: this }) this.requester = new RequestClient({ accessToken: params.apiAccessToken, businessAccountId: params.businessAccountId, phoneNumberId: params.phoneNumberId, client: this, host: Client.baseUrl, - apiVersion: '', - protocol: 'https', - userAgent: params.userAgent + apiVersion: Client.apiVersion, + protocol: 'https' }) } + static getClient() { + return this + } + emit(eventName: T, data: EventDataMap[T]): boolean { return super.emit(eventName, data) } @@ -74,7 +82,7 @@ export class Client extends EventEmitter implements ClientInterface { async initiate() { this.webhook.listen(() => { - this.status = 'Ready' + this.status = ClientStatusEnum.Ready this.emit('Ready', null) }) diff --git a/packages/wapi.js/src/client/interface.ts b/packages/wapi.js/src/client/interface.ts index 2400776..52be2e6 100644 --- a/packages/wapi.js/src/client/interface.ts +++ b/packages/wapi.js/src/client/interface.ts @@ -1,8 +1,9 @@ import { type EventDataMap } from '../webhook/schema' import type { RequestClient } from './request-client' -import {type PhoneNumberManager } from '../manager/phone' +import { type PhoneNumberManager } from '../manager/phone' import { type MediaManager } from '../manager/media' import { type Webhook } from '../webhook' +import { type MessageManager } from '../manager/message' import { type Client } from './index' export interface ClientInterface { @@ -10,7 +11,8 @@ export interface ClientInterface { media: MediaManager webhook: Webhook requester: RequestClient - status: 'Ready' | 'Idle' | null + message: MessageManager + status: ClientStatusEnum | null readyAtTimeStamp: Date | null getReadyAt: () => Date | null @@ -39,3 +41,8 @@ export interface RequestClientInterface { method: 'GET' | 'POST' | 'DELETE' }): Promise } + +export enum ClientStatusEnum { + Ready = 'ready', + Idle = 'idle' +} diff --git a/packages/wapi.js/src/client/request-client.ts b/packages/wapi.js/src/client/request-client.ts index 6a51354..29bc35d 100644 --- a/packages/wapi.js/src/client/request-client.ts +++ b/packages/wapi.js/src/client/request-client.ts @@ -7,7 +7,6 @@ type RequestClientConfigOptions = { businessAccountId: string apiVersion: string client: Client - userAgent: string accessToken: string } @@ -18,8 +17,8 @@ export class RequestClient { businessAccountId: string apiVersion: string client: Client - userAgent: string accessToken: string + private userAgent: string constructor(options: RequestClientConfigOptions) { this.host = options.host @@ -28,7 +27,7 @@ export class RequestClient { this.businessAccountId = options.businessAccountId this.client = options.client this.phoneNumberId = options.phoneNumberId - this.userAgent = options.userAgent + this.userAgent = '' this.accessToken = options.accessToken } diff --git a/packages/wapi.js/src/manager/index.ts b/packages/wapi.js/src/manager/index.ts new file mode 100644 index 0000000..5a01bf6 --- /dev/null +++ b/packages/wapi.js/src/manager/index.ts @@ -0,0 +1,11 @@ +export * from './base/index' +export * from './base/interface' + +export * from './media/index' +export * from './media/interface' + +export * from './phone/index' +export * from './phone/interface' + +export * from './message/index' +export * from './message/interface' diff --git a/packages/wapi.js/src/manager/message/index.ts b/packages/wapi.js/src/manager/message/index.ts index adcaafd..fd6c72c 100644 --- a/packages/wapi.js/src/manager/message/index.ts +++ b/packages/wapi.js/src/manager/message/index.ts @@ -1,8 +1,9 @@ -import { type Client } from '../../..' +import { type Client } from '../../client' +import { type BaseMessage } from '../../structures/message' import { BaseManager } from '../base' -import { type MessagerManagerInterface } from './interface' +import { type MessageManagerInterface } from './interface' -export class MessageManager extends BaseManager implements MessagerManagerInterface { +export class MessageManager extends BaseManager implements MessageManagerInterface { client: Client constructor(props: { client: Client }) { @@ -10,10 +11,14 @@ export class MessageManager extends BaseManager implements MessagerManagerInterf this.client = props.client } - async send() { - await Promise.resolve() + async send(props: { message: T; phoneNumber: string }): Promise { + const response = await this.client.requester.requestCloudApi({ + path: '/messages', + body: props.message.toJson(), + method: 'POST' + }) - return '' + return response } async read(messageId: string) { diff --git a/packages/wapi.js/src/manager/message/interface.ts b/packages/wapi.js/src/manager/message/interface.ts index a6dc907..2c467bc 100644 --- a/packages/wapi.js/src/manager/message/interface.ts +++ b/packages/wapi.js/src/manager/message/interface.ts @@ -1,10 +1,11 @@ -import { type Client } from '../../..' +import { type Client } from '../../client' +import { type BaseMessage } from '../../structures/message' import { type BaseManager } from '../base' -export interface MessagerManagerInterface extends BaseManager { +export interface MessageManagerInterface extends BaseManager { client: Client - send(props: { message: any; phoneNumber: string }): Promise + send(props: { message: T; phoneNumber: string }): Promise read(messageId: string): Promise } diff --git a/packages/wapi.js/src/manager/phone/index.ts b/packages/wapi.js/src/manager/phone/index.ts index 1b24812..070fb37 100644 --- a/packages/wapi.js/src/manager/phone/index.ts +++ b/packages/wapi.js/src/manager/phone/index.ts @@ -3,8 +3,19 @@ import { BaseManager } from '../base' import { type PhoneNumberManagerInterface } from './interface' export class PhoneNumberManager extends BaseManager implements PhoneNumberManagerInterface { - constructor(props: {client: Client}){ - super(props.client) + constructor(props: { client: Client }) { + super(props.client) + } - } + async sendVerificationCode(phoneNumber: string) { + console.log(phoneNumber) + await Promise.resolve(false) + return false + } + + async verifyCode(code: string) { + console.log(code) + await Promise.resolve(true) + return true + } } diff --git a/packages/wapi.js/src/manager/phone/interface.ts b/packages/wapi.js/src/manager/phone/interface.ts index 0a63d96..d46138f 100644 --- a/packages/wapi.js/src/manager/phone/interface.ts +++ b/packages/wapi.js/src/manager/phone/interface.ts @@ -1,3 +1,6 @@ import { type BaseManagerInterface } from '../base/interface' -export interface PhoneNumberManagerInterface extends BaseManagerInterface {} +export interface PhoneNumberManagerInterface extends BaseManagerInterface { + sendVerificationCode: (phoneNumber: string) => Promise + verifyCode: (code: string) => Promise +} diff --git a/packages/wapi.js/src/structures/audio/index.ts b/packages/wapi.js/src/structures/audio/index.ts index d80c18a..c96d14c 100644 --- a/packages/wapi.js/src/structures/audio/index.ts +++ b/packages/wapi.js/src/structures/audio/index.ts @@ -5,33 +5,38 @@ import { type z } from 'zod' import { AudioMessageConstructorParamSchemaType } from './schema' export class AudioMessage extends BaseMessage implements AudioMessageInterface { - readonly data: { id?: string | null; link?: string | null } = {} + readonly data: { mediaId?: string | null; link?: string | null } = {} private static schema = AudioMessageConstructorParamSchemaType constructor(params: z.infer) { super({ type: MessageTypeEnum.Audio }) + // parse the constructor payload for early feedback + AudioMessage.parseConstructorPayload(AudioMessage.schema, params) + if ('id' in params) { - this.data.id = params.id + this.data.mediaId = params.id } else { this.data.link = params.link } } - setId(id: string | null) { + setMediaId(id: string | null) { if (this.data.link) { // throw error saying you can either set id or a link } - this.data.id = id + this.data.mediaId = id } setLink(link: string | null) { - if (this.data.id) { + if (this.data.mediaId) { // throw error saying you can either set id or a link } this.data.link = link } + + toJson() {} } diff --git a/packages/wapi.js/src/structures/audio/interface.ts b/packages/wapi.js/src/structures/audio/interface.ts index 1d01bc8..2334cf5 100644 --- a/packages/wapi.js/src/structures/audio/interface.ts +++ b/packages/wapi.js/src/structures/audio/interface.ts @@ -1,6 +1,5 @@ import { type BaseMessageInterface } from '../message/interface' export interface AudioMessageInterface extends BaseMessageInterface { - id?: string - link?: string + data: { mediaId?: string | null; link?: string | null } } diff --git a/packages/wapi.js/src/structures/button/index.ts b/packages/wapi.js/src/structures/button/index.ts index db06791..d40225a 100644 --- a/packages/wapi.js/src/structures/button/index.ts +++ b/packages/wapi.js/src/structures/button/index.ts @@ -4,7 +4,5 @@ import { ButtonBuilderParamsSchemaType } from './schema' export class Button { private static schema = ButtonBuilderParamsSchemaType - constructor(params: z.infer) { - params - } + constructor(params: z.infer) {} } diff --git a/packages/wapi.js/src/structures/index.ts b/packages/wapi.js/src/structures/index.ts index 70051c3..37943a6 100644 --- a/packages/wapi.js/src/structures/index.ts +++ b/packages/wapi.js/src/structures/index.ts @@ -1,5 +1,4 @@ -export { AudioMessage } from './audio' -export { Button } from './button' -export { LocationMessage } from './location' -export { BaseMessage } from './message' -export { VideoMessage } from './video' +export * from './audio' +export * from './audio/interface' +export * from './text' +export * from './text/interface' diff --git a/packages/wapi.js/src/structures/message/index.ts b/packages/wapi.js/src/structures/message/index.ts index 5345517..08cabda 100644 --- a/packages/wapi.js/src/structures/message/index.ts +++ b/packages/wapi.js/src/structures/message/index.ts @@ -1,10 +1,54 @@ +import { type ZodSchema } from 'zod' import { type BaseMessageInterface } from './interface' import { type MessageTypeEnum } from './types' -export class BaseMessage implements BaseMessageInterface { +export abstract class BaseMessage implements BaseMessageInterface { type: MessageTypeEnum + id: string | null + messaging_product: 'whatsapp' + recipient_type: 'individual' + isRead: boolean + + protected static parseConstructorPayload(schema: ZodSchema, payload: any) { + const response = schema.safeParse(payload) + + if (!response.success) { + // throw error here + } + } constructor(params: { type: MessageTypeEnum }) { this.type = params.type + this.id = null + this.messaging_product = 'whatsapp' + this.recipient_type = 'individual' + this.isRead = false + } + + async reply() { + if (!this.id) { + throw new Error('Invalid context message id') + } + + await Promise.resolve(true) + + return 'sghj' + } + + setId(id: string): void { + this.id = id + } + + async markAsRead() { + if (!this.id) { + // ! TODO: throw error here + } + + await Promise.resolve(true) + return true + } + + toJson() { + return } } diff --git a/packages/wapi.js/src/structures/message/interface.ts b/packages/wapi.js/src/structures/message/interface.ts index 0d337f8..7d1dee1 100644 --- a/packages/wapi.js/src/structures/message/interface.ts +++ b/packages/wapi.js/src/structures/message/interface.ts @@ -2,4 +2,17 @@ import { type MessageTypeEnum } from './types' export interface BaseMessageInterface { type: MessageTypeEnum + id: string | null + messaging_product: 'whatsapp' + recipient_type: 'individual' + isRead: boolean + setId(id: string): void + markAsRead(): Promise + reply(): Promise + toJson(): void +} + +export enum MessageStatusEnum { + Read = 'read', + Send = 'sent' } diff --git a/packages/wapi.js/src/structures/text/index.ts b/packages/wapi.js/src/structures/text/index.ts index 7d5809a..f1364ff 100644 --- a/packages/wapi.js/src/structures/text/index.ts +++ b/packages/wapi.js/src/structures/text/index.ts @@ -3,17 +3,19 @@ import { MessageTypeEnum } from '../message/types' import { BaseMessage } from '../message' export class TextMessage extends BaseMessage implements TextMessageInterface { - readonly data: { text: string | null } + readonly data: { text: string | null; id: string | null } constructor(params: { text: string }) { super({ type: MessageTypeEnum.Text }) - this.data = { - text: params.text + text: params.text, + id: null } } setText(text: string | null) { this.data.text = text } + + toJson() {} } diff --git a/packages/wapi.js/src/structures/video/index.ts b/packages/wapi.js/src/structures/video/index.ts index 5d9fb91..d23bc99 100644 --- a/packages/wapi.js/src/structures/video/index.ts +++ b/packages/wapi.js/src/structures/video/index.ts @@ -5,9 +5,9 @@ import { BaseMessage } from '../message' export class VideoMessage extends BaseMessage implements VideoMessageInterface { readonly data: { id: string | null; link: string | null; caption?: string | undefined } - constructor(props: {id: string | null; link: string | null; caption?: string | undefined}) { + constructor(props: { id: string | null; link: string | null; caption?: string | undefined }) { super({ type: MessageTypeEnum.Video }) - this.data = {...props} + this.data = { ...props } } setId() {}