feat: another refactoring. Less code needed. No focus on marshalling now.
This commit is contained in:
parent
c576e891b8
commit
1471d7cdae
26 changed files with 205 additions and 260 deletions
13
beh.go
13
beh.go
|
@ -4,13 +4,12 @@ package tg
|
||||||
type Behaviour struct {
|
type Behaviour struct {
|
||||||
Root Component
|
Root Component
|
||||||
Init Action
|
Init Action
|
||||||
Screens ScreenMap
|
//Screens ScreenMap
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns new empty behaviour.
|
// Returns new empty behaviour.
|
||||||
func NewBehaviour() *Behaviour {
|
func NewBehaviour() *Behaviour {
|
||||||
return &Behaviour{
|
return &Behaviour{
|
||||||
Screens: make(ScreenMap),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +20,11 @@ func (b *Behaviour) SetInit(a Action) *Behaviour {
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*func (b *Behaviour) SetScreens(screens ScreenMap) *Behaviour {
|
||||||
|
b.Screens = screens
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
// Sets the root node of the Behaviour.
|
// Sets the root node of the Behaviour.
|
||||||
// Mostly used for commands and such stuff.
|
// Mostly used for commands and such stuff.
|
||||||
func (b *Behaviour) SetRootNode(node *RootNode) *Behaviour {
|
func (b *Behaviour) SetRootNode(node *RootNode) *Behaviour {
|
||||||
|
@ -28,6 +32,7 @@ func (b *Behaviour) SetRootNode(node *RootNode) *Behaviour {
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
// The function sets as the standard root widget CommandWidget
|
// The function sets as the standard root widget CommandWidget
|
||||||
// and its commands..
|
// and its commands..
|
||||||
func (b *Behaviour) SetRootWidget(root Component) *Behaviour {
|
func (b *Behaviour) SetRootWidget(root Component) *Behaviour {
|
||||||
|
@ -35,6 +40,7 @@ func (b *Behaviour) SetRootWidget(root Component) *Behaviour {
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
// Check whether the screen exists in the behaviour.
|
// Check whether the screen exists in the behaviour.
|
||||||
func (beh *Behaviour) PathExist(pth Path) bool {
|
func (beh *Behaviour) PathExist(pth Path) bool {
|
||||||
_, ok := beh.Screens[pth]
|
_, ok := beh.Screens[pth]
|
||||||
|
@ -43,7 +49,6 @@ func (beh *Behaviour) PathExist(pth Path) bool {
|
||||||
|
|
||||||
// Returns the screen by it's ID.
|
// Returns the screen by it's ID.
|
||||||
func (beh *Behaviour) GetScreen(pth Path) *Screen {
|
func (beh *Behaviour) GetScreen(pth Path) *Screen {
|
||||||
pth = pth.Clean()
|
|
||||||
if !beh.PathExist(pth) {
|
if !beh.PathExist(pth) {
|
||||||
panic(ScreenNotExistErr)
|
panic(ScreenNotExistErr)
|
||||||
}
|
}
|
||||||
|
@ -51,4 +56,4 @@ func (beh *Behaviour) GetScreen(pth Path) *Screen {
|
||||||
screen := beh.Screens[pth]
|
screen := beh.Screens[pth]
|
||||||
return screen
|
return screen
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
23
bot.go
23
bot.go
|
@ -43,7 +43,7 @@ func (bot *Bot) SetDebug(debug bool) *Bot {
|
||||||
return bot
|
return bot
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bot *Bot) Api() *tgbotapi.BotAPI {
|
func (bot *Bot) API() *tgbotapi.BotAPI {
|
||||||
return bot.api
|
return bot.api
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,16 +53,16 @@ func (bot *Bot) Me() User {
|
||||||
|
|
||||||
// Send the Renderable to the specified session client side.
|
// Send the Renderable to the specified session client side.
|
||||||
// Can be used for both group and private sessions because
|
// Can be used for both group and private sessions because
|
||||||
// SessionId represents both for chat IDs.
|
// SessionID represents both for chat IDs.
|
||||||
func (bot *Bot) Send(
|
func (bot *Bot) Send(
|
||||||
sid SessionId, v Sendable,
|
sid SessionID, v Sendable,
|
||||||
) (*Message, error) {
|
) (*Message, error) {
|
||||||
config := v.SendConfig(sid, bot)
|
config := v.SendConfig(sid, bot)
|
||||||
if config.Error != nil {
|
if config.Error != nil {
|
||||||
return nil, config.Error
|
return nil, config.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
msg, err := bot.api.Send(config.ToApi())
|
msg, err := bot.api.Send(config.ToAPI())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,7 @@ func (bot *Bot) Send(
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bot *Bot) Sendf(
|
func (bot *Bot) Sendf(
|
||||||
sid SessionId, format string, v ...any,
|
sid SessionID, format string, v ...any,
|
||||||
) (*Message, error){
|
) (*Message, error){
|
||||||
return bot.Send(
|
return bot.Send(
|
||||||
sid,
|
sid,
|
||||||
|
@ -81,7 +81,7 @@ func (bot *Bot) Sendf(
|
||||||
|
|
||||||
// Send to the session specified its ID raw chattable from the tgbotapi.
|
// Send to the session specified its ID raw chattable from the tgbotapi.
|
||||||
func (bot *Bot) SendRaw(
|
func (bot *Bot) SendRaw(
|
||||||
sid SessionId, v tgbotapi.Chattable,
|
sid SessionID, v tgbotapi.Chattable,
|
||||||
) (*Message, error) {
|
) (*Message, error) {
|
||||||
msg, err := bot.api.Send(v)
|
msg, err := bot.api.Send(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -93,7 +93,7 @@ func (bot *Bot) SendRaw(
|
||||||
// Get session by its ID. Can be used for any scope
|
// Get session by its ID. Can be used for any scope
|
||||||
// including private, group and channel.
|
// including private, group and channel.
|
||||||
func (bot *Bot) GotSession(
|
func (bot *Bot) GotSession(
|
||||||
sid SessionId,
|
sid SessionID,
|
||||||
) (*Session, bool) {
|
) (*Session, bool) {
|
||||||
session, ok := bot.sessions[sid]
|
session, ok := bot.sessions[sid]
|
||||||
return session, ok
|
return session, ok
|
||||||
|
@ -158,7 +158,7 @@ func (bot *Bot) SetCommands(
|
||||||
|
|
||||||
botCmds := []tgbotapi.BotCommand{}
|
botCmds := []tgbotapi.BotCommand{}
|
||||||
for _, cmd := range cmds {
|
for _, cmd := range cmds {
|
||||||
botCmds = append(botCmds, cmd.ToApi())
|
botCmds = append(botCmds, cmd.ToAPI())
|
||||||
}
|
}
|
||||||
|
|
||||||
//tgbotapi.NewBotCommandScopeAllPrivateChats(),
|
//tgbotapi.NewBotCommandScopeAllPrivateChats(),
|
||||||
|
@ -210,7 +210,7 @@ func (bot *Bot) Run() error {
|
||||||
go bot.handleGroup(chn)
|
go bot.handleGroup(chn)
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
me, _ := bot.Api().GetMe()
|
me, _ := bot.API().GetMe()
|
||||||
bot.me = me
|
bot.me = me
|
||||||
for up := range updates {
|
for up := range updates {
|
||||||
u := Update{
|
u := Update{
|
||||||
|
@ -238,11 +238,10 @@ func (bot *Bot) Run() error {
|
||||||
// The function handles updates supposed for the private
|
// The function handles updates supposed for the private
|
||||||
// chat with the bot.
|
// chat with the bot.
|
||||||
func (bot *Bot) handlePrivate(updates chan Update) {
|
func (bot *Bot) handlePrivate(updates chan Update) {
|
||||||
var sid SessionId
|
var sid SessionID
|
||||||
for u := range updates {
|
for u := range updates {
|
||||||
sid = SessionId(u.FromChat().ID)
|
sid = SessionID(u.FromChat().ID)
|
||||||
session, sessionOk := bot.sessions[sid]
|
session, sessionOk := bot.sessions[sid]
|
||||||
|
|
||||||
if u.Message != nil && !sessionOk {
|
if u.Message != nil && !sessionOk {
|
||||||
// Creating session if we have none
|
// Creating session if we have none
|
||||||
// but only on text messages.
|
// but only on text messages.
|
||||||
|
|
|
@ -78,14 +78,14 @@ func (btn Button) WithSendLocation(ok bool) Button {
|
||||||
return btn
|
return btn
|
||||||
}
|
}
|
||||||
|
|
||||||
func (btn Button) Go(pth Path) Button {
|
func (btn Button) Go(pth Widget) Button {
|
||||||
return btn.WithAction(ScreenGo{
|
return btn.WithAction(WidgetGo{
|
||||||
Path: pth,
|
Path: pth,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (btn Button) GoWithArg(pth Path, arg any) Button {
|
func (btn Button) GoWithArg(pth Widget, arg any) Button {
|
||||||
return btn.WithAction(ScreenGo{
|
return btn.WithAction(WidgetGo{
|
||||||
Path: pth,
|
Path: pth,
|
||||||
Arg: arg,
|
Arg: arg,
|
||||||
})
|
})
|
||||||
|
|
|
@ -20,7 +20,7 @@ var BotCommands = []tg.Command{
|
||||||
tg.NewCommand(
|
tg.NewCommand(
|
||||||
"start",
|
"start",
|
||||||
"start or restart the bot or move to the start screen",
|
"start or restart the bot or move to the start screen",
|
||||||
).Go(StartAbsPath),
|
).Go(StartWidget),
|
||||||
tg.NewCommand(
|
tg.NewCommand(
|
||||||
"info",
|
"info",
|
||||||
"info desc",
|
"info desc",
|
||||||
|
|
|
@ -5,10 +5,9 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
// A simple example widget to show
|
||||||
IncDecPath tg.Path = "inc-dec"
|
// how to store and get session data values
|
||||||
)
|
// and working with dynamic panels.
|
||||||
|
|
||||||
var IncDecWidget = tg.RenderFunc(func(c tg.Context) tg.UI {
|
var IncDecWidget = tg.RenderFunc(func(c tg.Context) tg.UI {
|
||||||
var (
|
var (
|
||||||
kbd *tg.InlineCompo
|
kbd *tg.InlineCompo
|
||||||
|
|
|
@ -4,8 +4,8 @@ import (
|
||||||
"surdeus.su/core/tg"
|
"surdeus.su/core/tg"
|
||||||
)
|
)
|
||||||
|
|
||||||
var HomeButton = tg.Buttonf("Home").Go("/")
|
var HomeButton = tg.Buttonf("Home").Go(StartWidget)
|
||||||
var BackButton = tg.Buttonf("Back").Go("-")
|
var BackButton = tg.Buttonf("Back").Go(tg.Back)
|
||||||
var BackKeyboard = tg.NewKeyboard().Row(
|
var BackKeyboard = tg.NewKeyboard().Row(
|
||||||
BackButton,
|
BackButton,
|
||||||
)
|
)
|
||||||
|
|
|
@ -4,10 +4,6 @@ import (
|
||||||
"surdeus.su/core/tg"
|
"surdeus.su/core/tg"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
LocationPath tg.Path = "location"
|
|
||||||
)
|
|
||||||
|
|
||||||
var LocationWidget = tg.RenderFunc(func(c tg.Context) tg.UI {
|
var LocationWidget = tg.RenderFunc(func(c tg.Context) tg.UI {
|
||||||
return tg.UI{
|
return tg.UI{
|
||||||
tg.Messagef(
|
tg.Messagef(
|
||||||
|
|
|
@ -22,67 +22,36 @@ func ExtractSessionData(c tg.Context) *SessionData {
|
||||||
var beh = tg.NewBehaviour().SetInit(tg.Func(func(c tg.Context) {
|
var beh = tg.NewBehaviour().SetInit(tg.Func(func(c tg.Context) {
|
||||||
// The session initialization.
|
// The session initialization.
|
||||||
c.SetSessionData(&SessionData{})
|
c.SetSessionData(&SessionData{})
|
||||||
})).SetRootNode(tg.NewRootNode(
|
})).SetRootWidget(
|
||||||
// The "/" widget.
|
// Setting as the most top
|
||||||
StartWidget,
|
// widget command handling
|
||||||
|
// so we can call them at any screen.
|
||||||
tg.NewNode(
|
tg.NewCommandCompo().SetUsage(
|
||||||
PanelPath,
|
|
||||||
PanelWidget,
|
|
||||||
),
|
|
||||||
|
|
||||||
tg.NewNode(
|
|
||||||
MutateMessagesPath,
|
|
||||||
MutateMessagesWidget,
|
|
||||||
|
|
||||||
tg.NewNode(
|
|
||||||
UpperCasePath,
|
|
||||||
MutateMessagesToUpperCaseWidget,
|
|
||||||
),
|
|
||||||
tg.NewNode(
|
|
||||||
LowerCasePath,
|
|
||||||
MutateMessagesToLowerCaseWidget,
|
|
||||||
),
|
|
||||||
tg.NewNode(
|
|
||||||
EscapePath,
|
|
||||||
MutateMessagesEscapeWidget,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
tg.NewNode(
|
|
||||||
IncDecPath,
|
|
||||||
IncDecWidget,
|
|
||||||
),
|
|
||||||
|
|
||||||
tg.NewNode(
|
|
||||||
LocationPath,
|
|
||||||
LocationWidget,
|
|
||||||
),
|
|
||||||
)).SetRootWidget(tg.NewCommandCompo().SetUsage(
|
|
||||||
UsageAction,
|
UsageAction,
|
||||||
).SetPreStart(
|
).SetPreStart(
|
||||||
PreStartAction,
|
PreStartAction,
|
||||||
).SetCommands(
|
).SetCommands(
|
||||||
BotCommands...,
|
BotCommands...,
|
||||||
))
|
),
|
||||||
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
token := os.Getenv("BOT_TOKEN")
|
token := os.Getenv("BOT_TOKEN")
|
||||||
|
|
||||||
bot, err := tg.NewBot(token)
|
bot, err := tg.NewBot(token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panic(err)
|
log.Fatalf("tg.NewBot(...): %s", err)
|
||||||
}
|
}
|
||||||
bot = bot.SetBehaviour(beh)
|
bot = bot.SetBehaviour(beh)
|
||||||
//SetDebug(true)
|
//bot.API().Debug = true
|
||||||
|
|
||||||
bot.SetData(&BotData{
|
bot.SetData(&BotData{
|
||||||
Name: "Jay",
|
Name: "Jay",
|
||||||
})
|
})
|
||||||
|
|
||||||
log.Printf("Authorized on account %s", bot.Api().Self.UserName)
|
log.Printf("Authorized on account %s", bot.API().Self.UserName)
|
||||||
err = bot.Run()
|
err = bot.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
log.Fatalf("bot.Run(...): %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,22 +43,15 @@ func (w *MutateMessageCompo) Filter(u tg.Update) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
|
||||||
UpperCasePath tg.Path = "upper-case"
|
|
||||||
LowerCasePath = "lower-case"
|
|
||||||
EscapePath = "escape"
|
|
||||||
MutateMessagesPath = "mutate-messages"
|
|
||||||
)
|
|
||||||
|
|
||||||
var MutateMessagesWidget= tg.RenderFunc(func(c tg.Context) tg.UI {
|
var MutateMessagesWidget= tg.RenderFunc(func(c tg.Context) tg.UI {
|
||||||
return tg.UI{
|
return tg.UI{
|
||||||
tg.Messagef(
|
tg.Messagef(
|
||||||
"Choose widget to mutate strings",
|
"Choose widget to mutate strings",
|
||||||
).Reply(
|
).Reply(
|
||||||
tg.NewKeyboard().Row(
|
tg.NewKeyboard().Row(
|
||||||
tg.Buttonf("Upper case").Go(UpperCasePath),
|
tg.Buttonf("Upper case").Go(UpperCaseWidget),
|
||||||
tg.Buttonf("Lower case").Go(LowerCasePath),
|
tg.Buttonf("Lower case").Go(LowerCaseWidget),
|
||||||
tg.Buttonf("Escape chars").Go(EscapePath),
|
tg.Buttonf("Escape chars").Go(EscapeWidget),
|
||||||
).Row(
|
).Row(
|
||||||
BackButton,
|
BackButton,
|
||||||
).Reply(),
|
).Reply(),
|
||||||
|
@ -66,7 +59,7 @@ var MutateMessagesWidget = tg.RenderFunc(func(c tg.Context) tg.UI {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
var MutateMessagesToLowerCaseWidget = tg.RenderFunc(func(c tg.Context) tg.UI {
|
var LowerCaseWidget = tg.RenderFunc(func(c tg.Context) tg.UI {
|
||||||
return tg.UI{
|
return tg.UI{
|
||||||
tg.Messagef(
|
tg.Messagef(
|
||||||
"Type a string and the bot will convert it to lower case",
|
"Type a string and the bot will convert it to lower case",
|
||||||
|
@ -77,7 +70,7 @@ var MutateMessagesToLowerCaseWidget = tg.RenderFunc(func(c tg.Context) tg.UI {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
var MutateMessagesToUpperCaseWidget = tg.RenderFunc(func(c tg.Context) tg.UI {
|
var UpperCaseWidget = tg.RenderFunc(func(c tg.Context) tg.UI {
|
||||||
return tg.UI{
|
return tg.UI{
|
||||||
tg.Messagef(
|
tg.Messagef(
|
||||||
"Type a string and the bot will convert it to upper case",
|
"Type a string and the bot will convert it to upper case",
|
||||||
|
@ -87,7 +80,7 @@ var MutateMessagesToUpperCaseWidget = tg.RenderFunc(func(c tg.Context) tg.UI {
|
||||||
NewMutateMessageCompo(strings.ToUpper),
|
NewMutateMessageCompo(strings.ToUpper),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
var MutateMessagesEscapeWidget = tg.RenderFunc(func(c tg.Context) tg.UI {
|
var EscapeWidget = tg.RenderFunc(func(c tg.Context) tg.UI {
|
||||||
return tg.UI{
|
return tg.UI{
|
||||||
tg.Messagef(
|
tg.Messagef(
|
||||||
"Type a string and the bot will escape characters in it",
|
"Type a string and the bot will escape characters in it",
|
||||||
|
|
|
@ -4,11 +4,7 @@ import (
|
||||||
"surdeus.su/core/tg"
|
"surdeus.su/core/tg"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
var DynamicPanelWidget = tg.RenderFunc(func(c tg.Context) tg.UI {
|
||||||
PanelPath tg.Path = "panel"
|
|
||||||
)
|
|
||||||
|
|
||||||
var PanelWidget = tg.RenderFunc(func(c tg.Context) tg.UI {
|
|
||||||
var (
|
var (
|
||||||
n = 0
|
n = 0
|
||||||
ln = 4
|
ln = 4
|
||||||
|
|
|
@ -5,36 +5,30 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
StartAbsPath tg.Path = "/"
|
|
||||||
)
|
|
||||||
|
|
||||||
var StartWidget = tg.RenderFunc(func(c tg.Context) tg.UI {
|
var StartWidget = tg.RenderFunc(func(c tg.Context) tg.UI {
|
||||||
return tg.UI{
|
return tg.UI{
|
||||||
tg.Messagef(
|
tg.Messagef(
|
||||||
fmt.Sprint(
|
fmt.Sprint(
|
||||||
"Hello, %s!\n",
|
"Hello, %s!",
|
||||||
"The testing bot started!\n",
|
"The testing bot started!",
|
||||||
"You can see the basics of usage in the ",
|
"You can see the basics of usage in the ",
|
||||||
"cmd/test/main.go file!",
|
"cmd/test/main.go file and other files in the cmd/test!",
|
||||||
),
|
),
|
||||||
c.CallbackUpdate().SentFrom().UserName,
|
c.CallbackUpdate().SentFrom().UserName,
|
||||||
).Inline(
|
).Inline(
|
||||||
tg.NewKeyboard().Row(
|
tg.NewKeyboard().Row(
|
||||||
tg.Buttonf("TeleGopher Vultras page").
|
tg.Buttonf("TeleGopher surdeus.su page").
|
||||||
WithUrl("https://vultras.su/core/tg"),
|
WithUrl("https://surdeus.su/core/tg"),
|
||||||
).Inline(),
|
).Inline(),
|
||||||
),
|
),
|
||||||
|
|
||||||
tg.Messagef("Choose your interest").Reply(
|
tg.Messagef("Choose your interest").Reply(
|
||||||
tg.NewKeyboard().Row(
|
tg.NewKeyboard().List(
|
||||||
tg.Buttonf("Inc/Dec").Go(IncDecPath),
|
tg.Buttonf("Inc/Dec").Go(IncDecWidget),
|
||||||
).Row(
|
tg.Buttonf("Mutate messages").Go(MutateMessagesWidget),
|
||||||
tg.Buttonf("Mutate messages").Go(MutateMessagesPath),
|
tg.Buttonf("Send location").Go(LocationWidget),
|
||||||
).Row(
|
tg.Buttonf("Dynamic panel").Go(DynamicPanelWidget),
|
||||||
tg.Buttonf("Send location").Go(LocationPath),
|
tg.Buttonf("Check panic").Go(nil),
|
||||||
).Row(
|
|
||||||
tg.Buttonf("Dynamic panel").Go(PanelPath),
|
|
||||||
).Reply(),
|
).Reply(),
|
||||||
),
|
),
|
||||||
|
|
||||||
|
|
18
command.go
18
command.go
|
@ -4,6 +4,7 @@ import (
|
||||||
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
type CommandType uint8
|
type CommandType uint8
|
||||||
const (
|
const (
|
||||||
PrivateCommandType CommandType = iota
|
PrivateCommandType CommandType = iota
|
||||||
|
@ -44,7 +45,7 @@ func (c Command) WithWidget(w Widget) Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert command into the tgbotapi.BotCommand
|
// Convert command into the tgbotapi.BotCommand
|
||||||
func (c Command) ToApi() tgbotapi.BotCommand {
|
func (c Command) ToAPI() tgbotapi.BotCommand {
|
||||||
ret := tgbotapi.BotCommand{}
|
ret := tgbotapi.BotCommand{}
|
||||||
ret.Command = string(c.Name)
|
ret.Command = string(c.Name)
|
||||||
ret.Description = c.Description
|
ret.Description = c.Description
|
||||||
|
@ -52,14 +53,14 @@ func (c Command) ToApi() tgbotapi.BotCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simple command to go to another screen.
|
// Simple command to go to another screen.
|
||||||
func (c Command) Go(pth Path) Command {
|
func (c Command) Go(pth Widget) Command {
|
||||||
return c.WithAction(ScreenGo{
|
return c.WithAction(WidgetGo{
|
||||||
Path: pth,
|
Path: pth,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c Command) GoWithArg(pth Path, arg any) Command {
|
func (c Command) GoWithArg(pth Widget, arg any) Command {
|
||||||
return c.WithAction(ScreenGo{
|
return c.WithAction(WidgetGo{
|
||||||
Path: pth,
|
Path: pth,
|
||||||
Arg: arg,
|
Arg: arg,
|
||||||
})
|
})
|
||||||
|
@ -125,7 +126,7 @@ func (compo *CommandCompo) Serve(c Context) {
|
||||||
// First should bring the new command into the action.
|
// First should bring the new command into the action.
|
||||||
c.Bot().DeleteCommands()
|
c.Bot().DeleteCommands()
|
||||||
err := c.Bot().SetCommands(
|
err := c.Bot().SetCommands(
|
||||||
tgbotapi.NewBotCommandScopeChat(c.SessionId().ToApi()),
|
tgbotapi.NewBotCommandScopeChat(c.SessionID().ToAPI()),
|
||||||
compo.Commands,
|
compo.Commands,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -135,11 +136,12 @@ func (compo *CommandCompo) Serve(c Context) {
|
||||||
|
|
||||||
var cmdUpdates *UpdateChan
|
var cmdUpdates *UpdateChan
|
||||||
for u := range c.Input() {
|
for u := range c.Input() {
|
||||||
if c.Path() == "" && u.Message != nil {
|
if c.Path() == nil && u.Message != nil {
|
||||||
// Skipping and executing the preinit action
|
// Skipping and executing the preinit action
|
||||||
// while we have the empty screen.
|
// while we have the empty screen.
|
||||||
// E. g. the session did not start.
|
// E. g. the session did not start.
|
||||||
if !(u.Message.IsCommand() && u.Message.Command() == "start") {
|
if !u.Message.IsCommand() ||
|
||||||
|
u.Message.Command() != "start" {
|
||||||
c.WithUpdate(u).Run(compo.PreStart)
|
c.WithUpdate(u).Run(compo.PreStart)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
87
context.go
87
context.go
|
@ -30,7 +30,7 @@ type Context struct {
|
||||||
// maybe you will find another usage for this.
|
// maybe you will find another usage for this.
|
||||||
// Returns users context by specified session ID
|
// Returns users context by specified session ID
|
||||||
// or false if the user is not logged in.
|
// or false if the user is not logged in.
|
||||||
func (c Context) As(sid SessionId) (Context, bool) {
|
func (c Context) As(sid SessionID) (Context, bool) {
|
||||||
s, ok := c.Bot().GotSession(sid)
|
s, ok := c.Bot().GotSession(sid)
|
||||||
if !ok {
|
if !ok {
|
||||||
return Context{}, false
|
return Context{}, false
|
||||||
|
@ -58,6 +58,9 @@ func (f Func) Render(_ Context) UI {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The type represents type
|
||||||
|
// of current context the processing is happening
|
||||||
|
// in.
|
||||||
type ContextType uint8
|
type ContextType uint8
|
||||||
const (
|
const (
|
||||||
NoContextType ContextType = iota
|
NoContextType ContextType = iota
|
||||||
|
@ -69,8 +72,15 @@ const (
|
||||||
func (c Context) serve() {
|
func (c Context) serve() {
|
||||||
beh := c.Bot().behaviour
|
beh := c.Bot().behaviour
|
||||||
c.Run(beh.Init)
|
c.Run(beh.Init)
|
||||||
|
for {
|
||||||
|
defer func(){
|
||||||
|
if err := recover() ; err != nil {
|
||||||
|
// Need to add some handling later.
|
||||||
|
}
|
||||||
|
}()
|
||||||
beh.Root.Serve(c)
|
beh.Root.Serve(c)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (c Context) Arg() any {
|
func (c Context) Arg() any {
|
||||||
return c.arg
|
return c.arg
|
||||||
|
@ -85,12 +95,12 @@ func (c Context) Run(a Action) {
|
||||||
|
|
||||||
// Sends to the Sendable object to the session user.
|
// Sends to the Sendable object to the session user.
|
||||||
func (c Context) Send(v Sendable) (*Message, error) {
|
func (c Context) Send(v Sendable) (*Message, error) {
|
||||||
config := v.SendConfig(c.SessionId(), c.Bot())
|
config := v.SendConfig(c.SessionID(), c.Bot())
|
||||||
if config.Error != nil {
|
if config.Error != nil {
|
||||||
return nil, config.Error
|
return nil, config.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
msg, err := c.Bot().Api().Send(config.ToApi())
|
msg, err := c.Bot().API().Send(config.ToAPI())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -172,14 +182,16 @@ func (c Context) CallbackUpdate() *Update {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the reader for specified file ID and path.
|
// Returns the reader for specified file ID and path.
|
||||||
func (c Context) GetFile(fileId FileId) (io.ReadCloser, string, error) {
|
func (c Context) GetFile(fileID FileID) (io.ReadCloser, string, error) {
|
||||||
file, err := c.Bot().Api().GetFile(tgbotapi.FileConfig{FileID:string(fileId)})
|
file, err := c.Bot().API().GetFile(tgbotapi.FileConfig{
|
||||||
|
FileID: string(fileID),
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
r, err := http.Get(fmt.Sprintf(
|
r, err := http.Get(fmt.Sprintf(
|
||||||
"https://api.telegram.org/file/bot%s/%s",
|
"https://api.telegram.org/file/bot%s/%s",
|
||||||
c.Bot().Api().Token,
|
c.Bot().API().Token,
|
||||||
file.FilePath,
|
file.FilePath,
|
||||||
))
|
))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -193,8 +205,8 @@ func (c Context) GetFile(fileId FileId) (io.ReadCloser, string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reads all the content from the specified file.
|
// Reads all the content from the specified file.
|
||||||
func (c Context) ReadFile(fileId FileId) ([]byte, string, error) {
|
func (c Context) ReadFile(fileID FileID) ([]byte, string, error) {
|
||||||
file, pth, err := c.GetFile(fileId)
|
file, pth, err := c.GetFile(fileID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
|
@ -240,10 +252,9 @@ func (c Context) runWidget(widget Widget, arg any) (*UpdateChan, error) {
|
||||||
return nil, EmptyWidgetErr
|
return nil, EmptyWidgetErr
|
||||||
}
|
}
|
||||||
|
|
||||||
pth := c.Path()
|
|
||||||
compos := widget.Render(c.WithArg(arg))
|
compos := widget.Render(c.WithArg(arg))
|
||||||
// Leave if changed path or components are empty.
|
// Leave if changed path or components are empty.
|
||||||
if compos == nil || pth != c.Path() {
|
if compos == nil {
|
||||||
return nil, EmptyCompoErr
|
return nil, EmptyCompoErr
|
||||||
}
|
}
|
||||||
chns := make([]*UpdateChan, len(compos))
|
chns := make([]*UpdateChan, len(compos))
|
||||||
|
@ -289,53 +300,42 @@ func (c Context) runWidget(widget Widget, arg any) (*UpdateChan, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simple go without an argument for context.
|
// Simple go without an argument for context.
|
||||||
func (c Context) Go(pth Path) error {
|
func (c Context) Go(pth Widget) error {
|
||||||
return c.GoWithArg(pth, nil)
|
return c.GoWithArg(pth, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Changes screen of user to the Id one.
|
// Go to the specified widget with the
|
||||||
// Also gives the arg to the widget calling
|
// specificed argument.
|
||||||
// contexts.
|
func (c Context) GoWithArg(pth Widget, arg any) error {
|
||||||
func (c Context) GoWithArg(pth Path, arg any) error {
|
|
||||||
var err error
|
var err error
|
||||||
if pth == "" {
|
if pth == nil {
|
||||||
c.session.pathHistory = []Path{}
|
c.session.pathHistory = []Widget{}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var back bool
|
var back bool
|
||||||
if pth == "-" {
|
if pth == Back {
|
||||||
if len(c.session.pathHistory) < 2 {
|
if len(c.session.pathHistory) < 2 {
|
||||||
return c.GoWithArg("", arg)
|
return c.GoWithArg(nil, arg)
|
||||||
}
|
}
|
||||||
pth = c.session.pathHistory[len(c.session.pathHistory)-2]
|
pth = c.session.pathHistory[len(c.session.pathHistory)-2]
|
||||||
c.session.pathHistory = c.session.pathHistory[:len(c.session.pathHistory)-1]
|
c.session.pathHistory =
|
||||||
}
|
c.session.pathHistory[:len(c.session.pathHistory)-1]
|
||||||
// Getting the screen and changing to
|
back = true
|
||||||
// then executing its widget.
|
|
||||||
if !pth.IsAbs() {
|
|
||||||
pth = (c.Path() + "/" + pth).Clean()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !c.PathExist(pth) {
|
if !back {
|
||||||
return ScreenNotExistErr
|
|
||||||
}
|
|
||||||
|
|
||||||
if !back && c.Path() != pth {
|
|
||||||
c.session.pathHistory = append(c.session.pathHistory, pth)
|
c.session.pathHistory = append(c.session.pathHistory, pth)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stopping the current widget.
|
// Stopping the current widget.
|
||||||
screen := c.Bot().behaviour.Screens[pth]
|
|
||||||
c.session.skippedUpdates.Close()
|
c.session.skippedUpdates.Close()
|
||||||
|
|
||||||
if screen.Widget != nil {
|
// Running the new one.
|
||||||
c.session.skippedUpdates, err = c.runWidget(screen.Widget, arg)
|
c.session.skippedUpdates, err = c.runWidget(pth, arg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
return NoWidgetForScreenErr
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -352,8 +352,8 @@ func (c Context) SessionData() any {
|
||||||
return c.session.Data
|
return c.session.Data
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c Context) SessionId() SessionId {
|
func (c Context) SessionID() SessionID {
|
||||||
return c.session.Id
|
return c.session.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c Context) SessionScope() SessionScope {
|
func (c Context) SessionScope() SessionScope {
|
||||||
|
@ -372,20 +372,15 @@ func (c Context) Bot() *Bot {
|
||||||
return c.session.bot
|
return c.session.bot
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the path exists and false otherwise.
|
|
||||||
func (c Context) PathExist(pth Path) bool {
|
|
||||||
return c.session.bot.behaviour.PathExist(pth)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return context's session's path history.
|
// Return context's session's path history.
|
||||||
func (c Context) PathHistory() []Path {
|
func (c Context) PathHistory() []Widget {
|
||||||
return c.session.pathHistory
|
return c.session.pathHistory
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c Context) Path() Path {
|
func (c Context) Path() Widget {
|
||||||
ln := len(c.session.pathHistory)
|
ln := len(c.session.pathHistory)
|
||||||
if ln == 0 {
|
if ln == 0 {
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
return c.session.pathHistory[ln-1]
|
return c.session.pathHistory[ln-1]
|
||||||
}
|
}
|
||||||
|
|
4
devel-loop
Executable file
4
devel-loop
Executable file
|
@ -0,0 +1,4 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
wgo sh -c './btest && ./exe/test'
|
||||||
|
|
7
file.go
7
file.go
|
@ -10,6 +10,7 @@ import (
|
||||||
"github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
"github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type FileID string
|
||||||
type FileConfig = tgbotapi.FileConfig
|
type FileConfig = tgbotapi.FileConfig
|
||||||
type PhotoConfig = tgbotapi.PhotoConfig
|
type PhotoConfig = tgbotapi.PhotoConfig
|
||||||
type FileType int
|
type FileType int
|
||||||
|
@ -107,10 +108,10 @@ func (f *File) SendData() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *File) SendConfig(
|
func (f *File) SendConfig(
|
||||||
sid SessionId, bot *Bot,
|
sid SessionID, bot *Bot,
|
||||||
) (SendConfig) {
|
) (SendConfig) {
|
||||||
var config SendConfig
|
var config SendConfig
|
||||||
cid := sid.ToApi()
|
cid := sid.ToAPI()
|
||||||
|
|
||||||
switch f.Type() {
|
switch f.Type() {
|
||||||
case PhotoFileType:
|
case PhotoFileType:
|
||||||
|
@ -119,7 +120,7 @@ func (f *File) SendConfig(
|
||||||
|
|
||||||
config.Chattable = photo
|
config.Chattable = photo
|
||||||
case DocumentFileType:
|
case DocumentFileType:
|
||||||
doc := tgbotapi.NewDocument(sid.ToApi(), f)
|
doc := tgbotapi.NewDocument(sid.ToAPI(), f)
|
||||||
doc.Caption = f.caption
|
doc.Caption = f.caption
|
||||||
config.Chattable = doc
|
config.Chattable = doc
|
||||||
default:
|
default:
|
||||||
|
|
25
go.go
25
go.go
|
@ -1,22 +1,33 @@
|
||||||
package tg
|
package tg
|
||||||
|
|
||||||
func Go(pth Path) UI {
|
func Go(pth Widget) UI {
|
||||||
return UI{
|
return UI{
|
||||||
GoWidget(pth),
|
WidgetGo{
|
||||||
|
Path: pth,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type GoWidget string
|
// The type implements changing current path to the widget.
|
||||||
|
type WidgetGo struct {
|
||||||
|
Path Widget
|
||||||
|
Arg any
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sc WidgetGo) Act(c Context) {
|
||||||
|
c.GoWithArg(sc.Path, sc.Arg)
|
||||||
|
}
|
||||||
|
|
||||||
// Implementing the Server interface.
|
// Implementing the Server interface.
|
||||||
func (widget GoWidget) Serve(c Context) {
|
func (widget WidgetGo) Serve(c Context) {
|
||||||
c.input.Close()
|
c.input.Close()
|
||||||
c.Go(Path(widget))
|
c.Go(widget)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (widget GoWidget) Render(c Context) UI {
|
func (widget WidgetGo) Render(c Context) UI {
|
||||||
return UI{widget}
|
return UI{widget}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (widget GoWidget) Filter(u Update) bool {
|
func (widget WidgetGo) Filter(u Update) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
16
inline.go
16
inline.go
|
@ -11,7 +11,7 @@ type Inline struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert the inline keyboard to markup for the tgbotapi.
|
// Convert the inline keyboard to markup for the tgbotapi.
|
||||||
func (kbd Inline) ToApi() tgbotapi.InlineKeyboardMarkup {
|
func (kbd Inline) ToAPI() tgbotapi.InlineKeyboardMarkup {
|
||||||
rows := [][]tgbotapi.InlineKeyboardButton{}
|
rows := [][]tgbotapi.InlineKeyboardButton{}
|
||||||
for _, row := range kbd.Rows {
|
for _, row := range kbd.Rows {
|
||||||
if row == nil {
|
if row == nil {
|
||||||
|
@ -38,12 +38,12 @@ type InlineCompo struct {
|
||||||
|
|
||||||
// Implementing the Sendable interface.
|
// Implementing the Sendable interface.
|
||||||
func (compo *InlineCompo) SendConfig(
|
func (compo *InlineCompo) SendConfig(
|
||||||
sid SessionId, bot *Bot,
|
sid SessionID, bot *Bot,
|
||||||
) (SendConfig) {
|
) (SendConfig) {
|
||||||
sendConfig := compo.MessageCompo.SendConfig(sid, bot)
|
sendConfig := compo.MessageCompo.SendConfig(sid, bot)
|
||||||
msg := sendConfig.Chattable.(tgbotapi.MessageConfig)
|
msg := sendConfig.Chattable.(tgbotapi.MessageConfig)
|
||||||
if len(compo.Inline.Rows) > 0 {
|
if len(compo.Inline.Rows) > 0 {
|
||||||
msg.ReplyMarkup = compo.Inline.ToApi()
|
msg.ReplyMarkup = compo.Inline.ToAPI()
|
||||||
}
|
}
|
||||||
sendConfig.Chattable = msg
|
sendConfig.Chattable = msg
|
||||||
|
|
||||||
|
@ -56,23 +56,23 @@ func (compo *InlineCompo) SendConfig(
|
||||||
func (compo *InlineCompo) Update(c Context) error {
|
func (compo *InlineCompo) Update(c Context) error {
|
||||||
if compo.Message != nil {
|
if compo.Message != nil {
|
||||||
var edit tgbotapi.Chattable
|
var edit tgbotapi.Chattable
|
||||||
markup := compo.Inline.ToApi()
|
markup := compo.Inline.ToAPI()
|
||||||
ln := len(markup.InlineKeyboard)
|
ln := len(markup.InlineKeyboard)
|
||||||
if ln == 0 || compo.Inline.Rows == nil {
|
if ln == 0 || compo.Inline.Rows == nil {
|
||||||
edit = tgbotapi.NewEditMessageText(
|
edit = tgbotapi.NewEditMessageText(
|
||||||
c.SessionId().ToApi(),
|
c.SessionID().ToAPI(),
|
||||||
compo.Message.MessageID,
|
compo.Message.MessageID,
|
||||||
compo.Text,
|
compo.Text,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
edit = tgbotapi.NewEditMessageTextAndMarkup(
|
edit = tgbotapi.NewEditMessageTextAndMarkup(
|
||||||
c.SessionId().ToApi(),
|
c.SessionID().ToAPI(),
|
||||||
compo.Message.MessageID,
|
compo.Message.MessageID,
|
||||||
compo.Text,
|
compo.Text,
|
||||||
markup,
|
markup,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
msg, err := c.Bot().Api().Send(edit)
|
msg, err := c.Bot().API().Send(edit)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -113,7 +113,7 @@ func (compo *InlineCompo) OnOneUpdate(c Context, u Update) error {
|
||||||
)
|
)
|
||||||
data := u.CallbackQuery.Data
|
data := u.CallbackQuery.Data
|
||||||
|
|
||||||
_, err := c.Bot().Api().Request(cb)
|
_, err := c.Bot().API().Request(cb)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ type InvoiceCompo struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (compo *InvoiceCompo) SendConfig(
|
func (compo *InvoiceCompo) SendConfig(
|
||||||
sid SessionId, bot *Bot,
|
sid SessionID, bot *Bot,
|
||||||
) (*SendConfig) {
|
) (*SendConfig) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,9 +12,9 @@ type LocationCompo struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (compo *LocationCompo) SendConfig(
|
func (compo *LocationCompo) SendConfig(
|
||||||
sid SessionId, bot *Bot,
|
sid SessionID, bot *Bot,
|
||||||
) (SendConfig) {
|
) (SendConfig) {
|
||||||
cid := sid.ToApi()
|
cid := sid.ToAPI()
|
||||||
location := tgbotapi.NewLocation(
|
location := tgbotapi.NewLocation(
|
||||||
cid,
|
cid,
|
||||||
compo.Latitude,
|
compo.Latitude,
|
||||||
|
|
12
message.go
12
message.go
|
@ -34,11 +34,11 @@ func Escape2(str string) string {
|
||||||
// Call the function after the message was sent.
|
// Call the function after the message was sent.
|
||||||
func (compo *MessageCompo) Update(c Context) error {
|
func (compo *MessageCompo) Update(c Context) error {
|
||||||
edit := tgbotapi.NewEditMessageText(
|
edit := tgbotapi.NewEditMessageText(
|
||||||
c.Session().Id.ToApi(),
|
c.Session().ID.ToAPI(),
|
||||||
compo.Message.MessageID,
|
compo.Message.MessageID,
|
||||||
compo.Text,
|
compo.Text,
|
||||||
)
|
)
|
||||||
msg, err := c.Bot().Api().Send(edit)
|
msg, err := c.Bot().API().Send(edit)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -49,8 +49,8 @@ func (compo *MessageCompo) Update(c Context) error {
|
||||||
// Calling the method removes the message on the client side
|
// Calling the method removes the message on the client side
|
||||||
// and sets the Message in the component to nil.
|
// and sets the Message in the component to nil.
|
||||||
func (compo *MessageCompo) Delete(c Context) error {
|
func (compo *MessageCompo) Delete(c Context) error {
|
||||||
cfg := tgbotapi.NewDeleteMessage(c.session.Id.ToApi(), compo.Message.MessageID)
|
cfg := tgbotapi.NewDeleteMessage(c.session.ID.ToAPI(), compo.Message.MessageID)
|
||||||
_, err := c.Bot().Api().Send(cfg)
|
_, err := c.Bot().API().Send(cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -121,7 +121,7 @@ func (msg *MessageCompo) Location(
|
||||||
|
|
||||||
// Implementing the Sendable interface.
|
// Implementing the Sendable interface.
|
||||||
func (compo *MessageCompo) SendConfig(
|
func (compo *MessageCompo) SendConfig(
|
||||||
sid SessionId, bot *Bot,
|
sid SessionID, bot *Bot,
|
||||||
) (SendConfig) {
|
) (SendConfig) {
|
||||||
var (
|
var (
|
||||||
ret SendConfig
|
ret SendConfig
|
||||||
|
@ -136,7 +136,7 @@ func (compo *MessageCompo) SendConfig(
|
||||||
text = compo.Text
|
text = compo.Text
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := tgbotapi.NewMessage(sid.ToApi(), text)
|
msg := tgbotapi.NewMessage(sid.ToAPI(), text)
|
||||||
msg.ParseMode = compo.ParseMode
|
msg.ParseMode = compo.ParseMode
|
||||||
ret.Chattable = msg
|
ret.Chattable = msg
|
||||||
|
|
||||||
|
|
2
reply.go
2
reply.go
|
@ -64,7 +64,7 @@ type ReplyCompo struct {
|
||||||
|
|
||||||
// Implementing the sendable interface.
|
// Implementing the sendable interface.
|
||||||
func (compo *ReplyCompo) SendConfig(
|
func (compo *ReplyCompo) SendConfig(
|
||||||
sid SessionId, bot *Bot,
|
sid SessionID, bot *Bot,
|
||||||
) (SendConfig) {
|
) (SendConfig) {
|
||||||
sendConfig := compo.MessageCompo.SendConfig(sid, bot)
|
sendConfig := compo.MessageCompo.SendConfig(sid, bot)
|
||||||
|
|
||||||
|
|
66
screen.go
66
screen.go
|
@ -1,48 +1,32 @@
|
||||||
package tg
|
package tg
|
||||||
|
|
||||||
import (
|
type WidgetSpecial int
|
||||||
"path"
|
const (
|
||||||
|
widgetEmpty WidgetSpecial = iota
|
||||||
|
widgetBack
|
||||||
)
|
)
|
||||||
|
|
||||||
// The type implements changing screen to the underlying ScreenId
|
|
||||||
type ScreenGo struct {
|
func (w WidgetSpecial) Render(_ Context) UI {
|
||||||
Path Path
|
return nil
|
||||||
Arg any
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sc ScreenGo) Act(c Context) {
|
var (
|
||||||
c.GoWithArg(sc.Path, sc.Arg)
|
Back = Widget(widgetBack)
|
||||||
}
|
)
|
||||||
|
|
||||||
// The same as Act.
|
/*// Unique identifier for the screen.
|
||||||
func (sc ScreenGo) Serve(c Context) {
|
type Path int
|
||||||
sc.Act(c)
|
const (
|
||||||
}
|
PathEmpty Path = 0
|
||||||
|
// Going to the path returns
|
||||||
// Unique identifier for the screen
|
// a context to the previous screen.
|
||||||
// and relative paths to the screen.
|
PathBack Path = -1
|
||||||
type Path string
|
)
|
||||||
|
|
||||||
// Returns true if the path is empty.
|
// Returns true if the path is empty.
|
||||||
func (p Path) IsEmpty() bool {
|
func (p Path) IsEmpty() bool {
|
||||||
return p == ""
|
return p == 0
|
||||||
}
|
|
||||||
|
|
||||||
// Returns true if the path is absolute.
|
|
||||||
func (p Path) IsAbs() bool {
|
|
||||||
if len(p) == 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return p[0] == '/'
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p Path) Dir() Path {
|
|
||||||
return Path(path.Dir(string(p)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clean the path deleting exceed ., .. and / .
|
|
||||||
func (p Path) Clean() Path {
|
|
||||||
return Path(path.Clean(string(p)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Screen statement of the bot.
|
// Screen statement of the bot.
|
||||||
|
@ -64,10 +48,10 @@ type Node struct {
|
||||||
Path Path
|
Path Path
|
||||||
Screen *Screen
|
Screen *Screen
|
||||||
Subs []*Node
|
Subs []*Node
|
||||||
}
|
}*/
|
||||||
|
|
||||||
// Return new root node with the specified widget in the screen.
|
// Return new root node with the specified widget in the screen.
|
||||||
func NewRootNode(widget Widget, subs ...*Node) *RootNode {
|
/*func NewRootNode(widget Widget, subs ...*Node) *RootNode {
|
||||||
ret := &RootNode{}
|
ret := &RootNode{}
|
||||||
ret.Screen = NewScreen(widget)
|
ret.Screen = NewScreen(widget)
|
||||||
ret.Subs = subs
|
ret.Subs = subs
|
||||||
|
@ -114,15 +98,13 @@ func (n *Node) ScreenMap(root Path) ScreenMap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return m
|
return m
|
||||||
}
|
}*/
|
||||||
|
|
||||||
// Map structure for the screens.
|
|
||||||
type ScreenMap map[Path] *Screen
|
|
||||||
|
|
||||||
// Returns the new screen with specified name and widget.
|
// Returns the new screen with specified name and widget.
|
||||||
func NewScreen(widget Widget) *Screen {
|
/*func NewScreen(widget Widget) *Screen {
|
||||||
return &Screen{
|
return &Screen{
|
||||||
Widget: widget,
|
Widget: widget,
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
|
|
4
send.go
4
send.go
|
@ -10,7 +10,7 @@ type MessageId int64
|
||||||
// way to define what message will be
|
// way to define what message will be
|
||||||
// sent to the side of a user.
|
// sent to the side of a user.
|
||||||
type Sendable interface {
|
type Sendable interface {
|
||||||
SendConfig(SessionId, *Bot) (SendConfig)
|
SendConfig(SessionID, *Bot) (SendConfig)
|
||||||
SetMessage(*Message)
|
SetMessage(*Message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ type SendConfig struct {
|
||||||
type MessageMap map[string] *Message
|
type MessageMap map[string] *Message
|
||||||
|
|
||||||
// Convert to the bot.Api.Send format.
|
// Convert to the bot.Api.Send format.
|
||||||
func (config SendConfig) ToApi() tgbotapi.Chattable {
|
func (config SendConfig) ToAPI() tgbotapi.Chattable {
|
||||||
return config.Chattable
|
return config.Chattable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
20
session.go
20
session.go
|
@ -2,12 +2,12 @@ package tg
|
||||||
|
|
||||||
// The type represents map of sessions using
|
// The type represents map of sessions using
|
||||||
// as key.
|
// as key.
|
||||||
type SessionMap map[SessionId]*Session
|
type SessionMap map[SessionID]*Session
|
||||||
|
|
||||||
// Add new empty session by it's ID.
|
// Add new empty session by it's ID.
|
||||||
func (sm SessionMap) Add(
|
func (sm SessionMap) Add(
|
||||||
bot *Bot,
|
bot *Bot,
|
||||||
sid SessionId,
|
sid SessionID,
|
||||||
scope SessionScope,
|
scope SessionScope,
|
||||||
) *Session {
|
) *Session {
|
||||||
ret := NewSession(bot, sid, scope)
|
ret := NewSession(bot, sid, scope)
|
||||||
|
@ -27,32 +27,32 @@ const (
|
||||||
|
|
||||||
// Represents unique value to identify chats.
|
// Represents unique value to identify chats.
|
||||||
// In fact is simply ID of the chat.
|
// In fact is simply ID of the chat.
|
||||||
type SessionId int64
|
type SessionID int64
|
||||||
|
|
||||||
// Convert the SessionId to Telegram API's type.
|
// Convert the SessionID to Telegram API's type.
|
||||||
func (si SessionId) ToApi() int64 {
|
func (si SessionID) ToAPI() int64 {
|
||||||
return int64(si)
|
return int64(si)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The type represents current state of
|
// The type represents current state of
|
||||||
// user interaction per each of them.
|
// user interaction per each of them.
|
||||||
type Session struct {
|
type Session struct {
|
||||||
// Id of the chat of the user.
|
// ID of the chat of the user.
|
||||||
Id SessionId
|
ID SessionID
|
||||||
Scope SessionScope
|
Scope SessionScope
|
||||||
// Custom value for each user.
|
// Custom value for each user.
|
||||||
Data any
|
Data any
|
||||||
|
|
||||||
bot *Bot
|
bot *Bot
|
||||||
pathHistory []Path
|
pathHistory []Widget
|
||||||
skippedUpdates *UpdateChan
|
skippedUpdates *UpdateChan
|
||||||
updates *UpdateChan
|
updates *UpdateChan
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return new empty session.
|
// Return new empty session.
|
||||||
func NewSession(bot *Bot, id SessionId, scope SessionScope) *Session {
|
func NewSession(bot *Bot, id SessionID, scope SessionScope) *Session {
|
||||||
ret := &Session{}
|
ret := &Session{}
|
||||||
ret.Id = id
|
ret.ID = id
|
||||||
ret.Scope = scope
|
ret.Scope = scope
|
||||||
ret.bot = bot
|
ret.bot = bot
|
||||||
ret.updates = NewUpdateChan()
|
ret.updates = NewUpdateChan()
|
||||||
|
|
11
update.go
11
update.go
|
@ -2,7 +2,6 @@ package tg
|
||||||
|
|
||||||
import tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
import tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
||||||
|
|
||||||
type FileId string
|
|
||||||
|
|
||||||
type Update struct {
|
type Update struct {
|
||||||
tgbotapi.Update
|
tgbotapi.Update
|
||||||
|
@ -64,8 +63,8 @@ func (u Update) HasDocument() bool {
|
||||||
u.Message.Document != nil
|
u.Message.Document != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u Update) DocumentId() FileId {
|
func (u Update) DocumentID() FileID {
|
||||||
return FileId(u.Update.Message.Document.FileID)
|
return FileID(u.Update.Message.Document.FileID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *Update) DocumentName() string {
|
func (u *Update) DocumentName() string {
|
||||||
|
@ -85,10 +84,10 @@ func (u Update) HasPhotos() bool {
|
||||||
len(u.Message.Photo) != 0
|
len(u.Message.Photo) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u Update) PhotoIds() []FileId {
|
func (u Update) PhotoIDs() []FileID {
|
||||||
ret := make([]FileId, len(u.Message.Photo))
|
ret := make([]FileID, len(u.Message.Photo))
|
||||||
for i, photo := range u.Message.Photo {
|
for i, photo := range u.Message.Photo {
|
||||||
ret[i] = FileId(photo.FileID)
|
ret[i] = FileID(photo.FileID)
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue