WIP v0.5.0

This commit is contained in:
2026-02-11 17:27:05 +03:00
parent 7ac293dd38
commit f2d85b848f
32 changed files with 2721 additions and 727 deletions

91
api.go
View File

@@ -1,91 +0,0 @@
package laniakea
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"strings"
"git.nix13.pw/scuroneko/slog"
)
type Api struct {
token string
logger *slog.Logger
}
func NewAPI(token string) *Api {
l := slog.CreateLogger().Level(GetLoggerLevel()).Prefix("API")
l.AddWriter(l.CreateJsonStdoutWriter())
return &Api{token, l}
}
func (api *Api) CloseApi() error {
return api.logger.Close()
}
type ApiResponse[R any] struct {
Ok bool `json:"ok"`
Description string `json:"description,omitempty"`
Result R `json:"result,omitempty"`
ErrorCode int `json:"error_code,omitempty"`
}
type TelegramRequest[R, P any] struct {
method string
params P
}
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]) Do(api *Api) (*R, error) {
buf := bytes.NewBuffer(nil)
err := json.NewEncoder(buf).Encode(r.params)
if err != nil {
return nil, err
}
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, "<TOKEN>"))
}
res, err := http.Post(u, "application/json", buf)
if err != nil {
return nil, err
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
return nil, err
}
if api.logger != nil {
api.logger.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
}
if !response.Ok {
return nil, fmt.Errorf("[%d] %s", response.ErrorCode, response.Description)
}
return &response.Result, nil
}
func (b *Bot) GetFileByLink(link string) ([]byte, error) {
u := fmt.Sprintf("https://api.telegram.org/file/bot%s/%s", b.token, link)
res, err := http.Get(u)
if err != nil {
return nil, err
}
defer res.Body.Close()
return io.ReadAll(res.Body)
}

40
bot.go
View File

