301 lines
6.2 KiB
Go
301 lines
6.2 KiB
Go
package telegram
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"net/url"
|
|
"strings"
|
|
"time"
|
|
|
|
json "github.com/pquerna/ffjson/ffjson"
|
|
http "github.com/valyala/fasthttp"
|
|
)
|
|
|
|
type UpdatesChannel <-chan Update
|
|
|
|
func NewAnswerCallback(id string) *AnswerCallbackQueryParameters {
|
|
return &AnswerCallbackQueryParameters{
|
|
CallbackQueryID: id}
|
|
}
|
|
|
|
func NewAnswerInline(id string, results ...InlineQueryResult) *AnswerInlineQueryParameters {
|
|
return &AnswerInlineQueryParameters{
|
|
InlineQueryID: id,
|
|
Results: results,
|
|
}
|
|
}
|
|
|
|
func NewAnswerPreCheckout(id string, ok bool) *AnswerPreCheckoutQueryParameters {
|
|
return &AnswerPreCheckoutQueryParameters{
|
|
PreCheckoutQueryID: id,
|
|
Ok: ok,
|
|
}
|
|
}
|
|
|
|
func NewAnswerShipping(id string, ok bool) *AnswerShippingQueryParameters {
|
|
return &AnswerShippingQueryParameters{
|
|
ShippingQueryID: id,
|
|
Ok: ok,
|
|
}
|
|
}
|
|
|
|
func NewMessage(chatID int64, text string) *SendMessageParameters {
|
|
return &SendMessageParameters{
|
|
ChatID: chatID,
|
|
Text: text,
|
|
}
|
|
}
|
|
|
|
func NewMessageForward(from, to int64, messageID int) *ForwardMessageParameters {
|
|
return &ForwardMessageParameters{
|
|
FromChatID: from,
|
|
ChatID: to,
|
|
MessageID: messageID,
|
|
}
|
|
}
|
|
|
|
func NewInvoice(chatID int64, title, description, payload, providerToken, startParameter, currency string, prices ...LabeledPrice) *SendInvoiceParameters {
|
|
return &SendInvoiceParameters{
|
|
ChatID: chatID,
|
|
Title: title,
|
|
Description: description,
|
|
Payload: payload,
|
|
ProviderToken: providerToken,
|
|
StartParameter: startParameter,
|
|
Currency: currency,
|
|
Prices: prices,
|
|
}
|
|
}
|
|
|
|
func NewReplyKeyboard(rows ...[]KeyboardButton) *ReplyKeyboardMarkup {
|
|
var keyboard [][]KeyboardButton
|
|
keyboard = append(keyboard, rows...)
|
|
return &ReplyKeyboardMarkup{
|
|
Keyboard: keyboard,
|
|
ResizeKeyboard: true,
|
|
}
|
|
}
|
|
|
|
func NewReplyKeyboardRow(buttons ...KeyboardButton) []KeyboardButton {
|
|
var row []KeyboardButton
|
|
row = append(row, buttons...)
|
|
return row
|
|
}
|
|
|
|
func NewReplyKeyboardButton(text string) KeyboardButton {
|
|
return KeyboardButton{
|
|
Text: text,
|
|
}
|
|
}
|
|
|
|
func NewReplyKeyboardButtonContact(text string) KeyboardButton {
|
|
return KeyboardButton{
|
|
Text: text,
|
|
RequestContact: true,
|
|
}
|
|
}
|
|
|
|
func NewReplyKeyboardButtonLocation(text string) KeyboardButton {
|
|
return KeyboardButton{
|
|
Text: text,
|
|
RequestLocation: true,
|
|
}
|
|
}
|
|
|
|
func NewInlineKeyboard(rows ...[]InlineKeyboardButton) InlineKeyboardMarkup {
|
|
var keyboard [][]InlineKeyboardButton
|
|
keyboard = append(keyboard, rows...)
|
|
return InlineKeyboardMarkup{InlineKeyboard: keyboard}
|
|
}
|
|
|
|
func NewInlineKeyboardRow(buttons ...InlineKeyboardButton) []InlineKeyboardButton {
|
|
var row []InlineKeyboardButton
|
|
row = append(row, buttons...)
|
|
return row
|
|
}
|
|
|
|
func NewInlineKeyboardButton(text, data string) InlineKeyboardButton {
|
|
return InlineKeyboardButton{
|
|
Text: text,
|
|
CallbackData: data,
|
|
}
|
|
}
|
|
|
|
func NewInlineKeyboardButtonURL(text, url string) InlineKeyboardButton {
|
|
return InlineKeyboardButton{
|
|
Text: text,
|
|
URL: url,
|
|
}
|
|
}
|
|
|
|
func NewInlineKeyboardButtonSwitch(text, query string) InlineKeyboardButton {
|
|
return InlineKeyboardButton{
|
|
Text: text,
|
|
SwitchInlineQuery: query,
|
|
}
|
|
}
|
|
|
|
func NewInlineKeyboardButtonSwitchSelf(text, query string) InlineKeyboardButton {
|
|
return InlineKeyboardButton{
|
|
Text: text,
|
|
SwitchInlineQueryCurrentChat: query,
|
|
}
|
|
}
|
|
|
|
func NewInlineKeyboardButtonGame(text string) InlineKeyboardButton {
|
|
return InlineKeyboardButton{
|
|
Text: text,
|
|
CallbackGame: &CallbackGame{},
|
|
}
|
|
}
|
|
|
|
func NewInlineKeyboardButtonPay(text string) InlineKeyboardButton {
|
|
return InlineKeyboardButton{
|
|
Text: text,
|
|
Pay: true,
|
|
}
|
|
}
|
|
|
|
func NewWebhook(url string, file interface{}) *SetWebhookParameters {
|
|
params := &SetWebhookParameters{URL: url}
|
|
|
|
if file != nil {
|
|
var input InputFile = file
|
|
params.Certificate = &input
|
|
}
|
|
|
|
return params
|
|
}
|
|
|
|
func (bot *Bot) NewLongPollingChannel(params *GetUpdatesParameters) UpdatesChannel {
|
|
if params == nil {
|
|
params = &GetUpdatesParameters{
|
|
Offset: 0,
|
|
Limit: 100,
|
|
Timeout: 60,
|
|
}
|
|
}
|
|
|
|
channel := make(chan Update, params.Limit)
|
|
|
|
go func() {
|
|
for {
|
|
updates, err := bot.GetUpdates(params)
|
|
if err != nil {
|
|
log.Println(err.Error())
|
|
log.Println("failed to get updates, retrying in 3 seconds...")
|
|
time.Sleep(time.Second * 3)
|
|
|
|
continue
|
|
}
|
|
|
|
for _, update := range updates {
|
|
if update.ID >= params.Offset {
|
|
params.Offset = update.ID + 1
|
|
channel <- update
|
|
}
|
|
}
|
|
}
|
|
}()
|
|
|
|
return channel
|
|
}
|
|
|
|
func NewWebhookChannel(serve, listen string, params *GetUpdatesParameters) UpdatesChannel {
|
|
if params == nil {
|
|
params = &GetUpdatesParameters{
|
|
Offset: 0,
|
|
Limit: 100,
|
|
Timeout: 60,
|
|
}
|
|
}
|
|
|
|
channel := make(chan Update, params.Limit)
|
|
|
|
go func() {
|
|
if err := http.ListenAndServe(serve, func(ctx *http.RequestCtx) {
|
|
log.Println("PATH:", string(ctx.Path()))
|
|
if strings.HasPrefix(string(ctx.Path()), listen) {
|
|
log.Println("rawBody:", string(ctx.Request.Body()))
|
|
var update Update
|
|
json.Unmarshal(ctx.Request.Body(), &update)
|
|
channel <- update
|
|
}
|
|
}); err != nil {
|
|
panic(err.Error())
|
|
}
|
|
}()
|
|
|
|
return channel
|
|
}
|
|
|
|
func (msg *Message) IsCommand() bool {
|
|
if len(msg.Entities) <= 0 {
|
|
return false
|
|
}
|
|
|
|
if msg.Entities[0].Type == EntityBotCommand &&
|
|
msg.Entities[0].Offset == 0 {
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func (msg *Message) Command() string {
|
|
if !msg.IsCommand() {
|
|
return ""
|
|
}
|
|
|
|
return string([]rune(msg.Text)[1:msg.Entities[0].Length])
|
|
}
|
|
|
|
func (msg *Message) CommandArgument() string {
|
|
if !msg.IsCommand() {
|
|
return ""
|
|
}
|
|
|
|
arg := strings.TrimPrefix(
|
|
msg.Text,
|
|
fmt.Sprint("/", msg.Command()),
|
|
)
|
|
|
|
return strings.TrimPrefix(arg, " ")
|
|
}
|
|
|
|
func (msg *Message) HasArgument() bool {
|
|
if !msg.IsCommand() {
|
|
return false
|
|
}
|
|
|
|
if msg.CommandArgument() != "" {
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func (chat *Chat) IsPrivate() bool {
|
|
return chat.Type == ChatPrivate
|
|
}
|
|
|
|
func (chat *Chat) IsGroup() bool {
|
|
return chat.Type == ChatGroup
|
|
}
|
|
|
|
func (chat *Chat) IsSuperGroup() bool {
|
|
return chat.Type == ChatSuperGroup
|
|
}
|
|
|
|
func (chat *Chat) IsChannel() bool {
|
|
return chat.Type == ChatChannel
|
|
}
|
|
|
|
func (entity *MessageEntity) ParseURL() (*url.URL, error) {
|
|
if entity.Type != EntityTextLink {
|
|
return nil, nil
|
|
}
|
|
|
|
return url.Parse(entity.URL)
|
|
}
|