Skip to content

Commit 5f6757e

Browse files
committed
added new features
1 parent 19e2e92 commit 5f6757e

File tree

5 files changed

+91
-23
lines changed

5 files changed

+91
-23
lines changed

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Features
88
- Embedded a tiny `Expression Engine` to support simple scripting
99
- Supports the following tags `meta, text, label, p, line, inline, span, embed, resource, media, div, menu, nav, dialog, form, template`
1010
- Supports custom replies from custom templates
11+
- Automatically paginate long `Menus` to be compatible with messenger `max-items-limit`
1112

1213
Status
1314
====
@@ -31,6 +32,9 @@ Demo
3132
<!-- here we define the main-menu element, `main` is the id of the main menu -->
3233
<meta name="main-menu" content="main" />
3334

35+
<!-- here we define the welcome menu "after pressing get started button" -->
36+
<meta name="welcome-menu" content="welcome" />
37+
3438
<!-- whether the bkit server should verify the incoming request "from messenger itself" or not -->
3539
<meta name="messenger-verify" content="true" />
3640

@@ -53,6 +57,11 @@ Demo
5357
<a href="#collect" reset="true">Collect Data</a>
5458
</menu>
5559

60+
<menu id="welcome" inline="true">
61+
<a href="#about">Click Here 1</a>
62+
<a href="#about">Click Here 2</a>
63+
</menu>
64+
5665
<div id="about">
5766
<text>I'm bkit, the bots-kit engine</text>
5867
<text>;)</text>

bot.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ type Menu struct {
1818
Title string
1919
If string
2020
Buttons []*Button
21+
Inline bool
2122
}
2223