@@ -9,27 +9,20 @@ import (
"time" "time"
"git.nix13.pw/scuroneko/extypes" "git.nix13.pw/scuroneko/extypes"
"git.nix13.pw/scuroneko/laniakea/tgapi"
"git.nix13.pw/scuroneko/slog" "git.nix13.pw/scuroneko/slog"
"github.com/redis/go-redis/v9" "github.com/redis/go-redis/v9"
"github.com/vinovest/sqlx" "github.com/vinovest/sqlx"
"go.mongodb.org/mongo-driver/v2/mongo" "go.mongodb.org/mongo-driver/v2/mongo"
) )
type ParseMode string
const (
ParseMDV2 ParseMode = "MarkdownV2"
ParseHTML ParseMode = "HTML"
ParseMD ParseMode = "Markdown"
)
type Bot struct { type Bot struct {
token string token string
debug bool debug bool
errorTemplate string errorTemplate string
logger *slog.Logger logger *slog.Logger
requestLogger *slog.Logger RequestLogger *slog.Logger
plugins []Plugin plugins []Plugin
middlewares []Middleware middlewares []Middleware
@@ -37,15 +30,20 @@ type Bot struct {
runners []Runner runners []Runner
dbContext *DatabaseContext dbContext *DatabaseContext
api *Api api *tgapi.Api
dbWriterRequested extypes.Slice[*slog.Logger] dbWriterRequested extypes.Slice[*slog.Logger]
updateOffset int updateOffset int
updateTypes []string updateTypes []string
updateQueue *extypes.Queue[*Update] 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() []string { return b.updateTypes }
func (b *Bot) GetQueue() *extypes.Queue[*tgapi.Update] { return b.updateQueue }
type BotSettings struct { type BotSettings struct {
Token string Token string
Debug bool Debug bool
@@ -77,15 +75,15 @@ func LoadPrefixesFromEnv() []string {
return strings.Split(prefixesS, ";") return strings.Split(prefixesS, ";")
} }
func NewBot(settings *BotSettings) *Bot { func NewBot(settings *BotSettings) *Bot {
updateQueue := extypes.CreateQueue[*Update](256) updateQueue := extypes.CreateQueue[*tgapi.Update](256)
api := NewAPI(settings.Token) api := tgapi.NewAPI(settings.Token)
bot := &Bot{ bot := &Bot{
updateOffset: 0, plugins: make([]Plugin, 0), debug: settings.Debug, errorTemplate: "%s", updateOffset: 0, plugins: make([]Plugin, 0), debug: settings.Debug, errorTemplate: "%s",
prefixes: settings.Prefixes, updateTypes: make([]string, 0), runners: make([]Runner, 0), prefixes: settings.Prefixes, updateTypes: make([]string, 0), runners: make([]Runner, 0),
updateQueue: updateQueue, api: api, dbWriterRequested: make([]*slog.Logger, 0), updateQueue: updateQueue, api: api, dbWriterRequested: make([]*slog.Logger, 0),
token: settings.Token, token: settings.Token,
} }
bot.dbWriterRequested = bot.dbWriterRequested.Push(api.logger) bot.dbWriterRequested = bot.dbWriterRequested.Push(api.Logger)
if len(settings.ErrorTemplate) > 0 { if len(settings.ErrorTemplate) > 0 {
bot.errorTemplate = settings.ErrorTemplate bot.errorTemplate = settings.ErrorTemplate
@@ -111,15 +109,15 @@ func NewBot(settings *BotSettings) *Bot {
} }
if settings.UseRequestLogger { if settings.UseRequestLogger {
bot.requestLogger = slog.CreateLogger().Level(level).Prefix("REQUESTS") bot.RequestLogger = slog.CreateLogger().Level(level).Prefix("REQUESTS")
bot.requestLogger.AddWriter(bot.requestLogger.CreateJsonStdoutWriter()) bot.RequestLogger.AddWriter(bot.RequestLogger.CreateJsonStdoutWriter())
if settings.WriteToFile { if settings.WriteToFile {
path := fmt.Sprintf("%s/requests.log", strings.TrimRight(settings.LoggerBasePath, "/")) path := fmt.Sprintf("%s/requests.log", strings.TrimRight(settings.LoggerBasePath, "/"))
fileWriter, err := bot.requestLogger.CreateTextFileWriter(path) fileWriter, err := bot.RequestLogger.CreateTextFileWriter(path)
if err != nil { if err != nil {
bot.logger.Fatal(err) bot.logger.Fatal(err)
} }
bot.requestLogger.AddWriter(fileWriter) bot.RequestLogger.AddWriter(fileWriter)
} }
} }
@@ -137,7 +135,7 @@ func (b *Bot) Close() {
if err != nil { if err != nil {
log.Println(err) log.Println(err)
} }
err = b.requestLogger.Close() err = b.RequestLogger.Close()
if err != nil { if err != nil {
log.Println(err) log.Println(err)
} }
@@ -152,8 +150,8 @@ type DatabaseContext struct {
func (b *Bot) AddDatabaseLogger(writer func(db *DatabaseContext) slog.LoggerWriter) *Bot { func (b *Bot) AddDatabaseLogger(writer func(db *DatabaseContext) slog.LoggerWriter) *Bot {
w := writer(b.dbContext) w := writer(b.dbContext)
b.logger.AddWriter(w) b.logger.AddWriter(w)
if b.requestLogger != nil { if b.RequestLogger != nil {
b.requestLogger.AddWriter(w) b.RequestLogger.AddWriter(w)
} }
for _, l := range b.dbWriterRequested { for _, l := range b.dbWriterRequested {
l.AddWriter(w) l.AddWriter(w)

View File

@@ -3,9 +3,11 @@ package laniakea
import ( import (
"encoding/json" "encoding/json"
"strings" "strings"
"git.nix13.pw/scuroneko/laniakea/tgapi"
) )
func (b *Bot) handleMessage(update *Update, ctx *MsgContext) { func (b *Bot) handleMessage(update *tgapi.Update, ctx *MsgContext) {
if update.Message == nil { if update.Message == nil {
return return
} }
@@ -60,7 +62,7 @@ func (b *Bot) handleMessage(update *Update, ctx *MsgContext) {
} }
} }
func (b *Bot) handleCallback(update *Update, ctx *MsgContext) { func (b *Bot) handleCallback(update *tgapi.Update, ctx *MsgContext) {
data := new(CallbackData) data := new(CallbackData)
err := json.Unmarshal([]byte(update.CallbackQuery.Data), data) err := json.Unmarshal([]byte(update.CallbackQuery.Data), data)
if err != nil { if err != nil {

View File

@@ -5,18 +5,19 @@ import (
"fmt" "fmt"
"git.nix13.pw/scuroneko/extypes" "git.nix13.pw/scuroneko/extypes"
"git.nix13.pw/scuroneko/laniakea/tgapi"
) )
const ( const (
ButtonStyleDanger KeyboardButtonStyle = "danger" ButtonStyleDanger tgapi.KeyboardButtonStyle = "danger"
ButtonStyleSuccess KeyboardButtonStyle = "success" ButtonStyleSuccess tgapi.KeyboardButtonStyle = "success"
ButtonStylePrimary KeyboardButtonStyle = "primary" ButtonStylePrimary tgapi.KeyboardButtonStyle = "primary"
) )
type InlineKbButtonBuilder struct { type InlineKbButtonBuilder struct {
text string text string
iconCustomEmojiID string iconCustomEmojiID string
style KeyboardButtonStyle style tgapi.KeyboardButtonStyle
url string url string
callbackData string callbackData string
} }
@@ -28,7 +29,7 @@ func (b InlineKbButtonBuilder) SetIconCustomEmojiId(id string) InlineKbButtonBui
b.iconCustomEmojiID = id b.iconCustomEmojiID = id
return b return b
} }
func (b InlineKbButtonBuilder) SetStyle(style KeyboardButtonStyle) InlineKbButtonBuilder { func (b InlineKbButtonBuilder) SetStyle(style tgapi.KeyboardButtonStyle) InlineKbButtonBuilder {
b.style = style b.style = style
return b return b
} }
@@ -41,8 +42,8 @@ func (b InlineKbButtonBuilder) SetCallbackData(cmd string, args ...any) InlineKb
return b return b
} }
func (b InlineKbButtonBuilder) build() InlineKeyboardButton { func (b InlineKbButtonBuilder) build() tgapi.InlineKeyboardButton {
return InlineKeyboardButton{ return tgapi.InlineKeyboardButton{
Text: b.text, Text: b.text,
URL: b.url, URL: b.url,
Style: b.style, Style: b.style,
@@ -52,20 +53,20 @@ func (b InlineKbButtonBuilder) build() InlineKeyboardButton {
} }
type InlineKeyboard struct { type InlineKeyboard struct {
CurrentLine extypes.Slice[InlineKeyboardButton] CurrentLine extypes.Slice[tgapi.InlineKeyboardButton]
Lines [][]InlineKeyboardButton Lines [][]tgapi.InlineKeyboardButton
maxRow int maxRow int
} }
func NewInlineKeyboard(maxRow int) *InlineKeyboard { func NewInlineKeyboard(maxRow int) *InlineKeyboard {
return &InlineKeyboard{ return &InlineKeyboard{
CurrentLine: make(extypes.Slice[InlineKeyboardButton], 0), CurrentLine: make(extypes.Slice[tgapi.InlineKeyboardButton], 0),
Lines: make([][]InlineKeyboardButton, 0), Lines: make([][]tgapi.InlineKeyboardButton, 0),
maxRow: maxRow, maxRow: maxRow,
} }
} }
func (in *InlineKeyboard) append(button InlineKeyboardButton) *InlineKeyboard { func (in *InlineKeyboard) append(button tgapi.InlineKeyboardButton) *InlineKeyboard {
if in.CurrentLine.Len() == in.maxRow { if in.CurrentLine.Len() == in.maxRow {
in.AddLine() in.AddLine()
} }
@@ -74,18 +75,18 @@ func (in *InlineKeyboard) append(button InlineKeyboardButton) *InlineKeyboard {
} }
func (in *InlineKeyboard) AddUrlButton(text, url string) *InlineKeyboard { func (in *InlineKeyboard) AddUrlButton(text, url string) *InlineKeyboard {
return in.append(InlineKeyboardButton{Text: text, URL: url}) return in.append(tgapi.InlineKeyboardButton{Text: text, URL: url})
} }
func (in *InlineKeyboard) AddUrlButtonStyle(text string, style KeyboardButtonStyle, url string) *InlineKeyboard { func (in *InlineKeyboard) AddUrlButtonStyle(text string, style tgapi.KeyboardButtonStyle, url string) *InlineKeyboard {
return in.append(InlineKeyboardButton{Text: text, Style: style, URL: url}) return in.append(tgapi.InlineKeyboardButton{Text: text, Style: style, URL: url})
} }
func (in *InlineKeyboard) AddCallbackButton(text string, cmd string, args ...any) *InlineKeyboard { func (in *InlineKeyboard) AddCallbackButton(text string, cmd string, args ...any) *InlineKeyboard {
return in.append(InlineKeyboardButton{ return in.append(tgapi.InlineKeyboardButton{
Text: text, CallbackData: NewCallbackData(cmd, args...).ToJson(), Text: text, CallbackData: NewCallbackData(cmd, args...).ToJson(),
}) })
} }
func (in *InlineKeyboard) AddCallbackButtonStyle(text string, style KeyboardButtonStyle, cmd string, args ...any) *InlineKeyboard { func (in *InlineKeyboard) AddCallbackButtonStyle(text string, style tgapi.KeyboardButtonStyle, cmd string, args ...any) *InlineKeyboard {
return in.append(InlineKeyboardButton{ return in.append(tgapi.InlineKeyboardButton{
Text: text, Style: style, Text: text, Style: style,
CallbackData: NewCallbackData(cmd, args...).ToJson(), CallbackData: NewCallbackData(cmd, args...).ToJson(),
}) })
@@ -99,14 +100,14 @@ func (in *InlineKeyboard) AddLine() *InlineKeyboard {
return in return in
} }
in.Lines = append(in.Lines, in.CurrentLine) in.Lines = append(in.Lines, in.CurrentLine)
in.CurrentLine = make(extypes.Slice[InlineKeyboardButton], 0) in.CurrentLine = make(extypes.Slice[tgapi.InlineKeyboardButton], 0)
return in return in
} }
func (in *InlineKeyboard) Get() *InlineKeyboardMarkup { func (in *InlineKeyboard) Get() *tgapi.ReplyMarkup {
if in.CurrentLine.Len() > 0 { if in.CurrentLine.Len() > 0 {
in.Lines = append(in.Lines, in.CurrentLine) in.Lines = append(in.Lines, in.CurrentLine)
} }
return &InlineKeyboardMarkup{InlineKeyboard: in.Lines} return &tgapi.ReplyMarkup{InlineKeyboard: in.Lines}
} }
type CallbackData struct { type CallbackData struct {

View File

@@ -2,359 +2,51 @@ package laniakea
import ( import (
"encoding/json" "encoding/json"
"fmt"
"io"
"net/http"
"git.nix13.pw/scuroneko/laniakea/tgapi"
) )
type EmptyParams struct{} func (b *Bot) Updates() ([]*tgapi.Update, error) {
offset := b.GetUpdateOffset()
var NoParams = EmptyParams{} params := tgapi.UpdateParams{
Offset: offset,
type UpdateParams struct {
Offset int `json:"offset"`
Timeout int `json:"timeout"`
AllowedUpdates []string `json:"allowed_updates"`
}
func (b *Bot) Updates() ([]*Update, error) {
params := UpdateParams{
Offset: b.updateOffset,
Timeout: 30, Timeout: 30,
AllowedUpdates: b.updateTypes, AllowedUpdates: b.GetUpdateTypes(),
} }
req := NewRequest[[]*Update]("getUpdates", params) req := tgapi.NewRequest[[]*tgapi.Update]("getUpdates", params)
res, err := req.Do(b.api) res, err := req.Do(b.api)
if err != nil { if err != nil {
return nil, err return nil, err
} }
for _, u := range *res { for _, u := range *res {
b.updateOffset = u.UpdateID + 1 b.SetUpdateOffset(u.UpdateID + 1)
err = b.updateQueue.Enqueue(u) err = b.GetQueue().Enqueue(u)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if b.requestLogger != nil { if b.RequestLogger != nil {
j, err := json.Marshal(u) j, err := json.Marshal(u)
if err != nil { if err != nil {
b.logger.Error(err) b.Logger().Error(err)
} }
b.requestLogger.Debugf("UPDATE %s\n", j) b.RequestLogger.Debugf("UPDATE %s\n", j)
} }
} }
return *res, err return *res, err
} }
func (api *Api) GetMe() (*User, error) { func (b *Bot) GetFileByLink(link string) ([]byte, error) {
req := NewRequest[User, EmptyParams]("getMe", NoParams) u := fmt.Sprintf("https://api.telegram.org/file/bot%s/%s", b.token, link)
return req.Do(api) res, err := http.Get(u)
}
func (api *Api) LogOut() (bool, error) {
req := NewRequest[bool, EmptyParams]("logOut", NoParams)
res, err := req.Do(api)
if err != nil { if err != nil {
return false, err return nil, err
} }
return *res, nil defer res.Body.Close()
} return io.ReadAll(res.Body)
func (api *Api) Close() (bool, error) {
req := NewRequest[bool, EmptyParams]("close", NoParams)
res, err := req.Do(api)
if err != nil {
return false, err
}
return *res, nil
}
type SendMessageP struct {
BusinessConnectionID string `json:"business_connection_id,omitempty"`
ChatID int `json:"chat_id"`
MessageThreadID int `json:"message_thread_id,omitempty"`
DirectMessageTopicID int `json:"direct_message_topic_id,omitempty"`
Text string `json:"text"`
ParseMode ParseMode `json:"parse_mode,omitempty"`
Entities []*MessageEntity `json:"entities,omitempty"`
LinkPreviewOptions *LinkPreviewOptions `json:"link_preview_options,omitempty"`
DisableNotifications bool `json:"disable_notifications,omitempty"`
ProtectContent bool `json:"protect_content,omitempty"`
AllowPaidBroadcast bool `json:"allow_paid_broadcast,omitempty"`
MessageEffectID string `json:"message_effect_id,omitempty"`
SuggestedPostParameters *SuggestedPostParameters `json:"suggested_post_parameters,omitempty"`
ReplyParameters *ReplyParameters `json:"reply_parameters,omitempty"`
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
}
func (api *Api) SendMessage(params *SendMessageP) (*Message, error) {
req := NewRequest[Message, SendMessageP]("sendMessage", *params)
return req.Do(api)
}
type ForwardMessageP struct {
ChatID int `json:"chat_id"`
MessageThreadID int `json:"message_thread_id,omitempty"`
DirectMessageTopicID int `json:"direct_message_topic_id,omitempty"`
MessageID int `json:"message_id,omitempty"`
FromChatID int `json:"from_chat_id,omitempty"`
VideoStartTimestamp int `json:"video_start_timestamp,omitempty"`
DisableNotification bool `json:"disable_notification,omitempty"`
ProtectContent bool `json:"protect_content,omitempty"`
MessageEffectID string `json:"message_effect_id,omitempty"`
SuggestedPostParameters *SuggestedPostParameters `json:"suggested_post_parameters,omitempty"`
}
func (api *Api) ForwardMessage(params ForwardMessageP) (*Message, error) {
req := NewRequest[Message]("forwardMessage", params)
return req.Do(api)
}
type ForwardMessagesP struct {
ChatID int `json:"chat_id"`
MessageThreadID int `json:"message_thread_id,omitempty"`
DirectMessageTopicID int `json:"direct_message_topic_id,omitempty"`
FromChatID int `json:"from_chat_id,omitempty"`
MessageIDs []int `json:"message_ids,omitempty"`
DisableNotification bool `json:"disable_notification,omitempty"`
ProtectContent bool `json:"protect_content,omitempty"`
}
func (api *Api) ForwardMessages(params ForwardMessagesP) ([]int, error) {
req := NewRequest[[]int]("forwardMessages", params)
res, err := req.Do(api)
if err != nil {
return []int{}, err
}
return *res, nil
}
type CopyMessageP struct {
ChatID int `json:"chat_id"`
MessageThreadID int `json:"message_thread_id,omitempty"`
DirectMessageTopicID int `json:"direct_message_topic_id,omitempty"`
FromChatID int `json:"from_chat_id"`
MessageID int `json:"message_id"`
VideoStartTimestamp int `json:"video_start_timestamp,omitempty"`
Caption string `json:"caption,omitempty"`
ParseMode ParseMode `json:"parse_mode,omitempty"`
CaptionEntities []*MessageEntity `json:"caption_entities,omitempty"`
ShowCaptionAboveMedia bool `json:"show_caption_above_media,omitempty"`
DisableNotification bool `json:"disable_notification,omitempty"`
ProtectContent bool `json:"protect_content,omitempty"`
AllowPaidBroadcast bool `json:"allow_paid_broadcast,omitempty"`
MessageEffectID string `json:"message_effect_id,omitempty"`
SuggestedPostParameters *SuggestedPostParameters `json:"suggested_post_parameters,omitempty"`
ReplyParameters *ReplyParameters `json:"reply_parameters,omitempty"`
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
}
func (api *Api) CopyMessage(params CopyMessageP) (int, error) {
req := NewRequest[int]("copyMessage", params)
res, err := req.Do(api)
if err != nil {
return 0, err
}
return *res, nil
}
type CopyMessagesP struct {
ChatID int `json:"chat_id"`
MessageThreadID int `json:"message_thread_id,omitempty"`
DirectMessageTopicID int `json:"direct_message_topic_id,omitempty"`
FromChatID int `json:"from_chat_id,omitempty"`
MessageIDs []int `json:"message_ids,omitempty"`
DisableNotification bool `json:"disable_notification,omitempty"`
ProtectContent bool `json:"protect_content,omitempty"`
RemoveCaption bool `json:"remove_caption,omitempty"`
}
func (api *Api) CopyMessages(params CopyMessagesP) ([]int, error) {
req := NewRequest[[]int]("copyMessages", params)
res, err := req.Do(api)
if err != nil {
return []int{}, err
}
return *res, nil
}
type SendPhotoBaseP struct {
BusinessConnectionID string `json:"business_connection_id,omitempty"`
ChatID int `json:"chat_id"`
MessageThreadID int `json:"message_thread_id,omitempty"`
ParseMode ParseMode `json:"parse_mode,omitempty"`
Caption string `json:"caption,omitempty"`
CaptionEntities []*MessageEntity `json:"caption_entities,omitempty"`
ShowCaptionAboveMedia bool `json:"show_caption_above_media,omitempty"`
HasSpoiler bool `json:"has_spoiler,omitempty"`
DisableNotifications bool `json:"disable_notifications,omitempty"`
ProtectContent bool `json:"protect_content,omitempty"`
AllowPaidBroadcast bool `json:"allow_paid_broadcast,omitempty"`
MessageEffectID string `json:"message_effect_id,omitempty"`
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
}
type SendPhotoP struct {
BusinessConnectionID string `json:"business_connection_id,omitempty"`
ChatID int `json:"chat_id"`
MessageThreadID int `json:"message_thread_id,omitempty"`
DirectMessagesTopicID int `json:"direct_messages_topic_id,omitempty"`
Photo string `json:"photo"`
Caption string `json:"caption,omitempty"`
ParseMode ParseMode `json:"parse_mode,omitempty"`
CaptionEntities []*MessageEntity `json:"caption_entities,omitempty"`
ShowCaptionAboveMedia bool `json:"show_caption_above_media,omitempty"`
HasSpoiler bool `json:"has_spoiler,omitempty"`
DisableNotifications bool `json:"disable_notifications,omitempty"`
ProtectContent bool `json:"protect_content,omitempty"`
AllowPaidBroadcast bool `json:"allow_paid_broadcast,omitempty"`
MessageEffectID string `json:"message_effect_id,omitempty"`
SuggestedPostParameters *SuggestedPostParameters `json:"suggested_post_parameters,omitempty"`
ReplyParameters *ReplyParameters `json:"reply_parameters,omitempty"`
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
}
func (api *Api) SendPhoto(params *SendPhotoP) (*Message, error) {
req := NewRequest[Message]("sendPhoto", params)
return req.Do(api)
}
type EditMessageTextP struct {
BusinessConnectionID string `json:"business_connection_id,omitempty"`
ChatID int `json:"chat_id,omitempty"`
MessageID int `json:"message_id,omitempty"`
InlineMessageID string `json:"inline_message_id,omitempty"`
Text string `json:"text"`
ParseMode ParseMode `json:"parse_mode,omitempty"`
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
}
func (api *Api) EditMessageText(params *EditMessageTextP) (*Message, error) {
req := NewRequest[Message]("editMessageText", params)
return req.Do(api)
}
type EditMessageCaptionP struct {
BusinessConnectionID string `json:"business_connection_id,omitempty"`
ChatID int `json:"chat_id,omitempty"`
MessageID int `json:"message_id,omitempty"`
InlineMessageID string `json:"inline_message_id,omitempty"`
Caption string `json:"caption"`
ParseMode ParseMode `json:"parse_mode,omitempty"`
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
}
func (api *Api) EditMessageCaption(params *EditMessageCaptionP) (*Message, error) {
req := NewRequest[Message]("editMessageCaption", params)
return req.Do(api)
}
type DeleteMessageP struct {
ChatID int `json:"chat_id"`
MessageID int `json:"message_id"`
}
func (api *Api) DeleteMessage(params *DeleteMessageP) (bool, error) {
req := NewRequest[bool]("deleteMessage", params)
ok, err := req.Do(api)
if err != nil {
return false, err
}
return *ok, err
}
type AnswerCallbackQueryP struct {
CallbackQueryID string `json:"callback_query_id"`
Text string `json:"text,omitempty"`
ShowAlert bool `json:"show_alert,omitempty"`
URL string `json:"url,omitempty"`
CacheTime int `json:"cache_time,omitempty"`
}
func (api *Api) AnswerCallbackQuery(params *AnswerCallbackQueryP) (bool, error) {
req := NewRequest[bool]("answerCallbackQuery", params)
ok, err := req.Do(api)
if err != nil {
return false, err
}
return *ok, err
}
type GetFileP struct {
FileId string `json:"file_id"`
}
func (api *Api) GetFile(params *GetFileP) (*File, error) {
req := NewRequest[File]("getFile", params)
return req.Do(api)
}
type SendChatActionP struct {
BusinessConnectionID string `json:"business_connection_id,omitempty"`
ChatID int `json:"chat_id"`
MessageThreadID int `json:"message_thread_id,omitempty"`
Action ChatActions `json:"action"`
}
func (api *Api) SendChatAction(params SendChatActionP) (bool, error) {
req := NewRequest[bool]("sendChatAction", params)
res, err := req.Do(api)
if err != nil {
return false, err
}
return *res, err
}
type SetMessageReactionP struct {
ChatId int `json:"chat_id"`
MessageId int `json:"message_id"`
IsBig bool `json:"is_big,omitempty"`
}
type SetMessageReactionEmojiP struct {
SetMessageReactionP
Reaction []ReactionTypeEmoji `json:"reaction"`
}
func (api *Api) SetMessageReactionEmoji(params SetMessageReactionEmojiP) (bool, error) {
req := NewRequest[bool]("setMessageReaction", params)
res, err := req.Do(api)
if err != nil {
return false, err
}
return *res, err
}
type SetMessageReactionCustomEmojiP struct {
SetMessageReactionP
Reaction []ReactionTypeCustomEmoji `json:"reaction"`
}
func (api *Api) SetMessageReactionCustom(params SetMessageReactionCustomEmojiP) (bool, error) {
req := NewRequest[bool]("setMessageReaction", params)
res, err := req.Do(api)
if err != nil {
return false, err
}
return *res, err
}
type SetMessageReactionPaidP struct {
SetMessageReactionP
}
func (api *Api) SetMessageReactionPaid(params SetMessageReactionPaidP) (bool, error) {
req := NewRequest[bool]("setMessageReaction", params)
res, err := req.Do(api)
if err != nil {
return false, err
}
return *res, err
} }

View File

@@ -1,14 +1,19 @@
package laniakea package laniakea
import "fmt" import (
"fmt"
"git.nix13.pw/scuroneko/laniakea/tgapi"
"git.nix13.pw/scuroneko/laniakea/utils"
)
type MsgContext struct { type MsgContext struct {
Bot *Bot Bot *Bot
Api *Api Api *tgapi.Api
Msg *Message Msg *tgapi.Message
Update *Update Update *tgapi.Update
From *User From *tgapi.User
CallbackMsgId int CallbackMsgId int
CallbackQueryId string CallbackQueryId string
FromID int FromID int
@@ -26,18 +31,18 @@ type AnswerMessage struct {
} }
func (ctx *MsgContext) edit(messageId int, text string, keyboard *InlineKeyboard) *AnswerMessage { func (ctx *MsgContext) edit(messageId int, text string, keyboard *InlineKeyboard) *AnswerMessage {
params := &EditMessageTextP{ params := &tgapi.EditMessageTextP{
MessageID: messageId, MessageID: messageId,
ChatID: ctx.Msg.Chat.ID, ChatID: ctx.Msg.Chat.ID,
Text: text, Text: text,
ParseMode: ParseMD, ParseMode: tgapi.ParseMD,
} }
if keyboard != nil { if keyboard != nil {
params.ReplyMarkup = keyboard.Get() params.ReplyMarkup = keyboard.Get()
} }
msg, err := ctx.Api.EditMessageText(params) msg, err := ctx.Api.EditMessageText(params)
if err != nil { if err != nil {
ctx.Api.logger.Errorln(err) ctx.Api.Logger.Errorln(err)
return nil return nil
} }
return &AnswerMessage{ return &AnswerMessage{
@@ -49,7 +54,7 @@ func (m *AnswerMessage) Edit(text string) *AnswerMessage {
} }
func (ctx *MsgContext) EditCallback(text string, keyboard *InlineKeyboard) *AnswerMessage { func (ctx *MsgContext) EditCallback(text string, keyboard *InlineKeyboard) *AnswerMessage {
if ctx.CallbackMsgId == 0 { if ctx.CallbackMsgId == 0 {
ctx.Api.logger.Errorln("Can't edit non-callback update message") ctx.Api.Logger.Errorln("Can't edit non-callback update message")
return nil return nil
} }
@@ -60,18 +65,18 @@ func (ctx *MsgContext) EditCallbackf(format string, keyboard *InlineKeyboard, ar
} }
func (ctx *MsgContext) editPhotoText(messageId int, text string, kb *InlineKeyboard) *AnswerMessage { func (ctx *MsgContext) editPhotoText(messageId int, text string, kb *InlineKeyboard) *AnswerMessage {
params := &EditMessageCaptionP{ params := &tgapi.EditMessageCaptionP{
ChatID: ctx.Msg.Chat.ID, ChatID: ctx.Msg.Chat.ID,
MessageID: messageId, MessageID: messageId,
Caption: text, Caption: text,
ParseMode: ParseMD, ParseMode: tgapi.ParseMD,
} }
if kb != nil { if kb != nil {
params.ReplyMarkup = kb.Get() params.ReplyMarkup = kb.Get()
} }
msg, err := ctx.Api.EditMessageCaption(params) msg, err := ctx.Api.EditMessageCaption(params)
if err != nil { if err != nil {
ctx.Api.logger.Errorln(err) ctx.Api.Logger.Errorln(err)
} }
return &AnswerMessage{ return &AnswerMessage{
MessageID: msg.MessageID, ctx: ctx, Text: text, IsMedia: true, MessageID: msg.MessageID, ctx: ctx, Text: text, IsMedia: true,
@@ -79,7 +84,7 @@ func (ctx *MsgContext) editPhotoText(messageId int, text string, kb *InlineKeybo
} }
func (m *AnswerMessage) EditCaption(text string) *AnswerMessage { func (m *AnswerMessage) EditCaption(text string) *AnswerMessage {
if m.MessageID == 0 { if m.MessageID == 0 {
m.ctx.Api.logger.Errorln("Can't edit caption message, message id is zero") m.ctx.Api.Logger.Errorln("Can't edit caption message, message id is zero")
return m return m
} }
return m.ctx.editPhotoText(m.MessageID, text, nil) return m.ctx.editPhotoText(m.MessageID, text, nil)
@@ -89,10 +94,10 @@ func (m *AnswerMessage) EditCaptionKeyboard(text string, kb *InlineKeyboard) *An
} }
func (ctx *MsgContext) answer(text string, keyboard *InlineKeyboard) *AnswerMessage { func (ctx *MsgContext) answer(text string, keyboard *InlineKeyboard) *AnswerMessage {
params := &SendMessageP{ params := &tgapi.SendMessageP{
ChatID: ctx.Msg.Chat.ID, ChatID: ctx.Msg.Chat.ID,
Text: text, Text: text,
ParseMode: ParseMD, ParseMode: tgapi.ParseMD,
} }
if keyboard != nil { if keyboard != nil {
params.ReplyMarkup = keyboard.Get() params.ReplyMarkup = keyboard.Get()
@@ -100,7 +105,7 @@ func (ctx *MsgContext) answer(text string, keyboard *InlineKeyboard) *AnswerMess
msg, err := ctx.Api.SendMessage(params) msg, err := ctx.Api.SendMessage(params)
if err != nil { if err != nil {
ctx.Api.logger.Errorln(err) ctx.Api.Logger.Errorln(err)
return nil return nil
} }
return &AnswerMessage{ return &AnswerMessage{
@@ -118,10 +123,10 @@ func (ctx *MsgContext) Keyboard(text string, kb *InlineKeyboard) *AnswerMessage
} }
func (ctx *MsgContext) answerPhoto(photoId, text string, kb *InlineKeyboard) *AnswerMessage { func (ctx *MsgContext) answerPhoto(photoId, text string, kb *InlineKeyboard) *AnswerMessage {
params := &SendPhotoP{ params := &tgapi.SendPhotoP{
ChatID: ctx.Msg.Chat.ID, ChatID: ctx.Msg.Chat.ID,
Caption: text, Caption: text,
ParseMode: ParseMD, ParseMode: tgapi.ParseMD,
Photo: photoId, Photo: photoId,
} }
if kb != nil { if kb != nil {
@@ -129,7 +134,7 @@ func (ctx *MsgContext) answerPhoto(photoId, text string, kb *InlineKeyboard) *An
} }
msg, err := ctx.Api.SendPhoto(params) msg, err := ctx.Api.SendPhoto(params)
if err != nil { if err != nil {
ctx.Api.logger.Errorln(err) ctx.Api.Logger.Errorln(err)
return &AnswerMessage{ return &AnswerMessage{
ctx: ctx, Text: text, IsMedia: true, ctx: ctx, Text: text, IsMedia: true,
} }
@@ -146,12 +151,12 @@ func (ctx *MsgContext) AnswerPhotoKeyboard(photoId, text string, kb *InlineKeybo
} }
func (ctx *MsgContext) delete(messageId int) { func (ctx *MsgContext) delete(messageId int) {
_, err := ctx.Api.DeleteMessage(&DeleteMessageP{ _, err := ctx.Api.DeleteMessage(&tgapi.DeleteMessageP{
ChatID: ctx.Msg.Chat.ID, ChatID: ctx.Msg.Chat.ID,
MessageID: messageId, MessageID: messageId,
}) })
if err != nil { if err != nil {
ctx.Api.logger.Errorln(err) ctx.Api.Logger.Errorln(err)
} }
} }
func (m *AnswerMessage) Delete() { func (m *AnswerMessage) Delete() {
@@ -165,12 +170,12 @@ func (ctx *MsgContext) answerCallbackQuery(url, text string, showAlert bool) {
if len(ctx.CallbackQueryId) == 0 { if len(ctx.CallbackQueryId) == 0 {
return return
} }
_, err := ctx.Api.AnswerCallbackQuery(&AnswerCallbackQueryP{ _, err := ctx.Api.AnswerCallbackQuery(&tgapi.AnswerCallbackQueryP{
CallbackQueryID: ctx.CallbackQueryId, CallbackQueryID: ctx.CallbackQueryId,
Text: text, ShowAlert: showAlert, URL: url, Text: text, ShowAlert: showAlert, URL: url,
}) })
if err != nil { if err != nil {
ctx.Api.logger.Errorln(err) ctx.Api.Logger.Errorln(err)
} }
} }
func (ctx *MsgContext) AnswerCbQuery() { func (ctx *MsgContext) AnswerCbQuery() {
@@ -186,24 +191,24 @@ func (ctx *MsgContext) AnswerCbQueryUrl(u string) {
ctx.answerCallbackQuery(u, "", false) ctx.answerCallbackQuery(u, "", false)
} }
func (ctx *MsgContext) SendAction(action ChatActions) { func (ctx *MsgContext) SendAction(action tgapi.ChatActionType) {
_, err := ctx.Api.SendChatAction(SendChatActionP{ _, err := ctx.Api.SendChatAction(tgapi.SendChatActionP{
ChatID: ctx.Msg.Chat.ID, Action: action, ChatID: ctx.Msg.Chat.ID, Action: action,
}) })
if err != nil { if err != nil {
ctx.Api.logger.Errorln(err) ctx.Api.Logger.Errorln(err)
} }
} }
func (ctx *MsgContext) error(err error) { func (ctx *MsgContext) error(err error) {
text := fmt.Sprintf(ctx.Bot.errorTemplate, EscapeMarkdown(err.Error())) text := fmt.Sprintf(ctx.Bot.errorTemplate, utils.EscapeMarkdown(err.Error()))
if ctx.CallbackQueryId != "" { if ctx.CallbackQueryId != "" {
ctx.answerCallbackQuery("", text, false) ctx.answerCallbackQuery("", text, false)
} else { } else {
ctx.answer(text, nil) ctx.answer(text, nil)
} }
ctx.Bot.logger.Errorln(err) ctx.Bot.Logger().Errorln(err)
} }
func (ctx *MsgContext) Error(err error) { func (ctx *MsgContext) Error(err error) {
ctx.error(err) ctx.error(err)

105
tgapi/api.go Normal file
View File

@@ -0,0 +1,105 @@
package tgapi
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"strings"
"time"
"git.nix13.pw/scuroneko/laniakea/utils"
"git.nix13.pw/scuroneko/slog"
)
type Api struct {
token string
client *http.Client
Logger *slog.Logger
}
func NewAPI(token string) *Api {
l := slog.CreateLogger().Level(utils.GetLoggerLevel()).Prefix("API")
l.AddWriter(l.CreateJsonStdoutWriter())
client := &http.Client{Timeout: time.Second * 10}
return &Api{token, client, l}
}
func (api *Api) CloseApi() error {
return api.Logger.Close()
}
type ApiResponse[R any] struct {
Ok bool `json:"ok"`
Description string `json:"description,omitempty"`
Result R `json:"result,omitempty"`
ErrorCode int `json:"error_code,omitempty"`
}
type TelegramRequest[R, P any] struct {
method string
params P
}
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) {
var zero R
data, err := json.Marshal(r.params)
if err != nil {
return zero, err
}
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, "<TOKEN>"))
}
req, err := http.NewRequestWithContext(ctx, "POST", u, buf)
if err != nil {
return zero, err
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Accept", "application/json")
req.Header.Set("User-Agent", fmt.Sprintf("Laniakea/%s", utils.VersionString))
res, err := 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)
data, err = io.ReadAll(reader)
if err != nil {
return zero, err
}
if api.Logger != nil {
api.Logger.Debugln(fmt.Sprintf("RES %s %s", 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) {
ctx := context.Background()
return r.DoWithContext(ctx, api)
}

View File

@@ -0,0 +1,262 @@
package tgapi
type SendPhotoP struct {
BusinessConnectionID string `json:"business_connection_id,omitempty"`
ChatID int `json:"chat_id"`
MessageThreadID int `json:"message_thread_id,omitempty"`
DirectMessagesTopicID int `json:"direct_messages_topic_id,omitempty"`
Photo string `json:"photo"`
Caption string `json:"caption,omitempty"`
ParseMode ParseMode `json:"parse_mode,omitempty"`
CaptionEntities []*MessageEntity `json:"caption_entities,omitempty"`
ShowCaptionAboveMedia bool `json:"show_caption_above_media,omitempty"`
HasSpoiler bool `json:"has_spoiler,omitempty"`
DisableNotifications bool `json:"disable_notifications,omitempty"`
ProtectContent bool `json:"protect_content,omitempty"`
AllowPaidBroadcast bool `json:"allow_paid_broadcast,omitempty"`
MessageEffectID string `json:"message_effect_id,omitempty"`
SuggestedPostParameters *SuggestedPostParameters `json:"suggested_post_parameters,omitempty"`
ReplyParameters *ReplyParameters `json:"reply_parameters,omitempty"`
ReplyMarkup *ReplyMarkup `json:"reply_markup,omitempty"`
}
func (api *Api) SendPhoto(params SendPhotoP) (Message, error) {
req := NewRequest[Message]("sendPhoto", params)
return req.Do(api)
}
type SendAudioP struct {
BusinessConnectionID string `json:"business_connection_id,omitempty"`
ChatID int `json:"chat_id"`
MessageThreadID int `json:"message_thread_id,omitempty"`
DirectMessagesTopicID int `json:"direct_messages_topic_id,omitempty"`
Audio string `json:"audio"`
Caption string `json:"caption,omitempty"`
ParseMode ParseMode `json:"parse_mode,omitempty"`
CaptionEntities []*MessageEntity `json:"caption_entities,omitempty"`
Duration int `json:"duration,omitempty"`
Performer string `json:"performer,omitempty"`
Title string `json:"title,omitempty"`
DisableNotification bool `json:"disable_notification,omitempty"`
ProtectContent bool `json:"protect_content,omitempty"`
AllowPaidBroadcast bool `json:"allow_paid_broadcast,omitempty"`
MessageEffectID string `json:"message_effect_id,omitempty"`
SuggestedPostParameters *SuggestedPostParameters `json:"suggested_post_parameters,omitempty"`
ReplyParameters *ReplyParameters `json:"reply_parameters,omitempty"`
ReplyMarkup *ReplyMarkup `json:"reply_markup,omitempty"`
}
func (api *Api) SendAudio(params SendAudioP) (Message, error) {
req := NewRequest[Message]("sendAudio", params)
return req.Do(api)
}
type SendDocumentP struct {
BusinessConnectionID string `json:"business_connection_id,omitempty"`
ChatID int `json:"chat_id"`
MessageThreadID int `json:"message_thread_id,omitempty"`
DirectMessagesTopicID int `json:"direct_messages_topic_id,omitempty"`
Document string `json:"document"`
Caption string `json:"caption,omitempty"`
ParseMode ParseMode `json:"parse_mode,omitempty"`
CaptionEntities []*MessageEntity `json:"caption_entities,omitempty"`
DisableNotification bool `json:"disable_notification,omitempty"`
ProtectContent bool `json:"protect_content,omitempty"`
AllowPaidBroadcast bool `json:"allow_paid_broadcast,omitempty"`
MessageEffectID string `json:"message_effect_id,omitempty"`
SuggestedPostParameters *SuggestedPostParameters `json:"suggested_post_parameters,omitempty"`
ReplyParameters *ReplyParameters `json:"reply_parameters,omitempty"`
ReplyMarkup *ReplyMarkup `json:"reply_markup,omitempty"`
}
func (api *Api) SendDocument(params SendDocumentP) (Message, error) {
req := NewRequest[Message]("sendDocument", params)
return req.Do(api)
}
type SendVideoP struct {
BusinessConnectionID string `json:"business_connection_id,omitempty"`
ChatID int `json:"chat_id"`
MessageThreadID int `json:"message_thread_id,omitempty"`
DirectMessagesTopicID int `json:"direct_messages_topic_id,omitempty"`
Video string `json:"video"`
Duration int `json:"duration,omitempty"`
Width int `json:"width,omitempty"`
Height int `json:"height,omitempty"`
Cover string `json:"cover,omitempty"`
StartTimestamp int `json:"start_timestamp,omitempty"`
Caption string `json:"caption,omitempty"`
ParseMode ParseMode `json:"parse_mode,omitempty"`
CaptionEntities []*MessageEntity `json:"caption_entities,omitempty"`
ShowCaptionAboveMedia bool `json:"show_caption_above_media,omitempty"`
HasSpoiler bool `json:"has_spoiler,omitempty"`
SupportsStreaming bool `json:"supports_streaming,omitempty"`
DisableNotification bool `json:"disable_notification,omitempty"`
ProtectContent bool `json:"protect_content,omitempty"`
AllowPaidBroadcast bool `json:"allow_paid_broadcast,omitempty"`
MessageEffectID string `json:"message_effect_id,omitempty"`
SuggestedPostParameters *SuggestedPostParameters `json:"suggested_post_parameters,omitempty"`
ReplyParameters *ReplyParameters `json:"reply_parameters,omitempty"`
ReplyMarkup *ReplyMarkup `json:"reply_markup,omitempty"`
}
func (api *Api) SendVideo(params SendVideoP) (Message, error) {
req := NewRequest[Message]("sendVideo", params)
return req.Do(api)
}
type SendAnimationP struct {
BusinessConnectionID string `json:"business_connection_id,omitempty"`
ChatID int `json:"chat_id"`
MessageThreadID int `json:"message_thread_id,omitempty"`
DirectMessagesTopicID int `json:"direct_messages_topic_id,omitempty"`
Animation string `json:"animation"`
Duration int `json:"duration,omitempty"`
Width int `json:"width,omitempty"`
Height int `json:"height,omitempty"`
Caption string `json:"caption,omitempty"`
ParseMode ParseMode `json:"parse_mode,omitempty"`
CaptionEntities []*MessageEntity `json:"caption_entities,omitempty"`
ShowCaptionAboveMedia bool `json:"show_caption_above_media,omitempty"`
HasSpoiler bool `json:"has_spoiler,omitempty"`
DisableNotification bool `json:"disable_notification,omitempty"`
ProtectContent bool `json:"protect_content,omitempty"`
AllowPaidBroadcast bool `json:"allow_paid_broadcast,omitempty"`
MessageEffectID string `json:"message_effect_id,omitempty"`
SuggestedPostParameters *SuggestedPostParameters `json:"suggested_post_parameters,omitempty"`
ReplyParameters *ReplyParameters `json:"reply_parameters,omitempty"`
ReplyMarkup *ReplyMarkup `json:"reply_markup,omitempty"`
}
func (api *Api) SendAnimation(p SendAnimationP) (Message, error) {
req := NewRequest[Message]("sendAnimation", p)
return req.Do(api)
}
type SendVoiceP struct {
BusinessConnectionID string `json:"business_connection_id,omitempty"`
ChatID int `json:"chat_id"`
MessageThreadID int `json:"message_thread_id,omitempty"`
DirectMessagesTopicID int `json:"direct_messages_topic_id,omitempty"`
Voice string `json:"voice"`
Caption string `json:"caption,omitempty"`
ParseMode ParseMode `json:"parse_mode,omitempty"`
CaptionEntities []*MessageEntity `json:"caption_entities,omitempty"`
Duration int `json:"duration,omitempty"`
DisableNotification bool `json:"disable_notification,omitempty"`
ProtectContent bool `json:"protect_content,omitempty"`
AllowPaidBroadcast bool `json:"allow_paid_broadcast,omitempty"`
MessageEffectID string `json:"message_effect_id,omitempty"`
SuggestedPostParameters *SuggestedPostParameters `json:"suggested_post_parameters,omitempty"`
ReplyParameters *ReplyParameters `json:"reply_parameters,omitempty"`
ReplyMarkup *ReplyMarkup `json:"reply_markup,omitempty"`
}
func (api *Api) SendVoice(params *SendVoiceP) (Message, error) {
req := NewRequest[Message]("sendVoice", params)
return req.Do(api)
}
type SendVideoNoteP struct {
BusinessConnectionID string `json:"business_connection_id,omitempty"`
ChatID int `json:"chat_id"`
MessageThreadID int `json:"message_thread_id,omitempty"`
DirectMessagesTopicID int `json:"direct_messages_topic_id,omitempty"`
VideoNote string `json:"video_note"`
Duration int `json:"duration,omitempty"`
Length int `json:"length,omitempty"`
DisableNotification bool `json:"disable_notification,omitempty"`
ProtectContent bool `json:"protect_content,omitempty"`
AllowPaidBroadcast bool `json:"allow_paid_broadcast,omitempty"`
MessageEffectID string `json:"message_effect_id,omitempty"`
SuggestedPostParameters *SuggestedPostParameters `json:"suggested_post_parameters,omitempty"`
ReplyParameters *ReplyParameters `json:"reply_parameters,omitempty"`
ReplyMarkup *ReplyMarkup `json:"reply_markup,omitempty"`
}
func (api *Api) SendVideoNote(params SendVideoNoteP) (Message, error) {
req := NewRequest[Message]("sendVideoNote", params)
return req.Do(api)
}
type SendPaidMediaP[T InputPaidMedia] struct {
BusinessConnectionID string `json:"business_connection_id,omitempty"`
ChatID int `json:"chat_id"`
MessageThreadID int `json:"message_thread_id,omitempty"`
DirectMessagesTopicID int `json:"direct_messages_topic_id,omitempty"`
StarCount int `json:"star_count,omitempty"`
Media []T `json:"media"`
Payload string `json:"payload,omitempty"`
Caption string `json:"caption,omitempty"`
ParseMode ParseMode `json:"parse_mode,omitempty"`
CaptionEntities []*MessageEntity `json:"caption_entities,omitempty"`
ShowCaptionAboveMedia bool `json:"show_caption_above_media,omitempty"`
DisableNotification bool `json:"disable_notification,omitempty"`
ProtectContent bool `json:"protect_content,omitempty"`
AllowPaidBroadcast bool `json:"allow_paid_broadcast,omitempty"`
SuggestedPostParameters *SuggestedPostParameters `json:"suggested_post_parameters,omitempty"`
ReplyParameters *ReplyParameters `json:"reply_parameters,omitempty"`
ReplyMarkup *ReplyMarkup `json:"reply_markup,omitempty"`
}
func (api *Api) SendPaidMediaPhoto(params SendPaidMediaP[InputPaidMediaPhoto]) (Message, error) {
req := NewRequest[Message]("sendPaidMedia", params)
return req.Do(api)
}
func (api *Api) SendPaidMediaVideo(params SendPaidMediaP[InputPaidMediaVideo]) (Message, error) {
req := NewRequest[Message]("sendPaidMedia", params)
return req.Do(api)
}
type SendMediaGroupP[T InputMedia] struct {
BusinessConnectionID string `json:"business_connection_id,omitempty"`
ChatID int `json:"chat_id"`
MessageThreadID int `json:"message_thread_id,omitempty"`
DirectMessagesTopicID int `json:"direct_messages_topic_id,omitempty"`
Media []T `json:"media"`
DisableNotification bool `json:"disable_notification,omitempty"`
ProtectContent bool `json:"protect_content,omitempty"`
AllowPaidBroadcast bool `json:"allow_paid_broadcast,omitempty"`
MessageEffectID string `json:"message_effect_id,omitempty"`
ReplyParameters *ReplyParameters `json:"reply_parameters,omitempty"`
}
func (api *Api) SendMediaGroupAudio(p SendMediaGroupP[InputMediaAudio]) (Message, error) {
req := NewRequest[Message]("sendMediaGroupAudio", p)
return req.Do(api)
}
func (api *Api) SendMediaGroupDocument(p SendMediaGroupP[InputMediaDocument]) (Message, error) {
req := NewRequest[Message]("sendMediaGroupDocument", p)
return req.Do(api)
}
func (api *Api) SendMediaGroupPhoto(p SendMediaGroupP[InputMediaPhoto]) (Message, error) {
req := NewRequest[Message]("sendMediaGroupPhoto", p)
return req.Do(api)
}
func (api *Api) SendMediaGroupVideo(p SendMediaGroupP[InputMediaVideo]) (Message, error) {
req := NewRequest[Message]("sendMediaGroupVideo", p)
return req.Do(api)
}

109
tgapi/attachments_types.go Normal file
View File

@@ -0,0 +1,109 @@
package tgapi
type InputMedia interface {
InputMediaPhoto | InputMediaVideo | InputMediaAudio | InputMediaDocument
}
type InputMediaType string
const (
InputMediaTypeAnimation InputMediaType = "animation"
InputMediaTypeDocument InputMediaType = "document"
InputMediaTypePhoto InputMediaType = "photo"
InputMediaTypeVideo InputMediaType = "video"
InputMediaTypeAudio InputMediaType = "audio"
)
type InputMediaPhoto struct {
Type InputMediaType `json:"type"`
Media string `json:"media"`
Caption string `json:"caption,omitempty"`
ParseMode ParseMode `json:"parse_mode,omitempty"`
CaptionEntities []MessageEntity `json:"caption_entities,omitempty"`
ShowCaptionAboveMedia bool `json:"show_caption_above_media,omitempty"`
HasSpoiler bool `json:"has_spoiler,omitempty"`
}
type InputMediaVideo struct {
Type InputMediaType `json:"type"`
Media string `json:"media"`
Cover string `json:"cover"`
StartTimestamp int `json:"start_timestamp"`
Caption string `json:"caption,omitempty"`
ParseMode ParseMode `json:"parse_mode,omitempty"`
CaptionEntities []MessageEntity `json:"caption_entities,omitempty"`
ShowCaptionAboveMedia bool `json:"show_caption_above_media,omitempty"`
Width int `json:"width,omitempty"`
Height int `json:"height,omitempty"`
Duration int `json:"duration,omitempty"`
SupportsStreaming bool `json:"supports_streaming,omitempty"`
HasSpoiler bool `json:"has_spoiler,omitempty"`
}
type InputMediaAnimation struct {
Type InputMediaType `json:"type"`
Media string `json:"media"`
Caption string `json:"caption,omitempty"`
ParseMode ParseMode `json:"parse_mode,omitempty"`
CaptionEntities []MessageEntity `json:"caption_entities,omitempty"`
ShowCaptionAboveMedia bool `json:"show_caption_above_media,omitempty"`
Width int `json:"width,omitempty"`
Height int `json:"height,omitempty"`
Duration int `json:"duration,omitempty"`
HasSpoiler bool `json:"has_spoiler,omitempty"`
}
type InputMediaAudio struct {
Type InputMediaType `json:"type"`
Media string `json:"media"`
Caption string `json:"caption,omitempty"`
ParseMode ParseMode `json:"parse_mode,omitempty"`
CaptionEntities []MessageEntity `json:"caption_entities,omitempty"`
Duration int `json:"duration,omitempty"`
Performer string `json:"performer,omitempty"`
Title string `json:"title,omitempty"`
}
type InputMediaDocument struct {
Type InputMediaType `json:"type"`
Media string `json:"media"`
Caption string `json:"caption,omitempty"`
ParseMode ParseMode `json:"parse_mode,omitempty"`
CaptionEntities []MessageEntity `json:"caption_entities,omitempty"`
}
type InputPaidMediaType string
const (
InputPaidMediaTypeVideo InputPaidMediaType = "video"
InputPaidMediaTypePhoto InputPaidMediaType = "photo"
)
type InputPaidMedia interface {
InputPaidMediaVideo | InputPaidMediaPhoto
}
type InputPaidMediaPhoto struct {
Type InputPaidMediaType `json:"type"`
Media string `json:"media"`
}
type InputPaidMediaVideo struct {
Type InputPaidMediaType `json:"type"`
Media string `json:"media"`
Cover string `json:"cover"`
StartTimestamp int64 `json:"start_timestamp"`
Width int `json:"width"`
Height int `json:"height"`
Duration int `json:"duration"`
SupportsStreaming bool `json:"supports_streaming"`
}
type PhotoSize struct {
FileID string `json:"file_id"`
FileUniqueID string `json:"file_unique_id"`
Width int `json:"width"`
Height int `json:"height"`
FileSize int `json:"file_size,omitempty"`
}

186
tgapi/bot_methods.go Normal file
View File

@@ -0,0 +1,186 @@
package tgapi
type SetMyCommandsP struct {
Commands []BotCommand `json:"commands"`
Scope *BaseBotCommandScope `json:"scope,omitempty"`
Language string `json:"language_code,omitempty"`
}
func (api *Api) SetMyCommands(p SetMyCommandsP) (bool, error) {
req := NewRequest[bool]("setMyCommands", p)
return req.Do(api)
}
type DeleteMyCommandsP struct {
Scope *BaseBotCommandScope `json:"scope,omitempty"`
Language string `json:"language_code,omitempty"`
}
func (api *Api) DeleteMyCommands(p DeleteMyCommandsP) (bool, error) {
req := NewRequest[bool]("deleteMyCommands", p)
return req.Do(api)
}
type GetMyCommands struct {
Scope *BaseBotCommandScope `json:"scope,omitempty"`
Language string `json:"language_code,omitempty"`
}
func (api *Api) GetMyCommands(p GetMyCommands) ([]BotCommand, error) {
req := NewRequest[[]BotCommand]("getMyCommands", p)
return req.Do(api)
}
type SetMyName struct {
Name string `json:"name"`
Language string `json:"language_code,omitempty"`
}
func (api *Api) SetMyName(p SetMyName) (bool, error) {
req := NewRequest[bool]("setMyName", p)
return req.Do(api)
}
type GetMyName struct {
Language string `json:"language_code,omitempty"`
}
func (api *Api) GetMyName(p GetMyName) (BotName, error) {
req := NewRequest[BotName]("getMyName", p)
return req.Do(api)
}
type SetMyDescription struct {
Description string `json:"description"`
Language string `json:"language_code,omitempty"`
}
func (api *Api) SetMyDescription(p SetMyDescription) (bool, error) {
req := NewRequest[bool]("setMyDescription", p)
return req.Do(api)
}
type GetMyDescription struct {
Language string `json:"language_code,omitempty"`
}
func (api *Api) GetMyDescription(p GetMyDescription) (BotDescription, error) {
req := NewRequest[BotDescription]("getMyDescription", p)
return req.Do(api)
}
type SetMyShortDescription struct {
ShortDescription string `json:"short_description,omitempty"`
Language string `json:"language_code,omitempty"`
}
func (api *Api) SetMyShortDescription(p SetMyShortDescription) (bool, error) {
req := NewRequest[bool]("setMyShortDescription", p)
return req.Do(api)
}
type GetMyShortDescription struct {
Language string `json:"language_code,omitempty"`
}
func (api *Api) GetMyShortDescription(p GetMyShortDescription) (BotShortDescription, error) {
req := NewRequest[BotShortDescription]("getMyShortDescription", p)
return req.Do(api)
}
type SetMyProfilePhotoP[T InputProfilePhoto] struct {
Photo T `json:"photo"`
}
func (api *Api) SetMyProfilePhotoStatic(p SetMyProfilePhotoP[InputProfilePhotoStatic]) (bool, error) {
req := NewRequest[bool]("setMyProfilePhoto", p)
return req.Do(api)
}
func (api *Api) SetMyProfilePhotoAnimated(p SetMyProfilePhotoP[InputProfilePhotoAnimated]) (bool, error) {
req := NewRequest[bool]("setMyProfilePhoto", p)
return req.Do(api)
}
func (api *Api) RemoveMyProfilePhoto() (bool, error) {
req := NewRequest[bool]("removeMyProfilePhoto", NoParams)
return req.Do(api)
}
type SetChatMenuButtonP[T MenuButton] struct {
ChatID int `json:"chat_id"`
MenuButton T `json:"menu_button"`
}
func (api *Api) SetChatMenuButtonCommands(p SetChatMenuButtonP[MenuButtonCommands]) (bool, error) {
req := NewRequest[bool]("setChatMenuButton", p)
return req.Do(api)
}
func (api *Api) SetChatMenuButtonWebApp(p SetChatMenuButtonP[MenuButtonWebApp]) (bool, error) {
req := NewRequest[bool]("setChatMenuButton", p)
return req.Do(api)
}
func (api *Api) SetChatMenuButtonDefault(p SetChatMenuButtonP[MenuButtonDefault]) (bool, error) {
req := NewRequest[bool]("setChatMenuButton", p)
return req.Do(api)
}
type GetChatMenuButtonP struct {
ChatID int `json:"chat_id"`
}
func (api *Api) GetChatMenuButton(p GetChatMenuButtonP) (BaseMenuButton, error) {
req := NewRequest[BaseMenuButton]("getChatMenuButton", p)
return req.Do(api)
}
type SetMyDefaultAdministratorRightsP struct {
Rights *ChatAdministratorRights `json:"rights"`
ForChannels bool `json:"for_channels"`
}
func (api *Api) SetMyDefaultAdministratorRights(p SetMyDefaultAdministratorRightsP) (bool, error) {
req := NewRequest[bool]("setMyDefaultAdministratorRights", p)
return req.Do(api)
}
type GetMyDefaultAdministratorRightsP struct {
ForChannels bool `json:"for_channels"`
}
func (api *Api) GetMyDefaultAdministratorRights(p GetMyDefaultAdministratorRightsP) (ChatAdministratorRights, error) {
req := NewRequest[ChatAdministratorRights]("getMyDefaultAdministratorRights", p)
return req.Do(api)
}
func (api *Api) GetAvailableGifts() (Gifts, error) {
req := NewRequest[Gifts]("getAvailableGifts", NoParams)
return req.Do(api)
}
type SendGiftP struct {
UserID int `json:"user_id,omitempty"`
ChatID int `json:"chat_id,omitempty"`
GiftID string `json:"gift_id"`
PayForUpgrade bool `json:"pay_for_upgrade"`
Text string `json:"text"`
TextParseMode ParseMode `json:"text_parse_mode,omitempty"`
TextEntities []MessageEntity `json:"text_entities,omitempty"`
}
func (api *Api) SendGift(p SendGiftP) (bool, error) {
req := NewRequest[bool]("sendGift", p)
return req.Do(api)
}
type GiftPremiumSubscriptionP struct {
UserID int `json:"user_id"`
MonthCount int `json:"month_count"`
StarCount int `json:"star_count"`
Text string `json:"text,omitempty"`
TextParseMode ParseMode `json:"text_parse_mode,omitempty"`
TextEntities []MessageEntity `json:"text_entities,omitempty"`
}
func (api *Api) GiftPremiumSubscription(p GiftPremiumSubscriptionP) (bool, error) {
req := NewRequest[bool]("giftPremiumSubscription", p)
return req.Do(api)
}

99
tgapi/bot_types.go Normal file
View File

@@ -0,0 +1,99 @@
package tgapi
type BotCommand struct {
Command string `json:"command"`
Description string `json:"description"`
}
type BotCommandScopeType string
const (
BotCommandScopeDefaultType BotCommandScopeType = "default"
BotCommandScopePrivateType BotCommandScopeType = "all_private_chats"
BotCommandScopeGroupType BotCommandScopeType = "all_groups_chats"
BotCommandScopeAllChatAdministratorsType BotCommandScopeType = "all_chat_administrators"
BotCommandScopeChatType BotCommandScopeType = "chat"
BotCommandScopeChatAdministratorsType BotCommandScopeType = "chat_administrators"
BotCommandScopeChatMemberType BotCommandScopeType = "chat_member"
)
type BaseBotCommandScope struct {
Type BotCommandScopeType `json:"type"`
}
type BotCommandScopeDefault struct {
BaseBotCommandScope
}
type BotCommandScopePrivateChats struct {
BaseBotCommandScope
}
type BotCommandScopeAllGroupChats struct {
BaseBotCommandScope
}
type BotCommandScopeAllChatAdministrators struct {
BaseBotCommandScope
}
type BotCommandScopeChat struct {
BaseBotCommandScope
ChatID int `json:"chat_id"`
}
type BotCommandScopeChatAdministrators struct {
BaseBotCommandScope
ChatID int `json:"chat_id"`
}
type BotCommandScopeChatMember struct {
BaseBotCommandScope
ChatID int `json:"chat_id"`
UserID int `json:"user_id"`
}
type BotName struct {
Name string `json:"name"`
}
type BotDescription struct {
Description string `json:"description"`
}
type BotShortDescription struct {
ShortDescription string `json:"short_description"`
}
const (
InputProfilePhotoStaticType InputProfilePhotoType = "static"
InputProfilePhotoAnimatedType InputProfilePhotoType = "animated"
)
type InputProfilePhotoType string
type InputProfilePhoto interface {
InputProfilePhotoStatic | InputProfilePhotoAnimated
}
type BaseInputProfilePhoto struct {
Type InputProfilePhotoType `json:"type"`
}
type InputProfilePhotoStatic struct {
BaseInputProfilePhoto
Photo string `json:"photo"`
}
type InputProfilePhotoAnimated struct {
BaseInputProfilePhoto
Animation string `json:"animation"`
MainFrameTimestamp float64 `json:"main_frame_timestamp"`
}
const (
MenuButtonCommandsType MenuButtonType = "commands"
MenuButtonWebAppType MenuButtonType = "web_app"
MenuButtonDefaultType MenuButtonType = "default"
)
type MenuButtonType string
type MenuButton interface {
MenuButtonCommands | MenuButtonDefault | MenuButtonWebApp
}
type BaseMenuButton struct {
Type MenuButtonType `json:"type"`
}
type MenuButtonCommands struct{ BaseMenuButton }
type MenuButtonDefault struct{ BaseMenuButton }
type MenuButtonWebApp struct {
BaseMenuButton
Text string `json:"text"`
WebApp WebAppInfo `json:"web_app"`
}

149
tgapi/business_methods.go Normal file
View File

@@ -0,0 +1,149 @@
package tgapi
type VerifyUserP struct {
UserID int `json:"user_id"`
CustomDescription string `json:"custom_description,omitempty"`
}
func (api *Api) VerifyUser(p VerifyUserP) (bool, error) {
req := NewRequest[bool]("verifyUser", p)
return req.Do(api)
}
type VerifyChatP struct {
ChatID int `json:"chat_id"`
CustomDescription string `json:"custom_description,omitempty"`
}
func (api *Api) VerifyChat(p VerifyChatP) (bool, error) {
req := NewRequest[bool]("verifyChat", p)
return req.Do(api)
}
type RemoveUserVerificationP struct {
UserID int `json:"user_id"`
}
func (api *Api) RemoveUserVerification(p RemoveUserVerificationP) (bool, error) {
req := NewRequest[bool]("removeUserVerification", p)
return req.Do(api)
}
type RemoveChatVerificationP struct {
ChatID int `json:"chat_id"`
}
func (api *Api) RemoveChatVerification(p RemoveChatVerificationP) (bool, error) {
req := NewRequest[bool]("removeChatVerification", p)
return req.Do(api)
}
type ReadBusinessMessageP struct {
BusinessConnectionID string `json:"business_connection_id"`
ChatID int `json:"chat_id"`
MessageID int `json:"message_id"`
}
func (api *Api) ReadBusinessMessage(p ReadBusinessMessageP) (bool, error) {
req := NewRequest[bool]("readBusinessMessage", p)
return req.Do(api)
}
type DeleteBusinessMessageP struct {
BusinessConnectionID string `json:"business_connection_id"`
MessageIDs []int `json:"message_ids"`
}
func (api *Api) DeleteBusinessMessage(p DeleteBusinessMessageP) (bool, error) {
req := NewRequest[bool]("deleteBusinessMessage", p)
return req.Do(api)
}
type SetBusinessAccountNameP struct {
BusinessConnectionID string `json:"business_connection_id"`
FirstName string `json:"first_name"`
LastName string `json:"last_name,omitempty"`
}
func (api *Api) SetBusinessAccountName(p SetBusinessAccountNameP) (bool, error) {
req := NewRequest[bool]("setBusinessAccountName", p)
return req.Do(api)
}
type SetBusinessAccountUsernameP struct {
BusinessConnectionID string `json:"business_connection_id"`
Username string `json:"username,omitempty"`
}
func (api *Api) SetBusinessAccountUsername(p SetBusinessAccountUsernameP) (bool, error) {
req := NewRequest[bool]("setBusinessAccountUsername", p)
return req.Do(api)
}
type SetBusinessAccountBioP struct {
BusinessConnectionID string `json:"business_connection_id"`
Bio string `json:"bio,omitempty"`
}
func (api *Api) SetBusinessAccountBio(p SetBusinessAccountBioP) (bool, error) {
req := NewRequest[bool]("setBusinessAccountBio", p)
return req.Do(api)
}
type SetBusinessAccountProfilePhoto[T InputProfilePhoto] struct {
BusinessConnectionID string `json:"business_connection_id"`
Photo T `json:"photo,omitempty"`
IsPublic bool `json:"is_public,omitempty"`
}
func (api *Api) SetBusinessAccountProfilePhotoStatic(p SetMyProfilePhotoP[InputProfilePhotoStatic]) (bool, error) {
req := NewRequest[bool]("setBusinessAccountProfilePhoto", p)
return req.Do(api)
}
func (api *Api) SetBusinessAccountProfilePhotoAnimated(p SetMyProfilePhotoP[InputProfilePhotoAnimated]) (bool, error) {
req := NewRequest[bool]("setBusinessAccountProfilePhoto", p)
return req.Do(api)
}
type RemoveBusinessAccountProfilePhotoP struct {
BusinessConnectionID string `json:"business_connection_id"`
IsPublic bool `json:"is_public,omitempty"`
}
func (api *Api) RemoveBusinessAccountProfilePhoto(p RemoveBusinessAccountProfilePhotoP) (bool, error) {
req := NewRequest[bool]("removeBusinessAccountProfilePhoto", p)
return req.Do(api)
}
type SetBusinessAccountGiftSettingsP struct {
BusinessConnectionID string `json:"business_connection_id"`
ShowGiftButton bool `json:"show_gift_button"`
AcceptedGiftTypes AcceptedGiftTypes `json:"accepted_gift_types"`
}
func (api *Api) SetBusinessAccountGiftSettings(p SetBusinessAccountGiftSettingsP) (bool, error) {
req := NewRequest[bool]("setBusinessAccountGiftSettings", p)
return req.Do(api)
}
type GetBusinessAccountStarBalanceP struct {
BusinessConnectionID string `json:"business_connection_id"`
}
func (api *Api) GetBusinessAccountStarBalance(p GetBusinessAccountStarBalanceP) (StarAmount, error) {
req := NewRequest[StarAmount]("getBusinessAccountGiftSettings", p)
return req.Do(api)
}
type TransferBusinessAccountStartP struct {
BusinessConnectionID string `json:"business_connection_id"`
StarCount int `json:"star_count"`
}
func (api *Api) TransferBusinessAccountStart(p TransferBusinessAccountStartP) (bool, error) {
req := NewRequest[bool]("transferBusinessAccountStart", p)
return req.Do(api)
}
type GetBusinessAccountGiftsP struct {
}

44
tgapi/business_types.go Normal file
View File

@@ -0,0 +1,44 @@
package tgapi
type BusinessIntro struct {
Title string `json:"title,omitempty"`
Message string `json:"message,omitempty"`
Sticker *Sticker `json:"sticker,omitempty"`
}
type BusinessLocation struct {
Address string `json:"address"`
Location *Location `json:"location,omitempty"`
}
type BusinessOpeningHoursInterval struct {
OpeningMinute int `json:"opening_minute"`
ClosingMinute int `json:"closing_minute"`
}
type BusinessOpeningHours struct {
TimeZoneName string `json:"time_zone_name"`
OpeningHours []Birthdate `json:"opening_hours"`
}
type BusinessBotRights struct {
CanReply *bool `json:"can_reply,omitempty"`
CanReadMessages *bool `json:"can_read_messages,omitempty"`
CanDeleteSentMessages *bool `json:"can_delete_sent_messages,omitempty"`
CanDeleteAllMessages *bool `json:"can_delete_all_messages,omitempty"`
CanEditName *bool `json:"can_edit_name,omitempty"`
CanEditBio *bool `json:"can_edit_bio,omitempty"`
CanEditProfilePhoto *bool `json:"can_edit_profile_photo,omitempty"`
CanEditUsername *bool `json:"can_edit_username,omitempty"`
CanChangeGiftSettings *bool `json:"can_change_gift_settings,omitempty"`
CanViewGiftsAndStars *bool `json:"can_view_gifts_and_stars,omitempty"`
CanConvertGiftsToStars *bool `json:"can_convert_gifts_to_stars,omitempty"`
CanTransferAndUpgradeGifts *bool `json:"can_transfer_and_upgrade_gifts,omitempty"`
CanTransferStars *bool `json:"can_transfer_stars,omitempty"`
CanManageStories *bool `json:"can_manage_stories,omitempty"`
}
type BusinessConnection struct {
ID string `json:"id"`
User User `json:"user"`
UserChatID int `json:"user_chat_id"`
Date int `json:"date"`
Rights *BusinessBotRights `json:"rights,omitempty"`
IsEnabled bool `json:"id_enabled"`
}

337
tgapi/chat_methods.go Normal file
View File

@@ -0,0 +1,337 @@
package tgapi
type BanChatMemberP struct {
ChatID int `json:"chat_id"`
UserID int `json:"user_id"`
UntilDate int64 `json:"until_date,omitempty"`
RevokeMessages bool `json:"revoke_messages,omitempty"`
}
func (api *Api) BanChatMember(p BanChatMemberP) (bool, error) {
req := NewRequest[bool]("banChatMember", p)
return req.Do(api)
}
type UnbanChatMemberP struct {
ChatID int `json:"chat_id"`
UserID int `json:"user_id"`
OnlyIfBanned bool `json:"only_if_banned"`
}
func (api *Api) UnbanChatMember(p UnbanChatMemberP) (bool, error) {
req := NewRequest[bool]("unbanChatMember", p)
return req.Do(api)
}
type RestrictChatMemberP struct {
ChatID int `json:"chat_id"`
UserID int `json:"user_id"`
Permissions ChatPermissions `json:"permissions"`
UseIndependentChatPermissions bool `json:"use_independent_chat_permissions,omitempty"`
UntilDate int `json:"until_date,omitempty"`
}
func (api *Api) RestrictChatMember(p RestrictChatMemberP) (bool, error) {
req := NewRequest[bool]("restrictChatMember", p)
return req.Do(api)
}
type PromoteChatMember struct {
ChatID int `json:"chat_id"`
UserID int `json:"user_id"`
IsAnonymous bool `json:"is_anonymous,omitempty"`
CanManageChat bool `json:"can_manage_chat,omitempty"`
CanDeleteMessages bool `json:"can_delete_messages,omitempty"`
CanManageVideoChats bool `json:"can_manage_video_chats,omitempty"`
CanRestrictMembers bool `json:"can_restrict_members,omitempty"`
CanPromoteMembers bool `json:"can_promote_members,omitempty"`
CanChangeInfo bool `json:"can_change_info,omitempty"`
CanInviteUsers bool `json:"can_invite_users,omitempty"`
CanPostStories bool `json:"can_post_stories,omitempty"`
CanEditStories bool `json:"can_edit_stories,omitempty"`
CanDeleteStories bool `json:"can_delete_stories,omitempty"`
CanPostMessages bool `json:"can_post_messages,omitempty"`
CanEditMessages bool `json:"can_edit_messages,omitempty"`
CanPinMessages bool `json:"can_pin_messages,omitempty"`
CanManageTopics bool `json:"can_manage_topics,omitempty"`
CanManageDirectMessages bool `json:"can_manage_direct_messages,omitempty"`
}
func (api *Api) PromoteChatMember(p PromoteChatMember) (bool, error) {
req := NewRequest[bool]("promoteChatMember", p)
return req.Do(api)
}
type SetChatAdministratorCustomTitleP struct {
ChatID int `json:"chat_id"`
UserID int `json:"user_id"`
CustomTitle string `json:"custom_title"`
}
func (api *Api) SetChatAdministratorCustomTitle(p SetChatAdministratorCustomTitleP) (bool, error) {
req := NewRequest[bool]("setChatAdministratorCustomTitle", p)
return req.Do(api)
}
type BanChatSenderChatP struct {
ChatID int `json:"chat_id"`
SenderChatID int `json:"sender_chat_id"`
}
func (api *Api) BanChatSenderChat(p BanChatSenderChatP) (bool, error) {
req := NewRequest[bool]("banChatSenderChat", p)
return req.Do(api)
}
type UnbanChatSenderChatP struct {
ChatID int `json:"chat_id"`
SenderChatID int `json:"sender_chat_id"`
}
func (api *Api) UnbanChatSenderChat(p BanChatSenderChatP) (bool, error) {
req := NewRequest[bool]("unbanChatSenderChat", p)
return req.Do(api)
}
type SetChatPermissionsP struct {
ChatID int `json:"chat_id"`
Permissions ChatPermissions `json:"permissions"`
UseIndependentChatPermissions bool `json:"use_independent_chat_permissions,omitempty"`
}
func (api *Api) SetChatPermissions(p SetChatPermissionsP) (bool, error) {
req := NewRequest[bool]("setChatPermissions", p)
return req.Do(api)
}
type ExportChatInviteLinkP struct {
ChatID int `json:"chat_id"`
}
func (api *Api) ExportChatInviteLink(p ExportChatInviteLinkP) (string, error) {
req := NewRequest[string]("exportChatInviteLink", p)
return req.Do(api)
}
type CreateChatInviteLinkP struct {
ChatID int `json:"chat_id"`
Name string `json:"name,omitempty"`
ExpireDate int `json:"expire_date,omitempty"`
MemberLimit int `json:"member_limit,omitempty"`
CreatesJoinRequest int `json:"creates_join_request,omitempty"`
}
func (api *Api) CreateChatInviteLink(p CreateChatInviteLinkP) (ChatInviteLink, error) {
req := NewRequest[ChatInviteLink]("createChatInviteLink", p)
return req.Do(api)
}
type EditChatInviteLinkP struct {
ChatID int `json:"chat_id"`
InviteLink string `json:"invite_link"`
Name string `json:"name,omitempty"`
ExpireDate int `json:"expire_date,omitempty"`
MemberLimit int `json:"member_limit,omitempty"`
CreatesJoinRequest int `json:"creates_join_request,omitempty"`
}
func (api *Api) EditChatInviteLink(p EditChatInviteLinkP) (ChatInviteLink, error) {
req := NewRequest[ChatInviteLink]("editChatInviteLink", p)
return req.Do(api)
}
type CreateChatSubscriptionInviteLinkP struct {
ChatID int `json:"chat_id"`
Name string `json:"name,omitempty"`
SubscriptionPeriod int `json:"subscription_period,omitempty"`
SubscriptionPrice int `json:"subscription_price,omitempty"`
}
func (api *Api) CreateChatSubscriptionInviteLink(p CreateChatSubscriptionInviteLinkP) (ChatInviteLink, error) {
req := NewRequest[ChatInviteLink]("createChatSubscriptionInviteLink", p)
return req.Do(api)
}
type EditChatSubscriptionInviteLinkP struct {
ChatID int `json:"chat_id"`
InviteLink string `json:"invite_link"`
Name string `json:"name,omitempty"`
}
func (api *Api) EditChatSubscriptionInviteLink(p EditChatSubscriptionInviteLinkP) (ChatInviteLink, error) {
req := NewRequest[ChatInviteLink]("editChatSubscriptionInviteLink", p)
return req.Do(api)
}
type RevokeChatInviteLinkP struct {
ChatID int `json:"chat_id"`
InviteLink string `json:"invite_link"`
}
func (api *Api) RevokeChatInviteLink(p RevokeChatInviteLinkP) (ChatInviteLink, error) {
req := NewRequest[ChatInviteLink]("revokeChatInviteLink", p)
return req.Do(api)
}
type ApproveChatJoinRequestP struct {
ChatID int `json:"chat_id"`
UserID int `json:"user_id"`
}
func (api *Api) ApproveChatJoinRequest(p ApproveChatJoinRequestP) (bool, error) {
req := NewRequest[bool]("approveChatJoinRequest", p)
return req.Do(api)
}
type DeclineChatJoinRequestP struct {
ChatID int `json:"chat_id"`
UserID int `json:"user_id"`
}
func (api *Api) DeclineChatJoinRequest(p DeclineChatJoinRequestP) (bool, error) {
req := NewRequest[bool]("declineChatJoinRequest", p)
return req.Do(api)
}
func (api *Api) SetChatPhoto() {
uploader := NewUploader(api)
defer uploader.Close()
}
type DeleteChatPhotoP struct {
ChatID int `json:"chat_id"`
}
func (api *Api) DeleteChatPhoto(p DeleteChatPhotoP) (bool, error) {
req := NewRequest[bool]("deleteChatPhoto", p)
return req.Do(api)
}
type SetChatTitleP struct {
ChatID int `json:"chat_id"`
Title string `json:"title"`
}
func (api *Api) SetChatTitle(p SetChatTitleP) (bool, error) {
req := NewRequest[bool]("setChatTitle", p)
return req.Do(api)
}
type SetChatDescriptionP struct {
ChatID int `json:"chat_id"`
Description string `json:"description"`
}
func (api *Api) SetChatDescription(p SetChatDescriptionP) (bool, error) {
req := NewRequest[bool]("setChatDescription", p)
return req.Do(api)
}
type PinChatMessageP struct {
BusinessConnectionID string `json:"business_connection_id,omitempty"`
ChatID int `json:"chat_id"`
MessageID int `json:"message_id"`
DisableNotification bool `json:"disable_notification,omitempty"`
}
func (api *Api) PinChatMessage(p PinChatMessageP) (bool, error) {
req := NewRequest[bool]("pinChatMessage", p)
return req.Do(api)
}
type UnpinChatMessageP struct {
BusinessConnectionID string `json:"business_connection_id,omitempty"`
ChatID int `json:"chat_id"`
MessageID int `json:"message_id"`
}
func (api *Api) UnpinChatMessage(p UnpinChatMessageP) (bool, error) {
req := NewRequest[bool]("unpinChatMessage", p)
return req.Do(api)
}
type UnpinAllChatMessagesP struct {
ChatID int `json:"chat_id"`
}
func (api *Api) UnpinAllChatMessages(p UnpinAllChatMessagesP) (bool, error) {
req := NewRequest[bool]("unpinAllChatMessages", p)
return req.Do(api)
}
type LeaveChatP struct {
ChatID int `json:"chat_id"`
}
func (api *Api) LeaveChat(p LeaveChatP) (bool, error) {
req := NewRequest[bool]("leaveChatP", p)
return req.Do(api)
}
type GetChatP struct {
ChatID int `json:"chat_id"`
}
func (api *Api) GetChatP(p GetChatP) (ChatFullInfo, error) {
req := NewRequest[ChatFullInfo]("getChatP", p)
return req.Do(api)
}
type GetChatAdministratorsP struct {
ChatID int `json:"chat_id"`
}
func (api *Api) GetChatAdministrators(p GetChatAdministratorsP) ([]BaseChatMember, error) {
req := NewRequest[[]BaseChatMember]("getChatAdministrators", p)
return req.Do(api)
}
type GetChatMembersCountP struct {
ChatID int `json:"chat_id"`
}
func (api *Api) GetChatMemberCount(p GetChatMembersCountP) (int, error) {
req := NewRequest[int]("getChatMemberCount", p)
return req.Do(api)
}
type GetChatMemberP struct {
ChatID int `json:"chat_id"`
UserID int `json:"user_id"`
}
func (api *Api) GetChatMember(p GetChatMemberP) (BaseChatMember, error) {
req := NewRequest[BaseChatMember]("getChatMember", p)
return req.Do(api)
}
type SetChatStickerSetP struct {
ChatID int `json:"chat_id"`
StickerSetName string `json:"sticker_set_name"`
}
func (api *Api) SetChatStickerSet(p SetChatStickerSetP) (bool, error) {
req := NewRequest[bool]("setChatStickerSet", p)
return req.Do(api)
}
type DeleteChatStickerSetP struct {
ChatID int `json:"chat_id"`
}
func (api *Api) DeleteChatStickerSet(p DeleteChatStickerSetP) (bool, error) {
req := NewRequest[bool]("deleteChatStickerSet", p)
return req.Do(api)
}
type GetUserChatBoostsP struct {
ChatID int `json:"chat_id"`
UserID int `json:"user_id"`
}
func (api *Api) GetUserChatBoosts(p GetUserChatBoostsP) (UserChatBoosts, error) {
req := NewRequest[UserChatBoosts]("getUserChatBoosts", p)
return req.Do(api)
}

242
tgapi/chat_types.go Normal file
View File

@@ -0,0 +1,242 @@
package tgapi
type Chat struct {
ID int `json:"id"`
Type string `json:"type"`
Title *string `json:"title,omitempty"`
Username *string `json:"username,omitempty"`
FirstName *string `json:"first_name,omitempty"`
LastName *string `json:"last_name,omitempty"`
IsForum *bool `json:"is_forum,omitempty"`
IsDirectMessages *bool `json:"is_direct_messages,omitempty"`
}
type ChatType string
const (
ChatTypePrivate ChatType = "private"
ChatTypeGroup ChatType = "group"
ChatTypeSupergroup ChatType = "supergroup"
ChatTypeChannel ChatType = "channel"
)
type ChatFullInfo struct {
ID int `json:"id"`
Type ChatType `json:"type"`
Title string `json:"title"`
Username string `json:"username"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
IsForum bool `json:"is_forum"`
IsDirectMessages bool `json:"is_direct_messages"`
AccentColorID int `json:"accent_color_id"`
MaxReactionCount int `json:"max_reaction_count"`
Photo *ChatPhoto `json:"photo,omitempty"`
ActiveUsernames []string `json:"active_usernames,omitempty"`
Birthdate *Birthdate `json:"birthdate,omitempty"`
BusinessIntro *BusinessIntro `json:"business_intro,omitempty"`
BusinessLocation *BusinessLocation `json:"business_location,omitempty"`
BusinessOpeningHours *BusinessOpeningHours `json:"business_opening_hours,omitempty"`
PersonalChat *Chat `json:"personal_chat,omitempty"`
ParentChat *Chat `json:"parent_chat,omitempty"`
AvailableReaction []BaseReaction `json:"available_reaction,omitempty"`
BackgroundCustomEmojiID *string `json:"background_custom_emoji_id,omitempty"`
ProfileAccentColorID *int `json:"profile_accent_color_id,omitempty"`
ProfileBackgroundCustomEmojiID *string `json:"profile_background_custom_emoji_id,omitempty"`
EmojiStatusCustomEmojiID *string `json:"emoji_status_custom_emoji_id,omitempty"`
EmojiStatusExpirationDate *int `json:"emoji_status_expiration_date,omitempty"`
Bio *string `json:"bio,omitempty"`
HasPrivateForwards *bool `json:"has_private_forwards,omitempty"`
HasRestrictedVoiceAndVideoMessages *bool `json:"has_restricted_voice_and_video_messages,omitempty"`
JoinToSendMessages *bool `json:"join_to_send_messages,omitempty"`
JoinByRequest *bool `json:"join_by_request,omitempty"`
Description *string `json:"description,omitempty"`
InviteLink *string `json:"invite_link,omitempty"`
PinnedMessage *Message `json:"pinned_message,omitempty"`
Permissions *ChatPermissions `json:"permissions,omitempty"`
AcceptedGiftTypes *AcceptedGiftTypes `json:"accepted_gift_types,omitempty"`
CanSendPaidMedia *bool `json:"can_send_paid_media,omitempty"`
SlowModeDelay *int `json:"slow_mode_delay,omitempty"`
UnrestrictedBoostCount *int `json:"unrestricted_boost_count,omitempty"`
MessageAutoDeleteTime *int `json:"message_auto_delete_time,omitempty"`
HasAggressiveAntiSpamEnabled *bool `json:"has_aggressive_anti_spam_enabled,omitempty"`
HasHiddenMembers *bool `json:"has_hidden_members,omitempty"`
HasProtectedContent *bool `json:"has_protected_content,omitempty"`
HasVisibleHistory *bool `json:"has_visible_history,omitempty"`
StickerSetName *string `json:"sticker_set_name,omitempty"`
CanSetStickerSet *bool `json:"can_set_sticker_set,omitempty"`
CustomEmojiStickerSetName *string `json:"custom_emoji_sticker_set_name,omitempty"`
LinkedChatID *int `json:"linked_chat_id,omitempty"`
Location *ChatLocation `json:"location,omitempty"`
Rating *UserRating `json:"rating,omitempty"`
FirstProfileAudio *Audio `json:"first_profile_audio,omitempty"`
UniqueGiftColors *UniqueGiftColors `json:"unique_gift_colors,omitempty"`
PaidMessageStarCount *int `json:"paid_message_star_count,omitempty"`
}
type ChatPhoto struct {
SmallFileID string `json:"small_file_id"`
SmallFileUniqueID string `json:"small_file_unique_id"`
BigFileID string `json:"big_file_id"`
BigFileUniqueID string `json:"big_file_unique_id"`
}
type ChatPermissions struct {
CanSendMessages bool `json:"can_send_messages"`
CanSendAudios bool `json:"can_send_audios"`
CanSendDocuments bool `json:"can_send_documents"`
CanSendPhotos bool `json:"can_send_photos"`
CanSendVideoNotes bool `json:"can_send_video_notes"`
CanSendVoiceNotes bool `json:"can_send_voice_notes"`
CanSendPolls bool `json:"can_send_polls"`
CanSendOtherMessages bool `json:"can_send_other_messages"`
CanAddWebPagePreview bool `json:"can_add_web_page_preview"`
CanChangeInfo bool `json:"can_change_info"`
CanInviteUsers bool `json:"can_invite_users"`
CanPinMessages bool `json:"can_pin_messages"`
CanManageTopics bool `json:"can_manage_topics"`
}
type ChatLocation struct {
Location Location `json:"location"`
Address string `json:"address"`
}
type ChatInviteLink struct {
InviteLink string `json:"invite_link"`
Creator User `json:"creator"`
CreateJoinRequest bool `json:"create_join_request"`
IsPrimary bool `json:"is_primary"`
IsRevoked bool `json:"is_revoked"`
Name *string `json:"name,omitempty"`
ExpireDate *int `json:"expire_date,omitempty"`
MemberLimit *int `json:"member_limit,omitempty"`
PendingJoinRequestCount *int `json:"pending_join_request_count,omitempty"`
SubscriptionPeriod *int `json:"subscription_period,omitempty"`
SubscriptionPrice *int `json:"subscription_price,omitempty"`
}
type ChatMemberStatusType string
const (
ChatMemberStatusOwner ChatMemberStatusType = "owner"
ChatMemberStatusAdministrator ChatMemberStatusType = "administrator"
ChatMemberStatusMember ChatMemberStatusType = "member"
ChatMemberStatusRestricted ChatMemberStatusType = "restricted"
ChatMemberStatusLeft ChatMemberStatusType = "left"
ChatMemberStatusBanned ChatMemberStatusType = "kicked"
)
type ChatMember interface {
ChatMemberOwner | ChatMemberAdministrator | ChatMemberMember | ChatMemberRestricted | ChatMemberLeft | ChatMemberBanned
}
type BaseChatMember struct {
Status ChatMemberStatusType `json:"status"`
User User `json:"user"`
}
type ChatMemberOwner struct {
BaseChatMember
IsAnonymous bool `json:"is_anonymous"`
CustomTitle *string `json:"custom_title,omitempty"`
}
type ChatMemberAdministrator struct {
BaseChatMember
CanBeEdited bool `json:"can_be_edited"`
IsAnonymous bool `json:"is_anonymous"`
CanManageChat bool `json:"can_manage_chat"`
CanDeleteMessages bool `json:"can_delete_messages"`
CanManageVideoChats bool `json:"can_manage_video_chats"`
CanRestrictMembers bool `json:"can_restrict_members"`
CanPromoteMembers bool `json:"can_promote_members"`
CanChangeInfo bool `json:"can_change_info"`
CanInviteUsers bool `json:"can_invite_users"`
CanPostStories bool `json:"can_post_stories"`
CanEditStories bool `json:"can_edit_stories"`
CanDeleteStories bool `json:"can_delete_stories"`
CanPostMessages *bool `json:"can_post_messages,omitempty"`
CanEditMessages *bool `json:"can_edit_messages,omitempty"`
CanPinMessages *bool `json:"can_pin_messages,omitempty"`
CanManageTopics *bool `json:"can_manage_topics,omitempty"`
CanManageDirectMessages *bool `json:"can_manage_direct_messages,omitempty"`
CustomTitle *string `json:"custom_title,omitempty"`
}
type ChatMemberMember struct {
BaseChatMember
UntilDate *int `json:"until_date,omitempty"`
}
type ChatMemberRestricted struct {
BaseChatMember
IsMember bool `json:"is_member"`
CanSendMessages bool `json:"can_send_messages"`
CanSendAudios bool `json:"can_send_audios"`
CanSendDocuments bool `json:"can_send_documents"`
CanSendVideos bool `json:"can_send_videos"`
CanSendVideoNotes bool `json:"can_send_video_notes"`
CanSendVoiceNotes bool `json:"can_send_voice_notes"`
CanSendPolls bool `json:"can_send_polls"`
CanSendOtherMessages bool `json:"can_send_other_messages"`
CanAddWebPagePreview bool `json:"can_add_web_page_preview"`
CanChangeInfo bool `json:"can_change_info"`
CanInviteUsers bool `json:"can_invite_users"`
CanPinMessages bool `json:"can_pin_messages"`
CanManageTopics bool `json:"can_manage_topics"`
UntilDate int `json:"until_date"`
}
type ChatMemberLeft struct {
BaseChatMember
}
type ChatMemberBanned struct {
BaseChatMember
UntilDate int `json:"until_date"`
}
type BaseChatBoostSource struct {
Source string `json:"source"`
User User `json:"user"`
}
type ChatBoostSourcePremium struct{ BaseChatBoostSource }
type ChatBoostSourceGiftCode struct{ BaseChatBoostSource }
type ChatBoostSourceGiveaway struct {
BaseChatBoostSource
GiveawayMessageID int `json:"giveaway_message_id"`
PrizeStarCount *int `json:"prize_star_count,omitempty"`
IsUnclaimed bool `json:"is_unclaimed"`
}
type ChatBoost[T BaseChatBoostSource] struct {
BoostID int `json:"boost_id"`
AddDate int `json:"add_date"`
ExpirationDate int `json:"expiration_date"`
Source T `json:"source"`
}
type UserChatBoosts struct {
Boosts []ChatBoost[BaseChatBoostSource] `json:"boosts"`
}
type ChatAdministratorRights struct {
IsAnonymous bool `json:"is_anonymous"`
CanManageChat bool `json:"can_manage_chat"`
CanDeleteMessages bool `json:"can_delete_messages"`
CanManageVideoChats bool `json:"can_manage_video_chats"`
CanRestrictMembers bool `json:"can_restrict_members"`
CanPromoteMembers bool `json:"can_promote_members"`
CanChangeInfo bool `json:"can_change_info"`
CanInviteUsers bool `json:"can_invite_users"`
CanPostStories bool `json:"can_post_stories"`
CanEditStories bool `json:"can_edit_stories"`
CanDeleteStories bool `json:"can_delete_stories"`
CanPostMessages *bool `json:"can_post_messages,omitempty"`
CanEditMessages *bool `json:"can_edit_messages,omitempty"`
CanPinMessages *bool `json:"can_pin_messages,omitempty"`
CanManageTopics *bool `json:"can_manage_topics,omitempty"`
CanManageDirectMessages *bool `json:"can_manage_direct_messages,omitempty"`
}

86
tgapi/forum_methods.go Normal file
View File

@@ -0,0 +1,86 @@
package tgapi
type BaseForumTopicP struct {
ChatID int `json:"chat_id"`
MessageThreadID int `json:"message_thread_id"`
}
func (api *Api) GetForumTopicIconSet() ([]Sticker, error) {
req := NewRequest[[]Sticker]("getForumTopicIconSet", NoParams)
return req.Do(api)
}
type CreateForumTopicP struct {
ChatID int `json:"chat_id"`
Name string `json:"name"`
IconColor ForumTopicIconColor `json:"icon_color"`
IconCustomEmojiID string `json:"icon_custom_emoji_id"`
}
func (api *Api) CreateForumTopic(p CreateForumTopicP) (ForumTopic, error) {
req := NewRequest[ForumTopic]("createForumTopic", p)
return req.Do(api)
}
type EditForumTopicP struct {
BaseForumTopicP
Name string `json:"name"`
IconCustomEmojiID string `json:"icon_custom_emoji_id"`
}
func (api *Api) EditForumTopic(p EditForumTopicP) (bool, error) {
req := NewRequest[bool]("editForumTopic", p)
return req.Do(api)
}
func (api *Api) CloseForumTopic(p BaseForumTopicP) (bool, error) {
req := NewRequest[bool]("closeForumTopic", p)
return req.Do(api)
}
func (api *Api) ReopenForumTopic(p BaseForumTopicP) (bool, error) {
req := NewRequest[bool]("reopenForumTopic", p)
return req.Do(api)
}
func (api *Api) DeleteForumTopic(p BaseForumTopicP) (bool, error) {
req := NewRequest[bool]("deleteForumTopic", p)
return req.Do(api)
}
func (api *Api) UnpinAllForumTopicMessages(p BaseForumTopicP) (bool, error) {
req := NewRequest[bool]("unpinAllForumTopicMessages", p)
return req.Do(api)
}
type BaseGeneralForumTopicP struct {
ChatID int `json:"chat_id"`
}
type EditGeneralForumTopicP struct {
ChatID int `json:"chat_id"`
Name string `json:"name"`
}
func (api *Api) EditGeneralForumTopic(p EditGeneralForumTopicP) (bool, error) {
req := NewRequest[bool]("editGeneralForumTopic", p)
return req.Do(api)
}
func (api *Api) CloseGeneralForumTopic(p BaseGeneralForumTopicP) (bool, error) {
req := NewRequest[bool]("closeGeneralForumTopic", p)
return req.Do(api)
}
func (api *Api) ReopenGeneralForumTopic(p BaseGeneralForumTopicP) (bool, error) {
req := NewRequest[bool]("reopenGeneralForumTopic", p)
return req.Do(api)
}
func (api *Api) HideGeneralForumTopic(p BaseGeneralForumTopicP) (bool, error) {
req := NewRequest[bool]("hideGeneralForumTopic", p)
return req.Do(api)
}
func (api *Api) UnhideGeneralForumTopic(p BaseGeneralForumTopicP) (bool, error) {
req := NewRequest[bool]("unhideGeneralForumTopic", p)
return req.Do(api)
}
func (api *Api) UnpinAllGeneralForumTopicMessages(p BaseGeneralForumTopicP) (bool, error) {
req := NewRequest[bool]("unpinAllGeneralForumTopicMessages", p)
return req.Do(api)
}

15
tgapi/forum_types.go Normal file
View File

@@ -0,0 +1,15 @@
package tgapi
type ForumTopic struct {
MessageThreadID int `json:"message_thread_id"`
Name string `json:"name"`
IconColor int `json:"icon_color"`
IconCustomEmojiID string `json:"icon_custom_emoji_id,omitempty"`
IsNameImplicit bool `json:"is_name_implicit,omitempty"`
}
type ForumTopicIconColor int
const (
ForumTopicIconColorBlue ForumTopicIconColor = 7322096
)

367
tgapi/messages_methods.go Normal file
View File

@@ -0,0 +1,367 @@
package tgapi
type SendMessageP struct {
BusinessConnectionID string `json:"business_connection_id,omitempty"`
ChatID int `json:"chat_id"`
MessageThreadID int `json:"message_thread_id,omitempty"`
DirectMessagesTopicID int `json:"direct_messages_topic_id,omitempty"`
Text string `json:"text"`
ParseMode ParseMode `json:"parse_mode,omitempty"`
Entities []*MessageEntity `json:"entities,omitempty"`
LinkPreviewOptions *LinkPreviewOptions `json:"link_preview_options,omitempty"`
DisableNotifications bool `json:"disable_notifications,omitempty"`
ProtectContent bool `json:"protect_content,omitempty"`
AllowPaidBroadcast bool `json:"allow_paid_broadcast,omitempty"`
MessageEffectID string `json:"message_effect_id,omitempty"`
SuggestedPostParameters *SuggestedPostParameters `json:"suggested_post_parameters,omitempty"`
ReplyParameters *ReplyParameters `json:"reply_parameters,omitempty"`
ReplyMarkup *ReplyMarkup `json:"reply_markup,omitempty"`
}
func (api *Api) SendMessage(params *SendMessageP) (Message, error) {
req := NewRequest[Message, SendMessageP]("sendMessage", *params)
return req.Do(api)
}
type ForwardMessageP struct {
ChatID int `json:"chat_id"`
MessageThreadID int `json:"message_thread_id,omitempty"`
DirectMessagesTopicID int `json:"direct_messages_topic_id,omitempty"`
MessageID int `json:"message_id,omitempty"`
FromChatID int `json:"from_chat_id,omitempty"`
VideoStartTimestamp int `json:"video_start_timestamp,omitempty"`
DisableNotification bool `json:"disable_notification,omitempty"`
ProtectContent bool `json:"protect_content,omitempty"`
MessageEffectID string `json:"message_effect_id,omitempty"`
SuggestedPostParameters *SuggestedPostParameters `json:"suggested_post_parameters,omitempty"`
}
func (api *Api) ForwardMessage(params ForwardMessageP) (Message, error) {
req := NewRequest[Message]("forwardMessage", params)
return req.Do(api)
}
type ForwardMessagesP struct {
ChatID int `json:"chat_id"`
MessageThreadID int `json:"message_thread_id,omitempty"`
DirectMessagesTopicID int `json:"direct_messages_topic_id,omitempty"`
FromChatID int `json:"from_chat_id,omitempty"`
MessageIDs []int `json:"message_ids,omitempty"`
DisableNotification bool `json:"disable_notification,omitempty"`
ProtectContent bool `json:"protect_content,omitempty"`
}
func (api *Api) ForwardMessages(params ForwardMessagesP) ([]int, error) {
req := NewRequest[[]int]("forwardMessages", params)
return req.Do(api)
}
type CopyMessageP struct {
ChatID int `json:"chat_id"`
MessageThreadID int `json:"message_thread_id,omitempty"`
DirectMessagesTopicID int `json:"direct_messages_topic_id,omitempty"`
FromChatID int `json:"from_chat_id"`
MessageID int `json:"message_id"`
VideoStartTimestamp int `json:"video_start_timestamp,omitempty"`
Caption string `json:"caption,omitempty"`
ParseMode ParseMode `json:"parse_mode,omitempty"`
CaptionEntities []*MessageEntity `json:"caption_entities,omitempty"`
ShowCaptionAboveMedia bool `json:"show_caption_above_media,omitempty"`
DisableNotification bool `json:"disable_notification,omitempty"`
ProtectContent bool `json:"protect_content,omitempty"`
AllowPaidBroadcast bool `json:"allow_paid_broadcast,omitempty"`
MessageEffectID string `json:"message_effect_id,omitempty"`
SuggestedPostParameters *SuggestedPostParameters `json:"suggested_post_parameters,omitempty"`
ReplyParameters *ReplyParameters `json:"reply_parameters,omitempty"`
ReplyMarkup *ReplyMarkup `json:"reply_markup,omitempty"`
}
func (api *Api) CopyMessage(params CopyMessageP) (int, error) {
req := NewRequest[int]("copyMessage", params)
return req.Do(api)
}
type CopyMessagesP struct {
ChatID int `json:"chat_id"`
MessageThreadID int `json:"message_thread_id,omitempty"`
DirectMessagesTopicID int `json:"direct_messages_topic_id,omitempty"`
FromChatID int `json:"from_chat_id,omitempty"`
MessageIDs []int `json:"message_ids,omitempty"`
DisableNotification bool `json:"disable_notification,omitempty"`
ProtectContent bool `json:"protect_content,omitempty"`
RemoveCaption bool `json:"remove_caption,omitempty"`
}
func (api *Api) CopyMessages(params CopyMessagesP) ([]int, error) {
req := NewRequest[[]int]("copyMessages", params)
return req.Do(api)
}
type SendLocationP struct {
BusinessConnectionID int `json:"business_connection_id,omitempty"`
ChatID int `json:"chat_id"`
MessageThreadID int `json:"message_thread_id,omitempty"`
DirectMessagesTopicID int `json:"direct_messages_topic_id,omitempty"`
Latitude float64 `json:"latitude"`
Longitude float64 `json:"longitude"`
HorizontalAccuracy float64 `json:"horizontal_accuracy,omitempty"`
LivePeriod int `json:"live_period,omitempty"`
Heading int `json:"heading,omitempty"`
ProximityAlertRadius int `json:"proximity_alert_radius,omitempty"`
DisableNotification bool `json:"disable_notification,omitempty"`
ProtectContent bool `json:"protect_content,omitempty"`
AllowPaidBroadcast bool `json:"allow_paid_broadcast,omitempty"`
MessageEffectID string `json:"message_effect_id,omitempty"`
SuggestedPostParameters *SuggestedPostParameters `json:"suggested_post_parameters,omitempty"`
ReplyParameters *ReplyParameters `json:"reply_parameters,omitempty"`
ReplyMarkup *ReplyMarkup `json:"reply_markup,omitempty"`
}
func (api *Api) SendLocation(params SendLocationP) (Message, error) {
req := NewRequest[Message]("sendLocation", params)
return req.Do(api)
}
type SendVenueP struct {
BusinessConnectionID int `json:"business_connection_id,omitempty"`
ChatID int `json:"chat_id"`
MessageThreadID int `json:"message_thread_id,omitempty"`
DirectMessagesTopicID int `json:"direct_messages_topic_id,omitempty"`
Latitude float64 `json:"latitude"`
Longitude float64 `json:"longitude"`
Title string `json:"title"`
Address string `json:"address"`
FoursquareID string `json:"foursquare_id,omitempty"`
FoursquareType string `json:"foursquare_type,omitempty"`
GooglePlaceID string `json:"google_place_id,omitempty"`
GooglePlaceType string `json:"google_place_type,omitempty"`
DisableNotification bool `json:"disable_notification,omitempty"`
ProtectContent bool `json:"protect_content,omitempty"`
AllowPaidBroadcast bool `json:"allow_paid_broadcast,omitempty"`
MessageEffectID string `json:"message_effect_id,omitempty"`
SuggestedPostParameters *SuggestedPostParameters `json:"suggested_post_parameters,omitempty"`
ReplyParameters *ReplyParameters `json:"reply_parameters,omitempty"`
ReplyMarkup *ReplyMarkup `json:"reply_markup,omitempty"`
}
func (api *Api) SendVenue(params SendVenueP) (Message, error) {
req := NewRequest[Message]("sendVenue", params)
return req.Do(api)
}
type SendContactP struct {
BusinessConnectionID int `json:"business_connection_id,omitempty"`
ChatID int `json:"chat_id"`
MessageThreadID int `json:"message_thread_id,omitempty"`
DirectMessagesTopicID int `json:"direct_messages_topic_id,omitempty"`
PhoneNumber string `json:"phone_number"`
FirstName string `json:"first_name"`
LastName string `json:"last_name,omitempty"`
Vcard string `json:"vcard"`
DisableNotification bool `json:"disable_notification,omitempty"`
ProtectContent bool `json:"protect_content,omitempty"`
AllowPaidBroadcast bool `json:"allow_paid_broadcast,omitempty"`
MessageEffectID string `json:"message_effect_id,omitempty"`
SuggestedPostParameters *SuggestedPostParameters `json:"suggested_post_parameters,omitempty"`
ReplyParameters *ReplyParameters `json:"reply_parameters,omitempty"`
ReplyMarkup *ReplyMarkup `json:"reply_markup,omitempty"`
}
func (api *Api) SendContact(params SendContactP) (Message, error) {
req := NewRequest[Message]("sendContact", params)
return req.Do(api)
}
type SendPollP struct {
BusinessConnectionID int `json:"business_connection_id,omitempty"`
ChatID int `json:"chat_id"`
MessageThreadID int `json:"message_thread_id,omitempty"`
Question string `json:"question"`
QuestionParseMode ParseMode `json:"question_mode,omitempty"`
QuestionEntities []*MessageEntity `json:"question_entities,omitempty"`
Options []InputPollOption `json:"options"`
IsAnonymous bool `json:"is_anonymous,omitempty"`
Type PollType `json:"type"`
AllowsMultipleAnswers bool `json:"allows_multiple_answers,omitempty"`
CorrectOptionID int `json:"correct_option_id,omitempty"`
Explanation string `json:"explanation,omitempty"`
ExplanationParseMode ParseMode `json:"explanation_parse_mode,omitempty"`
ExplanationEntities []*MessageEntity `json:"explanation_entities,omitempty"`
OpenPeriod int `json:"open_period,omitempty"`
CloseDate int `json:"close_date"`
IsClosed bool `json:"is_closed,omitempty"`
DisableNotification bool `json:"disable_notification,omitempty"`
ProtectContent bool `json:"protect_content,omitempty"`
AllowPaidBroadcast bool `json:"allow_paid_broadcast,omitempty"`
MessageEffectID string `json:"message_effect_id,omitempty"`
ReplyParameters *ReplyParameters `json:"reply_parameters,omitempty"`
ReplyMarkup *ReplyMarkup `json:"reply_markup,omitempty"`
}
func (api *Api) SendPoll(params SendPollP) (Message, error) {
req := NewRequest[Message]("sendPoll", params)
return req.Do(api)
}
type SendChecklistP struct {
BusinessConnectionID int `json:"business_connection_id"`
ChatID int `json:"chat_id"`
Checklist InputChecklist `json:"checklist"`
DisableNotification bool `json:"disable_notification,omitempty"`
ProtectContent bool `json:"protect_content,omitempty"`
MessageEffectID string `json:"message_effect_id,omitempty"`
ReplyParameters *ReplyParameters `json:"reply_parameters,omitempty"`
ReplyMarkup *ReplyMarkup `json:"reply_markup,omitempty"`
}
func (api *Api) SendChecklist(params SendChecklistP) (Message, error) {
req := NewRequest[Message]("sendChecklist", params)
return req.Do(api)
}
type SendDiceP struct {
BusinessConnectionID int `json:"business_connection_id,omitempty"`
ChatID int `json:"chat_id"`
MessageThreadID int `json:"message_thread_id,omitempty"`
DirectMessagesTopicID int `json:"direct_messages_topic_id,omitempty"`
Emoji string `json:"emoji,omitempty"`
DisableNotification bool `json:"disable_notification,omitempty"`
ProtectContent bool `json:"protect_content,omitempty"`
AllowPaidBroadcast bool `json:"allow_paid_broadcast,omitempty"`
MessageEffectID string `json:"message_effect_id,omitempty"`
SuggestedPostParameters *SuggestedPostParameters `json:"suggested_post_parameters,omitempty"`
ReplyParameters *ReplyParameters `json:"reply_parameters,omitempty"`
ReplyMarkup *ReplyMarkup `json:"reply_markup,omitempty"`
}
func (api *Api) SendDice(params SendDiceP) (Message, error) {
req := NewRequest[Message]("sendDice", params)
return req.Do(api)
}
type SendMessageDraftP struct {
ChatID int `json:"chat_id"`
MessageThreadID int `json:"message_thread_id,omitempty"`
DraftID int `json:"draft_id"`
Text string `json:"text"`
ParseMode ParseMode `json:"parse_mode,omitempty"`
Entities []*MessageEntity `json:"entities,omitempty"`
}
func (api *Api) SendMessageDraft(params SendMessageDraftP) (bool, error) {
req := NewRequest[bool]("sendMessageDraft", params)
return req.Do(api)
}
type SendChatActionP struct {
BusinessConnectionID string `json:"business_connection_id,omitempty"`
ChatID int `json:"chat_id"`
MessageThreadID int `json:"message_thread_id,omitempty"`
Action ChatActionType `json:"action"`
}
func (api *Api) SendChatAction(params SendChatActionP) (bool, error) {
req := NewRequest[bool]("sendChatAction", params)
return req.Do(api)
}
type SetMessageReactionP[T ReactionType] struct {
ChatId int `json:"chat_id"`
MessageId int `json:"message_id"`
Reaction []T `json:"reaction"`
IsBig bool `json:"is_big,omitempty"`
}
func (api *Api) SetMessageReactionEmoji(params SetMessageReactionP[ReactionTypeEmoji]) (bool, error) {
req := NewRequest[bool]("setMessageReaction", params)
return req.Do(api)
}
func (api *Api) SetMessageReactionCustom(params SetMessageReactionP[ReactionTypeCustomEmoji]) (bool, error) {
req := NewRequest[bool]("setMessageReaction", params)
return req.Do(api)
}
func (api *Api) SetMessageReactionPaid(params SetMessageReactionP[ReactionTypePaid]) (bool, error) {
req := NewRequest[bool]("setMessageReaction", params)
return req.Do(api)
}
// Message update methods
type EditMessageTextP struct {
BusinessConnectionID string `json:"business_connection_id,omitempty"`
ChatID int `json:"chat_id,omitempty"`
MessageID int `json:"message_id,omitempty"`
InlineMessageID string `json:"inline_message_id,omitempty"`
Text string `json:"text"`
ParseMode ParseMode `json:"parse_mode,omitempty"`
ReplyMarkup *ReplyMarkup `json:"reply_markup,omitempty"`
}
func (api *Api) EditMessageText(params *EditMessageTextP) (Message, error) {
req := NewRequest[Message]("editMessageText", params)
return req.Do(api)
}
type EditMessageCaptionP struct {
BusinessConnectionID string `json:"business_connection_id,omitempty"`
ChatID int `json:"chat_id,omitempty"`
MessageID int `json:"message_id,omitempty"`
InlineMessageID string `json:"inline_message_id,omitempty"`
Caption string `json:"caption"`
ParseMode ParseMode `json:"parse_mode,omitempty"`
ReplyMarkup *ReplyMarkup `json:"reply_markup,omitempty"`
}
func (api *Api) EditMessageCaption(params *EditMessageCaptionP) (Message, error) {
req := NewRequest[Message]("editMessageCaption", params)
return req.Do(api)
}
type DeleteMessageP struct {
ChatID int `json:"chat_id"`
MessageID int `json:"message_id"`
}
func (api *Api) DeleteMessage(params *DeleteMessageP) (bool, error) {
req := NewRequest[bool]("deleteMessage", params)
return req.Do(api)
}
type AnswerCallbackQueryP struct {
CallbackQueryID string `json:"callback_query_id"`
Text string `json:"text,omitempty"`
ShowAlert bool `json:"show_alert,omitempty"`
URL string `json:"url,omitempty"`
CacheTime int `json:"cache_time,omitempty"`
}
func (api *Api) AnswerCallbackQuery(params *AnswerCallbackQueryP) (bool, error) {
req := NewRequest[bool]("answerCallbackQuery", params)
return req.Do(api)
}

View File

@@ -1,49 +1,4 @@
package laniakea package tgapi
import "git.nix13.pw/scuroneko/extypes"
type Update struct {
UpdateID int `json:"update_id"`
Message *Message `json:"message"`
EditedMessage *Message `json:"edited_message,omitempty"`
ChannelPost *Message `json:"channel_post,omitempty"`
EditedChannelPost *Message `json:"edited_channel_post,omitempty"`
BusinessConnection *BusinessConnection `json:"business_connection,omitempty"`
BusinessMessage *Message `json:"business_message,omitempty"`
EditedBusinessMessage *Message `json:"edited_business_message,omitempty"`
DeletedBusinessMessage *Message `json:"deleted_business_messages,omitempty"`
MessageReaction *MessageReactionUpdated `json:"message_reaction,omitempty"`
MessageReactionCount *MessageReactionCountUpdated `json:"message_reaction_count,omitempty"`
CallbackQuery *CallbackQuery `json:"callback_query,omitempty"`
InlineQuery int
ChosenInlineResult int
}
type User struct {
ID int `json:"id"`
IsBot bool `json:"is_bot"`
FirstName string `json:"first_name"`
LastName string `json:"last_name,omitempty"`
Username string `json:"username,omitempty"`
LanguageCode string `json:"language_code,omitempty"`
IsPremium bool `json:"is_premium,omitempty"`
AddedToAttachmentMenu bool `json:"added_to_attachment_menu,omitempty"`
CanJoinGroups bool `json:"can_join_groups,omitempty"`
CanReadAllGroupMessages bool `json:"can_read_all_group_messages,omitempty"`
SupportsInlineQueries bool `json:"supports_inline_queries,omitempty"`
CanConnectToBusiness bool `json:"can_connect_to_business,omitempty"`
HasMainWebApp bool `json:"has_main_web_app,omitempty"`
}
type Chat struct {
ID int `json:"id"`
Type string `json:"type"`
Title string `json:"title,omitempty"`
Username string `json:"username,omitempty"`
FirstName string `json:"first_name,omitempty"`
LastName string `json:"last_name,omitempty"`
IsForum bool `json:"is_forum,omitempty"`
}
type MessageReplyMarkup struct { type MessageReplyMarkup struct {
InlineKeyboard [][]InlineKeyboardButton `json:"inline_keyboard"` InlineKeyboard [][]InlineKeyboardButton `json:"inline_keyboard"`
@@ -71,9 +26,9 @@ type Message struct {
Text string `json:"text"` Text string `json:"text"`
Photo extypes.Slice[*PhotoSize] `json:"photo,omitempty"` Photo []*PhotoSize `json:"photo,omitempty"`
Caption string `json:"caption,omitempty"` Caption string `json:"caption,omitempty"`
CaptionEntities []MessageEntity `json:"caption_entities,omitempty"` CaptionEntities []MessageEntity `json:"caption_entities,omitempty"`
Date int `json:"date"` Date int `json:"date"`
EditDate int `json:"edit_date"` EditDate int `json:"edit_date"`
@@ -87,14 +42,13 @@ type Message struct {
EffectID string `json:"effect_id,omitempty"` EffectID string `json:"effect_id,omitempty"`
} }
type InaccessableMessage struct { type InaccessibleMessage struct {
Chat *Chat `json:"chat"` Chat Chat `json:"chat"`
MessageID int `json:"message_id"` MessageID int `json:"message_id"`
Date int `json:"date"` Date int `json:"date"`
} }
type MaybeInaccessibleMessage struct { type MaybeInaccessibleMessage interface{ Message | InaccessibleMessage }
}
type MessageEntityType string type MessageEntityType string
@@ -143,14 +97,6 @@ type ReplyParameters struct {
ChecklistTaskID int `json:"checklist_task_id,omitempty"` ChecklistTaskID int `json:"checklist_task_id,omitempty"`
} }
type PhotoSize struct {
FileID string `json:"file_id"`
FileUniqueID string `json:"file_unique_id"`
Width int `json:"width"`
Height int `json:"height"`
FileSize int `json:"file_size,omitempty"`
}
type LinkPreviewOptions struct { type LinkPreviewOptions struct {
IsDisabled bool `json:"is_disabled,omitempty"` IsDisabled bool `json:"is_disabled,omitempty"`
URL string `json:"url,omitempty"` URL string `json:"url,omitempty"`
@@ -191,30 +137,61 @@ type ReplyKeyboardMarkup struct {
} }
type CallbackQuery struct { type CallbackQuery struct {
ID string `json:"id"` ID string `json:"id"`
From *User `json:"from"` From User `json:"from"`
Message *Message `json:"message"` Message Message `json:"message"`
Data string `json:"data"` Data string `json:"data"`
} }
type BusinessConnection struct { type InputPollOption struct {
ID string `json:"id"` Text string `json:"text"`
User *User `json:"user"` TextParseMode ParseMode `json:"text_parse_mode,omitempty"`
UserChatID int `json:"user_chat_id"` TextEntities []*MessageEntity `json:"text_entities,omitempty"`
Date int `json:"date"` }
CanReply bool `json:"can_reply"` type PollType string
IsEnabled bool `json:"id_enabled"`
const (
PollTypeRegular PollType = "regular"
PollTypeQuiz PollType = "quiz"
)
type InputChecklistTask struct {
ID int `json:"id"`
Text string `json:"text"`
ParseMode ParseMode `json:"parse_mode,omitempty"`
TextEntities []*MessageEntity `json:"text_entities,omitempty"`
}
type InputChecklist struct {
Title string `json:"title"`
ParseMode ParseMode `json:"parse_mode,omitempty"`
TitleEntities []*MessageEntity `json:"title_entities,omitempty"`
Tasks []InputChecklistTask `json:"tasks"`
OtherCanAddTasks bool `json:"other_can_add_tasks,omitempty"`
OtherCanMarkTasksAsDone bool `json:"other_can_mark_tasks_as_done,omitempty"`
} }
type ChatActionType string
const (
ChatActionTyping ChatActionType = "typing"
ChatActionUploadPhoto ChatActionType = "upload_photo"
ChatActionUploadVideo ChatActionType = "upload_video"
ChatActionUploadVoice ChatActionType = "upload_voice"
ChatActionUploadDocument ChatActionType = "upload_document"
ChatActionChooseSticker ChatActionType = "choose_sticker"
ChatActionFindLocation ChatActionType = "find_location"
ChatActionUploadVideoNone ChatActionType = "upload_video_none"
)
type MessageReactionUpdated struct { type MessageReactionUpdated struct {
Chat *Chat `json:"chat"` Chat *Chat `json:"chat"`
MessageID int `json:"message_id"` MessageID int `json:"message_id"`
User *User `json:"user,omitempty"` User *User `json:"user,omitempty"`
ActorChat *Chat `json:"actor_chat"` ActorChat *Chat `json:"actor_chat"`
Date int `json:"date"` Date int `json:"date"`
OldReaction []*ReactionType `json:"old_reaction"` OldReaction []BaseReaction `json:"old_reaction"`
NewReaction []*ReactionType `json:"new_reaction"` NewReaction []BaseReaction `json:"new_reaction"`
} }
type MessageReactionCountUpdated struct { type MessageReactionCountUpdated struct {
@@ -224,45 +201,28 @@ type MessageReactionCountUpdated struct {
Reactions []*ReactionCount `json:"reactions"` Reactions []*ReactionCount `json:"reactions"`
} }
type ReactionType struct { type ReactionType interface {
ReactionTypeEmoji | ReactionTypeCustomEmoji | ReactionTypePaid
}
type BaseReaction struct {
Type string `json:"type"` Type string `json:"type"`
} }
type ReactionTypeEmoji struct { type ReactionTypeEmoji struct {
ReactionType Type string `json:"type"`
Emoji string `json:"emoji"` Emoji string `json:"emoji"`
} }
type ReactionTypeCustomEmoji struct { type ReactionTypeCustomEmoji struct {
ReactionType Type string `json:"type"`
CustomEmojiID string `json:"custom_emoji_id"` CustomEmojiID string `json:"custom_emoji_id"`
} }
type ReactionTypePaid struct { type ReactionTypePaid struct {
ReactionType Type string `json:"type"`
} }
type ReactionCount struct { type ReactionCount struct {
Type *ReactionType `json:"type"` Type BaseReaction `json:"type"`
TotalCount int `json:"total_count"` TotalCount int `json:"total_count"`
} }
type File struct {
FileId string `json:"file_id"`
FileUniqueID string `json:"file_unique_id"`
FileSize int `json:"file_size,omitempty"`
FilePath string `json:"file_path,omitempty"`
}
type ChatActions string
const (
ChatActionTyping ChatActions = "typing"
ChatActionUploadPhoto ChatActions = "upload_photo"
ChatActionUploadVideo ChatActions = "upload_video"
ChatActionUploadVoice ChatActions = "upload_voice"
ChatActionUploadDocument ChatActions = "upload_document"
ChatActionChooseSticker ChatActions = "choose_sticker"
ChatActionFindLocation ChatActions = "find_location"
ChatActionUploadVideoNone ChatActions = "upload_video_none"
)
type SuggestedPostPrice struct { type SuggestedPostPrice struct {
Currency string `json:"currency"` Currency string `json:"currency"`
Amount int `json:"amount"` Amount int `json:"amount"`

41
tgapi/methods.go Normal file
View File

@@ -0,0 +1,41 @@
package tgapi
type ParseMode string
const (
ParseMDV2 ParseMode = "MarkdownV2"
ParseHTML ParseMode = "HTML"
ParseMD ParseMode = "Markdown"
)
type EmptyParams struct{}
var NoParams = EmptyParams{}
type UpdateParams struct {
Offset int `json:"offset"`
Timeout int `json:"timeout"`
AllowedUpdates []string `json:"allowed_updates"`
}
func (api *Api) GetMe() (User, error) {
req := NewRequest[User, EmptyParams]("getMe", NoParams)
return req.Do(api)
}
func (api *Api) LogOut() (bool, error) {
req := NewRequest[bool, EmptyParams]("logOut", NoParams)
return req.Do(api)
}
func (api *Api) Close() (bool, error) {
req := NewRequest[bool, EmptyParams]("close", NoParams)
return req.Do(api)
}
type GetFileP struct {
FileId string `json:"file_id"`
}
func (api *Api) GetFile(params GetFileP) (File, error) {
req := NewRequest[File]("getFile", params)
return req.Do(api)
}

166
tgapi/stickers_methods.go Normal file
View File

@@ -0,0 +1,166 @@
package tgapi
type SendStickerP struct {
BusinessConnectionID string `json:"business_connection_id,omitempty"`
ChatID int `json:"chat_id"`
MessageThreadID int `json:"message_thread_id,omitempty"`
DirectMessagesTopicID int `json:"direct_messages_topic_id,omitempty"`
Sticker string `json:"sticker"`
Emoji string `json:"emoji,omitempty"`
DisableNotification bool `json:"disable_notification,omitempty"`
ProtectContent bool `json:"protect_content,omitempty"`
AllowPaidBroadcast bool `json:"allow_paid_broadcast,omitempty"`
MessageEffectID string `json:"message_effect_id,omitempty"`
}
func (api *Api) SendSticker(p SendStickerP) (Message, error) {
req := NewRequest[Message]("sendSticker", p)
return req.Do(api)
}
type GetStickerSetP struct {
Name string `json:"name"`
}
func (api *Api) GetStickerSet(p GetStickerSetP) (StickerSet, error) {
req := NewRequest[StickerSet]("getStickerSet", p)
return req.Do(api)
}
type GetCustomEmojiStickersP struct {
CustomEmojiIDs []string `json:"custom_emoji_ids"`
}
func (api *Api) GetCustomEmojiStickers(p GetCustomEmojiStickersP) ([]Sticker, error) {
req := NewRequest[[]Sticker]("getCustomEmojiStickers", p)
return req.Do(api)
}
type CreateNewStickerSetP struct {
UserID int `json:"user_id"`
Name string `json:"name"`
Title string `json:"title"`
Stickers []InputSticker `json:"stickers"`
StickerType StickerType `json:"sticker_type,omitempty"`
NeedsRepainting bool `json:"needs_repainting,omitempty"`
}
func (api *Api) CreateNewStickerSet(p CreateNewStickerSetP) (bool, error) {
req := NewRequest[bool]("createNewStickerSet", p)
return req.Do(api)
}
type AddStickerToSetP struct {
UserID int `json:"user_id"`
Name string `json:"name"`
Sticker InputSticker `json:"sticker"`
}
func (api *Api) AddStickerToSet(p AddStickerToSetP) (bool, error) {
req := NewRequest[bool]("addStickerToSet", p)
return req.Do(api)
}
type SetStickerPositionInSetP struct {
Sticker string `json:"sticker"`
Position int `json:"position"`
}
func (api *Api) SetStickerPosition(p SetStickerPositionInSetP) (bool, error) {
req := NewRequest[bool]("setStickerPosition", p)
return req.Do(api)
}
type DeleteStickerFromSetP struct {
Sticker string `json:"sticker"`
}
func (api *Api) DeleteStickerFromSet(p DeleteStickerFromSetP) (bool, error) {
req := NewRequest[bool]("deleteStickerFromSet", p)
return req.Do(api)
}
type ReplaceStickerInSetP struct {
UserID int `json:"user_id"`
Name string `json:"name"`
OldSticker string `json:"old_sticker"`
Sticker InputSticker `json:"sticker"`
}
func (api *Api) ReplaceStickerInSet(p ReplaceStickerInSetP) (bool, error) {
req := NewRequest[bool]("replaceStickerInSet", p)
return req.Do(api)
}
type SetStickerEmojiListP struct {
Sticker string `json:"sticker"`
EmojiList []string `json:"emoji_list"`
}
func (api *Api) SetStickerEmojiList(p SetStickerEmojiListP) (bool, error) {
req := NewRequest[bool]("setStickerEmojiList", p)
return req.Do(api)
}
type SetStickerKeywordsP struct {
Sticker string `json:"sticker"`
Keywords []string `json:"keywords"`
}
func (api *Api) SetStickerKeywords(p SetStickerKeywordsP) (bool, error) {
req := NewRequest[bool]("setStickerKeywords", p)
return req.Do(api)
}
type SetStickerMaskPositionP struct {
Sticker string `json:"sticker"`
MaskPosition *MaskPosition `json:"mask_position,omitempty"`
}
func (api *Api) SetStickerMaskPosition(p SetStickerMaskPositionP) (bool, error) {
req := NewRequest[bool]("setStickerMaskPosition", p)
return req.Do(api)
}
type SetStickerSetTitleP struct {
Name string `json:"name"`
Title string `json:"title"`
}
func (api *Api) SetStickerSetTitle(p SetStickerSetTitleP) (bool, error) {
req := NewRequest[bool]("setStickerSetTitle", p)
return req.Do(api)
}
type SetStickerSetThumbnailP struct {
Name string `json:"name"`
UserID int `json:"user_id"`
Thumbnail string `json:"thumbnail"`
Format InputStickerFormat `json:"format"`
}
func (api *Api) SetStickerSetThumbnail(p SetStickerSetThumbnailP) (bool, error) {
req := NewRequest[bool]("setStickerSetThumbnail", p)
return req.Do(api)
}
type SetCustomEmojiStickerSetThumbnailP struct {
Name string `json:"name"`
CustomEmojiID string `json:"custom_emoji_id,omitempty"`
}
func (api *Api) SetCustomEmojiStickerSetThumbnail(p SetStickerSetThumbnailP) (bool, error) {
req := NewRequest[bool]("setCustomEmojiStickerSetThumbnail", p)
return req.Do(api)
}
type DeleteStickerSetP struct {
Name string `json:"name"`
}
func (api *Api) DeleteStickerSet(p DeleteStickerSetP) (bool, error) {
req := NewRequest[bool]("deleteStickerSet", p)
return req.Do(api)
}

View File

@@ -1,4 +1,4 @@
package laniakea package tgapi
type MaskPositionPoint string type MaskPositionPoint string
@@ -34,12 +34,12 @@ type Sticker struct {
IsVideo bool `json:"is_video"` IsVideo bool `json:"is_video"`
Thumbnail *PhotoSize `json:"thumbnail,omitempty"` Thumbnail *PhotoSize `json:"thumbnail,omitempty"`
Emoji string `json:"emoji,omitempty"` Emoji *string `json:"emoji,omitempty"`
SetName string `json:"set_name,omitempty"` SetName *string `json:"set_name,omitempty"`
MaskPosition *MaskPosition `json:"mask_position,omitempty"` MaskPosition *MaskPosition `json:"mask_position,omitempty"`
CustomEmojiID string `json:"custom_emoji_id,omitempty"` CustomEmojiID *string `json:"custom_emoji_id,omitempty"`
NeedRepainting bool `json:"need_repainting,omitempty"` NeedRepainting *bool `json:"need_repainting,omitempty"`
FileSize int `json:"file_size,omitempty"` FileSize *int `json:"file_size,omitempty"`
} }
type StickerSet struct { type StickerSet struct {
Name string `json:"name"` Name string `json:"name"`
@@ -63,31 +63,3 @@ type InputSticker struct {
MaskPosition *MaskPosition `json:"mask_position,omitempty"` MaskPosition *MaskPosition `json:"mask_position,omitempty"`
Keywords []string `json:"keywords,omitempty"` Keywords []string `json:"keywords,omitempty"`
} }
type SendStickerP struct {
BusinessConnectionID string `json:"business_connection_id,omitempty"`
ChatID int `json:"chat_id"`
MessageThreadID int `json:"message_thread_id,omitempty"`
DirectMessagesTopicID int `json:"direct_messages_topic_id,omitempty"`
Sticker string `json:"sticker"`
Emoji string `json:"emoji,omitempty"`
DisableNotification bool `json:"disable_notification,omitempty"`
ProtectContent bool `json:"protect_content,omitempty"`
AllowPaidBroadcast bool `json:"allow_paid_broadcast,omitempty"`
MessageEffectID string `json:"message_effect_id,omitempty"`
}
func (api *Api) SendSticker(p SendStickerP) (*Message, error) {
req := NewRequest[Message]("sendSticker", p)
return req.Do(api)
}
type GetStickerSetP struct {
Name string `json:"name"`
}
func (api *Api) GetStickerSet(p GetStickerSetP) (*StickerSet, error) {
req := NewRequest[StickerSet]("getStickerSet", p)
return req.Do(api)
}

113
tgapi/types.go Normal file
View File

@@ -0,0 +1,113 @@
package tgapi
type Update struct {
UpdateID int `json:"update_id"`
Message *Message `json:"message"`
EditedMessage *Message `json:"edited_message,omitempty"`
ChannelPost *Message `json:"channel_post,omitempty"`
EditedChannelPost *Message `json:"edited_channel_post,omitempty"`
BusinessConnection *BusinessConnection `json:"business_connection,omitempty"`
BusinessMessage *Message `json:"business_message,omitempty"`
EditedBusinessMessage *Message `json:"edited_business_message,omitempty"`
DeletedBusinessMessage *Message `json:"deleted_business_messages,omitempty"`
MessageReaction *MessageReactionUpdated `json:"message_reaction,omitempty"`
MessageReactionCount *MessageReactionCountUpdated `json:"message_reaction_count,omitempty"`
CallbackQuery *CallbackQuery `json:"callback_query,omitempty"`
InlineQuery int
ChosenInlineResult int
}
type File struct {
FileId string `json:"file_id"`
FileUniqueID string `json:"file_unique_id"`
FileSize int `json:"file_size,omitempty"`
FilePath string `json:"file_path,omitempty"`
}
type Audio struct {
FileID string `json:"file_id"`
FileUniqueID string `json:"file_unique_id"`
Duration int `json:"duration"`
Performer string `json:"performer,omitempty"`
Title string `json:"title,omitempty"`
FileName string `json:"file_name,omitempty"`
MimeType string `json:"mime_type,omitempty"`
FileSize int `json:"file_size,omitempty"`
Thumbnail *PhotoSize `json:"thumbnail,omitempty"`
}
type Location struct {
Latitude float64 `json:"latitude"`
Longitude float64 `json:"longitude"`
HorizontalAccuracy float64 `json:"horizontal_accuracy"`
LivePeriod int `json:"live_period"`
Heading int `json:"heading"`
ProximityAlertRadius int `json:"proximity_alert_radius"`
}
type Venue struct {
Location Location `json:"location"`
Title string `json:"title"`
Address string `json:"address"`
FoursquareID string `json:"foursquare_id,omitempty"`
FoursquareType string `json:"foursquare_type,omitempty"`
GooglePlaceID string `json:"google_place_id,omitempty"`
GooglePlaceType string `json:"google_place_type,omitempty"`
}
type WebAppInfo struct {
URL string `json:"url"`
}
type StarAmount struct {
Amount int `json:"amount"`
NanostarAmount int `json:"nanostar_amount"`
}
// Gifts
type AcceptedGiftTypes struct {
UnlimitedGifts bool `json:"unlimited_gifts"`
LimitedGifts bool `json:"limited_gifts"`
UniqueGifts bool `json:"unique_gifts"`
PremiumSubscription bool `json:"premium_subscription"`
GiftsFromChannels bool `json:"gifts_from_channels"`
}
type UniqueGiftColors struct {
ModelCustomEmojiID string `json:"model_custom_emoji_id"`
SymbolCustomEmojiID string `json:"symbol_custom_emoji_id"`
LightThemeMainColor int `json:"light_theme_main_color"`
LightThemeOtherColors []int `json:"light_theme_other_colors"`
DarkThemeMainColor int `json:"dark_theme_main_color"`
DarkThemeOtherColors []int `json:"dark_theme_other_colors"`
}
type GiftBackground struct {
CenterColor int `json:"center_color"`
EdgeColor int `json:"edge_color"`
TextColor int `json:"text_color"`
}
type Gift struct {
ID string `json:"id"`
Sticker Sticker `json:"sticker"`
StarCount int `json:"star_count"`
UpdateStarCount *int `json:"update_star_count,omitempty"`
IsPremium *bool `json:"is_premium,omitempty"`
HasColors *bool `json:"has_colors,omitempty"`
TotalCount *int `json:"total_count,omitempty"`
RemainingCount *int `json:"remaining_count,omitempty"`
PersonalTotalCount *int `json:"personal_total_count,omitempty"`
PersonalRemainingCount *int `json:"personal_remaining_count,omitempty"`
Background GiftBackground `json:"background,omitempty"`
UniqueGiftVariantColor *int `json:"unique_gift_variant_color,omitempty"`
PublisherChat *Chat `json:"publisher_chat,omitempty"`
}
type Gifts struct {
Gifts []Gift `json:"gifts"`
}
type OwnedGiftType string
type BaseOwnedGift struct {
Type OwnedGiftType `json:"type"`
}

View File

@@ -1,4 +1,4 @@
package laniakea package tgapi
import ( import (
"bytes" "bytes"
@@ -9,6 +9,7 @@ import (
"net/http" "net/http"
"path/filepath" "path/filepath"
"git.nix13.pw/scuroneko/laniakea/utils"
"git.nix13.pw/scuroneko/slog" "git.nix13.pw/scuroneko/slog"
) )
@@ -80,7 +81,7 @@ func (u UploaderRequest[R, P]) Do(up *Uploader) (*R, error) {
w.Close() w.Close()
return nil, err return nil, err
} }
err = Encode(w, u.params) err = utils.Encode(w, u.params)
if err != nil { if err != nil {
w.Close() w.Close()
return nil, err return nil, err
@@ -122,11 +123,31 @@ func (u UploaderRequest[R, P]) Do(up *Uploader) (*R, error) {
return response.Result, nil return response.Result, nil
} }
func (u *Uploader) UploadPhoto(file UploaderFile, params SendPhotoBaseP) (*Message, error) { type UploadPhotoP struct {
BusinessConnectionID string `json:"business_connection_id,omitempty"`
ChatID int `json:"chat_id"`
MessageThreadID int `json:"message_thread_id,omitempty"`
ParseMode ParseMode `json:"parse_mode,omitempty"`
Caption string `json:"caption,omitempty"`
CaptionEntities []*MessageEntity `json:"caption_entities,omitempty"`
ShowCaptionAboveMedia bool `json:"show_caption_above_media,omitempty"`
HasSpoiler bool `json:"has_spoiler,omitempty"`
DisableNotifications bool `json:"disable_notifications,omitempty"`
ProtectContent bool `json:"protect_content,omitempty"`
AllowPaidBroadcast bool `json:"allow_paid_broadcast,omitempty"`
MessageEffectID string `json:"message_effect_id,omitempty"`
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
}
func (u *Uploader) UploadPhoto(file UploaderFile, params UploadPhotoP) (*Message, error) {
req := NewUploaderRequest[Message]("sendPhoto", file, params) req := NewUploaderRequest[Message]("sendPhoto", file, params)
return req.Do(u) return req.Do(u)
} }
// setChatPhoto https://core.telegram.org/bots/api#setchatphoto
type UploadChatPhotoP struct {
}
func uploaderTypeByExt(filename string) UploaderFileType { func uploaderTypeByExt(filename string) UploaderFileType {
ext := filepath.Ext(filename) ext := filepath.Ext(filename)
switch ext { switch ext {

34
tgapi/users_methods.go Normal file
View File

@@ -0,0 +1,34 @@
package tgapi
type GetUserProfilePhotosP struct {
UserID int `json:"user_id"`
Offset int `json:"offset,omitempty"`
Limit int `json:"limit,omitempty"`
}
func (api *Api) GetUserProfilePhotos(p GetUserProfilePhotosP) (UserProfilePhotos, error) {
req := NewRequest[UserProfilePhotos]("getUserProfilePhotos", p)
return req.Do(api)
}
type GetUserProfileAudiosP struct {
UserID int `json:"user_id"`
Offset int `json:"offset,omitempty"`
Limit int `json:"limit,omitempty"`
}
func (api *Api) GetUserProfileAudios(p GetUserProfileAudiosP) (UserProfileAudios, error) {
req := NewRequest[UserProfileAudios]("getUserProfileAudios", p)
return req.Do(api)
}
type SetUserEmojiStatusP struct {
UserID int `json:"user_id"`
EmojiID string `json:"emoji_status_custom_emoji_id,omitempty"`
ExpirationDate int `json:"emoji_status_expiration_date,omitempty"`
}
func (api *Api) SetUserEmojiStatus(p SetUserEmojiStatusP) (bool, error) {
req := NewRequest[bool]("setUserEmojiStatus", p)
return req.Do(api)
}

40
tgapi/users_types.go Normal file
View File

@@ -0,0 +1,40 @@
package tgapi
type User struct {
ID int `json:"id"`
IsBot bool `json:"is_bot"`
FirstName string `json:"first_name"`
LastName string `json:"last_name,omitempty"`
Username string `json:"username,omitempty"`
LanguageCode string `json:"language_code,omitempty"`
IsPremium bool `json:"is_premium,omitempty"`
AddedToAttachmentMenu bool `json:"added_to_attachment_menu,omitempty"`
CanJoinGroups bool `json:"can_join_groups,omitempty"`
CanReadAllGroupMessages bool `json:"can_read_all_group_messages,omitempty"`
SupportsInlineQueries bool `json:"supports_inline_queries,omitempty"`
CanConnectToBusiness bool `json:"can_connect_to_business,omitempty"`
HasMainWebApp bool `json:"has_main_web_app,omitempty"`
HasTopicsEnabled bool `json:"has_topics_enabled,omitempty"`
AllowsUsersToCreateTopics bool `json:"allows_users_to_create_topics,omitempty"`
}
type UserProfilePhotos struct {
TotalCount int `json:"total_count"`
Photos [][]PhotoSize `json:"photos"`
}
type UserProfileAudios struct {
TotalCount int `json:"total_count"`
Audios []Audio `json:"audios"`
}
type UserRating struct {
Level int `json:"level"`
Rating int `json:"rating"`
CurrentLevelRating int `json:"current_level_rating"`
NextLevelRating int `json:"next_level_rating"`
}
type Birthdate struct {
Day int `json:"day"`
Month int `json:"month"`
Year int `json:"year"`
}

15
tgapi/utils.go Normal file
View File

@@ -0,0 +1,15 @@
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
}

View File

@@ -1,86 +1,10 @@
package laniakea package laniakea
import ( func Ptr[T any](v T) *T { return &v }
"encoding/json"
"fmt"
"os"
"strings"
"git.nix13.pw/scuroneko/slog" func Val[T any](p *T, def T) T {
) if p != nil {
return *p
func GetLoggerLevel() slog.LogLevel {
level := slog.FATAL
if os.Getenv("DEBUG") == "true" {
level = slog.DEBUG
} }
return level return def
}
// 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, "*", `\*`)
s = strings.ReplaceAll(s, "[", `\[`)
return strings.ReplaceAll(s, "`", "\\`")
}
func EscapeMarkdownV2(s string) string {
symbols := []string{"_", "*", "[", "]", "(", ")", "~", "`", ">", "#", "+", "-", "=", "|", "{", "}", ".", "!"}
for _, symbol := range symbols {
s = strings.ReplaceAll(s, symbol, fmt.Sprintf("\\%s", symbol))
}
return s
} }

View File

@@ -1,4 +1,4 @@
package laniakea package utils
import ( import (
"encoding/json" "encoding/json"

100
utils/utils.go Normal file
View File

@@ -0,0 +1,100 @@
package utils
import (
"encoding/json"
"fmt"
"os"
"strings"
"git.nix13.pw/scuroneko/slog"
)
func GetLoggerLevel() slog.LogLevel {
level := slog.FATAL
if os.Getenv("DEBUG") == "true" {
level = slog.DEBUG
}
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, "*", `\*`)
s = strings.ReplaceAll(s, "[", `\[`)
return strings.ReplaceAll(s, "`", "\\`")
}
func EscapeMarkdownV2(s string) string {
symbols := []string{"_", "*", "[", "]", "(", ")", "~", "`", ">", "#", "+", "-", "=", "|", "{", "}", ".", "!"}
for _, symbol := range symbols {
s = strings.ReplaceAll(s, symbol, fmt.Sprintf("\\%s", symbol))
}
return s
}

8
utils/version.go Normal file
View File

@@ -0,0 +1,8 @@
package utils
const (
VersionString = "0.5.0"
VersionMajor = 0
VersionMinor = 5
VersionPatch = 0
)

View File

@@ -1,8 +0,0 @@
package laniakea
const (
VersionString = "0.4.4-1"
VersionMajor = 0
VersionMinor = 4
VersionPatch = 4
)