Compare commits
23 Commits
af8982be2d
...
master
Author | SHA1 | Date | |
---|---|---|---|
a49827afc2 | |||
9e122d1a12 | |||
57d11c7671 | |||
b04a779236 | |||
9298c6402b | |||
01d04199fd | |||
f4346d8859 | |||
dd0307e382 | |||
b7f1e3e9ed | |||
c6ce1913dc | |||
1377e03b5e | |||
c0143707e9 | |||
d035524ebc | |||
e396d6a885 | |||
906c769453 | |||
d797a52029 | |||
599584ea58 | |||
b074189d31 | |||
e2ba9565d5 | |||
677f28182a | |||
3a06ae5f0e | |||
1a8decf4d4 | |||
5842815c95 |
31
bot.go
31
bot.go
@ -2,6 +2,7 @@ package nechotron
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
echo "github.com/NicoNex/echotron/v3"
|
||||
@ -9,10 +10,18 @@ import (
|
||||
)
|
||||
|
||||
type bot struct {
|
||||
chatID int64
|
||||
me *echo.User
|
||||
echo.API
|
||||
state *State
|
||||
chatID int64
|
||||
Me *echo.User
|
||||
data StateData
|
||||
lock sync.Mutex
|
||||
State Runnable
|
||||
handler UpdateHandler
|
||||
}
|
||||
|
||||
func DefaultHandler(u *Update) error {
|
||||
err := u.Bot.State.Call(u)
|
||||
return err
|
||||
}
|
||||
|
||||
func (b *bot) Update(u *echo.Update) {
|
||||
@ -25,11 +34,13 @@ func (b *bot) Update(u *echo.Update) {
|
||||
Ctx: ctx,
|
||||
}
|
||||
|
||||
newState, err := b.state.Fn(upd)
|
||||
if err != nil {
|
||||
upd.LogError("", err, true)
|
||||
}
|
||||
if newState != nil {
|
||||
b.state = newState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
// defer func() {
|
||||
// if r := recover(); r != nil {
|
||||
// log.Printf("[%s] Recovered. Error: %s\n", upd.UpdateID.String(), r)
|
||||
// }
|
||||
// }()
|
||||
|
||||
b.handler(upd)
|
||||
}
|
||||
|
25
callbacks.go
Normal file
25
callbacks.go
Normal file
@ -0,0 +1,25 @@
|
||||
package nechotron
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type CallbackFilter func(u *Update) bool
|
||||
|
||||
func CallbackExact(text string) CallbackFilter {
|
||||
return func(u *Update) bool {
|
||||
data := u.Callback()
|
||||
return text == data
|
||||
}
|
||||
}
|
||||
|
||||
func CallbackPrefix(text string) CallbackFilter {
|
||||
return func(u *Update) bool {
|
||||
data := u.Callback()
|
||||
if strings.HasPrefix(data, text) {
|
||||
u.Ctx = context.WithValue(u.Ctx, FilteredValue("cb_"+text), strings.TrimPrefix(data, text+":"))
|
||||
}
|
||||
return strings.HasPrefix(data, text)
|
||||
}
|
||||
}
|
61
command.go
Normal file
61
command.go
Normal file
@ -0,0 +1,61 @@
|
||||
package nechotron
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/NicoNex/echotron/v3"
|
||||
)
|
||||
|
||||
type Command struct {
|
||||
Body string
|
||||
IsAdminOnly bool
|
||||
Description string
|
||||
}
|
||||
|
||||
func NewCommand(body string, desc string, isAdminOnly bool) *Command {
|
||||
return &Command{
|
||||
Body: body,
|
||||
IsAdminOnly: isAdminOnly,
|
||||
Description: desc,
|
||||
}
|
||||
}
|
||||
func (c *Command) String() string {
|
||||
return "/" + c.Body
|
||||
}
|
||||
|
||||
func (c *Command) Param(text string) string {
|
||||
strs := strings.SplitN(text, " ", 2)
|
||||
if len(strs) > 1 {
|
||||
return strs[1]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func MakeCommandList(format string, commands ...*Command) string {
|
||||
result := ""
|
||||
for _, command := range commands {
|
||||
result += fmt.Sprintf(format, command.String(), EscapeMd2(command.Description))
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func botCommands(commands ...*Command) []echotron.BotCommand {
|
||||
cmds := []echotron.BotCommand{}
|
||||
for _, c := range commands {
|
||||
cmds = append(cmds, echotron.BotCommand{Command: c.Body, Description: c.Description})
|
||||
}
|
||||
return cmds
|
||||
}
|
||||
|
||||
func SetMyCommands(api echotron.API, langCode string, scope echotron.BotCommandScope, commands ...*Command) error {
|
||||
_, err := api.SetMyCommands(&echotron.CommandOptions{LanguageCode: "", Scope: scope}, botCommands(commands...)...)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// func HandleCommand(command *Command, handler cmdFunc) (bool, error)
|
104
dispatcher.go
Normal file
104
dispatcher.go
Normal file
@ -0,0 +1,104 @@
|
||||
package nechotron
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/NicoNex/echotron/v3"
|
||||
)
|
||||
|
||||
type UpdateHandler func(u *Update) error
|
||||
type CommandHandler func(u *Update, arg string) error
|
||||
type CallbackHandler func(u *Update, data string) error
|
||||
|
||||
type dispatchHandler func(u *Update) (bool, error)
|
||||
|
||||
type Dispatcher struct {
|
||||
handlers []dispatchHandler
|
||||
}
|
||||
|
||||
func NewDispatcher() *Dispatcher {
|
||||
return &Dispatcher{}
|
||||
}
|
||||
|
||||
func (d *Dispatcher) Run(u *Update) error {
|
||||
for _, h := range d.handlers {
|
||||
executed, err := h(u)
|
||||
if executed {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Dispatcher) Handle(handler func(u *Update) (bool, error)) *Dispatcher {
|
||||
d.handlers = append(d.handlers, handler)
|
||||
return d
|
||||
}
|
||||
|
||||
func (d *Dispatcher) HandleCommand(command *Command, handler CommandHandler) *Dispatcher {
|
||||
newHandler := func(u *Update) (bool, error) {
|
||||
if !strings.HasPrefix(u.Text(), command.String()) {
|
||||
return false, nil
|
||||
}
|
||||
if command.IsAdminOnly && !IsUserAdmin(u) && u.ChatID() < 0 {
|
||||
return false, nil
|
||||
}
|
||||
err := handler(u, command.Param(u.Text()))
|
||||
return true, err
|
||||
}
|
||||
d.handlers = append(d.handlers, newHandler)
|
||||
return d
|
||||
}
|
||||
|
||||
func (d *Dispatcher) HandleFilter(filter FilterFn, handler UpdateHandler) *Dispatcher {
|
||||
newHandler := func(u *Update) (bool, error) {
|
||||
if !filter(u) {
|
||||
return false, nil
|
||||
}
|
||||
err := handler(u)
|
||||
return true, err
|
||||
}
|
||||
d.handlers = append(d.handlers, newHandler)
|
||||
return d
|
||||
}
|
||||
|
||||
func (d *Dispatcher) HandleCallback(filter CallbackFilter, handler UpdateHandler) *Dispatcher {
|
||||
newHandler := func(u *Update) (bool, error) {
|
||||
if !u.IsCallback() {
|
||||
return false, nil
|
||||
}
|
||||
defer u.Bot.AnswerCallbackQuery(u.CallbackQuery.ID, &echotron.CallbackQueryOptions{})
|
||||
if !filter(u) {
|
||||
return false, nil
|
||||
}
|
||||
err := handler(u)
|
||||
return true, err
|
||||
}
|
||||
d.handlers = append(d.handlers, newHandler)
|
||||
return d
|
||||
}
|
||||
|
||||
func (d *Dispatcher) HandleReply(handler UpdateHandler) *Dispatcher {
|
||||
newHandler := func(u *Update) (bool, error) {
|
||||
if !u.IsMessage() {
|
||||
return false, nil
|
||||
}
|
||||
if u.Message.ReplyToMessage == nil {
|
||||
return false, nil
|
||||
}
|
||||
err := handler(u)
|
||||
return true, err
|
||||
}
|
||||
d.handlers = append(d.handlers, newHandler)
|
||||
return d
|
||||
}
|
||||
|
||||
// Runs each dispatcher or handled listed here until error is returned from any
|
||||
func RunEach(u *Update, disps ...*Dispatcher) error {
|
||||
for _, d := range disps {
|
||||
if err := d.Run(u); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
71
filters.go
Normal file
71
filters.go
Normal file
@ -0,0 +1,71 @@
|
||||
package nechotron
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
type FilterFn func(u *Update) bool
|
||||
type FilteredValue interface{}
|
||||
|
||||
func TextStartsWith(text string) FilterFn {
|
||||
return func(u *Update) bool {
|
||||
return strings.HasPrefix(u.Text(), text)
|
||||
}
|
||||
}
|
||||
|
||||
func TextStartsWithAny(subs ...string) FilterFn {
|
||||
return func(u *Update) bool {
|
||||
text := u.Text()
|
||||
for _, sub := range subs {
|
||||
if strings.HasPrefix(text, sub) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func TextHas(text string) FilterFn {
|
||||
return func(u *Update) bool {
|
||||
return strings.Contains(u.Text(), text)
|
||||
}
|
||||
}
|
||||
|
||||
func TextHasAny(subs ...string) FilterFn {
|
||||
return func(u *Update) bool {
|
||||
text := u.Text()
|
||||
for _, sub := range subs {
|
||||
if strings.Contains(text, sub) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func IsPrivate(u *Update) bool {
|
||||
return u.ChatID() > 0
|
||||
}
|
||||
|
||||
func IsForum(u *Update) bool {
|
||||
return u.Chat().IsForum
|
||||
}
|
||||
|
||||
func IsReply(u *Update) bool {
|
||||
return u.IsReply()
|
||||
}
|
||||
|
||||
func IsCallback(u *Update) bool {
|
||||
return u.IsCallback()
|
||||
}
|
||||
|
||||
func IsUserAdmin(u *Update) bool {
|
||||
if IsPrivate(u) {
|
||||
return true
|
||||
}
|
||||
member, err := u.Bot.GetChatMember(u.ChatID(), u.From().ID)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return member.Result.Status == "administrator" || member.Result.Status == "creator"
|
||||
}
|
8
go.mod
Normal file
8
go.mod
Normal file
@ -0,0 +1,8 @@
|
||||
module git.nefrace.ru/nefrace/nechotron
|
||||
|
||||
go 1.21
|
||||
|
||||
require (
|
||||
github.com/NicoNex/echotron/v3 v3.27.0
|
||||
github.com/google/uuid v1.4.0
|
||||
)
|
8
go.sum
Normal file
8
go.sum
Normal file
@ -0,0 +1,8 @@
|
||||
github.com/NicoNex/echotron/v3 v3.26.0 h1:kNO9AD0CNXAlbd96Z4jT8NHcn2OPD3wTXs6HnjXHXU0=
|
||||
github.com/NicoNex/echotron/v3 v3.26.0/go.mod h1:LpP5IyHw0y+DZUZMBgXEDAF9O8feXrQu7w7nlJzzoZI=
|
||||
github.com/NicoNex/echotron/v3 v3.27.0 h1:iq4BLPO+Dz1JHjh2HPk0D0NldAZSYcAjaOicgYEhUzw=
|
||||
github.com/NicoNex/echotron/v3 v3.27.0/go.mod h1:LpP5IyHw0y+DZUZMBgXEDAF9O8feXrQu7w7nlJzzoZI=
|
||||
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
|
||||
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
|
||||
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
@ -6,6 +6,10 @@ type InKeyboard struct {
|
||||
Buttons [][]echotron.InlineKeyboardButton
|
||||
}
|
||||
|
||||
func NewInlineKeyboard() *InKeyboard {
|
||||
return &InKeyboard{}
|
||||
}
|
||||
|
||||
func (i *InKeyboard) Row(buttons ...echotron.InlineKeyboardButton) *InKeyboard {
|
||||
i.Buttons = append(i.Buttons, buttons)
|
||||
return i
|
||||
|
21
markdown.go
Normal file
21
markdown.go
Normal file
@ -0,0 +1,21 @@
|
||||
package nechotron
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/NicoNex/echotron/v3"
|
||||
)
|
||||
|
||||
var chars = []string{"_", "\\*", "\\[", "\\]", "\\(", "\\)", "~", "`", ">", "#", "\\+", "\\-", "=", "|", "{", "}", "\\.", "!"}
|
||||
var r = strings.Join(chars, "")
|
||||
var reg = regexp.MustCompile("[" + r + "]+")
|
||||
|
||||
func EscapeMd2(s string) string {
|
||||
return reg.ReplaceAllString(s, "\\$0")
|
||||
}
|
||||
|
||||
func UserMention(u *echotron.User) string {
|
||||
return fmt.Sprintf("[%s](tg://user?id=%d)", EscapeMd2(u.FirstName), u.ID)
|
||||
}
|
3
middleware.go
Normal file
3
middleware.go
Normal file
@ -0,0 +1,3 @@
|
||||
package nechotron
|
||||
|
||||
type Middleware func(next UpdateHandler) UpdateHandler
|
23
nechotron.go
23
nechotron.go
@ -8,7 +8,9 @@ import (
|
||||
|
||||
type Nechotron struct {
|
||||
Token string
|
||||
DefaultState *State
|
||||
DefaultState Runnable
|
||||
ApiServer string
|
||||
Handler UpdateHandler
|
||||
}
|
||||
|
||||
func NewTron(token string, defaultState *State) *Nechotron {
|
||||
@ -19,20 +21,24 @@ func NewTron(token string, defaultState *State) *Nechotron {
|
||||
return &Nechotron{
|
||||
Token: token,
|
||||
DefaultState: state,
|
||||
Handler: DefaultHandler,
|
||||
}
|
||||
}
|
||||
|
||||
func (n *Nechotron) newBot(chatID int64) echo.Bot {
|
||||
a := echo.NewAPI(n.Token)
|
||||
// a := echo.NewAPI(n.Token)
|
||||
me, _ := a.GetMe()
|
||||
// log.Println("New bot active: ", chatID, me.Result)
|
||||
b := &bot{
|
||||
chatID: chatID,
|
||||
me: me.Result,
|
||||
API: a,
|
||||
state: n.DefaultState,
|
||||
chatID: chatID,
|
||||
Me: me.Result,
|
||||
API: a,
|
||||
State: n.DefaultState,
|
||||
data: make(StateData),
|
||||
handler: n.Handler,
|
||||
}
|
||||
b.state = n.DefaultState
|
||||
b.State = n.DefaultState
|
||||
return b
|
||||
}
|
||||
|
||||
@ -41,3 +47,8 @@ func (n *Nechotron) DispatchPoll() error {
|
||||
log.Println("Nechotron poll dispatcher started")
|
||||
return dispatcher.Poll()
|
||||
}
|
||||
|
||||
func (n *Nechotron) Use(mid Middleware) *Nechotron {
|
||||
n.Handler = mid(n.Handler)
|
||||
return n
|
||||
}
|
||||
|
130
options.go
Normal file
130
options.go
Normal file
@ -0,0 +1,130 @@
|
||||
package nechotron
|
||||
|
||||
import "github.com/NicoNex/echotron/v3"
|
||||
|
||||
type OptionsBuilder struct {
|
||||
caption string
|
||||
replyMarkup echotron.ReplyMarkup
|
||||
parseMode echotron.ParseMode
|
||||
entities []echotron.MessageEntity
|
||||
messageThreadID int64
|
||||
replyToMessageID int
|
||||
disableWebPagePreview bool
|
||||
disableNotification bool
|
||||
protectContent bool
|
||||
allowSendingWithoutReply bool
|
||||
hasSpoiler bool
|
||||
}
|
||||
|
||||
func NewOptions() *OptionsBuilder {
|
||||
return &OptionsBuilder{}
|
||||
}
|
||||
|
||||
func (o *OptionsBuilder) Caption(text string) *OptionsBuilder {
|
||||
o.caption = text
|
||||
return o
|
||||
}
|
||||
|
||||
func (o *OptionsBuilder) ReplyMarkup(markup echotron.ReplyMarkup) *OptionsBuilder {
|
||||
o.replyMarkup = markup
|
||||
return o
|
||||
}
|
||||
|
||||
func (o *OptionsBuilder) MarkdownV2() *OptionsBuilder {
|
||||
o.parseMode = echotron.MarkdownV2
|
||||
return o
|
||||
}
|
||||
|
||||
func (o *OptionsBuilder) Spoiler() *OptionsBuilder {
|
||||
o.hasSpoiler = true
|
||||
return o
|
||||
}
|
||||
|
||||
func (o *OptionsBuilder) Entities(entities []echotron.MessageEntity) *OptionsBuilder {
|
||||
o.entities = entities
|
||||
return o
|
||||
}
|
||||
|
||||
func (o *OptionsBuilder) Thread(id int64) *OptionsBuilder {
|
||||
o.messageThreadID = id
|
||||
return o
|
||||
}
|
||||
|
||||
func (o *OptionsBuilder) ReplyTo(id int) *OptionsBuilder {
|
||||
o.replyToMessageID = id
|
||||
return o
|
||||
}
|
||||
|
||||
func (o *OptionsBuilder) DisableNotification() *OptionsBuilder {
|
||||
o.disableNotification = true
|
||||
return o
|
||||
}
|
||||
|
||||
func (o *OptionsBuilder) ProtectContent() *OptionsBuilder {
|
||||
o.protectContent = true
|
||||
return o
|
||||
}
|
||||
|
||||
func (o *OptionsBuilder) DisableWebPagePreview() *OptionsBuilder {
|
||||
o.disableWebPagePreview = true
|
||||
return o
|
||||
}
|
||||
|
||||
func (o *OptionsBuilder) AllowSendingWithoutReply() *OptionsBuilder {
|
||||
o.allowSendingWithoutReply = true
|
||||
return o
|
||||
}
|
||||
|
||||
func (o *OptionsBuilder) MessageOptions() *echotron.MessageOptions {
|
||||
return &echotron.MessageOptions{
|
||||
ReplyMarkup: o.replyMarkup,
|
||||
ParseMode: o.parseMode,
|
||||
Entities: o.entities,
|
||||
MessageThreadID: o.messageThreadID,
|
||||
ReplyToMessageID: o.replyToMessageID,
|
||||
DisableWebPagePreview: o.allowSendingWithoutReply,
|
||||
DisableNotification: o.disableNotification,
|
||||
ProtectContent: o.protectContent,
|
||||
AllowSendingWithoutReply: o.allowSendingWithoutReply,
|
||||
}
|
||||
}
|
||||
|
||||
func (o *OptionsBuilder) MessageTextOptions() *echotron.MessageTextOptions {
|
||||
return &echotron.MessageTextOptions{
|
||||
ReplyMarkup: o.replyMarkup.(echotron.InlineKeyboardMarkup),
|
||||
ParseMode: o.parseMode,
|
||||
Entities: o.entities,
|
||||
DisableWebPagePreview: o.allowSendingWithoutReply,
|
||||
}
|
||||
}
|
||||
|
||||
func (o *OptionsBuilder) PhotoOptions() *echotron.PhotoOptions {
|
||||
return &echotron.PhotoOptions{
|
||||
ReplyMarkup: o.replyMarkup,
|
||||
ParseMode: o.parseMode,
|
||||
Caption: o.caption,
|
||||
CaptionEntities: o.entities,
|
||||
MessageThreadID: int(o.messageThreadID),
|
||||
ReplyToMessageID: o.replyToMessageID,
|
||||
HasSpoiler: o.hasSpoiler,
|
||||
DisableNotification: o.disableNotification,
|
||||
ProtectContent: o.protectContent,
|
||||
AllowSendingWithoutReply: o.allowSendingWithoutReply,
|
||||
}
|
||||
}
|
||||
|
||||
func (o *OptionsBuilder) VideoOptions() *echotron.VideoOptions {
|
||||
return &echotron.VideoOptions{
|
||||
ReplyMarkup: o.replyMarkup,
|
||||
ParseMode: o.parseMode,
|
||||
Caption: o.caption,
|
||||
CaptionEntities: o.entities,
|
||||
SupportsStreaming: true,
|
||||
MessageThreadID: int(o.messageThreadID),
|
||||
ReplyToMessageID: o.replyToMessageID,
|
||||
HasSpoiler: o.hasSpoiler,
|
||||
DisableNotification: o.disableNotification,
|
||||
ProtectContent: o.protectContent,
|
||||
AllowSendingWithoutReply: o.allowSendingWithoutReply,
|
||||
}
|
||||
}
|
46
state.go
46
state.go
@ -1,23 +1,55 @@
|
||||
package nechotron
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/NicoNex/echotron/v3"
|
||||
)
|
||||
|
||||
type State struct {
|
||||
Fn stateFn
|
||||
Data context.Context
|
||||
type StateData map[string]interface{}
|
||||
|
||||
type Runnable interface {
|
||||
Call(*Update) error
|
||||
}
|
||||
|
||||
type stateFn func(*Update) (*State, error)
|
||||
type State struct {
|
||||
Fn stateFn
|
||||
}
|
||||
|
||||
func (s *State) Call(u *Update) error {
|
||||
return s.Fn(u)
|
||||
}
|
||||
|
||||
type stateFn func(*Update) error
|
||||
|
||||
func (d StateData) Set(name string, data interface{}) {
|
||||
d[name] = data
|
||||
}
|
||||
|
||||
func (d StateData) Get(name string) (interface{}, error) {
|
||||
data, ok := d[name]
|
||||
if !ok {
|
||||
return nil, errors.New("can't get data from statedata")
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (d StateData) Has(name string) bool {
|
||||
_, ok := d[name]
|
||||
return ok
|
||||
}
|
||||
|
||||
func (d StateData) Clear() {
|
||||
for k := range d {
|
||||
delete(d, k)
|
||||
}
|
||||
}
|
||||
|
||||
var EchoState = State{
|
||||
Fn: EchoFunc,
|
||||
}
|
||||
|
||||
func EchoFunc(u *Update) (*State, error) {
|
||||
func EchoFunc(u *Update) error {
|
||||
u.AnswerText(u.Text(), &echotron.MessageOptions{})
|
||||
return nil, nil
|
||||
return nil
|
||||
}
|
||||
|
98
update.go
98
update.go
@ -13,6 +13,10 @@ type U echotron.Update
|
||||
|
||||
var emptyOpts = echotron.MessageOptions{}
|
||||
|
||||
type Event interface {
|
||||
Upd() *echotron.Update
|
||||
}
|
||||
|
||||
type Update struct {
|
||||
U
|
||||
Bot *bot
|
||||
@ -20,10 +24,35 @@ type Update struct {
|
||||
Ctx context.Context
|
||||
}
|
||||
|
||||
type UpdateCommand struct {
|
||||
Update
|
||||
Param string
|
||||
}
|
||||
|
||||
func (u *Update) Upd() *echotron.Update {
|
||||
return (*echotron.Update)(&u.U)
|
||||
}
|
||||
|
||||
func (u *Update) Chat() echotron.Chat {
|
||||
if u.IsMessage() {
|
||||
return u.Message.Chat
|
||||
}
|
||||
if u.IsCallback() {
|
||||
return u.CallbackQuery.Message.Chat
|
||||
}
|
||||
if u.EditedMessage != nil {
|
||||
return u.EditedMessage.Chat
|
||||
}
|
||||
if u.ChatMember != nil {
|
||||
return u.ChatMember.Chat
|
||||
}
|
||||
if u.MyChatMember != nil {
|
||||
return u.MyChatMember.Chat
|
||||
}
|
||||
log.Fatalf("[%s] Can't get ChatID of update %v+", u.UpdateID, u.U)
|
||||
return echotron.Chat{}
|
||||
}
|
||||
|
||||
func (u *Update) ChatID() int64 {
|
||||
if u.IsMessage() {
|
||||
return u.Message.Chat.ID
|
||||
@ -44,6 +73,18 @@ func (u *Update) MessageID() int {
|
||||
log.Fatalf("[%s] Can't get ChatID of update %v+", u.UpdateID, u.U)
|
||||
return 0
|
||||
}
|
||||
func (u *Update) ThreadID() int64 {
|
||||
if !u.Chat().IsForum {
|
||||
return 0
|
||||
}
|
||||
if u.IsMessage() {
|
||||
return int64(u.Message.ThreadID)
|
||||
}
|
||||
if u.IsCallback() {
|
||||
return int64(u.CallbackQuery.Message.ThreadID)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (u *Update) AnswerText(text string, options *echotron.MessageOptions) (echotron.APIResponseMessage, error) {
|
||||
return u.Bot.SendMessage(text, u.ChatID(), options)
|
||||
@ -54,12 +95,15 @@ func (u *Update) EditText(text string, options *echotron.MessageTextOptions) (ec
|
||||
}
|
||||
|
||||
func (u *Update) AnswerPlain(text string) (echotron.APIResponseMessage, error) {
|
||||
return u.Bot.SendMessage(text, u.ChatID(), &emptyOpts)
|
||||
return u.Bot.SendMessage(text, u.ChatID(), &echotron.MessageOptions{
|
||||
MessageThreadID: u.ThreadID(),
|
||||
})
|
||||
}
|
||||
|
||||
func (u *Update) AnswerMarkdown(text string) (echotron.APIResponseMessage, error) {
|
||||
return u.Bot.SendMessage(text, u.ChatID(), &echotron.MessageOptions{
|
||||
ParseMode: echotron.MarkdownV2,
|
||||
ParseMode: echotron.MarkdownV2,
|
||||
MessageThreadID: u.ThreadID(),
|
||||
})
|
||||
}
|
||||
|
||||
@ -87,6 +131,9 @@ func (u *Update) IsMessage() bool {
|
||||
func (u *Update) IsCallback() bool {
|
||||
return u.CallbackQuery != nil
|
||||
}
|
||||
func (u *Update) IsReply() bool {
|
||||
return u.IsMessage() && u.Message.ReplyToMessage != nil
|
||||
}
|
||||
func (u *Update) IsButton(b *Button) bool {
|
||||
if u.IsText() && u.Text() == b.text {
|
||||
return true
|
||||
@ -151,14 +198,43 @@ func (u *Update) From() *echotron.User {
|
||||
if u.IsMessage() {
|
||||
return u.Message.From
|
||||
}
|
||||
if u.EditedMessage != nil {
|
||||
return u.EditedMessage.From
|
||||
}
|
||||
if u.ChatMember != nil {
|
||||
return &u.ChatMember.From
|
||||
}
|
||||
if u.MyChatMember != nil {
|
||||
return &u.MyChatMember.From
|
||||
}
|
||||
return u.CallbackQuery.From
|
||||
}
|
||||
|
||||
func GetText(u *echotron.Message) string {
|
||||
if u.Text != "" {
|
||||
return u.Text
|
||||
}
|
||||
if u.Caption != "" {
|
||||
return u.Caption
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (u *Update) Text() string {
|
||||
if u.IsText() {
|
||||
return u.Message.Text
|
||||
}
|
||||
return u.Message.Caption
|
||||
if u.IsMessage() {
|
||||
return u.Message.Caption
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (u *Update) Callback() string {
|
||||
if u.IsCallback() {
|
||||
return u.CallbackQuery.Data
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (u *Update) Entities() []*echotron.MessageEntity {
|
||||
@ -168,27 +244,13 @@ func (u *Update) Entities() []*echotron.MessageEntity {
|
||||
return u.Message.CaptionEntities
|
||||
}
|
||||
|
||||
func (u *Update) IsUserAdmin() bool {
|
||||
ids := []int64{
|
||||
60441930, // v.rud
|
||||
327487258, // vika shet
|
||||
}
|
||||
from := u.From()
|
||||
for i := range ids {
|
||||
if from.ID == ids[i] {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (u *Update) LogError(text string, e error, send bool) {
|
||||
if text != "" {
|
||||
text = "Ошибка: " + text
|
||||
} else {
|
||||
text = "Произошла внутренняя ошибка"
|
||||
}
|
||||
log.Printf("[%s] %s: %v", u.UpdateID.String(), text, e)
|
||||
log.Printf("ERROR :: [%s] :: %s: %v", u.UpdateID.String(), text, e)
|
||||
if send {
|
||||
u.AnswerMarkdown(fmt.Sprintf("%s\nКод запроса: `%s`", text, u.UpdateID.String()))
|
||||
}
|
||||
|
Reference in New Issue
Block a user