Files
aura-crm/production/backend/internal/clientnotify/max.go
T

71 lines
2.2 KiB
Go

package clientnotify
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"net/http"
)
// maxBaseURL isn't self-hostable like Telegram's Bot API server — MAX only
// runs platform-api2.max.ru — so there's no equivalent of TGAPIBaseURL to
// read from settings.
const maxBaseURL = "https://platform-api2.max.ru"
// buildMaxSendRequest — unlike Telegram's sendMessage, MAX's /messages
// takes chat_id as a query parameter, not a body field (verified against
// the official Go SDK's wire format, github.com/max-messenger/
// max-bot-api-client-go's messages.go), and auth is a raw
// `Authorization: <token>` header rather than the token embedded in the
// URL path.
func buildMaxSendRequest(ctx context.Context, text, botToken, chatID string) (*http.Request, error) {
payload, err := json.Marshal(map[string]string{"text": text})
if err != nil {
return nil, err
}
url := maxBaseURL + "/messages?chat_id=" + chatID
req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(payload))
if err != nil {
return nil, err
}
req.Header.Set("Authorization", botToken)
req.Header.Set("Content-Type", "application/json")
return req, nil
}
// The success and error response bodies both use a top-level "message"
// key, but with different JSON types (an object vs a string — see
// error.go in the official SDK) — decoded separately by status code rather
// than sharing one struct, which a single "message" field can't express
// for both shapes at once.
type maxSendSuccess struct {
Message struct {
Body struct {
Mid string `json:"mid"`
} `json:"body"`
} `json:"message"`
}
type maxSendError struct {
Code string `json:"code"`
Message string `json:"message"`
}
func parseMaxSendResponse(statusCode int, body io.Reader) (string, error) {
if statusCode >= 300 {
var e maxSendError
if err := json.NewDecoder(body).Decode(&e); err != nil {
return "", fmt.Errorf("max: malformed error response (status %d): %w", statusCode, err)
}
return "", fmt.Errorf("max: %s: %s", e.Code, e.Message)
}
var r maxSendSuccess
if err := json.NewDecoder(body).Decode(&r); err != nil {
return "", fmt.Errorf("max: malformed response: %w", err)
}
return r.Message.Body.Mid, nil
}