Great refactoring and rethinking of the Context.
This commit is contained in:
parent
d99ea68198
commit
1fc2acbbd6
7 changed files with 157 additions and 90 deletions
|
@ -26,11 +26,14 @@ func NewMutateMessageWidget(fn func(string) string) *MutateMessageWidget {
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *MutateMessageWidget) Serve(c *tg.Context, updates *tg.UpdateChan) {
|
func (w *MutateMessageWidget) Serve(c *tg.Context) {
|
||||||
for _, arg := range c.Args {
|
args, ok := c.Arg.([]any)
|
||||||
|
if ok {
|
||||||
|
for _, arg := range args {
|
||||||
c.Sendf("%v", arg)
|
c.Sendf("%v", arg)
|
||||||
}
|
}
|
||||||
for u := range updates.Chan() {
|
}
|
||||||
|
for u := range c.Input() {
|
||||||
text := u.Message.Text
|
text := u.Message.Text
|
||||||
c.Sendf("%s", w.Mutate(text))
|
c.Sendf("%s", w.Mutate(text))
|
||||||
}
|
}
|
||||||
|
@ -49,7 +52,7 @@ func ExtractSessionData(c *tg.Context) *SessionData {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
startScreenButton = tg.NewButton("🏠 To the start screen").
|
startScreenButton = tg.NewButton("🏠 To the start screen").
|
||||||
ScreenChange("start")
|
ScreenChange("/start")
|
||||||
|
|
||||||
incDecKeyboard = tg.NewKeyboard().Row(
|
incDecKeyboard = tg.NewKeyboard().Row(
|
||||||
tg.NewButton("+").ActionFunc(func(c *tg.Context) {
|
tg.NewButton("+").ActionFunc(func(c *tg.Context) {
|
||||||
|
@ -67,14 +70,14 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
navKeyboard = tg.NewKeyboard().Row(
|
navKeyboard = tg.NewKeyboard().Row(
|
||||||
tg.NewButton("Inc/Dec").ScreenChange("start/inc-dec"),
|
tg.NewButton("Inc/Dec").ScreenChange("/start/inc-dec"),
|
||||||
).Row(
|
).Row(
|
||||||
tg.NewButton("Upper case").ActionFunc(func(c *tg.Context){
|
tg.NewButton("Upper case").ActionFunc(func(c *tg.Context){
|
||||||
c.ChangeScreen("start/upper-case", "this shit", "works")
|
c.ChangeScreen("/start/upper-case", "this shit", "works")
|
||||||
}),
|
}),
|
||||||
tg.NewButton("Lower case").ScreenChange("start/lower-case"),
|
tg.NewButton("Lower case").ScreenChange("/start/lower-case"),
|
||||||
).Row(
|
).Row(
|
||||||
tg.NewButton("Send location").ScreenChange("start/send-location"),
|
tg.NewButton("Send location").ScreenChange("/start/send-location"),
|
||||||
).Reply().WithOneTime(true)
|
).Reply().WithOneTime(true)
|
||||||
|
|
||||||
sendLocationKeyboard = tg.NewKeyboard().Row(
|
sendLocationKeyboard = tg.NewKeyboard().Row(
|
||||||
|
@ -107,7 +110,7 @@ var beh = tg.NewBehaviour().
|
||||||
// The session initialization.
|
// The session initialization.
|
||||||
c.Session.Data = &SessionData{}
|
c.Session.Data = &SessionData{}
|
||||||
}).WithScreens(
|
}).WithScreens(
|
||||||
tg.NewScreen("start", tg.NewPage(
|
tg.NewScreen("/start", tg.NewPage(
|
||||||
"",
|
"",
|
||||||
).WithInline(
|
).WithInline(
|
||||||
tg.NewKeyboard().Row(
|
tg.NewKeyboard().Row(
|
||||||
|
@ -118,7 +121,7 @@ var beh = tg.NewBehaviour().
|
||||||
navKeyboard.Widget("Choose what you are interested in"),
|
navKeyboard.Widget("Choose what you are interested in"),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
tg.NewScreen("start/inc-dec", tg.NewPage(
|
tg.NewScreen("/start/inc-dec", tg.NewPage(
|
||||||
"The screen shows how "+
|
"The screen shows how "+
|
||||||
"user separated data works "+
|
"user separated data works "+
|
||||||
"by saving the counter for each of users "+
|
"by saving the counter for each of users "+
|
||||||
|
@ -132,7 +135,7 @@ var beh = tg.NewBehaviour().
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
|
|
||||||
tg.NewScreen("start/upper-case", tg.NewPage(
|
tg.NewScreen("/start/upper-case", tg.NewPage(
|
||||||
"Type text and the bot will send you the upper case version to you",
|
"Type text and the bot will send you the upper case version to you",
|
||||||
).WithReply(
|
).WithReply(
|
||||||
navToStartKeyboard.Widget(""),
|
navToStartKeyboard.Widget(""),
|
||||||
|
@ -141,7 +144,7 @@ var beh = tg.NewBehaviour().
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
tg.NewScreen("start/lower-case", tg.NewPage(
|
tg.NewScreen("/start/lower-case", tg.NewPage(
|
||||||
"Type text and the bot will send you the lower case version",
|
"Type text and the bot will send you the lower case version",
|
||||||
).WithReply(
|
).WithReply(
|
||||||
navToStartKeyboard.Widget(""),
|
navToStartKeyboard.Widget(""),
|
||||||
|
@ -150,7 +153,7 @@ var beh = tg.NewBehaviour().
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
tg.NewScreen("start/send-location", tg.NewPage(
|
tg.NewScreen("/start/send-location", tg.NewPage(
|
||||||
"",
|
"",
|
||||||
).WithReply(
|
).WithReply(
|
||||||
sendLocationKeyboard.Widget("Press the button to send your location!"),
|
sendLocationKeyboard.Widget("Press the button to send your location!"),
|
||||||
|
@ -172,7 +175,7 @@ var beh = tg.NewBehaviour().
|
||||||
Desc("start or restart the bot or move to the start screen").
|
Desc("start or restart the bot or move to the start screen").
|
||||||
ActionFunc(func(c *tg.Context){
|
ActionFunc(func(c *tg.Context){
|
||||||
c.Sendf("Your username is %q", c.Message.From.UserName)
|
c.Sendf("Your username is %q", c.Message.From.UserName)
|
||||||
c.ChangeScreen("start")
|
c.ChangeScreen("/start")
|
||||||
}),
|
}),
|
||||||
tg.NewCommand("hello").
|
tg.NewCommand("hello").
|
||||||
Desc("sends the 'Hello, World!' message back").
|
Desc("sends the 'Hello, World!' message back").
|
||||||
|
@ -181,9 +184,9 @@ var beh = tg.NewBehaviour().
|
||||||
}),
|
}),
|
||||||
tg.NewCommand("read").
|
tg.NewCommand("read").
|
||||||
Desc("reads a string and sends it back").
|
Desc("reads a string and sends it back").
|
||||||
WidgetFunc(func(c *tg.Context, updates *tg.UpdateChan) {
|
WidgetFunc(func(c *tg.Context) {
|
||||||
c.Sendf("Type text and I will send it back to you")
|
c.Sendf("Type text and I will send it back to you")
|
||||||
for u := range updates.Chan() {
|
for u := range c.Input() {
|
||||||
if u.Message == nil {
|
if u.Message == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
@ -233,7 +233,8 @@ func (bot *Bot) handlePrivate(updates chan *Update) {
|
||||||
go (&Context{
|
go (&Context{
|
||||||
context: ctx,
|
context: ctx,
|
||||||
Update: u,
|
Update: u,
|
||||||
}).Serve(chn)
|
input: chn,
|
||||||
|
}).serve()
|
||||||
}
|
}
|
||||||
} else if u.Message != nil {
|
} else if u.Message != nil {
|
||||||
// Create session on any message
|
// Create session on any message
|
||||||
|
@ -249,7 +250,8 @@ func (bot *Bot) handlePrivate(updates chan *Update) {
|
||||||
go (&Context{
|
go (&Context{
|
||||||
context: ctx,
|
context: ctx,
|
||||||
Update: u,
|
Update: u,
|
||||||
}).Serve(chn)
|
input: chn,
|
||||||
|
}).serve()
|
||||||
}
|
}
|
||||||
|
|
||||||
chn, ok := chans[sid]
|
chn, ok := chans[sid]
|
||||||
|
|
|
@ -153,10 +153,7 @@ func (widget *Command) Filter(
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (widget *CommandWidget) Serve(
|
func (widget *CommandWidget) Serve(c *Context) {
|
||||||
c *Context,
|
|
||||||
updates *UpdateChan,
|
|
||||||
) {
|
|
||||||
commanders := make(map[CommandName] BotCommander)
|
commanders := make(map[CommandName] BotCommander)
|
||||||
for k, v := range widget.Commands {
|
for k, v := range widget.Commands {
|
||||||
commanders[k] = v
|
commanders[k] = v
|
||||||
|
@ -167,7 +164,7 @@ func (widget *CommandWidget) Serve(
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdUpdates *UpdateChan
|
var cmdUpdates *UpdateChan
|
||||||
for u := range updates.Chan() {
|
for u := range c.Input() {
|
||||||
if c.ScreenId() == "" && u.Message != nil {
|
if c.ScreenId() == "" && 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.
|
||||||
|
@ -190,20 +187,12 @@ func (widget *CommandWidget) Serve(
|
||||||
c.Run(cmd.Action, u)
|
c.Run(cmd.Action, u)
|
||||||
if cmd.Widget != nil {
|
if cmd.Widget != nil {
|
||||||
cmdUpdates.Close()
|
cmdUpdates.Close()
|
||||||
cmdUpdates = NewUpdateChan()
|
cmdUpdates = c.RunWidget(cmd.Widget)
|
||||||
go func() {
|
|
||||||
cmd.Widget.Serve(
|
|
||||||
&Context{context: c.context, Update: u},
|
|
||||||
cmdUpdates,
|
|
||||||
)
|
|
||||||
cmdUpdates.Close()
|
|
||||||
cmdUpdates = nil
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if cmdUpdates != nil {
|
if !cmdUpdates.Closed() {
|
||||||
// Send to the commands channel if we are
|
// Send to the commands channel if we are
|
||||||
// executing one.
|
// executing one.
|
||||||
cmdUpdates.Send(u)
|
cmdUpdates.Send(u)
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
|
|
||||||
// Simple text message type.
|
// Simple text message type.
|
||||||
type MessageConfig struct {
|
type MessageConfig struct {
|
||||||
|
ParseMode string
|
||||||
Text string
|
Text string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,14 +14,35 @@ type MessageConfig struct {
|
||||||
func NewMessage(text string) *MessageConfig {
|
func NewMessage(text string) *MessageConfig {
|
||||||
ret := &MessageConfig{}
|
ret := &MessageConfig{}
|
||||||
ret.Text = text
|
ret.Text = text
|
||||||
|
ret.ParseMode = tgbotapi.ModeMarkdown
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (msg *MessageConfig) withParseMode(mode string) *MessageConfig{
|
||||||
|
msg.ParseMode = mode
|
||||||
|
return msg
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the default Markdown parsing mode.
|
||||||
|
func (msg *MessageConfig) MD() *MessageConfig {
|
||||||
|
return msg.withParseMode(tgbotapi.ModeMarkdown)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (msg *MessageConfig) MD2() *MessageConfig {
|
||||||
|
return msg.withParseMode(tgbotapi.ModeMarkdownV2)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func (msg *MessageConfig) HTML() *MessageConfig {
|
||||||
|
return msg.withParseMode(tgbotapi.ModeHTML)
|
||||||
|
}
|
||||||
|
|
||||||
func (config *MessageConfig) SendConfig(
|
func (config *MessageConfig) SendConfig(
|
||||||
sid SessionId, bot *Bot,
|
sid SessionId, bot *Bot,
|
||||||
) (*SendConfig) {
|
) (*SendConfig) {
|
||||||
var ret SendConfig
|
var ret SendConfig
|
||||||
msg := tgbotapi.NewMessage(sid.ToApi(), config.Text)
|
msg := tgbotapi.NewMessage(sid.ToApi(), config.Text)
|
||||||
ret.Message = &msg
|
ret.Message = &msg
|
||||||
|
ret.Message.ParseMode = config.ParseMode
|
||||||
return &ret
|
return &ret
|
||||||
}
|
}
|
||||||
|
|
16
tg/page.go
16
tg/page.go
|
@ -85,26 +85,24 @@ func (p *Page) Filter(
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Page) Serve(
|
func (p *Page) Serve(c *Context) {
|
||||||
c *Context, updates *UpdateChan,
|
|
||||||
) {
|
|
||||||
msgs, _ := c.Render(p)
|
|
||||||
inlineMsg := msgs["page/inline"]
|
|
||||||
if p.Action != nil {
|
if p.Action != nil {
|
||||||
c.Run(p.Action, c.Update)
|
c.Run(p.Action, c.Update)
|
||||||
}
|
}
|
||||||
|
msgs, _ := c.Render(p)
|
||||||
|
inlineMsg := msgs["page/inline"]
|
||||||
|
|
||||||
subUpdates := c.RunWidgetBg(p.SubWidget)
|
subUpdates := c.RunWidget(p.SubWidget)
|
||||||
defer subUpdates.Close()
|
defer subUpdates.Close()
|
||||||
|
|
||||||
inlineUpdates := c.RunWidgetBg(p.Inline)
|
inlineUpdates := c.RunWidget(p.Inline)
|
||||||
defer inlineUpdates.Close()
|
defer inlineUpdates.Close()
|
||||||
|
|
||||||
replyUpdates := c.RunWidgetBg(p.Reply)
|
replyUpdates := c.RunWidget(p.Reply)
|
||||||
defer replyUpdates.Close()
|
defer replyUpdates.Close()
|
||||||
|
|
||||||
subFilter, subFilterOk := p.SubWidget.(Filterer)
|
subFilter, subFilterOk := p.SubWidget.(Filterer)
|
||||||
for u := range updates.Chan() {
|
for u := range c.Input() {
|
||||||
switch {
|
switch {
|
||||||
case !p.Inline.Filter(u, MessageMap{"": inlineMsg}) :
|
case !p.Inline.Filter(u, MessageMap{"": inlineMsg}) :
|
||||||
inlineUpdates.Send(u)
|
inlineUpdates.Send(u)
|
||||||
|
|
105
tg/private.go
105
tg/private.go
|
@ -6,6 +6,18 @@ import (
|
||||||
//tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
//tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type ContextType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
NoContextType = iota
|
||||||
|
PrivateContextType
|
||||||
|
GroupContextType
|
||||||
|
ChannelContextType
|
||||||
|
)
|
||||||
|
|
||||||
|
// General context for a specific user.
|
||||||
|
// Is always the same and is not reached
|
||||||
|
// inside end function-handlers.
|
||||||
type context struct {
|
type context struct {
|
||||||
Session *Session
|
Session *Session
|
||||||
// To reach the bot abilities inside callbacks.
|
// To reach the bot abilities inside callbacks.
|
||||||
|
@ -15,17 +27,13 @@ type context struct {
|
||||||
screenId, prevScreenId ScreenId
|
screenId, prevScreenId ScreenId
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// The type represents way to interact with user in
|
|
||||||
// handling functions. Is provided to Act() function always.
|
|
||||||
|
|
||||||
// Goroutie function to handle each user.
|
// Goroutie function to handle each user.
|
||||||
func (c *Context) Serve(updates *UpdateChan) {
|
func (c *Context) serve() {
|
||||||
beh := c.Bot.behaviour
|
beh := c.Bot.behaviour
|
||||||
if beh.Init != nil {
|
if beh.Init != nil {
|
||||||
c.Run(beh.Init, c.Update)
|
c.Run(beh.Init, c.Update)
|
||||||
}
|
}
|
||||||
beh.Root.Serve(c, updates)
|
beh.Root.Serve(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -70,6 +78,14 @@ func (c *Context) Sendf(format string, v ...any) (*Message, error) {
|
||||||
return c.Send(NewMessage(fmt.Sprintf(format, v...)))
|
return c.Send(NewMessage(fmt.Sprintf(format, v...)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Context) Sendf2(format string, v ...any) (*Message, error) {
|
||||||
|
return c.Send(NewMessage(fmt.Sprintf(format, v...)).MD2())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Context) SendfHTML(format string, v ...any) (*Message, error) {
|
||||||
|
return c.Send(NewMessage(fmt.Sprintf(format, v...)).HTML())
|
||||||
|
}
|
||||||
|
|
||||||
// Interface to interact with the user.
|
// Interface to interact with the user.
|
||||||
type Context struct {
|
type Context struct {
|
||||||
*context
|
*context
|
||||||
|
@ -78,9 +94,43 @@ type Context struct {
|
||||||
// Used as way to provide outer values redirection
|
// Used as way to provide outer values redirection
|
||||||
// into widgets and actions. It is like arguments
|
// into widgets and actions. It is like arguments
|
||||||
// for REST API request etc.
|
// for REST API request etc.
|
||||||
Args []any
|
Arg any
|
||||||
|
// Instead of updates as argument.
|
||||||
|
input *UpdateChan
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the input for current widget.
|
||||||
|
// Should be used inside handlers (aka "Serve").
|
||||||
|
func (c *Context) Input() chan *Update {
|
||||||
|
return c.input.Chan()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns copy of current context so
|
||||||
|
// it will not affect the current one.
|
||||||
|
// But be careful because
|
||||||
|
// most of the insides uses pointers
|
||||||
|
// which are not deeply copied.
|
||||||
|
func (c *Context) Copy() *Context {
|
||||||
|
ret := *c
|
||||||
|
return &ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Context) WithArg(v any) *Context {
|
||||||
|
c.Arg = v
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Context) WithUpdate(u *Update) *Context {
|
||||||
|
c.Update = u
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Context) WithInput(input *UpdateChan) *Context {
|
||||||
|
c.input = input
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Customized actions for the bot.
|
// Customized actions for the bot.
|
||||||
type Action interface {
|
type Action interface {
|
||||||
Act(*Context)
|
Act(*Context)
|
||||||
|
@ -121,19 +171,9 @@ func (c *Context) ChangeScreen(screenId ScreenId, args ...any) error {
|
||||||
|
|
||||||
// Stopping the current widget.
|
// Stopping the current widget.
|
||||||
c.skippedUpdates.Close()
|
c.skippedUpdates.Close()
|
||||||
// Making channel for the new widget.
|
c.skippedUpdates = nil
|
||||||
c.skippedUpdates = NewUpdateChan()
|
|
||||||
if screen.Widget != nil {
|
if screen.Widget != nil {
|
||||||
// Running the widget if the screen has one.
|
c.skippedUpdates = c.RunWidget(screen.Widget, args)
|
||||||
go func() {
|
|
||||||
updates := c.skippedUpdates
|
|
||||||
screen.Widget.Serve(&Context{
|
|
||||||
context: c.context,
|
|
||||||
Update: c.Update,
|
|
||||||
Args: args,
|
|
||||||
}, updates)
|
|
||||||
updates.Close()
|
|
||||||
}()
|
|
||||||
} else {
|
} else {
|
||||||
panic("no widget defined for the screen")
|
panic("no widget defined for the screen")
|
||||||
}
|
}
|
||||||
|
@ -141,6 +181,33 @@ func (c *Context) ChangeScreen(screenId ScreenId, args ...any) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Run widget in background returning the new input channel for it.
|
||||||
|
func (c *Context) RunWidget(widget Widget, args ...any) *UpdateChan {
|
||||||
|
if widget == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var arg any
|
||||||
|
if len(args) == 1 {
|
||||||
|
arg = args[0]
|
||||||
|
} else if len(args) > 1 {
|
||||||
|
arg = args
|
||||||
|
}
|
||||||
|
|
||||||
|
updates := NewUpdateChan()
|
||||||
|
go func() {
|
||||||
|
widget.Serve(
|
||||||
|
c.Copy().
|
||||||
|
WithInput(updates).
|
||||||
|
WithArg(arg),
|
||||||
|
)
|
||||||
|
updates.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
return updates
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Context) ChangeToPrevScreen() {
|
func (c *Context) ChangeToPrevScreen() {
|
||||||
c.ChangeScreen(c.PrevScreenId())
|
c.ChangeScreen(c.PrevScreenId())
|
||||||
}
|
}
|
||||||
|
|
42
tg/widget.go
42
tg/widget.go
|
@ -13,7 +13,7 @@ type Widget interface {
|
||||||
// widget MUST end its work.
|
// widget MUST end its work.
|
||||||
// Mostly made by looping over the
|
// Mostly made by looping over the
|
||||||
// updates range.
|
// updates range.
|
||||||
Serve(*Context, *UpdateChan)
|
Serve(*Context)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Needs implementation.
|
// Needs implementation.
|
||||||
|
@ -49,11 +49,13 @@ func (updates *UpdateChan) Chan() chan *Update {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send an update to the channel.
|
// Send an update to the channel.
|
||||||
func (updates *UpdateChan) Send(u *Update) {
|
// Returns true if the update was sent.
|
||||||
if updates != nil && updates.chn == nil {
|
func (updates *UpdateChan) Send(u *Update) bool {
|
||||||
return
|
if updates == nil || updates.chn == nil {
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
updates.chn <- u
|
updates.chn <- u
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read an update from the channel.
|
// Read an update from the channel.
|
||||||
|
@ -66,7 +68,7 @@ func (updates *UpdateChan) Read() *Update {
|
||||||
|
|
||||||
// Returns true if the channel is closed.
|
// Returns true if the channel is closed.
|
||||||
func (updates *UpdateChan) Closed() bool {
|
func (updates *UpdateChan) Closed() bool {
|
||||||
return updates.chn == nil
|
return updates==nil || updates.chn == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close the channel. Used in defers.
|
// Close the channel. Used in defers.
|
||||||
|
@ -78,16 +80,6 @@ func (updates *UpdateChan) Close() {
|
||||||
updates.chn = nil
|
updates.chn = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) RunWidgetBg(widget Widget) *UpdateChan {
|
|
||||||
if widget == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
updates := NewUpdateChan()
|
|
||||||
go widget.Serve(c, updates)
|
|
||||||
|
|
||||||
return updates
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implementing the interface provides
|
// Implementing the interface provides
|
||||||
type DynamicWidget interface {
|
type DynamicWidget interface {
|
||||||
|
@ -96,10 +88,10 @@ type DynamicWidget interface {
|
||||||
|
|
||||||
// The function that implements the Widget
|
// The function that implements the Widget
|
||||||
// interface.
|
// interface.
|
||||||
type WidgetFunc func(*Context, *UpdateChan)
|
type WidgetFunc func(*Context)
|
||||||
|
|
||||||
func (wf WidgetFunc) Serve(c *Context, updates *UpdateChan) {
|
func (wf WidgetFunc) Serve(c *Context) {
|
||||||
wf(c, updates)
|
wf(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (wf WidgetFunc) Filter(
|
func (wf WidgetFunc) Filter(
|
||||||
|
@ -145,11 +137,8 @@ func (widget *InlineKeyboardWidget) SendConfig(
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func (widget *InlineKeyboardWidget) Serve(
|
func (widget *InlineKeyboardWidget) Serve(c *Context) {
|
||||||
c *Context,
|
for u := range c.Input() {
|
||||||
updates *UpdateChan,
|
|
||||||
) {
|
|
||||||
for u := range updates.Chan() {
|
|
||||||
var act Action
|
var act Action
|
||||||
if u.CallbackQuery == nil {
|
if u.CallbackQuery == nil {
|
||||||
continue
|
continue
|
||||||
|
@ -263,11 +252,8 @@ func (widget *ReplyKeyboardWidget) Filter(
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (widget *ReplyKeyboardWidget) Serve(
|
func (widget *ReplyKeyboardWidget) Serve(c *Context) {
|
||||||
c *Context,
|
for u := range c.Input() {
|
||||||
updates *UpdateChan,
|
|
||||||
) {
|
|
||||||
for u := range updates.Chan() {
|
|
||||||
var btn *Button
|
var btn *Button
|
||||||
text := u.Message.Text
|
text := u.Message.Text
|
||||||
btns := widget.ButtonMap()
|
btns := widget.ButtonMap()
|
||||||
|
|
Loading…
Reference in a new issue