216 lines
6.6 KiB
Go
216 lines
6.6 KiB
Go
package handlers
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
|
|
"git.warky.dev/wdevs/whatshooked/pkg/utils"
|
|
"git.warky.dev/wdevs/whatshooked/pkg/whatsapp/businessapi"
|
|
"go.mau.fi/whatsmeow/types"
|
|
)
|
|
|
|
// ListCatalogs returns product catalogs for a Business API account.
|
|
// POST /api/catalogs {"account_id"}
|
|
func (h *Handlers) ListCatalogs(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodPost {
|
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
|
|
var req struct {
|
|
AccountID string `json:"account_id"`
|
|
}
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
baClient, err := h.getBusinessAPIClient(req.AccountID)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
resp, err := baClient.ListCatalogs(r.Context())
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
writeJSON(w, resp)
|
|
}
|
|
|
|
// ListProducts returns products in a specific catalog.
|
|
// POST /api/catalogs/products {"account_id","catalog_id"}
|
|
func (h *Handlers) ListProducts(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodPost {
|
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
|
|
var req struct {
|
|
AccountID string `json:"account_id"`
|
|
CatalogID string `json:"catalog_id"`
|
|
}
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if req.CatalogID == "" {
|
|
http.Error(w, "catalog_id is required", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
baClient, err := h.getBusinessAPIClient(req.AccountID)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
resp, err := baClient.ListProducts(r.Context(), req.CatalogID)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
writeJSON(w, resp)
|
|
}
|
|
|
|
// SendCatalogMessage sends a catalog message that shares the full product catalog.
|
|
// POST /api/send/catalog {"account_id","to","body_text","thumbnail_product_retailer_id"}
|
|
func (h *Handlers) SendCatalogMessage(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodPost {
|
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
|
|
var req struct {
|
|
AccountID string `json:"account_id"`
|
|
To string `json:"to"`
|
|
BodyText string `json:"body_text"`
|
|
ThumbnailProductRetailerID string `json:"thumbnail_product_retailer_id"`
|
|
}
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if req.BodyText == "" {
|
|
http.Error(w, "body_text is required", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
baClient, err := h.getBusinessAPIClient(req.AccountID)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
jid, err := types.ParseJID(utils.FormatPhoneToJID(req.To, h.config.Server.DefaultCountryCode))
|
|
if err != nil {
|
|
http.Error(w, "Invalid phone number", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if _, err := baClient.SendCatalogMessage(r.Context(), jid, req.BodyText, req.ThumbnailProductRetailerID); err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
writeJSON(w, map[string]string{"status": "ok"})
|
|
}
|
|
|
|
// SendSingleProduct sends a single-product interactive message.
|
|
// POST /api/send/product {"account_id","to","catalog_id","product_retailer_id","body_text","footer_text"}
|
|
func (h *Handlers) SendSingleProduct(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodPost {
|
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
|
|
var req struct {
|
|
AccountID string `json:"account_id"`
|
|
To string `json:"to"`
|
|
CatalogID string `json:"catalog_id"`
|
|
ProductRetailerID string `json:"product_retailer_id"`
|
|
BodyText string `json:"body_text"`
|
|
FooterText string `json:"footer_text"`
|
|
}
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if req.CatalogID == "" || req.ProductRetailerID == "" || req.BodyText == "" {
|
|
http.Error(w, "catalog_id, product_retailer_id, and body_text are required", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
baClient, err := h.getBusinessAPIClient(req.AccountID)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
jid, err := types.ParseJID(utils.FormatPhoneToJID(req.To, h.config.Server.DefaultCountryCode))
|
|
if err != nil {
|
|
http.Error(w, "Invalid phone number", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if _, err := baClient.SendSingleProduct(r.Context(), jid, req.CatalogID, req.ProductRetailerID, req.BodyText, req.FooterText); err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
writeJSON(w, map[string]string{"status": "ok"})
|
|
}
|
|
|
|
// SendProductList sends a multi-product list message (up to 30 products across up to 10 sections).
|
|
// POST /api/send/product-list {"account_id","to","header_text","body_text","footer_text","catalog_id","sections":[...]}
|
|
func (h *Handlers) SendProductList(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodPost {
|
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
|
|
var req struct {
|
|
AccountID string `json:"account_id"`
|
|
To string `json:"to"`
|
|
HeaderText string `json:"header_text"`
|
|
BodyText string `json:"body_text"`
|
|
FooterText string `json:"footer_text"`
|
|
CatalogID string `json:"catalog_id"`
|
|
Sections []businessapi.ProductListSection `json:"sections"`
|
|
}
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if req.CatalogID == "" || req.HeaderText == "" || req.BodyText == "" || len(req.Sections) == 0 {
|
|
http.Error(w, "catalog_id, header_text, body_text, and sections are required", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
baClient, err := h.getBusinessAPIClient(req.AccountID)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
jid, err := types.ParseJID(utils.FormatPhoneToJID(req.To, h.config.Server.DefaultCountryCode))
|
|
if err != nil {
|
|
http.Error(w, "Invalid phone number", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if _, err := baClient.SendProductList(r.Context(), jid, req.HeaderText, req.BodyText, req.FooterText, req.CatalogID, req.Sections); err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
writeJSON(w, map[string]string{"status": "ok"})
|
|
}
|