diff --git a/api.go b/api.go index 28efe22..e4c6645 100644 --- a/api.go +++ b/api.go @@ -3,20 +3,13 @@ package laniakea import ( "bytes" "encoding/json" - "errors" "fmt" "io" "net/http" "strings" ) -type ApiResponse struct { - Ok bool `json:"ok"` - Description string `json:"description,omitempty"` - Result any `json:"result,omitempty"` - ErrorCode int `json:"error_code,omitempty"` -} -type ApiResponseG[R any] struct { +type ApiResponse[R any] struct { Ok bool `json:"ok"` Description string `json:"description,omitempty"` Result R `json:"result,omitempty"` @@ -27,13 +20,9 @@ type TelegramRequest[R, P any] struct { method string params P } -type EmptyParams struct{} func NewRequest[R, P any](method string, params P) TelegramRequest[R, P] { - return TelegramRequest[R, P]{ - method: method, - params: params, - } + return TelegramRequest[R, P]{method: method, params: params} } func (r TelegramRequest[R, P]) Do(bot *Bot) (*R, error) { var buf bytes.Buffer @@ -42,6 +31,13 @@ func (r TelegramRequest[R, P]) Do(bot *Bot) (*R, error) { return nil, err } + if bot.requestLogger != nil { + bot.requestLogger.Debugln(strings.ReplaceAll(fmt.Sprintf( + "POST https://api.telegram.org/bot%s/%s %s", + "", r.method, buf.String(), + ), "\n", "")) + } + req, err := http.Post(fmt.Sprintf("https://api.telegram.org/bot%s/%s", bot.token, r.method), "application/json", &buf) if err != nil { return nil, err @@ -52,7 +48,11 @@ func (r TelegramRequest[R, P]) Do(bot *Bot) (*R, error) { return nil, err } - response := new(ApiResponseG[R]) + if bot.requestLogger != nil { + bot.requestLogger.Debugln(fmt.Sprintf("RES %s %s", r.method, string(data))) + } + + response := new(ApiResponse[R]) err = json.Unmarshal(data, &response) if err != nil { return nil, err @@ -63,53 +63,3 @@ func (r TelegramRequest[R, P]) Do(bot *Bot) (*R, error) { } return &response.Result, nil } - -// request is a low-level call to api. -func (b *Bot) request(methodName string, params any) (map[string]any, error) { - var buf bytes.Buffer - err := json.NewEncoder(&buf).Encode(params) - if err != nil { - return nil, err - } - - if b.debug && b.requestLogger != nil { - b.requestLogger.Debugln(strings.ReplaceAll(fmt.Sprintf( - "POST https://api.telegram.org/bot%s/%s %s", - "", - methodName, - buf.String(), - ), "\n", "")) - } - r, err := http.Post(fmt.Sprintf("https://api.telegram.org/bot%s/%s", b.token, methodName), "application/json", &buf) - if err != nil { - return nil, err - } - defer r.Body.Close() - data, err := io.ReadAll(r.Body) - if err != nil { - return nil, err - } - b.requestLogger.Debugln(fmt.Sprintf("RES %s %s", methodName, string(data))) - - response := new(ApiResponse) - err = json.Unmarshal(data, &response) - if err != nil { - return nil, err - } - - if !response.Ok { - return nil, fmt.Errorf("[%d] %s", response.ErrorCode, response.Description) - } - if res, ok := response.Result.(bool); ok { - return map[string]any{ - "data": res, - }, nil - } else if res, ok := response.Result.([]any); ok { - return map[string]any{ - "data": res, - }, nil - } else if res, ok := response.Result.(map[string]any); ok { - return res, nil - } - return map[string]any{}, errors.New("can't parse response") -} diff --git a/methods.go b/methods.go index 46c14ae..d2f02fe 100644 --- a/methods.go +++ b/methods.go @@ -5,31 +5,36 @@ import ( "fmt" ) -var NoParams = make(map[string]any) +type EmptyParams struct{} + +var NoParams = EmptyParams{} + +type UpdateParams struct { + Offset int `json:"offset"` + Timeout int `json:"timeout"` + AllowedUpdates []string `json:"allowed_updates"` +} func (b *Bot) Updates() ([]*Update, error) { - params := make(map[string]any) - params["offset"] = b.updateOffset - params["timeout"] = 30 - params["allowed_updates"] = b.updateTypes - - data, err := b.request("getUpdates", params) - if err != nil { - return nil, err - } - res := make([]*Update, 0) - err = AnyToStruct(data["data"], &res) - if err != nil { - return res, err + params := UpdateParams{ + Offset: b.updateOffset, + Timeout: 30, + AllowedUpdates: b.updateTypes, } - for _, u := range res { + req := NewRequest[[]*Update]("getUpdates", params) + res, err := req.Do(b) + if err != nil { + return []*Update{}, err + } + updates := *res + + for _, u := range updates { b.updateOffset = u.UpdateID + 1 err = b.updateQueue.Enqueue(u) if err != nil { - return res, err + return updates, err } - res = append(res, u) if b.debug && b.requestLogger != nil { j, err := json.Marshal(u) @@ -39,19 +44,12 @@ func (b *Bot) Updates() ([]*Update, error) { b.requestLogger.Debugln(fmt.Sprintf("UPDATE %s", j)) } } - return res, err + return updates, err } func (b *Bot) GetMe() (*User, error) { - //req := NewRequest[User, EmptyParams]("getMe", EmptyParams{}) - //user, err := req.Do(b) - data, err := b.request("getMe", NoParams) - if err != nil { - return nil, err - } - user := new(User) - err = MapToStruct(data, user) - return user, err + req := NewRequest[User, EmptyParams]("getMe", NoParams) + return req.Do(b) } type SendMessageP struct { @@ -73,14 +71,6 @@ type SendMessageP struct { func (b *Bot) SendMessage(params *SendMessageP) (*Message, error) { req := NewRequest[Message, SendMessageP]("sendMessage", *params) return req.Do(b) - - data, err := b.request("sendMessage", params) - if err != nil { - return nil, err - } - message := new(Message) - err = MapToStruct(data, message) - return message, err } type SendPhotoP struct { @@ -101,13 +91,8 @@ type SendPhotoP struct { } func (b *Bot) SendPhoto(params *SendPhotoP) (*Message, error) { - data, err := b.request("sendPhoto", params) - if err != nil { - return nil, err - } - message := new(Message) - err = MapToStruct(data, message) - return message, err + req := NewRequest[Message]("sendPhoto", params) + return req.Do(b) } type EditMessageTextP struct { @@ -121,13 +106,8 @@ type EditMessageTextP struct { } func (b *Bot) EditMessageText(params *EditMessageTextP) (*Message, error) { - data, err := b.request("editMessageText", params) - if err != nil { - return nil, err - } - message := new(Message) - err = MapToStruct(data, message) - return message, err + req := NewRequest[Message]("editMessageText", params) + return req.Do(b) } type EditMessageCaptionP struct { @@ -141,13 +121,8 @@ type EditMessageCaptionP struct { } func (b *Bot) EditMessageCaption(params *EditMessageCaptionP) (*Message, error) { - data, err := b.request("editMessageCaption", params) - if err != nil { - return nil, err - } - message := new(Message) - err = MapToStruct(data, message) - return message, err + req := NewRequest[Message]("editMessageCaption", params) + return req.Do(b) } type DeleteMessageP struct { @@ -156,11 +131,6 @@ type DeleteMessageP struct { } func (b *Bot) DeleteMessage(params *DeleteMessageP) (*Message, error) { - data, err := b.request("deleteMessage", params) - if err != nil { - return nil, err - } - message := new(Message) - err = MapToStruct(data, message) - return message, err + req := NewRequest[Message]("deleteMessage", params) + return req.Do(b) }