initial
This commit is contained in:
commit
af8982be2d
|
@ -0,0 +1,35 @@
|
||||||
|
package nechotron
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
echo "github.com/NicoNex/echotron/v3"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
type bot struct {
|
||||||
|
chatID int64
|
||||||
|
me *echo.User
|
||||||
|
echo.API
|
||||||
|
state *State
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *bot) Update(u *echo.Update) {
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
upd := &Update{
|
||||||
|
U: U(*u),
|
||||||
|
Bot: b,
|
||||||
|
UpdateID: uuid.New(),
|
||||||
|
Ctx: ctx,
|
||||||
|
}
|
||||||
|
|
||||||
|
newState, err := b.state.Fn(upd)
|
||||||
|
if err != nil {
|
||||||
|
upd.LogError("", err, true)
|
||||||
|
}
|
||||||
|
if newState != nil {
|
||||||
|
b.state = newState
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,104 @@
|
||||||
|
package nechotron
|
||||||
|
|
||||||
|
import "github.com/NicoNex/echotron/v3"
|
||||||
|
|
||||||
|
type InKeyboard struct {
|
||||||
|
Buttons [][]echotron.InlineKeyboardButton
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *InKeyboard) Row(buttons ...echotron.InlineKeyboardButton) *InKeyboard {
|
||||||
|
i.Buttons = append(i.Buttons, buttons)
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *InKeyboard) Markup() echotron.InlineKeyboardMarkup {
|
||||||
|
if len(i.Buttons) == 0 {
|
||||||
|
return echotron.InlineKeyboardMarkup{
|
||||||
|
InlineKeyboard: [][]echotron.InlineKeyboardButton{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return echotron.InlineKeyboardMarkup{
|
||||||
|
InlineKeyboard: i.Buttons,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func InButtonURL(text string, url string) echotron.InlineKeyboardButton {
|
||||||
|
return echotron.InlineKeyboardButton{
|
||||||
|
Text: text,
|
||||||
|
URL: url,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func InButtonCallback(text string, callback string) echotron.InlineKeyboardButton {
|
||||||
|
return echotron.InlineKeyboardButton{
|
||||||
|
Text: text,
|
||||||
|
CallbackData: callback,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type ReKeyboard struct {
|
||||||
|
Buttons [][]echotron.KeyboardButton
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *ReKeyboard) Row(buttons ...echotron.KeyboardButton) *ReKeyboard {
|
||||||
|
i.Buttons = append(i.Buttons, buttons)
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *ReKeyboard) Markup(oneTime bool) echotron.ReplyKeyboardMarkup {
|
||||||
|
if len(i.Buttons) == 0 {
|
||||||
|
return echotron.ReplyKeyboardMarkup{
|
||||||
|
OneTimeKeyboard: oneTime,
|
||||||
|
ResizeKeyboard: true,
|
||||||
|
Keyboard: [][]echotron.KeyboardButton{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return echotron.ReplyKeyboardMarkup{
|
||||||
|
OneTimeKeyboard: oneTime,
|
||||||
|
ResizeKeyboard: true,
|
||||||
|
Keyboard: i.Buttons,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReButton(text string) echotron.KeyboardButton {
|
||||||
|
return echotron.KeyboardButton{
|
||||||
|
Text: text,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Button struct {
|
||||||
|
text string
|
||||||
|
query string
|
||||||
|
url string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewButton() *Button {
|
||||||
|
return &Button{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Button) ReplyButton() echotron.KeyboardButton {
|
||||||
|
return echotron.KeyboardButton{Text: b.text}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Button) InlineCallback() echotron.InlineKeyboardButton {
|
||||||
|
return echotron.InlineKeyboardButton{CallbackData: b.query}
|
||||||
|
}
|
||||||
|
func (b *Button) InlineURL() echotron.InlineKeyboardButton {
|
||||||
|
return echotron.InlineKeyboardButton{URL: b.url}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Button) Text(text string) *Button {
|
||||||
|
b.text = text
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Button) Query(query string) *Button {
|
||||||
|
b.query = query
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Button) URL(url string) *Button {
|
||||||
|
b.url = url
|
||||||
|
return b
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
package nechotron
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
|
echo "github.com/NicoNex/echotron/v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Nechotron struct {
|
||||||
|
Token string
|
||||||
|
DefaultState *State
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTron(token string, defaultState *State) *Nechotron {
|
||||||
|
state := defaultState
|
||||||
|
if state == nil {
|
||||||
|
state = &EchoState
|
||||||
|
}
|
||||||
|
return &Nechotron{
|
||||||
|
Token: token,
|
||||||
|
DefaultState: state,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *Nechotron) newBot(chatID int64) echo.Bot {
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
b.state = n.DefaultState
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *Nechotron) DispatchPoll() error {
|
||||||
|
dispatcher := echo.NewDispatcher(n.Token, n.newBot)
|
||||||
|
log.Println("Nechotron poll dispatcher started")
|
||||||
|
return dispatcher.Poll()
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package nechotron
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/NicoNex/echotron/v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
type State struct {
|
||||||
|
Fn stateFn
|
||||||
|
Data context.Context
|
||||||
|
}
|
||||||
|
|
||||||
|
type stateFn func(*Update) (*State, error)
|
||||||
|
|
||||||
|
var EchoState = State{
|
||||||
|
Fn: EchoFunc,
|
||||||
|
}
|
||||||
|
|
||||||
|
func EchoFunc(u *Update) (*State, error) {
|
||||||
|
u.AnswerText(u.Text(), &echotron.MessageOptions{})
|
||||||
|
return nil, nil
|
||||||
|
}
|
|
@ -0,0 +1,196 @@
|
||||||
|
package nechotron
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/NicoNex/echotron/v3"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
type U echotron.Update
|
||||||
|
|
||||||
|
var emptyOpts = echotron.MessageOptions{}
|
||||||
|
|
||||||
|
type Update struct {
|
||||||
|
U
|
||||||
|
Bot *bot
|
||||||
|
UpdateID uuid.UUID
|
||||||
|
Ctx context.Context
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *Update) Upd() *echotron.Update {
|
||||||
|
return (*echotron.Update)(&u.U)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *Update) ChatID() int64 {
|
||||||
|
if u.IsMessage() {
|
||||||
|
return u.Message.Chat.ID
|
||||||
|
}
|
||||||
|
if u.IsCallback() {
|
||||||
|
return u.CallbackQuery.Message.Chat.ID
|
||||||
|
}
|
||||||
|
log.Fatalf("[%s] Can't get ChatID of update %v+", u.UpdateID, u.U)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
func (u *Update) MessageID() int {
|
||||||
|
if u.IsMessage() {
|
||||||
|
return u.Message.ID
|
||||||
|
}
|
||||||
|
if u.IsCallback() {
|
||||||
|
return u.CallbackQuery.Message.ID
|
||||||
|
}
|
||||||
|
log.Fatalf("[%s] Can't get ChatID of update %v+", u.UpdateID, u.U)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *Update) AnswerText(text string, options *echotron.MessageOptions) (echotron.APIResponseMessage, error) {
|
||||||
|
return u.Bot.SendMessage(text, u.ChatID(), options)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *Update) EditText(text string, options *echotron.MessageTextOptions) (echotron.APIResponse, error) {
|
||||||
|
return u.Bot.EditMessageText(text, echotron.NewMessageID(u.ChatID(), u.MessageID()), options)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *Update) AnswerPlain(text string) (echotron.APIResponseMessage, error) {
|
||||||
|
return u.Bot.SendMessage(text, u.ChatID(), &emptyOpts)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *Update) AnswerMarkdown(text string) (echotron.APIResponseMessage, error) {
|
||||||
|
return u.Bot.SendMessage(text, u.ChatID(), &echotron.MessageOptions{
|
||||||
|
ParseMode: echotron.MarkdownV2,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *Update) DeleteMessage() (echotron.APIResponse, error) {
|
||||||
|
return u.Bot.DeleteMessage(u.ChatID(), u.MessageID())
|
||||||
|
}
|
||||||
|
|
||||||
|
type MessageType uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
MESSAGE_UNKNOWN MessageType = iota
|
||||||
|
MESSAGE_TEXT
|
||||||
|
MESSAGE_PHOTO
|
||||||
|
MESSAGE_VIDEO
|
||||||
|
MESSAGE_DOCUMENT
|
||||||
|
MESSAGE_AUDIO
|
||||||
|
MESSAGE_VOICE
|
||||||
|
MESSAGE_VIDEONOTE
|
||||||
|
MESSAGE_CALLBACK
|
||||||
|
)
|
||||||
|
|
||||||
|
func (u *Update) IsMessage() bool {
|
||||||
|
return u.Message != nil
|
||||||
|
}
|
||||||
|
func (u *Update) IsCallback() bool {
|
||||||
|
return u.CallbackQuery != nil
|
||||||
|
}
|
||||||
|
func (u *Update) IsButton(b *Button) bool {
|
||||||
|
if u.IsText() && u.Text() == b.text {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if u.IsCallback() && u.CallbackQuery.Data == b.query {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *Update) IsText() bool {
|
||||||
|
return u.IsMessage() && u.Message.Text != ""
|
||||||
|
}
|
||||||
|
func (u *Update) IsPhoto() bool {
|
||||||
|
return u.IsMessage() && u.Message.Photo != nil
|
||||||
|
}
|
||||||
|
func (u *Update) IsVideo() bool {
|
||||||
|
return u.IsMessage() && u.Message.Video != nil
|
||||||
|
}
|
||||||
|
func (u *Update) IsDocument() bool {
|
||||||
|
return u.IsMessage() && u.Message.Document != nil
|
||||||
|
}
|
||||||
|
func (u *Update) IsAudio() bool {
|
||||||
|
return u.IsMessage() && u.Message.Audio != nil
|
||||||
|
}
|
||||||
|
func (u *Update) IsVoice() bool {
|
||||||
|
return u.IsMessage() && u.Message.Voice != nil
|
||||||
|
}
|
||||||
|
func (u *Update) IsVideoNote() bool {
|
||||||
|
return u.IsMessage() && u.Message.VideoNote != nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *Update) Type() MessageType {
|
||||||
|
if u.IsCallback() {
|
||||||
|
return MESSAGE_CALLBACK
|
||||||
|
}
|
||||||
|
if u.IsText() {
|
||||||
|
return MESSAGE_TEXT
|
||||||
|
}
|
||||||
|
if u.IsAudio() {
|
||||||
|
return MESSAGE_AUDIO
|
||||||
|
}
|
||||||
|
if u.IsVideo() {
|
||||||
|
return MESSAGE_VIDEO
|
||||||
|
}
|
||||||
|
if u.IsPhoto() {
|
||||||
|
return MESSAGE_PHOTO
|
||||||
|
}
|
||||||
|
if u.IsDocument() {
|
||||||
|
return MESSAGE_DOCUMENT
|
||||||
|
}
|
||||||
|
if u.IsVoice() {
|
||||||
|
return MESSAGE_VOICE
|
||||||
|
}
|
||||||
|
if u.IsVideoNote() {
|
||||||
|
return MESSAGE_VIDEONOTE
|
||||||
|
}
|
||||||
|
return MESSAGE_UNKNOWN
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *Update) From() *echotron.User {
|
||||||
|
if u.IsMessage() {
|
||||||
|
return u.Message.From
|
||||||
|
}
|
||||||
|
return u.CallbackQuery.From
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *Update) Text() string {
|
||||||
|
if u.IsText() {
|
||||||
|
return u.Message.Text
|
||||||
|
}
|
||||||
|
return u.Message.Caption
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *Update) Entities() []*echotron.MessageEntity {
|
||||||
|
if u.IsText() {
|
||||||
|
return u.Message.Entities
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
if send {
|
||||||
|
u.AnswerMarkdown(fmt.Sprintf("%s\nКод запроса: `%s`", text, u.UpdateID.String()))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue