diff --git a/bot.go b/bot.go index d3cc5e9..3f1088b 100644 --- a/bot.go +++ b/bot.go @@ -16,34 +16,6 @@ import ( "go.mongodb.org/mongo-driver/v2/mongo" ) -type Bot struct { - token string - debug bool - errorTemplate string - - logger *slog.Logger - RequestLogger *slog.Logger - - plugins []Plugin - middlewares []Middleware - prefixes []string - runners []Runner - - dbContext *DatabaseContext - api *tgapi.Api - - dbWriterRequested extypes.Slice[*slog.Logger] - - updateOffset int - updateTypes []tgapi.UpdateType - updateQueue *extypes.Queue[*tgapi.Update] -} - -func (b *Bot) GetUpdateOffset() int { return b.updateOffset } -func (b *Bot) SetUpdateOffset(offset int) { b.updateOffset = offset } -func (b *Bot) GetUpdateTypes() []tgapi.UpdateType { return b.updateTypes } -func (b *Bot) GetQueue() *extypes.Queue[*tgapi.Update] { return b.updateQueue } - type BotSettings struct { Token string Debug bool @@ -74,6 +46,30 @@ func LoadPrefixesFromEnv() []string { } return strings.Split(prefixesS, ";") } + +type Bot struct { + token string + debug bool + errorTemplate string + + logger *slog.Logger + RequestLogger *slog.Logger + + plugins []Plugin + middlewares []Middleware + prefixes []string + runners []Runner + + dbContext *DatabaseContext + api *tgapi.API + + dbWriterRequested extypes.Slice[*slog.Logger] + + updateOffset int + updateTypes []tgapi.UpdateType + updateQueue *extypes.Queue[*tgapi.Update] +} + func NewBot(settings *BotSettings) *Bot { updateQueue := extypes.CreateQueue[*tgapi.Update](256) api := tgapi.NewAPI(settings.Token) @@ -141,6 +137,11 @@ func (b *Bot) Close() { } } +func (b *Bot) GetUpdateOffset() int { return b.updateOffset } +func (b *Bot) SetUpdateOffset(offset int) { b.updateOffset = offset } +func (b *Bot) GetUpdateTypes() []tgapi.UpdateType { return b.updateTypes } +func (b *Bot) GetQueue() *extypes.Queue[*tgapi.Update] { return b.updateQueue } + type DatabaseContext struct { PostgresSQL *sqlx.DB MongoDB *mongo.Client diff --git a/msg_context.go b/msg_context.go index d19274f..8ff7396 100644 --- a/msg_context.go +++ b/msg_context.go @@ -9,7 +9,7 @@ import ( type MsgContext struct { Bot *Bot - Api *tgapi.Api + Api *tgapi.API Msg *tgapi.Message Update tgapi.Update @@ -26,7 +26,6 @@ type AnswerMessage struct { MessageID int Text string IsMedia bool - Keyboard *InlineKeyboard ctx *MsgContext } diff --git a/tgapi/api.go b/tgapi/api.go index 4cda187..8e7f2c9 100644 --- a/tgapi/api.go +++ b/tgapi/api.go @@ -7,26 +7,25 @@ import ( "fmt" "io" "net/http" - "strings" "time" "git.nix13.pw/scuroneko/laniakea/utils" "git.nix13.pw/scuroneko/slog" ) -type Api struct { +type API struct { token string client *http.Client Logger *slog.Logger } -func NewAPI(token string) *Api { +func NewAPI(token string) *API { l := slog.CreateLogger().Level(utils.GetLoggerLevel()).Prefix("API") l.AddWriter(l.CreateJsonStdoutWriter()) client := &http.Client{Timeout: time.Second * 45} - return &Api{token, client, l} + return &API{token, client, l} } -func (api *Api) CloseApi() error { +func (api *API) CloseApi() error { return api.Logger.Close() } @@ -45,7 +44,7 @@ type TelegramRequest[R, P any] struct { func NewRequest[R, P any](method string, params P) TelegramRequest[R, P] { return TelegramRequest[R, P]{method: method, params: params} } -func (r TelegramRequest[R, P]) DoWithContext(ctx context.Context, api *Api) (R, error) { +func (r TelegramRequest[R, P]) DoWithContext(ctx context.Context, api *API) (R, error) { var zero R data, err := json.Marshal(r.params) if err != nil { @@ -54,12 +53,6 @@ func (r TelegramRequest[R, P]) DoWithContext(ctx context.Context, api *Api) (R, buf := bytes.NewBuffer(data) u := fmt.Sprintf("https://api.telegram.org/bot%s/%s", api.token, r.method) - if api.Logger != nil { - api.Logger.Debugln(strings.ReplaceAll(fmt.Sprintf( - "POST %s %s", u, buf.String(), - ), api.token, "")) - } - req, err := http.NewRequestWithContext(ctx, "POST", u, buf) if err != nil { return zero, err @@ -68,6 +61,7 @@ func (r TelegramRequest[R, P]) DoWithContext(ctx context.Context, api *Api) (R, req.Header.Set("Accept", "application/json") req.Header.Set("User-Agent", fmt.Sprintf("Laniakea/%s", utils.VersionString)) + api.Logger.Debugln("REQ", r.method, buf.String()) res, err := api.client.Do(req) if err != nil { return zero, err @@ -82,24 +76,20 @@ func (r TelegramRequest[R, P]) DoWithContext(ctx context.Context, api *Api) (R, if err != nil { return zero, err } - - if api.Logger != nil { - api.Logger.Debugln(fmt.Sprintf("RES %s %s", r.method, string(data))) - } + api.Logger.Debugln("RES", r.method, string(data)) var resp ApiResponse[R] err = json.Unmarshal(data, &resp) if err != nil { return zero, err } - if !resp.Ok { return zero, fmt.Errorf("[%d] %s", resp.ErrorCode, resp.Description) } return resp.Result, nil } -func (r TelegramRequest[R, P]) Do(api *Api) (R, error) { +func (r TelegramRequest[R, P]) Do(api *API) (R, error) { ctx := context.Background() return r.DoWithContext(ctx, api) } diff --git a/tgapi/attachments_methods.go b/tgapi/attachments_methods.go index 2e38771..7545e33 100644 --- a/tgapi/attachments_methods.go +++ b/tgapi/attachments_methods.go @@ -23,7 +23,7 @@ type SendPhotoP struct { ReplyMarkup *ReplyMarkup `json:"reply_markup,omitempty"` } -func (api *Api) SendPhoto(params SendPhotoP) (Message, error) { +func (api *API) SendPhoto(params SendPhotoP) (Message, error) { req := NewRequest[Message]("sendPhoto", params) return req.Do(api) } @@ -52,7 +52,7 @@ type SendAudioP struct { ReplyMarkup *ReplyMarkup `json:"reply_markup,omitempty"` } -func (api *Api) SendAudio(params SendAudioP) (Message, error) { +func (api *API) SendAudio(params SendAudioP) (Message, error) { req := NewRequest[Message]("sendAudio", params) return req.Do(api) } @@ -78,7 +78,7 @@ type SendDocumentP struct { ReplyMarkup *ReplyMarkup `json:"reply_markup,omitempty"` } -func (api *Api) SendDocument(params SendDocumentP) (Message, error) { +func (api *API) SendDocument(params SendDocumentP) (Message, error) { req := NewRequest[Message]("sendDocument", params) return req.Do(api) } @@ -113,7 +113,7 @@ type SendVideoP struct { ReplyMarkup *ReplyMarkup `json:"reply_markup,omitempty"` } -func (api *Api) SendVideo(params SendVideoP) (Message, error) { +func (api *API) SendVideo(params SendVideoP) (Message, error) { req := NewRequest[Message]("sendVideo", params) return req.Do(api) } @@ -144,7 +144,7 @@ type SendAnimationP struct { ReplyMarkup *ReplyMarkup `json:"reply_markup,omitempty"` } -func (api *Api) SendAnimation(params SendAnimationP) (Message, error) { +func (api *API) SendAnimation(params SendAnimationP) (Message, error) { req := NewRequest[Message]("sendAnimation", params) return req.Do(api) } @@ -170,7 +170,7 @@ type SendVoiceP struct { ReplyMarkup *ReplyMarkup `json:"reply_markup,omitempty"` } -func (api *Api) SendVoice(params *SendVoiceP) (Message, error) { +func (api *API) SendVoice(params *SendVoiceP) (Message, error) { req := NewRequest[Message]("sendVoice", params) return req.Do(api) } @@ -194,7 +194,7 @@ type SendVideoNoteP struct { ReplyMarkup *ReplyMarkup `json:"reply_markup,omitempty"` } -func (api *Api) SendVideoNote(params SendVideoNoteP) (Message, error) { +func (api *API) SendVideoNote(params SendVideoNoteP) (Message, error) { req := NewRequest[Message]("sendVideoNote", params) return req.Do(api) } @@ -221,7 +221,7 @@ type SendPaidMediaP struct { ReplyMarkup *ReplyMarkup `json:"reply_markup,omitempty"` } -func (api *Api) SendPaidMedia(params SendPaidMediaP) (Message, error) { +func (api *API) SendPaidMedia(params SendPaidMediaP) (Message, error) { req := NewRequest[Message]("sendPaidMedia", params) return req.Do(api) } @@ -240,7 +240,7 @@ type SendMediaGroupP struct { ReplyParameters *ReplyParameters `json:"reply_parameters,omitempty"` } -func (api *Api) SendMediaGroup(params SendMediaGroupP) (Message, error) { +func (api *API) SendMediaGroup(params SendMediaGroupP) (Message, error) { req := NewRequest[Message]("sendMediaGroup", params) return req.Do(api) } diff --git a/tgapi/bot_methods.go b/tgapi/bot_methods.go index 05741ae..2487f5e 100644 --- a/tgapi/bot_methods.go +++ b/tgapi/bot_methods.go @@ -6,7 +6,7 @@ type SetMyCommandsP struct { Language string `json:"language_code,omitempty"` } -func (api *Api) SetMyCommands(params SetMyCommandsP) (bool, error) { +func (api *API) SetMyCommands(params SetMyCommandsP) (bool, error) { req := NewRequest[bool]("setMyCommands", params) return req.Do(api) } @@ -16,7 +16,7 @@ type DeleteMyCommandsP struct { Language string `json:"language_code,omitempty"` } -func (api *Api) DeleteMyCommands(params DeleteMyCommandsP) (bool, error) { +func (api *API) DeleteMyCommands(params DeleteMyCommandsP) (bool, error) { req := NewRequest[bool]("deleteMyCommands", params) return req.Do(api) } @@ -26,7 +26,7 @@ type GetMyCommands struct { Language string `json:"language_code,omitempty"` } -func (api *Api) GetMyCommands(params GetMyCommands) ([]BotCommand, error) { +func (api *API) GetMyCommands(params GetMyCommands) ([]BotCommand, error) { req := NewRequest[[]BotCommand]("getMyCommands", params) return req.Do(api) } @@ -36,7 +36,7 @@ type SetMyName struct { Language string `json:"language_code,omitempty"` } -func (api *Api) SetMyName(params SetMyName) (bool, error) { +func (api *API) SetMyName(params SetMyName) (bool, error) { req := NewRequest[bool]("setMyName", params) return req.Do(api) } @@ -45,7 +45,7 @@ type GetMyName struct { Language string `json:"language_code,omitempty"` } -func (api *Api) GetMyName(params GetMyName) (BotName, error) { +func (api *API) GetMyName(params GetMyName) (BotName, error) { req := NewRequest[BotName]("getMyName", params) return req.Do(api) } @@ -55,7 +55,7 @@ type SetMyDescription struct { Language string `json:"language_code,omitempty"` } -func (api *Api) SetMyDescription(params SetMyDescription) (bool, error) { +func (api *API) SetMyDescription(params SetMyDescription) (bool, error) { req := NewRequest[bool]("setMyDescription", params) return req.Do(api) } @@ -64,7 +64,7 @@ type GetMyDescription struct { Language string `json:"language_code,omitempty"` } -func (api *Api) GetMyDescription(params GetMyDescription) (BotDescription, error) { +func (api *API) GetMyDescription(params GetMyDescription) (BotDescription, error) { req := NewRequest[BotDescription]("getMyDescription", params) return req.Do(api) } @@ -74,7 +74,7 @@ type SetMyShortDescription struct { Language string `json:"language_code,omitempty"` } -func (api *Api) SetMyShortDescription(params SetMyShortDescription) (bool, error) { +func (api *API) SetMyShortDescription(params SetMyShortDescription) (bool, error) { req := NewRequest[bool]("setMyShortDescription", params) return req.Do(api) } @@ -83,7 +83,7 @@ type GetMyShortDescription struct { Language string `json:"language_code,omitempty"` } -func (api *Api) GetMyShortDescription(params GetMyShortDescription) (BotShortDescription, error) { +func (api *API) GetMyShortDescription(params GetMyShortDescription) (BotShortDescription, error) { req := NewRequest[BotShortDescription]("getMyShortDescription", params) return req.Do(api) } @@ -92,11 +92,11 @@ type SetMyProfilePhotoP struct { Photo InputProfilePhoto `json:"photo"` } -func (api *Api) SetMyProfilePhoto(params SetMyProfilePhotoP) (bool, error) { +func (api *API) SetMyProfilePhoto(params SetMyProfilePhotoP) (bool, error) { req := NewRequest[bool]("setMyProfilePhoto", params) return req.Do(api) } -func (api *Api) RemoveMyProfilePhoto() (bool, error) { +func (api *API) RemoveMyProfilePhoto() (bool, error) { req := NewRequest[bool]("removeMyProfilePhoto", NoParams) return req.Do(api) } @@ -106,7 +106,7 @@ type SetChatMenuButtonP struct { MenuButton MenuButtonType `json:"menu_button"` } -func (api *Api) SetChatMenuButton(params SetChatMenuButtonP) (bool, error) { +func (api *API) SetChatMenuButton(params SetChatMenuButtonP) (bool, error) { req := NewRequest[bool]("setChatMenuButton", params) return req.Do(api) } @@ -115,7 +115,7 @@ type GetChatMenuButtonP struct { ChatID int `json:"chat_id"` } -func (api *Api) GetChatMenuButton(params GetChatMenuButtonP) (BaseMenuButton, error) { +func (api *API) GetChatMenuButton(params GetChatMenuButtonP) (BaseMenuButton, error) { req := NewRequest[BaseMenuButton]("getChatMenuButton", params) return req.Do(api) } @@ -125,7 +125,7 @@ type SetMyDefaultAdministratorRightsP struct { ForChannels bool `json:"for_channels"` } -func (api *Api) SetMyDefaultAdministratorRights(params SetMyDefaultAdministratorRightsP) (bool, error) { +func (api *API) SetMyDefaultAdministratorRights(params SetMyDefaultAdministratorRightsP) (bool, error) { req := NewRequest[bool]("setMyDefaultAdministratorRights", params) return req.Do(api) } @@ -134,12 +134,12 @@ type GetMyDefaultAdministratorRightsP struct { ForChannels bool `json:"for_channels"` } -func (api *Api) GetMyDefaultAdministratorRights(params GetMyDefaultAdministratorRightsP) (ChatAdministratorRights, error) { +func (api *API) GetMyDefaultAdministratorRights(params GetMyDefaultAdministratorRightsP) (ChatAdministratorRights, error) { req := NewRequest[ChatAdministratorRights]("getMyDefaultAdministratorRights", params) return req.Do(api) } -func (api *Api) GetAvailableGifts() (Gifts, error) { +func (api *API) GetAvailableGifts() (Gifts, error) { req := NewRequest[Gifts]("getAvailableGifts", NoParams) return req.Do(api) } @@ -154,7 +154,7 @@ type SendGiftP struct { TextEntities []MessageEntity `json:"text_entities,omitempty"` } -func (api *Api) SendGift(params SendGiftP) (bool, error) { +func (api *API) SendGift(params SendGiftP) (bool, error) { req := NewRequest[bool]("sendGift", params) return req.Do(api) } @@ -168,7 +168,7 @@ type GiftPremiumSubscriptionP struct { TextEntities []MessageEntity `json:"text_entities,omitempty"` } -func (api *Api) GiftPremiumSubscription(params GiftPremiumSubscriptionP) (bool, error) { +func (api *API) GiftPremiumSubscription(params GiftPremiumSubscriptionP) (bool, error) { req := NewRequest[bool]("giftPremiumSubscription", params) return req.Do(api) } diff --git a/tgapi/business_methods.go b/tgapi/business_methods.go index ff6792c..e06138b 100644 --- a/tgapi/business_methods.go +++ b/tgapi/business_methods.go @@ -5,7 +5,7 @@ type VerifyUserP struct { CustomDescription string `json:"custom_description,omitempty"` } -func (api *Api) VerifyUser(params VerifyUserP) (bool, error) { +func (api *API) VerifyUser(params VerifyUserP) (bool, error) { req := NewRequest[bool]("verifyUser", params) return req.Do(api) } @@ -15,7 +15,7 @@ type VerifyChatP struct { CustomDescription string `json:"custom_description,omitempty"` } -func (api *Api) VerifyChat(params VerifyChatP) (bool, error) { +func (api *API) VerifyChat(params VerifyChatP) (bool, error) { req := NewRequest[bool]("verifyChat", params) return req.Do(api) } @@ -24,7 +24,7 @@ type RemoveUserVerificationP struct { UserID int `json:"user_id"` } -func (api *Api) RemoveUserVerification(params RemoveUserVerificationP) (bool, error) { +func (api *API) RemoveUserVerification(params RemoveUserVerificationP) (bool, error) { req := NewRequest[bool]("removeUserVerification", params) return req.Do(api) } @@ -33,7 +33,7 @@ type RemoveChatVerificationP struct { ChatID int `json:"chat_id"` } -func (api *Api) RemoveChatVerification(params RemoveChatVerificationP) (bool, error) { +func (api *API) RemoveChatVerification(params RemoveChatVerificationP) (bool, error) { req := NewRequest[bool]("removeChatVerification", params) return req.Do(api) } @@ -44,7 +44,7 @@ type ReadBusinessMessageP struct { MessageID int `json:"message_id"` } -func (api *Api) ReadBusinessMessage(params ReadBusinessMessageP) (bool, error) { +func (api *API) ReadBusinessMessage(params ReadBusinessMessageP) (bool, error) { req := NewRequest[bool]("readBusinessMessage", params) return req.Do(api) } @@ -54,7 +54,7 @@ type DeleteBusinessMessageP struct { MessageIDs []int `json:"message_ids"` } -func (api *Api) DeleteBusinessMessage(params DeleteBusinessMessageP) (bool, error) { +func (api *API) DeleteBusinessMessage(params DeleteBusinessMessageP) (bool, error) { req := NewRequest[bool]("deleteBusinessMessage", params) return req.Do(api) } @@ -65,7 +65,7 @@ type SetBusinessAccountNameP struct { LastName string `json:"last_name,omitempty"` } -func (api *Api) SetBusinessAccountName(params SetBusinessAccountNameP) (bool, error) { +func (api *API) SetBusinessAccountName(params SetBusinessAccountNameP) (bool, error) { req := NewRequest[bool]("setBusinessAccountName", params) return req.Do(api) } @@ -75,7 +75,7 @@ type SetBusinessAccountUsernameP struct { Username string `json:"username,omitempty"` } -func (api *Api) SetBusinessAccountUsername(params SetBusinessAccountUsernameP) (bool, error) { +func (api *API) SetBusinessAccountUsername(params SetBusinessAccountUsernameP) (bool, error) { req := NewRequest[bool]("setBusinessAccountUsername", params) return req.Do(api) } @@ -85,7 +85,7 @@ type SetBusinessAccountBioP struct { Bio string `json:"bio,omitempty"` } -func (api *Api) SetBusinessAccountBio(params SetBusinessAccountBioP) (bool, error) { +func (api *API) SetBusinessAccountBio(params SetBusinessAccountBioP) (bool, error) { req := NewRequest[bool]("setBusinessAccountBio", params) return req.Do(api) } @@ -96,7 +96,7 @@ type SetBusinessAccountProfilePhoto struct { IsPublic bool `json:"is_public,omitempty"` } -func (api *Api) SetBusinessAccountProfilePhoto(params SetBusinessAccountProfilePhoto) (bool, error) { +func (api *API) SetBusinessAccountProfilePhoto(params SetBusinessAccountProfilePhoto) (bool, error) { req := NewRequest[bool]("setBusinessAccountProfilePhoto", params) return req.Do(api) } @@ -106,7 +106,7 @@ type RemoveBusinessAccountProfilePhotoP struct { IsPublic bool `json:"is_public,omitempty"` } -func (api *Api) RemoveBusinessAccountProfilePhoto(params RemoveBusinessAccountProfilePhotoP) (bool, error) { +func (api *API) RemoveBusinessAccountProfilePhoto(params RemoveBusinessAccountProfilePhotoP) (bool, error) { req := NewRequest[bool]("removeBusinessAccountProfilePhoto", params) return req.Do(api) } @@ -117,7 +117,7 @@ type SetBusinessAccountGiftSettingsP struct { AcceptedGiftTypes AcceptedGiftTypes `json:"accepted_gift_types"` } -func (api *Api) SetBusinessAccountGiftSettings(params SetBusinessAccountGiftSettingsP) (bool, error) { +func (api *API) SetBusinessAccountGiftSettings(params SetBusinessAccountGiftSettingsP) (bool, error) { req := NewRequest[bool]("setBusinessAccountGiftSettings", params) return req.Do(api) } @@ -126,7 +126,7 @@ type GetBusinessAccountStarBalanceP struct { BusinessConnectionID string `json:"business_connection_id"` } -func (api *Api) GetBusinessAccountStarBalance(params GetBusinessAccountStarBalanceP) (StarAmount, error) { +func (api *API) GetBusinessAccountStarBalance(params GetBusinessAccountStarBalanceP) (StarAmount, error) { req := NewRequest[StarAmount]("getBusinessAccountGiftSettings", params) return req.Do(api) } @@ -136,7 +136,7 @@ type TransferBusinessAccountStartP struct { StarCount int `json:"star_count"` } -func (api *Api) TransferBusinessAccountStart(params TransferBusinessAccountStartP) (bool, error) { +func (api *API) TransferBusinessAccountStart(params TransferBusinessAccountStartP) (bool, error) { req := NewRequest[bool]("transferBusinessAccountStart", params) return req.Do(api) } @@ -155,7 +155,7 @@ type GetBusinessAccountGiftsP struct { Limit int `json:"limit,omitempty"` } -func (api *Api) GetBusinessAccountGifts(params GetBusinessAccountGiftsP) (OwnedGifts, error) { +func (api *API) GetBusinessAccountGifts(params GetBusinessAccountGiftsP) (OwnedGifts, error) { req := NewRequest[OwnedGifts]("getBusinessAccountGifts", params) return req.Do(api) } @@ -165,7 +165,7 @@ type ConvertGiftToStarsP struct { OwnedGiftID string `json:"owned_gift_id"` } -func (api *Api) ConvertGiftToStars(params ConvertGiftToStarsP) (bool, error) { +func (api *API) ConvertGiftToStars(params ConvertGiftToStarsP) (bool, error) { req := NewRequest[bool]("convertGiftToStars", params) return req.Do(api) } @@ -177,7 +177,7 @@ type UpgradeGiftP struct { StarCount int `json:"star_count,omitempty"` } -func (api *Api) UpgradeGift(params UpgradeGiftP) (bool, error) { +func (api *API) UpgradeGift(params UpgradeGiftP) (bool, error) { req := NewRequest[bool]("upgradeGift", params) return req.Do(api) } @@ -189,7 +189,7 @@ type TransferGiftP struct { StarCount int `json:"star_count,omitempty"` } -func (api *Api) TransferGift(params TransferGiftP) (bool, error) { +func (api *API) TransferGift(params TransferGiftP) (bool, error) { req := NewRequest[bool]("transferGift", params) return req.Do(api) } @@ -208,11 +208,11 @@ type PostStoryP struct { ProtectContent bool `json:"protect_content,omitempty"` } -func (api *Api) PostStoryPhoto(params PostStoryP) (Story, error) { +func (api *API) PostStoryPhoto(params PostStoryP) (Story, error) { req := NewRequest[Story]("postStory", params) return req.Do(api) } -func (api *Api) PostStoryVideo(params PostStoryP) (Story, error) { +func (api *API) PostStoryVideo(params PostStoryP) (Story, error) { req := NewRequest[Story]("postStory", params) return req.Do(api) } @@ -226,7 +226,7 @@ type RepostStoryP struct { ProtectContent bool `json:"protect_content,omitempty"` } -func (api *Api) RepostStory(params RepostStoryP) (Story, error) { +func (api *API) RepostStory(params RepostStoryP) (Story, error) { req := NewRequest[Story]("repostStory", params) return req.Do(api) } @@ -242,7 +242,7 @@ type EditStoryP struct { Areas []StoryArea `json:"areas,omitempty"` } -func (api *Api) EditStory(params EditStoryP) (Story, error) { +func (api *API) EditStory(params EditStoryP) (Story, error) { req := NewRequest[Story]("editStory", params) return req.Do(api) } @@ -252,7 +252,7 @@ type DeleteStoryP struct { StoryID int `json:"story_id"` } -func (api *Api) DeleteStory(params DeleteStoryP) (bool, error) { +func (api *API) DeleteStory(params DeleteStoryP) (bool, error) { req := NewRequest[bool]("deleteStory", params) return req.Do(api) } diff --git a/tgapi/chat_methods.go b/tgapi/chat_methods.go index f75bee5..fc48a72 100644 --- a/tgapi/chat_methods.go +++ b/tgapi/chat_methods.go @@ -7,7 +7,7 @@ type BanChatMemberP struct { RevokeMessages bool `json:"revoke_messages,omitempty"` } -func (api *Api) BanChatMember(params BanChatMemberP) (bool, error) { +func (api *API) BanChatMember(params BanChatMemberP) (bool, error) { req := NewRequest[bool]("banChatMember", params) return req.Do(api) } @@ -18,7 +18,7 @@ type UnbanChatMemberP struct { OnlyIfBanned bool `json:"only_if_banned"` } -func (api *Api) UnbanChatMember(params UnbanChatMemberP) (bool, error) { +func (api *API) UnbanChatMember(params UnbanChatMemberP) (bool, error) { req := NewRequest[bool]("unbanChatMember", params) return req.Do(api) } @@ -31,7 +31,7 @@ type RestrictChatMemberP struct { UntilDate int `json:"until_date,omitempty"` } -func (api *Api) RestrictChatMember(params RestrictChatMemberP) (bool, error) { +func (api *API) RestrictChatMember(params RestrictChatMemberP) (bool, error) { req := NewRequest[bool]("restrictChatMember", params) return req.Do(api) } @@ -58,7 +58,7 @@ type PromoteChatMember struct { CanManageDirectMessages bool `json:"can_manage_direct_messages,omitempty"` } -func (api *Api) PromoteChatMember(params PromoteChatMember) (bool, error) { +func (api *API) PromoteChatMember(params PromoteChatMember) (bool, error) { req := NewRequest[bool]("promoteChatMember", params) return req.Do(api) } @@ -69,7 +69,7 @@ type SetChatAdministratorCustomTitleP struct { CustomTitle string `json:"custom_title"` } -func (api *Api) SetChatAdministratorCustomTitle(params SetChatAdministratorCustomTitleP) (bool, error) { +func (api *API) SetChatAdministratorCustomTitle(params SetChatAdministratorCustomTitleP) (bool, error) { req := NewRequest[bool]("setChatAdministratorCustomTitle", params) return req.Do(api) } @@ -79,7 +79,7 @@ type BanChatSenderChatP struct { SenderChatID int `json:"sender_chat_id"` } -func (api *Api) BanChatSenderChat(params BanChatSenderChatP) (bool, error) { +func (api *API) BanChatSenderChat(params BanChatSenderChatP) (bool, error) { req := NewRequest[bool]("banChatSenderChat", params) return req.Do(api) } @@ -89,7 +89,7 @@ type UnbanChatSenderChatP struct { SenderChatID int `json:"sender_chat_id"` } -func (api *Api) UnbanChatSenderChat(params BanChatSenderChatP) (bool, error) { +func (api *API) UnbanChatSenderChat(params BanChatSenderChatP) (bool, error) { req := NewRequest[bool]("unbanChatSenderChat", params) return req.Do(api) } @@ -100,7 +100,7 @@ type SetChatPermissionsP struct { UseIndependentChatPermissions bool `json:"use_independent_chat_permissions,omitempty"` } -func (api *Api) SetChatPermissions(params SetChatPermissionsP) (bool, error) { +func (api *API) SetChatPermissions(params SetChatPermissionsP) (bool, error) { req := NewRequest[bool]("setChatPermissions", params) return req.Do(api) } @@ -109,7 +109,7 @@ type ExportChatInviteLinkP struct { ChatID int `json:"chat_id"` } -func (api *Api) ExportChatInviteLink(params ExportChatInviteLinkP) (string, error) { +func (api *API) ExportChatInviteLink(params ExportChatInviteLinkP) (string, error) { req := NewRequest[string]("exportChatInviteLink", params) return req.Do(api) } @@ -122,7 +122,7 @@ type CreateChatInviteLinkP struct { CreatesJoinRequest int `json:"creates_join_request,omitempty"` } -func (api *Api) CreateChatInviteLink(params CreateChatInviteLinkP) (ChatInviteLink, error) { +func (api *API) CreateChatInviteLink(params CreateChatInviteLinkP) (ChatInviteLink, error) { req := NewRequest[ChatInviteLink]("createChatInviteLink", params) return req.Do(api) } @@ -137,7 +137,7 @@ type EditChatInviteLinkP struct { CreatesJoinRequest int `json:"creates_join_request,omitempty"` } -func (api *Api) EditChatInviteLink(params EditChatInviteLinkP) (ChatInviteLink, error) { +func (api *API) EditChatInviteLink(params EditChatInviteLinkP) (ChatInviteLink, error) { req := NewRequest[ChatInviteLink]("editChatInviteLink", params) return req.Do(api) } @@ -149,7 +149,7 @@ type CreateChatSubscriptionInviteLinkP struct { SubscriptionPrice int `json:"subscription_price,omitempty"` } -func (api *Api) CreateChatSubscriptionInviteLink(params CreateChatSubscriptionInviteLinkP) (ChatInviteLink, error) { +func (api *API) CreateChatSubscriptionInviteLink(params CreateChatSubscriptionInviteLinkP) (ChatInviteLink, error) { req := NewRequest[ChatInviteLink]("createChatSubscriptionInviteLink", params) return req.Do(api) } @@ -160,7 +160,7 @@ type EditChatSubscriptionInviteLinkP struct { Name string `json:"name,omitempty"` } -func (api *Api) EditChatSubscriptionInviteLink(params EditChatSubscriptionInviteLinkP) (ChatInviteLink, error) { +func (api *API) EditChatSubscriptionInviteLink(params EditChatSubscriptionInviteLinkP) (ChatInviteLink, error) { req := NewRequest[ChatInviteLink]("editChatSubscriptionInviteLink", params) return req.Do(api) } @@ -170,7 +170,7 @@ type RevokeChatInviteLinkP struct { InviteLink string `json:"invite_link"` } -func (api *Api) RevokeChatInviteLink(params RevokeChatInviteLinkP) (ChatInviteLink, error) { +func (api *API) RevokeChatInviteLink(params RevokeChatInviteLinkP) (ChatInviteLink, error) { req := NewRequest[ChatInviteLink]("revokeChatInviteLink", params) return req.Do(api) } @@ -180,7 +180,7 @@ type ApproveChatJoinRequestP struct { UserID int `json:"user_id"` } -func (api *Api) ApproveChatJoinRequest(params ApproveChatJoinRequestP) (bool, error) { +func (api *API) ApproveChatJoinRequest(params ApproveChatJoinRequestP) (bool, error) { req := NewRequest[bool]("approveChatJoinRequest", params) return req.Do(api) } @@ -190,12 +190,12 @@ type DeclineChatJoinRequestP struct { UserID int `json:"user_id"` } -func (api *Api) DeclineChatJoinRequest(params DeclineChatJoinRequestP) (bool, error) { +func (api *API) DeclineChatJoinRequest(params DeclineChatJoinRequestP) (bool, error) { req := NewRequest[bool]("declineChatJoinRequest", params) return req.Do(api) } -func (api *Api) SetChatPhoto() { +func (api *API) SetChatPhoto() { uploader := NewUploader(api) defer uploader.Close() } @@ -204,7 +204,7 @@ type DeleteChatPhotoP struct { ChatID int `json:"chat_id"` } -func (api *Api) DeleteChatPhoto(params DeleteChatPhotoP) (bool, error) { +func (api *API) DeleteChatPhoto(params DeleteChatPhotoP) (bool, error) { req := NewRequest[bool]("deleteChatPhoto", params) return req.Do(api) } @@ -214,7 +214,7 @@ type SetChatTitleP struct { Title string `json:"title"` } -func (api *Api) SetChatTitle(params SetChatTitleP) (bool, error) { +func (api *API) SetChatTitle(params SetChatTitleP) (bool, error) { req := NewRequest[bool]("setChatTitle", params) return req.Do(api) } @@ -224,7 +224,7 @@ type SetChatDescriptionP struct { Description string `json:"description"` } -func (api *Api) SetChatDescription(params SetChatDescriptionP) (bool, error) { +func (api *API) SetChatDescription(params SetChatDescriptionP) (bool, error) { req := NewRequest[bool]("setChatDescription", params) return req.Do(api) } @@ -236,7 +236,7 @@ type PinChatMessageP struct { DisableNotification bool `json:"disable_notification,omitempty"` } -func (api *Api) PinChatMessage(params PinChatMessageP) (bool, error) { +func (api *API) PinChatMessage(params PinChatMessageP) (bool, error) { req := NewRequest[bool]("pinChatMessage", params) return req.Do(api) } @@ -247,7 +247,7 @@ type UnpinChatMessageP struct { MessageID int `json:"message_id"` } -func (api *Api) UnpinChatMessage(params UnpinChatMessageP) (bool, error) { +func (api *API) UnpinChatMessage(params UnpinChatMessageP) (bool, error) { req := NewRequest[bool]("unpinChatMessage", params) return req.Do(api) } @@ -256,7 +256,7 @@ type UnpinAllChatMessagesP struct { ChatID int `json:"chat_id"` } -func (api *Api) UnpinAllChatMessages(params UnpinAllChatMessagesP) (bool, error) { +func (api *API) UnpinAllChatMessages(params UnpinAllChatMessagesP) (bool, error) { req := NewRequest[bool]("unpinAllChatMessages", params) return req.Do(api) } @@ -265,7 +265,7 @@ type LeaveChatP struct { ChatID int `json:"chat_id"` } -func (api *Api) LeaveChat(params LeaveChatP) (bool, error) { +func (api *API) LeaveChat(params LeaveChatP) (bool, error) { req := NewRequest[bool]("leaveChatP", params) return req.Do(api) } @@ -274,7 +274,7 @@ type GetChatP struct { ChatID int `json:"chat_id"` } -func (api *Api) GetChatP(params GetChatP) (ChatFullInfo, error) { +func (api *API) GetChatP(params GetChatP) (ChatFullInfo, error) { req := NewRequest[ChatFullInfo]("getChatP", params) return req.Do(api) } @@ -283,7 +283,7 @@ type GetChatAdministratorsP struct { ChatID int `json:"chat_id"` } -func (api *Api) GetChatAdministrators(params GetChatAdministratorsP) ([]ChatMember, error) { +func (api *API) GetChatAdministrators(params GetChatAdministratorsP) ([]ChatMember, error) { req := NewRequest[[]ChatMember]("getChatAdministrators", params) return req.Do(api) } @@ -292,7 +292,7 @@ type GetChatMembersCountP struct { ChatID int `json:"chat_id"` } -func (api *Api) GetChatMemberCount(params GetChatMembersCountP) (int, error) { +func (api *API) GetChatMemberCount(params GetChatMembersCountP) (int, error) { req := NewRequest[int]("getChatMemberCount", params) return req.Do(api) } @@ -302,7 +302,7 @@ type GetChatMemberP struct { UserID int `json:"user_id"` } -func (api *Api) GetChatMember(params GetChatMemberP) (ChatMember, error) { +func (api *API) GetChatMember(params GetChatMemberP) (ChatMember, error) { req := NewRequest[ChatMember]("getChatMember", params) return req.Do(api) } @@ -312,7 +312,7 @@ type SetChatStickerSetP struct { StickerSetName string `json:"sticker_set_name"` } -func (api *Api) SetChatStickerSet(params SetChatStickerSetP) (bool, error) { +func (api *API) SetChatStickerSet(params SetChatStickerSetP) (bool, error) { req := NewRequest[bool]("setChatStickerSet", params) return req.Do(api) } @@ -321,7 +321,7 @@ type DeleteChatStickerSetP struct { ChatID int `json:"chat_id"` } -func (api *Api) DeleteChatStickerSet(params DeleteChatStickerSetP) (bool, error) { +func (api *API) DeleteChatStickerSet(params DeleteChatStickerSetP) (bool, error) { req := NewRequest[bool]("deleteChatStickerSet", params) return req.Do(api) } @@ -331,7 +331,7 @@ type GetUserChatBoostsP struct { UserID int `json:"user_id"` } -func (api *Api) GetUserChatBoosts(params GetUserChatBoostsP) (UserChatBoosts, error) { +func (api *API) GetUserChatBoosts(params GetUserChatBoostsP) (UserChatBoosts, error) { req := NewRequest[UserChatBoosts]("getUserChatBoosts", params) return req.Do(api) } @@ -350,7 +350,7 @@ type GetChatGiftsP struct { Limit int `json:"limit,omitempty"` } -func (api *Api) GetChatGifts(params GetChatGiftsP) (OwnedGifts, error) { +func (api *API) GetChatGifts(params GetChatGiftsP) (OwnedGifts, error) { req := NewRequest[OwnedGifts]("getChatGifts", params) return req.Do(api) } diff --git a/tgapi/forum_methods.go b/tgapi/forum_methods.go index df2da3a..e098983 100644 --- a/tgapi/forum_methods.go +++ b/tgapi/forum_methods.go @@ -5,7 +5,7 @@ type BaseForumTopicP struct { MessageThreadID int `json:"message_thread_id"` } -func (api *Api) GetForumTopicIconSet() ([]Sticker, error) { +func (api *API) GetForumTopicIconSet() ([]Sticker, error) { req := NewRequest[[]Sticker]("getForumTopicIconSet", NoParams) return req.Do(api) } @@ -17,7 +17,7 @@ type CreateForumTopicP struct { IconCustomEmojiID string `json:"icon_custom_emoji_id"` } -func (api *Api) CreateForumTopic(params CreateForumTopicP) (ForumTopic, error) { +func (api *API) CreateForumTopic(params CreateForumTopicP) (ForumTopic, error) { req := NewRequest[ForumTopic]("createForumTopic", params) return req.Do(api) } @@ -28,24 +28,24 @@ type EditForumTopicP struct { IconCustomEmojiID string `json:"icon_custom_emoji_id"` } -func (api *Api) EditForumTopic(params EditForumTopicP) (bool, error) { +func (api *API) EditForumTopic(params EditForumTopicP) (bool, error) { req := NewRequest[bool]("editForumTopic", params) return req.Do(api) } -func (api *Api) CloseForumTopic(params BaseForumTopicP) (bool, error) { +func (api *API) CloseForumTopic(params BaseForumTopicP) (bool, error) { req := NewRequest[bool]("closeForumTopic", params) return req.Do(api) } -func (api *Api) ReopenForumTopic(params BaseForumTopicP) (bool, error) { +func (api *API) ReopenForumTopic(params BaseForumTopicP) (bool, error) { req := NewRequest[bool]("reopenForumTopic", params) return req.Do(api) } -func (api *Api) DeleteForumTopic(params BaseForumTopicP) (bool, error) { +func (api *API) DeleteForumTopic(params BaseForumTopicP) (bool, error) { req := NewRequest[bool]("deleteForumTopic", params) return req.Do(api) } -func (api *Api) UnpinAllForumTopicMessages(params BaseForumTopicP) (bool, error) { +func (api *API) UnpinAllForumTopicMessages(params BaseForumTopicP) (bool, error) { req := NewRequest[bool]("unpinAllForumTopicMessages", params) return req.Do(api) } @@ -59,28 +59,28 @@ type EditGeneralForumTopicP struct { Name string `json:"name"` } -func (api *Api) EditGeneralForumTopic(params EditGeneralForumTopicP) (bool, error) { +func (api *API) EditGeneralForumTopic(params EditGeneralForumTopicP) (bool, error) { req := NewRequest[bool]("editGeneralForumTopic", params) return req.Do(api) } -func (api *Api) CloseGeneralForumTopic(params BaseGeneralForumTopicP) (bool, error) { +func (api *API) CloseGeneralForumTopic(params BaseGeneralForumTopicP) (bool, error) { req := NewRequest[bool]("closeGeneralForumTopic", params) return req.Do(api) } -func (api *Api) ReopenGeneralForumTopic(params BaseGeneralForumTopicP) (bool, error) { +func (api *API) ReopenGeneralForumTopic(params BaseGeneralForumTopicP) (bool, error) { req := NewRequest[bool]("reopenGeneralForumTopic", params) return req.Do(api) } -func (api *Api) HideGeneralForumTopic(params BaseGeneralForumTopicP) (bool, error) { +func (api *API) HideGeneralForumTopic(params BaseGeneralForumTopicP) (bool, error) { req := NewRequest[bool]("hideGeneralForumTopic", params) return req.Do(api) } -func (api *Api) UnhideGeneralForumTopic(params BaseGeneralForumTopicP) (bool, error) { +func (api *API) UnhideGeneralForumTopic(params BaseGeneralForumTopicP) (bool, error) { req := NewRequest[bool]("unhideGeneralForumTopic", params) return req.Do(api) } -func (api *Api) UnpinAllGeneralForumTopicMessages(params BaseGeneralForumTopicP) (bool, error) { +func (api *API) UnpinAllGeneralForumTopicMessages(params BaseGeneralForumTopicP) (bool, error) { req := NewRequest[bool]("unpinAllGeneralForumTopicMessages", params) return req.Do(api) } diff --git a/tgapi/messages_methods.go b/tgapi/messages_methods.go index 09fc098..c17495e 100644 --- a/tgapi/messages_methods.go +++ b/tgapi/messages_methods.go @@ -20,7 +20,7 @@ type SendMessageP struct { ReplyMarkup *ReplyMarkup `json:"reply_markup,omitempty"` } -func (api *Api) SendMessage(params SendMessageP) (Message, error) { +func (api *API) SendMessage(params SendMessageP) (Message, error) { req := NewRequest[Message, SendMessageP]("sendMessage", params) return req.Do(api) } @@ -40,7 +40,7 @@ type ForwardMessageP struct { SuggestedPostParameters *SuggestedPostParameters `json:"suggested_post_parameters,omitempty"` } -func (api *Api) ForwardMessage(params ForwardMessageP) (Message, error) { +func (api *API) ForwardMessage(params ForwardMessageP) (Message, error) { req := NewRequest[Message]("forwardMessage", params) return req.Do(api) } @@ -56,7 +56,7 @@ type ForwardMessagesP struct { ProtectContent bool `json:"protect_content,omitempty"` } -func (api *Api) ForwardMessages(params ForwardMessagesP) ([]int, error) { +func (api *API) ForwardMessages(params ForwardMessagesP) ([]int, error) { req := NewRequest[[]int]("forwardMessages", params) return req.Do(api) } @@ -84,7 +84,7 @@ type CopyMessageP struct { ReplyMarkup *ReplyMarkup `json:"reply_markup,omitempty"` } -func (api *Api) CopyMessage(params CopyMessageP) (int, error) { +func (api *API) CopyMessage(params CopyMessageP) (int, error) { req := NewRequest[int]("copyMessage", params) return req.Do(api) } @@ -101,7 +101,7 @@ type CopyMessagesP struct { RemoveCaption bool `json:"remove_caption,omitempty"` } -func (api *Api) CopyMessages(params CopyMessagesP) ([]int, error) { +func (api *API) CopyMessages(params CopyMessagesP) ([]int, error) { req := NewRequest[[]int]("copyMessages", params) return req.Do(api) } @@ -129,7 +129,7 @@ type SendLocationP struct { ReplyMarkup *ReplyMarkup `json:"reply_markup,omitempty"` } -func (api *Api) SendLocation(params SendLocationP) (Message, error) { +func (api *API) SendLocation(params SendLocationP) (Message, error) { req := NewRequest[Message]("sendLocation", params) return req.Do(api) } @@ -159,7 +159,7 @@ type SendVenueP struct { ReplyMarkup *ReplyMarkup `json:"reply_markup,omitempty"` } -func (api *Api) SendVenue(params SendVenueP) (Message, error) { +func (api *API) SendVenue(params SendVenueP) (Message, error) { req := NewRequest[Message]("sendVenue", params) return req.Do(api) } @@ -185,7 +185,7 @@ type SendContactP struct { ReplyMarkup *ReplyMarkup `json:"reply_markup,omitempty"` } -func (api *Api) SendContact(params SendContactP) (Message, error) { +func (api *API) SendContact(params SendContactP) (Message, error) { req := NewRequest[Message]("sendContact", params) return req.Do(api) } @@ -219,7 +219,7 @@ type SendPollP struct { ReplyMarkup *ReplyMarkup `json:"reply_markup,omitempty"` } -func (api *Api) SendPoll(params SendPollP) (Message, error) { +func (api *API) SendPoll(params SendPollP) (Message, error) { req := NewRequest[Message]("sendPoll", params) return req.Do(api) } @@ -237,7 +237,7 @@ type SendChecklistP struct { ReplyMarkup *ReplyMarkup `json:"reply_markup,omitempty"` } -func (api *Api) SendChecklist(params SendChecklistP) (Message, error) { +func (api *API) SendChecklist(params SendChecklistP) (Message, error) { req := NewRequest[Message]("sendChecklist", params) return req.Do(api) } @@ -260,7 +260,7 @@ type SendDiceP struct { ReplyMarkup *ReplyMarkup `json:"reply_markup,omitempty"` } -func (api *Api) SendDice(params SendDiceP) (Message, error) { +func (api *API) SendDice(params SendDiceP) (Message, error) { req := NewRequest[Message]("sendDice", params) return req.Do(api) } @@ -274,7 +274,7 @@ type SendMessageDraftP struct { Entities []MessageEntity `json:"entities,omitempty"` } -func (api *Api) SendMessageDraft(params SendMessageDraftP) (bool, error) { +func (api *API) SendMessageDraft(params SendMessageDraftP) (bool, error) { req := NewRequest[bool]("sendMessageDraft", params) return req.Do(api) } @@ -286,7 +286,7 @@ type SendChatActionP struct { Action ChatActionType `json:"action"` } -func (api *Api) SendChatAction(params SendChatActionP) (bool, error) { +func (api *API) SendChatAction(params SendChatActionP) (bool, error) { req := NewRequest[bool]("sendChatAction", params) return req.Do(api) } @@ -298,7 +298,7 @@ type SetMessageReactionP struct { IsBig bool `json:"is_big,omitempty"` } -func (api *Api) SetMessageReaction(params SetMessageReactionP) (bool, error) { +func (api *API) SetMessageReaction(params SetMessageReactionP) (bool, error) { req := NewRequest[bool]("setMessageReaction", params) return req.Do(api) } @@ -317,7 +317,7 @@ type EditMessageTextP struct { // EditMessageText If inline message, first return will be zero-valued, and second will boolean // Otherwise, first return will be Message, and second false -func (api *Api) EditMessageText(params EditMessageTextP) (Message, bool, error) { +func (api *API) EditMessageText(params EditMessageTextP) (Message, bool, error) { var zero Message if params.InlineMessageID != "" { req := NewRequest[bool]("editMessageText", params) @@ -341,7 +341,7 @@ type EditMessageCaptionP struct { // EditMessageCaption If inline message, first return will be zero-valued, and second will boolean // Otherwise, first return will be Message, and second false -func (api *Api) EditMessageCaption(params EditMessageCaptionP) (Message, bool, error) { +func (api *API) EditMessageCaption(params EditMessageCaptionP) (Message, bool, error) { var zero Message if params.InlineMessageID != "" { req := NewRequest[bool]("editMessageCaption", params) @@ -364,7 +364,7 @@ type EditMessageMediaP struct { // EditMessageMedia If inline message, first return will be zero-valued, and second will boolean // Otherwise, first return will be Message, and second false -func (api *Api) EditMessageMedia(params EditMessageMediaP) (Message, bool, error) { +func (api *API) EditMessageMedia(params EditMessageMediaP) (Message, bool, error) { var zero Message if params.InlineMessageID != "" { req := NewRequest[bool]("editMessageMedia", params) @@ -393,7 +393,7 @@ type EditMessageLiveLocationP struct { // EditMessageLiveLocation If inline message, first return will be zero-valued, and second will boolean // Otherwise, first return will be Message, and second false -func (api *Api) EditMessageLiveLocation(params EditMessageLiveLocationP) (Message, bool, error) { +func (api *API) EditMessageLiveLocation(params EditMessageLiveLocationP) (Message, bool, error) { var zero Message if params.InlineMessageID != "" { req := NewRequest[bool]("editMessageLiveLocation", params) @@ -415,7 +415,7 @@ type StopMessageLiveLocationP struct { // StopMessageLiveLocation If inline message, first return will be zero-valued, and second will boolean // Otherwise, first return will be Message, and second false -func (api *Api) StopMessageLiveLocation(params StopMessageLiveLocationP) (Message, bool, error) { +func (api *API) StopMessageLiveLocation(params StopMessageLiveLocationP) (Message, bool, error) { var zero Message if params.InlineMessageID != "" { req := NewRequest[bool]("stopMessageLiveLocation", params) @@ -435,7 +435,7 @@ type EditMessageChecklistP struct { ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` } -func (api *Api) EditMessageChecklist(params EditMessageChecklistP) (Message, error) { +func (api *API) EditMessageChecklist(params EditMessageChecklistP) (Message, error) { req := NewRequest[Message]("editMessageChecklist", params) return req.Do(api) } @@ -448,7 +448,7 @@ type EditMessageReplyMarkupP struct { ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` } -func (api *Api) EditMessageReplyMarkup(params EditMessageReplyMarkupP) (Message, bool, error) { +func (api *API) EditMessageReplyMarkup(params EditMessageReplyMarkupP) (Message, bool, error) { var zero Message if params.InlineMessageID != "" { req := NewRequest[bool]("editMessageReplyMarkup", params) @@ -467,7 +467,7 @@ type StopPollP struct { InlineMessageID string `json:"inline_message_id,omitempty"` } -func (api *Api) StopPoll(params StopPollP) (Poll, error) { +func (api *API) StopPoll(params StopPollP) (Poll, error) { req := NewRequest[Poll]("stopPoll", params) return req.Do(api) } @@ -478,7 +478,7 @@ type ApproveSuggestedPostP struct { SendDate int `json:"send_date,omitempty"` } -func (api *Api) ApproveSuggestedPost(params ApproveSuggestedPostP) (bool, error) { +func (api *API) ApproveSuggestedPost(params ApproveSuggestedPostP) (bool, error) { req := NewRequest[bool]("approveSuggestedPost", params) return req.Do(api) } @@ -489,7 +489,7 @@ type DeclineSuggestedPostP struct { Comment string `json:"comment,omitempty"` } -func (api *Api) DeclineSuggestedPost(params DeclineSuggestedPostP) (bool, error) { +func (api *API) DeclineSuggestedPost(params DeclineSuggestedPostP) (bool, error) { req := NewRequest[bool]("declineSuggestedPost", params) return req.Do(api) } @@ -499,7 +499,7 @@ type DeleteMessageP struct { MessageID int `json:"message_id"` } -func (api *Api) DeleteMessage(params DeleteMessageP) (bool, error) { +func (api *API) DeleteMessage(params DeleteMessageP) (bool, error) { req := NewRequest[bool]("deleteMessage", params) return req.Do(api) } @@ -509,7 +509,7 @@ type DeleteMessagesP struct { MessageIDs []int `json:"message_ids"` } -func (api *Api) DeleteMessages(params DeleteMessagesP) (bool, error) { +func (api *API) DeleteMessages(params DeleteMessagesP) (bool, error) { req := NewRequest[bool]("deleteMessages", params) return req.Do(api) } @@ -522,7 +522,7 @@ type AnswerCallbackQueryP struct { CacheTime int `json:"cache_time,omitempty"` } -func (api *Api) AnswerCallbackQuery(params AnswerCallbackQueryP) (bool, error) { +func (api *API) AnswerCallbackQuery(params AnswerCallbackQueryP) (bool, error) { req := NewRequest[bool]("answerCallbackQuery", params) return req.Do(api) } diff --git a/tgapi/methods.go b/tgapi/methods.go index 9c20e88..bf0635f 100644 --- a/tgapi/methods.go +++ b/tgapi/methods.go @@ -19,19 +19,19 @@ type UpdateParams struct { AllowedUpdates []UpdateType `json:"allowed_updates"` } -func (api *Api) GetMe() (User, error) { +func (api *API) GetMe() (User, error) { req := NewRequest[User, EmptyParams]("getMe", NoParams) return req.Do(api) } -func (api *Api) LogOut() (bool, error) { +func (api *API) LogOut() (bool, error) { req := NewRequest[bool, EmptyParams]("logOut", NoParams) return req.Do(api) } -func (api *Api) Close() (bool, error) { +func (api *API) Close() (bool, error) { req := NewRequest[bool, EmptyParams]("close", NoParams) return req.Do(api) } -func (api *Api) GetUpdates(params UpdateParams) ([]Update, error) { +func (api *API) GetUpdates(params UpdateParams) ([]Update, error) { req := NewRequest[[]Update]("getUpdates", params) return req.Do(api) } @@ -40,7 +40,7 @@ type GetFileP struct { FileId string `json:"file_id"` } -func (api *Api) GetFile(params GetFileP) (File, error) { +func (api *API) GetFile(params GetFileP) (File, error) { req := NewRequest[File]("getFile", params) return req.Do(api) } diff --git a/tgapi/stickers_methods.go b/tgapi/stickers_methods.go index 99feeb8..abf6390 100644 --- a/tgapi/stickers_methods.go +++ b/tgapi/stickers_methods.go @@ -14,7 +14,7 @@ type SendStickerP struct { MessageEffectID string `json:"message_effect_id,omitempty"` } -func (api *Api) SendSticker(params SendStickerP) (Message, error) { +func (api *API) SendSticker(params SendStickerP) (Message, error) { req := NewRequest[Message]("sendSticker", params) return req.Do(api) } @@ -23,7 +23,7 @@ type GetStickerSetP struct { Name string `json:"name"` } -func (api *Api) GetStickerSet(params GetStickerSetP) (StickerSet, error) { +func (api *API) GetStickerSet(params GetStickerSetP) (StickerSet, error) { req := NewRequest[StickerSet]("getStickerSet", params) return req.Do(api) } @@ -32,7 +32,7 @@ type GetCustomEmojiStickersP struct { CustomEmojiIDs []string `json:"custom_emoji_ids"` } -func (api *Api) GetCustomEmojiStickers(params GetCustomEmojiStickersP) ([]Sticker, error) { +func (api *API) GetCustomEmojiStickers(params GetCustomEmojiStickersP) ([]Sticker, error) { req := NewRequest[[]Sticker]("getCustomEmojiStickers", params) return req.Do(api) } @@ -47,7 +47,7 @@ type CreateNewStickerSetP struct { NeedsRepainting bool `json:"needs_repainting,omitempty"` } -func (api *Api) CreateNewStickerSet(params CreateNewStickerSetP) (bool, error) { +func (api *API) CreateNewStickerSet(params CreateNewStickerSetP) (bool, error) { req := NewRequest[bool]("createNewStickerSet", params) return req.Do(api) } @@ -58,7 +58,7 @@ type AddStickerToSetP struct { Sticker InputSticker `json:"sticker"` } -func (api *Api) AddStickerToSet(params AddStickerToSetP) (bool, error) { +func (api *API) AddStickerToSet(params AddStickerToSetP) (bool, error) { req := NewRequest[bool]("addStickerToSet", params) return req.Do(api) } @@ -68,7 +68,7 @@ type SetStickerPositionInSetP struct { Position int `json:"position"` } -func (api *Api) SetStickerPosition(params SetStickerPositionInSetP) (bool, error) { +func (api *API) SetStickerPosition(params SetStickerPositionInSetP) (bool, error) { req := NewRequest[bool]("setStickerPosition", params) return req.Do(api) } @@ -77,7 +77,7 @@ type DeleteStickerFromSetP struct { Sticker string `json:"sticker"` } -func (api *Api) DeleteStickerFromSet(params DeleteStickerFromSetP) (bool, error) { +func (api *API) DeleteStickerFromSet(params DeleteStickerFromSetP) (bool, error) { req := NewRequest[bool]("deleteStickerFromSet", params) return req.Do(api) } @@ -89,7 +89,7 @@ type ReplaceStickerInSetP struct { Sticker InputSticker `json:"sticker"` } -func (api *Api) ReplaceStickerInSet(params ReplaceStickerInSetP) (bool, error) { +func (api *API) ReplaceStickerInSet(params ReplaceStickerInSetP) (bool, error) { req := NewRequest[bool]("replaceStickerInSet", params) return req.Do(api) } @@ -99,7 +99,7 @@ type SetStickerEmojiListP struct { EmojiList []string `json:"emoji_list"` } -func (api *Api) SetStickerEmojiList(params SetStickerEmojiListP) (bool, error) { +func (api *API) SetStickerEmojiList(params SetStickerEmojiListP) (bool, error) { req := NewRequest[bool]("setStickerEmojiList", params) return req.Do(api) } @@ -109,7 +109,7 @@ type SetStickerKeywordsP struct { Keywords []string `json:"keywords"` } -func (api *Api) SetStickerKeywords(params SetStickerKeywordsP) (bool, error) { +func (api *API) SetStickerKeywords(params SetStickerKeywordsP) (bool, error) { req := NewRequest[bool]("setStickerKeywords", params) return req.Do(api) } @@ -119,7 +119,7 @@ type SetStickerMaskPositionP struct { MaskPosition *MaskPosition `json:"mask_position,omitempty"` } -func (api *Api) SetStickerMaskPosition(params SetStickerMaskPositionP) (bool, error) { +func (api *API) SetStickerMaskPosition(params SetStickerMaskPositionP) (bool, error) { req := NewRequest[bool]("setStickerMaskPosition", params) return req.Do(api) } @@ -129,7 +129,7 @@ type SetStickerSetTitleP struct { Title string `json:"title"` } -func (api *Api) SetStickerSetTitle(params SetStickerSetTitleP) (bool, error) { +func (api *API) SetStickerSetTitle(params SetStickerSetTitleP) (bool, error) { req := NewRequest[bool]("setStickerSetTitle", params) return req.Do(api) } @@ -141,7 +141,7 @@ type SetStickerSetThumbnailP struct { Format InputStickerFormat `json:"format"` } -func (api *Api) SetStickerSetThumbnail(params SetStickerSetThumbnailP) (bool, error) { +func (api *API) SetStickerSetThumbnail(params SetStickerSetThumbnailP) (bool, error) { req := NewRequest[bool]("setStickerSetThumbnail", params) return req.Do(api) } @@ -151,7 +151,7 @@ type SetCustomEmojiStickerSetThumbnailP struct { CustomEmojiID string `json:"custom_emoji_id,omitempty"` } -func (api *Api) SetCustomEmojiStickerSetThumbnail(params SetStickerSetThumbnailP) (bool, error) { +func (api *API) SetCustomEmojiStickerSetThumbnail(params SetStickerSetThumbnailP) (bool, error) { req := NewRequest[bool]("setCustomEmojiStickerSetThumbnail", params) return req.Do(api) } @@ -160,7 +160,7 @@ type DeleteStickerSetP struct { Name string `json:"name"` } -func (api *Api) DeleteStickerSet(params DeleteStickerSetP) (bool, error) { +func (api *API) DeleteStickerSet(params DeleteStickerSetP) (bool, error) { req := NewRequest[bool]("deleteStickerSet", params) return req.Do(api) } diff --git a/tgapi/uploader_api.go b/tgapi/uploader_api.go new file mode 100644 index 0000000..d1aa164 --- /dev/null +++ b/tgapi/uploader_api.go @@ -0,0 +1,150 @@ +package tgapi + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "io" + "mime/multipart" + "net/http" + "path/filepath" + + "git.nix13.pw/scuroneko/laniakea/utils" + "git.nix13.pw/scuroneko/slog" +) + +const ( + UploaderPhotoType UploaderFileType = "photo" + UploaderVideoType UploaderFileType = "video" + UploaderAudioType UploaderFileType = "audio" + UploaderDocumentType UploaderFileType = "document" + UploaderVoiceType UploaderFileType = "voice" + UploaderVideoNoteType UploaderFileType = "video_note" + UploaderThumbnailType UploaderFileType = "thumbnail" +) + +type UploaderFileType string +type UploaderFile struct { + filename string + data []byte + field UploaderFileType +} + +func NewUploaderFile(name string, data []byte) UploaderFile { + t := uploaderTypeByExt(name) + return UploaderFile{filename: name, data: data, field: t} +} + +// SetType used when auto-detect failed. +// i.e. you sending a voice message, but it detects as audio, or if you send audio with thumbnail +func (f UploaderFile) SetType(t UploaderFileType) UploaderFile { + f.field = t + return f +} + +type Uploader struct { + api *API + logger *slog.Logger +} + +func NewUploader(api *API) *Uploader { + logger := slog.CreateLogger().Level(utils.GetLoggerLevel()).Prefix("UPLOADER") + logger.AddWriter(logger.CreateJsonStdoutWriter()) + return &Uploader{api, logger} +} +func (u *Uploader) Close() error { return u.logger.Close() } + +type UploaderRequest[R, P any] struct { + method string + files []UploaderFile + params P +} + +func NewUploaderRequest[R, P any](method string, params P, files ...UploaderFile) UploaderRequest[R, P] { + return UploaderRequest[R, P]{method, files, params} +} +func (u UploaderRequest[R, P]) DoWithContext(ctx context.Context, up *Uploader) (R, error) { + var zero R + url := fmt.Sprintf("https://api.telegram.org/bot%s/%s", up.api.token, u.method) + + buf := bytes.NewBuffer(nil) + w := multipart.NewWriter(buf) + + for _, file := range u.files { + fw, err := w.CreateFormFile(string(file.field), file.filename) + if err != nil { + _ = w.Close() + return zero, err + } + _, err = fw.Write(file.data) + if err != nil { + _ = w.Close() + return zero, err + } + } + + err := utils.Encode(w, u.params) + if err != nil { + _ = w.Close() + return zero, err + } + err = w.Close() + if err != nil { + return zero, err + } + + req, err := http.NewRequestWithContext(ctx, "POST", url, buf) + if err != nil { + return zero, err + } + req.Header.Set("Content-Type", w.FormDataContentType()) + req.Header.Set("Accept", "application/json") + req.Header.Set("User-Agent", fmt.Sprintf("Laniakea/%s", utils.VersionString)) + + up.logger.Debugln("UPLOADER REQ", u.method) + res, err := up.api.client.Do(req) + if err != nil { + return zero, err + } + defer res.Body.Close() + if res.StatusCode != http.StatusOK { + return zero, fmt.Errorf("unexpected status code: %d", res.StatusCode) + } + + reader := io.LimitReader(res.Body, 10<<20) + body, err := io.ReadAll(reader) + if err != nil { + return zero, err + } + up.logger.Debugln("UPLOADER RES", u.method, string(body)) + + var resp ApiResponse[R] + err = json.Unmarshal(body, &resp) + if err != nil { + return zero, err + } + if !resp.Ok { + return zero, fmt.Errorf("[%d] %s", resp.ErrorCode, resp.Description) + } + return resp.Result, nil +} +func (u UploaderRequest[R, P]) Do(up *Uploader) (R, error) { + return u.DoWithContext(context.Background(), up) +} + +func uploaderTypeByExt(filename string) UploaderFileType { + ext := filepath.Ext(filename) + switch ext { + case ".jpg", ".jpeg", ".png", ".webp", ".bmp": + return UploaderPhotoType + case ".mp4": + return UploaderVideoType + case ".mp3", ".m4a": + return UploaderAudioType + case ".ogg": + return UploaderVoiceType + default: + return UploaderDocumentType + } +} diff --git a/tgapi/uploader.go b/tgapi/uploader_methods.go similarity index 72% rename from tgapi/uploader.go rename to tgapi/uploader_methods.go index 7062503..835faf4 100644 --- a/tgapi/uploader.go +++ b/tgapi/uploader_methods.go @@ -1,139 +1,5 @@ package tgapi -import ( - "bytes" - "context" - "encoding/json" - "fmt" - "io" - "mime/multipart" - "net/http" - "path/filepath" - - "git.nix13.pw/scuroneko/laniakea/utils" - "git.nix13.pw/scuroneko/slog" -) - -type Uploader struct { - api *Api - logger *slog.Logger -} - -func NewUploader(api *Api) *Uploader { - logger := slog.CreateLogger().Level(GetLoggerLevel()).Prefix("UPLOADER") - logger.AddWriter(logger.CreateJsonStdoutWriter()) - return &Uploader{api, logger} -} -func (u *Uploader) Close() error { - return u.logger.Close() -} - -type UploaderFileType string - -const ( - UploaderPhotoType UploaderFileType = "photo" - UploaderVideoType UploaderFileType = "video" - UploaderAudioType UploaderFileType = "audio" - UploaderDocumentType UploaderFileType = "document" - UploaderVoiceType UploaderFileType = "voice" - UploaderVideoNoteType UploaderFileType = "video_note" - UploaderThumbnailType UploaderFileType = "thumbnail" -) - -type UploaderFile struct { - filename string - data []byte - field UploaderFileType -} - -func NewUploaderFile(name string, data []byte) UploaderFile { - t := uploaderTypeByExt(name) - return UploaderFile{filename: name, data: data, field: t} -} - -// SetType used when auto-detect failed. I.e. you sending a voice message, but it detects as audio, or if you send audio with thumbnail -func (f UploaderFile) SetType(t UploaderFileType) UploaderFile { - f.field = t - return f -} - -type UploaderRequest[R, P any] struct { - method string - files []UploaderFile - params P -} - -func NewUploaderRequest[R, P any](method string, params P, files ...UploaderFile) UploaderRequest[R, P] { - return UploaderRequest[R, P]{method, files, params} -} -func (u UploaderRequest[R, P]) DoWithContext(ctx context.Context, up *Uploader) (R, error) { - var zero R - url := fmt.Sprintf("https://api.telegram.org/bot%s/%s", up.api.token, u.method) - - buf := bytes.NewBuffer(nil) - w := multipart.NewWriter(buf) - - for _, file := range u.files { - fw, err := w.CreateFormFile(string(file.field), file.filename) - if err != nil { - w.Close() - return zero, err - } - _, err = fw.Write(file.data) - if err != nil { - w.Close() - return zero, err - } - } - - err := utils.Encode(w, u.params) - if err != nil { - w.Close() - return zero, err - } - err = w.Close() - if err != nil { - return zero, err - } - - req, err := http.NewRequestWithContext(ctx, "POST", url, buf) - if err != nil { - return zero, err - } - req.Header.Set("Content-Type", w.FormDataContentType()) - req.Header.Set("User-Agent", fmt.Sprintf("Laniakea/%s", utils.VersionString)) - - up.logger.Debugln("UPLOADER REQ", u.method) - res, err := up.api.client.Do(req) - if err != nil { - return zero, err - } - defer res.Body.Close() - - body, err := io.ReadAll(res.Body) - if err != nil { - return zero, err - } - up.logger.Debugln("UPLOADER RES", u.method, string(body)) - if res.StatusCode != http.StatusOK { - return zero, fmt.Errorf("[%d] %s", res.StatusCode, string(body)) - } - - var response ApiResponse[R] - err = json.Unmarshal(body, &response) - if err != nil { - return zero, err - } - if !response.Ok { - return zero, fmt.Errorf("[%d] %s", response.ErrorCode, response.Description) - } - return response.Result, nil -} -func (u UploaderRequest[R, P]) Do(up *Uploader) (R, error) { - ctx := context.Background() - return u.DoWithContext(ctx, up) -} - type UploadPhotoP struct { BusinessConnectionID string `json:"business_connection_id,omitempty"` ChatID int `json:"chat_id"` @@ -330,7 +196,6 @@ func (u *Uploader) UploadVideoNote(params UploadVideoNoteP, files ...UploaderFil return req.Do(u) } -// setChatPhoto https://core.telegram.org/bots/api#setchatphoto type UploadChatPhotoP struct { ChatID int `json:"chat_id"` } @@ -339,19 +204,3 @@ func (u *Uploader) UploadChatPhoto(params UploadChatPhotoP, photo UploaderFile) req := NewUploaderRequest[Message]("sendChatPhoto", params, photo) return req.Do(u) } - -func uploaderTypeByExt(filename string) UploaderFileType { - ext := filepath.Ext(filename) - switch ext { - case ".jpg", ".jpeg", ".png", ".webp", ".bmp": - return UploaderPhotoType - case ".mp4": - return UploaderVideoType - case ".mp3", ".m4a": - return UploaderAudioType - case ".ogg": - return UploaderVoiceType - default: - return UploaderDocumentType - } -} diff --git a/tgapi/users_methods.go b/tgapi/users_methods.go index d254140..a2cad10 100644 --- a/tgapi/users_methods.go +++ b/tgapi/users_methods.go @@ -6,7 +6,7 @@ type GetUserProfilePhotosP struct { Limit int `json:"limit,omitempty"` } -func (api *Api) GetUserProfilePhotos(params GetUserProfilePhotosP) (UserProfilePhotos, error) { +func (api *API) GetUserProfilePhotos(params GetUserProfilePhotosP) (UserProfilePhotos, error) { req := NewRequest[UserProfilePhotos]("getUserProfilePhotos", params) return req.Do(api) } @@ -17,7 +17,7 @@ type GetUserProfileAudiosP struct { Limit int `json:"limit,omitempty"` } -func (api *Api) GetUserProfileAudios(params GetUserProfileAudiosP) (UserProfileAudios, error) { +func (api *API) GetUserProfileAudios(params GetUserProfileAudiosP) (UserProfileAudios, error) { req := NewRequest[UserProfileAudios]("getUserProfileAudios", params) return req.Do(api) } @@ -28,7 +28,7 @@ type SetUserEmojiStatusP struct { ExpirationDate int `json:"emoji_status_expiration_date,omitempty"` } -func (api *Api) SetUserEmojiStatus(params SetUserEmojiStatusP) (bool, error) { +func (api *API) SetUserEmojiStatus(params SetUserEmojiStatusP) (bool, error) { req := NewRequest[bool]("setUserEmojiStatus", params) return req.Do(api) } @@ -45,7 +45,7 @@ type GetUserGiftsP struct { Limit int `json:"limit,omitempty"` } -func (api *Api) GetUserGifts(params GetUserGiftsP) (OwnedGifts, error) { +func (api *API) GetUserGifts(params GetUserGiftsP) (OwnedGifts, error) { req := NewRequest[OwnedGifts]("getUserGifts", params) return req.Do(api) } diff --git a/tgapi/utils.go b/tgapi/utils.go deleted file mode 100644 index a982ea3..0000000 --- a/tgapi/utils.go +++ /dev/null @@ -1,15 +0,0 @@ -package tgapi - -import ( - "os" - - "git.nix13.pw/scuroneko/slog" -) - -func GetLoggerLevel() slog.LogLevel { - level := slog.FATAL - if os.Getenv("DEBUG") == "true" { - level = slog.DEBUG - } - return level -} diff --git a/utils/utils.go b/utils/utils.go index c782c58..9d0cbac 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -1,7 +1,6 @@ package utils import ( - "encoding/json" "fmt" "os" "strings" @@ -17,73 +16,6 @@ func GetLoggerLevel() slog.LogLevel { return level } -func Cast[A, B any](src A) (*B, error) { - m, err := StructToMap(src) - if err != nil { - return nil, err - } - - out := new(B) - err = MapToStruct(m, out) - if err != nil { - return nil, err - } - return out, nil -} - -// MapToStruct unsafe function -func MapToStruct(m map[string]any, s any) error { - data, err := json.Marshal(m) - if err != nil { - return err - } - err = json.Unmarshal(data, s) - return err -} - -// SliceToStruct unsafe function -func SliceToStruct(sl []any, s any) error { - data, err := json.Marshal(sl) - if err != nil { - return err - } - err = json.Unmarshal(data, s) - return err -} - -// AnyToStruct unsafe function -func AnyToStruct(src, dest any) error { - data, err := json.Marshal(src) - if err != nil { - return err - } - err = json.Unmarshal(data, dest) - return err -} - -func MapToJson(m map[string]any) (string, error) { - data, err := json.Marshal(m) - return string(data), err -} - -func StructToMap(s any) (map[string]any, error) { - data, err := json.Marshal(s) - if err != nil { - return nil, err - } - m := make(map[string]any) - err = json.Unmarshal(data, &m) - return m, err -} - -func Map[T, V any](ts []T, fn func(T) V) []V { - result := make([]V, len(ts)) - for i, t := range ts { - result[i] = fn(t) - } - return result -} - func EscapeMarkdown(s string) string { s = strings.ReplaceAll(s, "_", `\_`) s = strings.ReplaceAll(s, "*", `\*`)