Skip to content

Commit 9c8dd36

Browse files
author
escalopa
committed
feat(multilang): add scripts handlers for user messages
1 parent f609a6e commit 9c8dd36

File tree

11 files changed

+349
-250
lines changed

11 files changed

+349
-250
lines changed

.pre-commit-config.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ repos:
1313
- id: go-imports
1414
- id: no-go-testing
1515
- id: golangci-lint
16-
stages: [ push ]
16+
stages: [push, merge-commit]
1717
- id: go-unit-tests
18-
stages: [ push ]
18+
stages: [push, merge-commit]
1919
- id: validate-toml
2020
- repo: https://github.com/alessandrojcm/commitlint-pre-commit-hook
2121
rev: v8.0.0

pkg/language/script.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package language
22

3+
import "strings"
4+
35
// Script is a struct that holds all the scripts for each language
46
type Script struct {
57
DataPickerStart string `json:"DataPickerStart"`
@@ -55,7 +57,7 @@ type Script struct {
5557
}
5658

5759
func (s *Script) GetPrayerByName(name string) string {
58-
switch name {
60+
switch strings.ToLower(name) {
5961
case "fajr":
6062
return s.Fajr
6163
case "sunrise":

telegram/cmd/main.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,9 @@ func run(ctx context.Context, b *bt.Bot, ownerID int, useCases *application.UseC
114114
if update.Message == nil {
115115
continue
116116
}
117-
h.Help(update)
117+
_, err := b.SendMessage(update.Message.Chat.Id, "/help", "", 0, false, false)
118+
if err != nil {
119+
log.Printf("failed to send message on unknown command, %v", err)
120+
}
118121
}
119122
}

telegram/internal/handler/admin.go

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
package handler
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"log"
7+
"strconv"
8+
"time"
9+
10+
objs "github.com/SakoDroid/telego/objects"
11+
)
12+
13+
// Respond to a user's feedback or bug report
14+
func (h *Handler) Respond(u *objs.Update) {
15+
chatID := strconv.Itoa(u.Message.Chat.Id)
16+
ch, err := h.b.AdvancedMode().RegisterChannel(chatID, "message")
17+
defer h.b.AdvancedMode().UnRegisterChannel(chatID, "message")
18+
if err != nil {
19+
log.Printf("failed to register channel for /respond: %s", err)
20+
return
21+
}
22+
23+
// Check if reply message is provided
24+
if u.Message.ReplyToMessage == nil {
25+
h.simpleSend(u.Message.Chat.Id, "No reply message provided, /respond", 0)
26+
return
27+
}
28+
29+
// Read userID, messageID, username from the old message that will be replied to
30+
userID, responseMessageID, _, ok := parseUserMessage(u.Message.ReplyToMessage.Text)
31+
if !ok {
32+
h.simpleSend(u.Message.Chat.Id, "Invalid message.", 0)
33+
return
34+
}
35+
36+
// Read response message
37+
messageID := h.simpleSend(u.Message.Chat.Id, "Send your response message, Or /cancel", 0)
38+
defer h.deleteMessage(u.Message.Chat.Id, messageID)
39+
40+
// Create new command context
41+
ctx, cancel := context.WithTimeout(h.userCtx[u.Message.Chat.Id].ctx, 1*time.Minute)
42+
defer cancel()
43+
44+
select {
45+
case <-ctx.Done():
46+
return
47+
case u = <-*ch:
48+
}
49+
50+
if h.cancelOperation(u.Message.Text, "Canceled response.", u.Message.Chat.Id) {
51+
return
52+
}
53+
54+
// Send response message to user
55+
_, err = h.b.SendMessage(userID, u.Message.Text, "", responseMessageID, false, false)
56+
if err != nil {
57+
h.simpleSend(u.Message.Chat.Id, "Failed to send response.", 0)
58+
log.Printf("failed to respond on user's message on : %s", err)
59+
return
60+
}
61+
62+
h.simpleSend(u.Message.Chat.Id, "Response sent successfully.", 0)
63+
}
64+
65+
// GetSubscribers returns the number of subscribers to the bot
66+
func (h *Handler) GetSubscribers(u *objs.Update) {
67+
ids, err := h.u.GetSubscribers(h.c)
68+
if err != nil {
69+
h.simpleSend(u.Message.Chat.Id, "Failed to get subscribers.", 0)
70+
log.Printf("failed to get subscribers on /subs : %s", err)
71+
return
72+
}
73+
h.simpleSend(u.Message.Chat.Id, fmt.Sprintf("Subscribers: %d", len(ids)), 0)
74+
}
75+
76+
// SendAll broadcasts a message to all subscribers
77+
func (h *Handler) SendAll(u *objs.Update) {
78+
// Register channel to receive messages
79+
chatID := u.Message.Chat.Id
80+
ch, err := h.b.AdvancedMode().RegisterChannel(strconv.Itoa(u.Message.Chat.Id), "message")
81+
defer h.b.AdvancedMode().UnRegisterChannel(strconv.Itoa(u.Message.Chat.Id), "message")
82+
if err != nil {
83+
log.Printf("failed to register channel for /sendall: %s", err)
84+
return
85+
}
86+
87+
// Wait for message or timeout after 2 minutes
88+
messageID := h.simpleSend(chatID, "Send your message, Or /cancel", 0)
89+
defer h.deleteMessage(chatID, messageID)
90+
91+
ctx1, cancel1 := context.WithTimeout(h.userCtx[chatID].ctx, 1*time.Minute)
92+
defer cancel1()
93+
94+
select {
95+
case u = <-*ch:
96+
case <-ctx1.Done():
97+
return
98+
}
99+
broadcastMessage := u.Message.Text
100+
101+
if h.cancelOperation(u.Message.Text, "Canceled broadcast.", chatID) {
102+
return
103+
}
104+
105+
// Double check that the owner still wants to send the message
106+
messageID = h.simpleSend(chatID, "Use /confirm to send the message, Or /cancel", 0)
107+
defer h.deleteMessage(chatID, messageID)
108+
109+
// Wait for confirmation message or timeout after 5 minutes
110+
ctx2, cancel2 := context.WithTimeout(h.userCtx[chatID].ctx, 1*time.Minute)
111+
defer cancel2()
112+
113+
select {
114+
case <-ctx2.Done():
115+
return
116+
case u = <-*ch:
117+
}
118+
119+
// Delete the bot message if the user sends the message or if the context times out
120+
defer h.deleteMessage(chatID, u.Message.MessageId)
121+
122+
if u.Message.Text != "/confirm" || h.cancelOperation(u.Message.Text, "Canceled broadcast.", chatID) {
123+
return
124+
}
125+
// Send message to all subscribers in a goroutine
126+
go func() {
127+
// Get all subscribers
128+
ids, err := h.u.GetSubscribers(h.c)
129+
if err != nil {
130+
h.simpleSend(chatID, "Failed to send message.", 0)
131+
log.Printf("failed to send message subscribers on /sendall : %s", err)
132+
return
133+
}
134+
// Send message to all subscribers
135+
for _, id := range ids {
136+
h.simpleSend(id, broadcastMessage, 0)
137+
}
138+
h.simpleSend(chatID, "Message sent successfully.", 0)
139+
}()
140+
}

telegram/internal/handler/calendar.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,16 @@ import (
1313
// The date is passed as two integers, day and month.
1414
func (h *Handler) newCalendar(chatID int, callBack func(int, int)) telego.MarkUps {
1515
kb := h.b.CreateInlineKeyboard()
16-
for i, v := range h.userScript[chatID].GetMonthNames() {
17-
row := (i-1)/2 + 1 // 3 buttons(months) per row.
18-
kb.AddCallbackButtonHandler(v, strconv.Itoa(i), row, func(u1 *objs.Update) {
16+
months := h.userScript[chatID].GetMonthNames()
17+
for i := 1; i <= 12; i++ {
18+
row := (i-1)/3 + 1 // 3 buttons(months) per row.
19+
kb.AddCallbackButtonHandler(months[i-1], strconv.Itoa(i), row, func(u1 *objs.Update) {
1920
// Sets the language.
2021
kb = h.b.CreateInlineKeyboard()
2122
month, _ := strconv.Atoi(u1.CallbackQuery.Data)
2223
daysInMonth := daysIn(time.Month(month), time.Now().Year())
2324
for j := 1; j <= daysInMonth; j++ {
24-
row := (j-1)/7 + 1 // 7 buttons(days) per row.
25+
row := (j-1)/3 + 1 // 3 buttons(days) per row.
2526
kb.AddCallbackButtonHandler(strconv.Itoa(j), strconv.Itoa(j), row, func(u2 *objs.Update) {
2627
day, _ := strconv.Atoi(u2.CallbackQuery.Data)
2728
callBack(day, month)
@@ -30,7 +31,7 @@ func (h *Handler) newCalendar(chatID int, callBack func(int, int)) telego.MarkUp
3031
editor := h.b.GetMsgEditor(u1.CallbackQuery.Message.Chat.Id)
3132
_, err := editor.EditText(
3233
u1.CallbackQuery.Message.MessageId,
33-
"Please choose date",
34+
h.userScript[chatID].DataPickerStart,
3435
"",
3536
"",
3637
nil,

telegram/internal/handler/handler.go

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -46,39 +46,39 @@ func (h *Handler) Run() error {
4646

4747
func (h *Handler) register() error {
4848
var err error
49-
err = h.b.AddHandler("/start", h.contextWrapper(h.Start), "all")
49+
err = h.b.AddHandler("/start", h.contextWrapper(h.scriptWrapper(h.Start)), "all")
5050
if err != nil {
5151
return err
5252
}
53-
err = h.b.AddHandler("/help", h.contextWrapper(h.Help), "all")
53+
err = h.b.AddHandler("/help", h.contextWrapper(h.scriptWrapper(h.Help)), "all")
5454
if err != nil {
5555
return err
5656
}
57-
err = h.b.AddHandler("/subscribe", h.contextWrapper(h.Subscribe), "all")
57+
err = h.b.AddHandler("/subscribe", h.contextWrapper(h.scriptWrapper(h.Subscribe)), "all")
5858
if err != nil {
5959
return err
6060
}
61-
err = h.b.AddHandler("/unsubscribe", h.contextWrapper(h.Unsubscribe), "all")
61+
err = h.b.AddHandler("/unsubscribe", h.contextWrapper(h.scriptWrapper(h.Unsubscribe)), "all")
6262
if err != nil {
6363
return err
6464
}
65-
err = h.b.AddHandler("/today", h.contextWrapper(h.GetPrayers), "all")
65+
err = h.b.AddHandler("/today", h.contextWrapper(h.scriptWrapper(h.GetPrayers)), "all")
6666
if err != nil {
6767
return err
6868
}
69-
err = h.b.AddHandler("/date", h.contextWrapper(h.GetPrayersByDate), "all")
69+
err = h.b.AddHandler("/date", h.contextWrapper(h.scriptWrapper(h.GetPrayersByDate)), "all")
7070
if err != nil {
7171
return err
7272
}
73-
err = h.b.AddHandler("/lang", h.contextWrapper(h.SetLang), "all")
73+
err = h.b.AddHandler("/lang", h.contextWrapper(h.scriptWrapper(h.SetLang)), "all")
7474
if err != nil {
7575
return err
7676
}
77-
err = h.b.AddHandler("/feedback", h.contextWrapper(h.Feedback), "all")
77+
err = h.b.AddHandler("/feedback", h.contextWrapper(h.scriptWrapper(h.Feedback)), "all")
7878
if err != nil {
7979
return err
8080
}
81-
err = h.b.AddHandler("/bug", h.contextWrapper(h.Bug), "all")
81+
err = h.b.AddHandler("/bug", h.contextWrapper(h.scriptWrapper(h.Bug)), "all")
8282
if err != nil {
8383
return err
8484
}
@@ -87,15 +87,15 @@ func (h *Handler) register() error {
8787
///// Admin Commands /////
8888
//////////////////////////
8989

90-
err = h.b.AddHandler("/respond", h.admin(h.contextWrapper(h.Respond)), "all")
90+
err = h.b.AddHandler("/respond", h.admin(h.contextWrapper(h.scriptWrapper(h.Respond))), "all")
9191
if err != nil {
9292
return err
9393
}
94-
err = h.b.AddHandler("/subs", h.admin(h.contextWrapper(h.GetSubscribers)), "all")
94+
err = h.b.AddHandler("/subs", h.admin(h.contextWrapper(h.scriptWrapper(h.GetSubscribers))), "all")
9595
if err != nil {
9696
return err
9797
}
98-
err = h.b.AddHandler("/sall", h.admin(h.contextWrapper(h.SendAll)), "all")
98+
err = h.b.AddHandler("/sall", h.admin(h.contextWrapper(h.scriptWrapper(h.SendAll))), "all")
9999
if err != nil {
100100
return err
101101
}

telegram/internal/handler/language.go

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ func (h *Handler) SetLang(u *objs.Update) {
3535
if err != nil {
3636
log.Printf("failed to set lang to %s: %v", u.CallbackQuery.Data, err)
3737
_, err = h.b.AdvancedMode().AAnswerCallbackQuery(u.CallbackQuery.Id,
38-
fmt.Sprintf("Failed to set lang to %s, Please try again later", u.CallbackQuery.Data),
38+
fmt.Sprintf(h.userScript[chatID].LanguageSelectionFail, u.CallbackQuery.Data),
3939
true, "", 0)
4040
if err != nil {
4141
log.Printf("failed to send callback query on /lang: %s", err)
@@ -47,7 +47,7 @@ func (h *Handler) SetLang(u *objs.Update) {
4747
if err != nil {
4848
log.Printf("failed to get script for %s: %v", u.CallbackQuery.Data, err)
4949
_, err = h.b.AdvancedMode().AAnswerCallbackQuery(u.CallbackQuery.Id,
50-
fmt.Sprintf("Failed to set lang to %s, Please try again later", u.CallbackQuery.Data),
50+
fmt.Sprintf(h.userScript[chatID].LanguageSelectionFail, u.CallbackQuery.Data),
5151
true, "", 0)
5252
if err != nil {
5353
log.Printf("failed to send callback query on /lang: %s", err)
@@ -56,12 +56,26 @@ func (h *Handler) SetLang(u *objs.Update) {
5656
}
5757
// Update the user script.
5858
h.userScript[chatID] = script
59-
h.simpleSend(chatID, fmt.Sprintf("Successfully set lang to %s", u.CallbackQuery.Data), 0)
59+
_, err = h.b.SendMessage(chatID, fmt.Sprintf(h.userScript[chatID].LanguageSelectionSuccess, u.CallbackQuery.Data), "HTML", 0, false, false)
60+
if err != nil {
61+
log.Printf("failed to send message on /lang: %s", err)
62+
}
6063
})
6164
}
6265

6366
// Sends the message along with the keyboard.
64-
r, err := h.b.AdvancedMode().ASendMessage(u.Message.Chat.Id, "Choose lang", "", u.Message.MessageId, false, false, nil, false, false, kb)
67+
r, err := h.b.AdvancedMode().ASendMessage(
68+
chatID,
69+
h.userScript[chatID].LanguageSelectionStart,
70+
"",
71+
u.Message.MessageId,
72+
false,
73+
false,
74+
nil,
75+
false,
76+
false,
77+
kb,
78+
)
6579
if err != nil {
6680
log.Printf("failed to send message on /lang: %s", err)
6781
}

0 commit comments

Comments
 (0)