71 lines
2.2 KiB
Go
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
|
|
}
|