Skip to content

Commit

Permalink
fix: beta launch refinements (#4)
Browse files Browse the repository at this point in the history
  • Loading branch information
sarthakjdev authored Jul 13, 2024
1 parent 5b61207 commit 65cd6fb
Show file tree
Hide file tree
Showing 24 changed files with 971 additions and 462 deletions.
23 changes: 11 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
<div align="center">
<br />
<p align="center">
<a href="https://wapijs.co"><img src="https://mintlify.s3-us-west-1.amazonaws.com/softlancer/assets/banner.svg" alt="@wapijs/Wapi.go" /></a>
<a href="https://wapijs.co"><img src="https://mintlify.s3-us-west-1.amazonaws.com/softlancer/assets/banner.svg" alt="Wapi.go" /></a>
</p>
<br />
</div>

Visit the documentation of the SDK [here](https://golang.wapikit.com)

## 📌 Status
## Status

Beta Version - This SDK is not stable right now. It is currently in beta version. Report issues [here](https://github.com/sarthakjdev/wapi.go/issues).

This SDK is part of a technical suite built to support the WhatsApp Business Application Development ecosystem. This SDK also has a Node.js version, you can check it out [here](https://sarthakjdev/wapi.js/js).

## 📖 About
## About

Wapi.go is a Golang SDK, that supports WhatsApp API products i.e., Business Management API and Cloud API
to build WhatsApp applications easily.
This SDK supports managing WhatsApp business accounts, and managing phone numbers for a WhatsApp business account which includes creating, verifying, and registering a phone number to use for messaging via cloud API and deregistering a phone number. This SDK also supports the management of message templates which includes creating new templates or updating/deleting the existing ones.

You can listen to the incoming webhook events via the inbuilt standalone HTTP server built using echo and also you can integrate the SDK within your existing backend applications using the getters for the route handlers of the webhook server.

## Features
## Features

- Supports multiple phone number messaging clients.
- Supports WhatsApp
Expand All @@ -32,7 +32,7 @@ You can listen to the incoming webhook events via the inbuilt standalone HTTP se
- Upload Media to WhatsApp servers
- Reply and React to incoming messages.

## 💻 Installation
## Installation

This assumes you already have a working Go environment, if not please see
[this page](https://golang.org/doc/install) first.
Expand All @@ -45,7 +45,7 @@ go get github.com/sarthakjdev/wapi.go

> Note: This SDK is not affiliated with the official WhatsApp Cloud API or does not act as any official solution provided the the Meta Inclusive Private Limited, this is just a open source SDK built for developers to support them in building whatsapp cloud api based chat bots easily.
## 🚀 Usage
## Usage

You can check out the example WhatsApp bot here. [Example Chatbot](./example-chat-bot/)

Expand Down Expand Up @@ -76,13 +76,13 @@ whatsappClient, err := wapi.New(wapi.ClientConfig{
})
```

## 🔗 References
## References

- **Message Structures**: Refer to the WhatsApp Docs [here](https://developers.facebook.com/docs/whatsapp/cloud-api/reference/messages).

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

## 🤝 Contribution Guidelines
## Contribution Guidelines

1. Fork the Project
2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)
Expand All @@ -96,14 +96,13 @@ For detailed guidelines, check [Contributing.md](./CONTRIBUTING.md).

- Handle errors gracefully
- Handle template and interactive messages gracefully
- Add support for more interactive messaged types like address input.
-
- Add support for more interactive message types like address input.

## 📜 License
## License

Distributed under the AGPL 3.0 License. View [LICENSE](./LICENSE).

## 📞 Contact
## Contact

- [Sarthak Jain](https://sarthakjdev.com)
- Email: sarthak@softlancer.co
Expand Down
2 changes: 1 addition & 1 deletion docs/guide/introduction.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ title: Introduction

## What is Wapi.go ?

Wapi.go is a node.js SDK that helps developers to **build whatsapp business API based app** with ease and faster. You can **build chat bots or integrate the SDK with you existing backend** to enable whatsapp based communication in your application.
Wapi.go is a golang SDK that helps developers to **build whatsapp business API based app** with ease and faster. You can **build chat bots or integrate the SDK with you existing backend** to enable whatsapp based communication in your application.

## What problems does it solves ?

Expand Down
1 change: 1 addition & 0 deletions docs/guide/references.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ title: Important Reference Links
- [Official WhatsApp Business Account Management API Docs](https://developers.facebook.com/docs/whatsapp/business-management-api)
- [API Reference](https://developers.facebook.com/docs/whatsapp/business-management-api/reference)
- [Setting Up Business Management API webhook](https://developers.facebook.com/docs/whatsapp/business-management-api/guides/set-up-webhooks)
- [Webhook Event Reference](https://developers.facebook.com/docs/graph-api/webhooks/reference/whatsapp-business-account)
- [Error Codes](https://developers.facebook.com/docs/whatsapp/business-management-api/error-codes)
- [Official WhatsApp Cloud API Docs](https://developers.facebook.com/docs/whatsapp/cloud-api)
- [Webhook Components](https://developers.facebook.com/docs/whatsapp/cloud-api/webhooks/components)
Expand Down
14 changes: 9 additions & 5 deletions internal/manager/media_manager.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package manager

import (
"net/http"
"strings"

"github.com/sarthakjdev/wapi.go/internal/request_client"
Expand All @@ -19,12 +20,15 @@ func NewMediaManager(requester request_client.RequestClient) *MediaManager {
}

// GetMediaUrlById retrieves the media URL by its ID.
func (mm *MediaManager) GetMediaUrlById(id string) {
apiRequest := mm.requester.NewApiRequest(strings.Join([]string{"media", id}, "/"), "GET")
apiRequest.Execute()

func (mm *MediaManager) GetMediaUrlById(id string) (string, error) {
apiRequest := mm.requester.NewApiRequest(strings.Join([]string{"media", id}, "/"), http.MethodGet)
response, err := apiRequest.Execute()
return response, err
}

// GetMediaIdByUrl retrieves the media ID by its URL.
func (mm *MediaManager) GetMediaIdByUrl(id string) {
func (mm *MediaManager) DeleteMedia(id string) (string, error) {
apiRequest := mm.requester.NewApiRequest(strings.Join([]string{"media", id}, "/"), http.MethodDelete)
response, err := apiRequest.Execute()
return response, err
}
5 changes: 2 additions & 3 deletions internal/manager/message_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ func NewMessageManager(requester request_client.RequestClient, phoneNumberId str
func (mm *MessageManager) Send(message components.BaseMessage, phoneNumber string) (string, error) {
body, err := message.ToJson(components.ApiCompatibleJsonConverterConfigs{
SendToPhoneNumber: phoneNumber,
// ReplyToMessageId: "wamid.HBgMOTE5NjQzNTAwNTQ1FQIAERgSQzVGOTlFMzExQ0VCQTg0MUFCAA==",
})
if err != nil {
// TODO: emit an error event here
Expand All @@ -37,6 +36,6 @@ func (mm *MessageManager) Send(message components.BaseMessage, phoneNumber strin

apiRequest := mm.requester.NewApiRequest(strings.Join([]string{mm.PhoneNumberId, "messages"}, "/"), http.MethodPost)
apiRequest.SetBody(string(body))
apiRequest.Execute()
return "ok", nil
response, err := apiRequest.Execute()
return response, err
}
1 change: 0 additions & 1 deletion internal/manager/phone_number_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ func (manager *PhoneNumberManager) Fetch(phoneNumberId string) (*WhatsappBusines
json.Unmarshal([]byte(response), &responseToReturn)

return &responseToReturn, nil

}

type CreatePhoneNumberResponse struct {
Expand Down
49 changes: 8 additions & 41 deletions internal/manager/template_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -300,53 +300,20 @@ type TemplateMessagePreviewEdge struct {
Paging internal.WhatsAppBusinessApiPaginationMeta `json:"paging,omitempty"`
}

func (tm *TemplateManager) FetchMessageTemplatePreviews() {
// https://developers.facebook.com/docs/graph-api/reference/whats-app-business-account/message_template_previews/
type TemplateMigrationResponse struct {
MigratedTemplates []string `json:"migrated_templates,omitempty"`
FailedTemplates map[string]string `json:"failed_templates,omitempty"`
}

type TemplateAnalyticsType struct {
}

type TemplatePerformanceAnalytics struct {
}

func (manager *TemplateManager) FetchPerformanceAnalytics(templateName, templateId string) (string, error) {
// /v20.0/{whats-app-business-account-id}/template_performance_metrics
// https://developers.facebook.com/docs/graph-api/reference/whats-app-business-account/template_performance_metrics/
apiRequest := manager.requester.NewApiRequest(strings.Join([]string{manager.businessAccountId, "template_performance_metrics"}, "/"), http.MethodGet)
apiRequest.AddQueryParam("name", templateName)
apiRequest.AddQueryParam("template_id", templateId)
response, err := apiRequest.Execute()

if err != nil {
return "", err
}

return response, nil
}

func (manager *TemplateManager) MigrateFromOtherBusinessAccount(sourcePageNumber int, sourceWabaId int) (string, error) {
// /{whats_app_business_account_id}/migrate_message_templates

func (manager *TemplateManager) MigrateFromOtherBusinessAccount(sourcePageNumber int, sourceWabaId int) (*TemplateMigrationResponse, error) {
apiRequest := manager.requester.NewApiRequest(strings.Join([]string{manager.businessAccountId, "migrate_message_templates"}, "/"), http.MethodGet)
apiRequest.AddQueryParam("page_number", string(sourcePageNumber))
apiRequest.AddQueryParam("source_waba_id", string(sourceWabaId))
response, err := apiRequest.Execute()

if err != nil {
return "", err
return nil, err
}

return response, nil

// Struct {
// migrated_templates: List [
// string
// ],
// failed_templates: Map {
// string: string
// },
// }

// return type
var responseToReturn TemplateMigrationResponse
json.Unmarshal([]byte(response), &responseToReturn)
return &responseToReturn, nil
}
151 changes: 148 additions & 3 deletions internal/manager/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,12 +235,157 @@ type Entry struct {
Changes []Change `json:"changes"`
}

type WebhookFieldEnum string

const (
WebhookFieldEnumAccountAlerts WebhookFieldEnum = "account_alerts"
WebhookFieldEnumMessages WebhookFieldEnum = "messages"
WebhookFieldEnumSecurity WebhookFieldEnum = "security"
WebhookFieldEnumAccountUpdate WebhookFieldEnum = "account_update"
WebhookFieldEnumAccountReview WebhookFieldEnum = "account_review"
WebhookFieldEnumBusinessCapability WebhookFieldEnum = "business_capability"
WebhookFieldEnumMessageTemplateQuality WebhookFieldEnum = "message_template_quality"
WebhookFieldEnumMessageTemplateStatus WebhookFieldEnum = "message_template_status"
WebhookFieldEnumPhoneNumberName WebhookFieldEnum = "phone_number_name"
WebhookFieldEnumPhoneNumberQuality WebhookFieldEnum = "phone_number_quality"
WebhookFieldEnumTemplateCategoryUpdate WebhookFieldEnum = "template_category"
)

type TemplateMessageStatusUpdateEventEnum string

const (
TemplateMessageStatusUpdateEventEnumApproved TemplateMessageStatusUpdateEventEnum = "APPROVED"
TemplateMessageStatusUpdateEventEnumRejected TemplateMessageStatusUpdateEventEnum = "REJECTED"
TemplateMessageStatusUpdateEventEnumFlaggedForDisabling TemplateMessageStatusUpdateEventEnum = "FLAGGED"
TemplateMessageStatusUpdateEventEnumPaused TemplateMessageStatusUpdateEventEnum = "PAUSED"
TemplateMessageStatusUpdateEventEnumPendingDeletion TemplateMessageStatusUpdateEventEnum = "PENDING_DELETION"
)

type TemplateMessageStatusUpdateDisableInfo struct {
DisableDate string `json:"disable_date"`
}

type TemplateMessageStatusUpdateOtherInfo struct {
Title string `json:"title"`
}

type TemplateMessageRejectionReasonEnum string

const (
TemplateMessageRejectionReasonEnumAbusiveContent TemplateMessageRejectionReasonEnum = "ABUSIVE_CONTENT"
TemplateMessageRejectionReasonEnumIncorrectCategory TemplateMessageRejectionReasonEnum = "INCORRECT_CATEGORY"
TemplateMessageRejectionReasonEnumInvalidFormat TemplateMessageRejectionReasonEnum = "INVALID_FORMAT"
TemplateMessageRejectionReasonEnumNone TemplateMessageRejectionReasonEnum = "NONE"
TemplateMessageRejectionReasonEnumScam TemplateMessageRejectionReasonEnum = "SCAM"
)

type TemplateStatusUpdateValue struct {
Event TemplateMessageStatusUpdateEventEnum `json:"event"`
MessageTemplateId string `json:"message_template_id"`
MessageTemplateName string `json:"message_template_name"`
MessageTemplateLanguage string `json:"message_template_language"`
Reason TemplateMessageRejectionReasonEnum `json:"reason"`
DisableInfo TemplateMessageStatusUpdateDisableInfo `json:"disable_info,omitempty"`
OtherInfo TemplateMessageStatusUpdateOtherInfo `json:"other_info,omitempty"`
}

type TemplateCategoryUpdateValue struct {
MessageTemplateId string `json:"message_template_id"`
MessageTemplateName string `json:"message_template_name"`
MessageTemplateLanguage string `json:"message_template_language"`
PreviousCategory MessageTemplateCategory `json:"previous_category"`
NewCategory MessageTemplateCategory `json:"new_category"`
CorrectCategory MessageTemplateCategory `json:"correct_category"`
}

type TemplateQualityUpdateValue struct {
PreviousQualityScore string `json:"previous_quality_score"`
NewQualityScore string `json:"new_quality_score"`
MessageTemplateId string `json:"message_template_id"`
MessageTemplateName string `json:"message_template_name"`
MessageTemplateLanguage string `json:"message_template_language"`
}

type PhoneNumberNameUpdateValue struct {
DisplayPhoneNumber string `json:"display_phone_number"`
Decision string `json:"decision"`
RequestedVerifiedName string `json:"requested_verified_name"`
RejectionReason string `json:"rejection_reason"`
}

type PhoneNumberQualityUpdateValue struct {
DisplayPhoneNumber string `json:"display_phone_number"`
Event string `json:"event"`
CurrentLimit string `json:"current_limit"`
}

type AccountAlertSeverityEnum string

const (
AccountAlertSeverityEnumCritical AccountAlertSeverityEnum = "CRITICAL"
AccountAlertSeverityEnumWarning AccountAlertSeverityEnum = "WARNING"
)

type AccountAlertsValue struct {
EntityType string `json:"entity_type"`
EntityId string `json:"entity_id"`
AlertSeverity AccountAlertSeverityEnum `json:"alert_severity"`
AlertStatus string `json:"alert_status"`
AlertType string `json:"alert_type"`
AlertDescription string `json:"alert_description"`
}

type AccountUpdateEventEnum string

type AccountUpdateBanInfo struct {
WabaBanState []string `json:"waba_ban_state"`
WabaBanDate string `json:"waba_ban_date"`
}

type AccountUpdateRestrictionInfo struct {
RestrictionType string `json:"restriction_type"`
Expiration string `json:"expiration"`
}

type AccountUpdateViolationInfo struct {
ViolationType string `json:"violation_type"`
}

const (
AccountUpdateEventEnumVerifiedAccount AccountUpdateEventEnum = "VERIFIED_ACCOUNT"
AccountUpdateEventEnumDisabledAccount AccountUpdateEventEnum = "DISABLED_UPDATE"
AccountUpdateEventEnumAccountViolation AccountUpdateEventEnum = "ACCOUNT_VIOLATION"
AccountUpdateEventEnumAccountRestriction AccountUpdateEventEnum = "ACCOUNT_RESTRICTION"
AccountUpdateEventEnumAccountDeleted AccountUpdateEventEnum = "ACCOUNT_DELETED"
AccountUpdateEventEnumPartnerRemoved AccountUpdateEventEnum = "PARTNER_REMOVED"
)

type AccountUpdateValue struct {
PhoneNumber string `json:"phone_number,omitempty"`
Event AccountUpdateEventEnum `json:"event"`
}

type AccountReviewUpdateValue struct {
Decision string `json:"decision"`
}

type BusinessCapabilityUpdateValue struct {
MaxDailyConversationPerPhone int `json:"max_daily_conversation_per_phone"`
MaxPhoneNumbersPerBusiness int `json:"max_phone_numbers_per_business"`
}

type SecurityValue struct {
DisplayPhoneNumber string `json:"display_phone_number"`
Event string `json:"event"`
Requester string `json:"requester"`
}

type Change struct {
Value Value `json:"value"`
Field string `json:"field"`
Value interface{} `json:"value"`
Field WebhookFieldEnum `json:"field"`
}

type Value struct {
type MessagesValue struct {
MessagingProduct string `json:"messaging_product"`
Metadata Metadata `json:"metadata"`
Contacts []Contact `json:"contacts,omitempty"`
Expand Down
Loading

0 comments on commit 65cd6fb

Please sign in to comment.