2324
type Button struct {

messenger_session.go

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -84,15 +84,16 @@ func (m *MessengerSession) SendInput(input *Input) error {
8484
return nil
8585
}
8686
if input.Type == "options" {
87-
callToActions := []messenger.StructuredMessageButton{}
88-
for _, btn := range input.Options {
89-
cta := messenger.StructuredMessageButton{}
90-
cta.Title = btn.Title
91-
cta.Type = "postback"
92-
cta.Payload = btn.Href
93-
callToActions = append(callToActions, cta)
94-
}
95-
return m.response.ButtonTemplate(input.Title, &callToActions, messenger.MessagingType("RESPONSE"))
87+
return m.SendInlineButtons(input.Title, input.Options)
88+
// callToActions := []messenger.StructuredMessageButton{}
89+
// for _, btn := range input.Options {
90+
// cta := messenger.StructuredMessageButton{}
91+
// cta.Title = btn.Title
92+
// cta.Type = "postback"
93+
// cta.Payload = btn.Href
94+
// callToActions = append(callToActions, cta)
95+
// }
96+
// return m.response.ButtonTemplate(input.Title, &callToActions, messenger.MessagingType("RESPONSE"))
9697
}
9798
return nil
9899
}
@@ -102,6 +103,9 @@ func (m *MessengerSession) SendBasicMenu(menu *Menu) error {
102103
if menu == nil {
103104
return nil
104105
}
106+
if menu.Inline {
107+
return m.SendInlineButtons(menu.Title, menu.Buttons)
108+
}
105109
callToActions := []messenger.StructuredMessageButton{}
106110
for _, btn := range menu.Buttons {
107111
cta := messenger.StructuredMessageButton{}
@@ -119,6 +123,19 @@ func (m *MessengerSession) SendBasicMenu(menu *Menu) error {
119123
return m.response.ButtonTemplate(menu.Title, &callToActions, messenger.MessagingType("RESPONSE"))
120124
}
121125

126+
// SendOptions - send a menu to the user
127+
func (m *MessengerSession) SendInlineButtons(title string, btns []*Button) error {
128+
callToActions := []messenger.QuickReply{}
129+
for _, btn := range btns {
130+
cta := messenger.QuickReply{}
131+
cta.Title = btn.Title
132+
cta.ContentType = "text"
133+
cta.Payload = fmt.Sprintf("trgt=%s&btn=%s", btn.Href[1:], btn.ID)
134+
callToActions = append(callToActions, cta)
135+
}
136+
return m.response.TextWithReplies(title, callToActions, messenger.MessagingType("RESPONSE"))
137+
}
138+
122139
// SendNodesOf - send the child nodes of the specified node
123140
func (m *MessengerSession) SendNodesOf(s *goquery.Selection) error {
124141
var err error

messenger_wrapper.go

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ func NewMessenger(b *Bot) *Messenger {
3737
}
3838

3939
// SendGreeting - send the greeting data/messages
40-
func (m Messenger) SendGreeting() error {
40+
func (m Messenger) SetGreeting() error {
4141
if desc, ok := m.bot.Configs["description"]; ok {
4242
return m.client.GreetingSetting(desc)
4343
}
@@ -55,7 +55,7 @@ func (m Messenger) GetMainMenu() *Menu {
5555
}
5656

5757
// SendMainMenu - sending the main messenger menu
58-
func (m Messenger) SendMainMenu(menu *Menu) error {
58+
func (m Messenger) SetMainMenu(menu *Menu) error {
5959
if menu == nil {
6060
return nil
6161
}
@@ -73,19 +73,33 @@ func (m Messenger) SendMainMenu(menu *Menu) error {
7373
}
7474
callToActions = append(callToActions, cta)
7575
}
76-
return m.client.CallToActionsSetting("existing_thread", callToActions)
76+
err := m.client.CallToActionsSetting("existing_thread", callToActions)
77+
if err != nil {
78+
return err
79+
}
80+
return m.client.CallToActionsSetting("new_thread", []messenger.CallToActionsItem{
81+
{
82+
Title: "Get Started ^_^",
83+
Type: "postback",
84+
Payload: "get_started",
85+
},
86+
})
87+
}
88+
89+
func (m Messenger) GetWelcomeMenu() *Menu {
90+
return m.bot.Menus[m.bot.Configs["welcome-menu"]]
7791
}
7892

7993
// Boot - Setup the default handlers
8094
func (m Messenger) Boot() {
8195
// send the main menu
82-
if err := m.SendMainMenu(m.GetMainMenu()); err != nil {
96+
if err := m.SetMainMenu(m.GetMainMenu()); err != nil {
8397
log.Println(err)
8498
return
8599
}
86100

87101
// send greetings
88-
if err := m.SendGreeting(); err != nil {
102+
if err := m.SetGreeting(); err != nil {
89103
log.Println(err)
90104
return
91105
}
@@ -146,12 +160,12 @@ func (m Messenger) Boot() {
146160

147161
// get started button ?
148162
if p.Payload == "get_started" {
149-
if err := m.SendGreeting(); err != nil {
150-
log.Println("[greeting]", err)
163+
if err := m.SetGreeting(); err != nil {
164+
log.Println("[greeting-message]", err)
151165
return
152166
}
153-
if err := session.SendBasicMenu(m.GetMainMenu()); err != nil {
154-
log.Println("[menu]", err)
167+
if err := session.SendBasicMenu(m.GetWelcomeMenu()); err != nil {
168+
log.Println("[welcome-menu]", err)
155169
return
156170
}
157171
return
@@ -187,7 +201,6 @@ func (m Messenger) Boot() {
187201
log.Println("[sending menu] has error?", session.SendBasicMenu(m.bot.Menus[trgt.AttrOr("id", "")]))
188202
default:
189203
r.Text("Sorry, I couldn't understand you", messenger.MessagingType("RESPONSE"))
190-
log.Println("[unknown]", "undefined node type", needle.Get("trgt"))
191204
}
192205
})
193206
}

parser.go

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,30 +29,58 @@ func NewBotFromReader(r io.Reader) (*Bot, error) {
2929
doc.Find("meta").Each(func(_ int, s *goquery.Selection) {
3030
key, _ := s.Attr("name")
3131
value, _ := s.Attr("content")
32-
32+
if key == "" {
33+
return
34+
}
3335
bot.Configs[key] = value
3436
})
3537

38+
// paginate the menu/navs buttons
39+
// messanger maximum navigation links are 3 - 4, we will make them 3 by maximum.
40+
doc.Find("menu,nav").Each(func(_ int, m *goquery.Selection) {
41+
m.SetAttr("inline", m.AttrOr("inline", "false"))
42+
if m.AttrOr("inline", "false") == "true" {
43+
return
44+
}
45+
if m.AttrOr("id", "") == bot.Configs["main-menu"] {
46+
return
47+
}
48+
p, cnt := m, 1
49+
m.Find("a,button").Each(func(i int, b *goquery.Selection) {
50+
if (i > 0) && (i%2 == 0) && m.Find("a,button").Length() > 3 {
51+
newId := fmt.Sprintf("%s-%d", m.AttrOr("id", ""), cnt)
52+
p.AppendHtml(fmt.Sprintf("<a href='#%s'>%s</a>", newId, "More"))
53+
p.AfterHtml(fmt.Sprintf("<menu id='%s' title='%s'></menu>", newId, m.AttrOr("title", "")))
54+
p = bot.Document.Find("#" + newId)
55+
cnt++
56+
}
57+
if p != m {
58+
p.AppendSelection(b.Clone())
59+
b.Remove()
60+
}
61+
})
62+
})
63+
3664
// populate the navs
3765
doc.Find("menu,nav").Each(func(i int, m *goquery.Selection) {
3866
menu := &Menu{}
3967
menu.ID = m.AttrOr("id", fmt.Sprintf("menu%d", i))
40-
menu.Title = m.AttrOr("title", "?")
68+
menu.Title = m.AttrOr("title", "Choose")
4169
menu.Buttons = []*Button{}
70+
menu.Inline = (m.AttrOr("inline", "false") == "true")
4271
m.Find("a,button").Each(func(i int, b *goquery.Selection) {
4372
btn := &Button{}
4473
btn.ID = b.AttrOr("id", fmt.Sprintf("button%d", len(bot.Buttons)+1))
4574
btn.Title = b.Text()
4675
btn.Href = b.AttrOr("href", "")
4776
btn.Embed = b.AttrOr("embed", "false")
4877
btn.Reset = (b.AttrOr("reset", "false") == "true")
49-
5078
menu.Buttons = append(menu.Buttons, btn)
5179
bot.Buttons[btn.ID] = btn
52-
5380
b.SetAttr("id", btn.ID)
5481
})
5582
m.SetAttr("id", menu.ID)
83+
m.SetAttr("title", menu.Title)
5684
bot.Menus[menu.ID] = menu
5785
})
5886

0 commit comments

Comments
 (0)