Various improvement

Signed-off-by: Ettore Dreucci <ettore.dreucci@gmail.com>
This commit is contained in:
2018-08-05 01:29:17 +02:00
parent 6f4653ce34
commit b73cb0b12e
7 changed files with 400 additions and 62 deletions

View File

@@ -68,7 +68,6 @@ func removeBotAdmins() error {
}
return returnErr
})
//for _, token := range tokens {
for _, botAdmin := range botAdmins {
adminID, err := strconv.Atoi(botAdmin)
if err != nil {
@@ -86,6 +85,35 @@ func removeBotAdmins() error {
return nil
}
func hasBotAdmins() (bool, error) {
if redisClient == nil {
return false, ErrNilPointer
}
adminNum, err := redisClient.SCard(adminUsers).Result()
if err != nil {
log.Printf("Error retrieving number of admins: %v", err)
return false, ErrRedisRetrieveSet
}
if adminNum <= 0 {
return false, nil
}
return true, nil
}
func isBotAdmin(userID int) (bool, error) {
if redisClient == nil {
return false, ErrNilPointer
}
admin, err := redisClient.SIsMember(adminUsers, strconv.Itoa(userID)).Result()
if err != nil {
log.Printf("Error checking if ID is bot admin: %v", err)
return false, ErrRedisCheckSet
}
return admin, nil
}
func addBotAdmin(newAdminID string) error {
if redisClient == nil {
return ErrNilPointer
@@ -126,11 +154,24 @@ func addBotAdmin(newAdminID string) error {
return ErrAddUser
}
}
isAuth, err := isAuthrizedUser(ID)
if err != nil {
log.Printf("Error checking if ID is authorized: %v", err)
return ErrAddAdmin
}
if !isAuth {
err = authorizeUser(ID, true)
if err != nil {
log.Printf("Error authorizing user: %v", err)
return ErrAddAuthUser
}
}
err = redisClient.SAdd(adminUsers, adminID).Err()
if err != nil {
log.Printf("Error in adding new admin ID: %v", err)
return ErrRedisAddSet
}
botStatus.hasAdmin = true
err = authorizeUser(ID, true)
if err != nil {
@@ -142,7 +183,7 @@ func addBotAdmin(newAdminID string) error {
log.Printf("Error getting user info: %v", err)
return ErrGetUser
}
err = sendMessage(user, newAdminMsg)
err = sendMsg(user, newAdminMsg)
if err != nil {
log.Printf("Error sending message to new admin: %v", err)
return ErrSendMsg
@@ -165,11 +206,18 @@ func removeBotAdmin(adminID int) error {
log.Printf("Error getting user info: %v", err)
return ErrGetUser
}
err = sendMessage(user, delAdminMsg)
err = sendMsg(user, delAdminMsg)
if err != nil {
log.Printf("Error sending message to removed admin: %v", err)
return ErrSendMsg
}
hasAdmin, err := hasBotAdmins()
if err != nil {
log.Printf("Error checking if bot has admins: %v", err)
return ErrRedisRetrieveSet
}
botStatus.hasAdmin = hasAdmin
return nil
}

View File

@@ -74,6 +74,38 @@ func getUserInfo(userID int) (*tb.User, error) {
return jsonUser, nil
}
func isStartedUser(userID int) (bool, error) {
if redisClient == nil {
return false, ErrNilPointer
}
started, err := redisClient.SIsMember(startedUsers, strconv.Itoa(userID)).Result()
if err != nil {
log.Printf("Error checking if user is started: %v", err)
return false, ErrRedisCheckSet
}
return started, nil
}
func startUser(userID int, started bool) error {
if redisClient == nil {
return ErrNilPointer
}
if started {
err := redisClient.SAdd(startedUsers, strconv.Itoa(userID)).Err()
if err != nil {
log.Printf("Error adding token to set: %v", err)
return ErrRedisAddSet
}
} else {
err := redisClient.SRem(startedUsers, strconv.Itoa(userID)).Err()
if err != nil {
log.Printf("Error removing token from set: %v", err)
return ErrRedisRemSet
}
}
return nil
}
func isAuthrizedUser(userID int) (bool, error) {
if redisClient == nil {
return false, ErrNilPointer

View File

@@ -8,13 +8,14 @@ import (
)
const (
botToken = "botToken"
botInfo = "botInfo"
usersID = "usersID"
usersInfo = "usersInfo"
usersGroups = "usersGroups"
authUsers = "authUsers"
adminUsers = "adminUsers"
botToken = "botToken"
botInfo = "botInfo"
usersID = "usersID"
usersInfo = "usersInfo"
usersGroups = "usersGroups"
startedUsers = "startedUsers"
authUsers = "authUsers"
adminUsers = "adminUsers"
)
var redisClient *redis.Client

View File

@@ -82,7 +82,7 @@ func getFlags() error {
}
func exit() error {
if isStartedBot {
if botStatus.isStarted {
log.Printf("Stopping %s", bot.Me.Username)
bot.Stop()
log.Println("Bot stopped")
@@ -99,7 +99,7 @@ func exit() error {
func mainMenu() *wmenu.Menu {
menu := wmenu.NewMenu("What do you want to do?")
menu.LoopOnInvalid()
if !isStartedBot {
if !botStatus.isStarted {
menu.Option("Start bot", nil, true, func(opt wmenu.Opt) error {
return botStart()
})
@@ -107,7 +107,7 @@ func mainMenu() *wmenu.Menu {
return setBotToken("")
})
}
if isStartedBot {
if botStatus.isStarted {
menu.Option("Stop bot", nil, true, func(opt wmenu.Opt) error {
return botStop()
})
@@ -115,9 +115,11 @@ func mainMenu() *wmenu.Menu {
menu.Option("Add bot admin(s)", nil, false, func(opt wmenu.Opt) error {
return addBotAdmins(nil)
})
menu.Option("Remove bot admin(s)", nil, false, func(opt wmenu.Opt) error {
return removeBotAdmins()
})
if botStatus.hasAdmin {
menu.Option("Remove bot admin(s)", nil, false, func(opt wmenu.Opt) error {
return removeBotAdmins()
})
}
menu.Option("Exit", nil, false, func(opt wmenu.Opt) error {
return exit()
})
@@ -127,15 +129,17 @@ func mainMenu() *wmenu.Menu {
func mainMenuLoop() error {
menu := mainMenu()
botStatus := isStartedBot
botStarted := botStatus.isStarted
hasAdmin := botStatus.hasAdmin
fmt.Println(welcomeMessage)
for {
err := menu.Run()
if err != nil {
log.Printf("Error in main menu: %v", err)
}
if botStatus != isStartedBot {
botStatus = isStartedBot
if botStarted != botStatus.isStarted || hasAdmin != botStatus.hasAdmin {
botStarted = botStatus.isStarted
hasAdmin = botStatus.hasAdmin
menu = mainMenu()
}
}

View File

@@ -3,20 +3,43 @@ package main
import (
"errors"
"log"
"strconv"
"time"
tb "gopkg.in/tucnak/telebot.v2"
)
type botBool struct {
isStarted bool
hasAdmin bool
}
const (
newAdminMsg string = "Sei stato aggiunto come amministratore. Adesso hai a disposizione una serie aggiuntiva di comandi e controlli per il bot."
delAdminMsg string = "Sei stato rimosso da amministratore."
startMsg string = "Salve, sono Stefano, il Magister! Come posso esservi d'aiuto?"
alreadyStartedMsg string = "Si, mi dica, che c'è?! Sono qui!"
restartMsg string = "Eccomi, sono tornato! Ha bisogno? Mi dica pure!"
stopMsg string = "Mi assenterò per qualche istante, d'altra parte anch'io ho pur diritto alla mia vita privata. Masino mi attende!"
newAdminMsg string = "Beh allora, vediamo... Ah si, la nomino amministratore! Da grandi poteri derivano grandi responsabilità. Mi raccomando, non me ne faccia pentire!"
delAdminMsg string = "Ecco, che le avevo detto?! Mi sembrava di essere stato chiaro! Dovrò sollevarla dall'incarico... Mi spiace molto ma da ora in avanti non sarà più amministratore"
)
var bot *tb.Bot
var isStartedBot bool
var genericCommands = map[string]bool{
"/start": true,
"/stop": true,
"/menu": true,
"/prossimoEvento": true,
}
var authCommands = map[string]bool{
"/prossimaProvaSezione": true,
"/prossimaProvaInsieme": true,
}
var adminCommands = map[string]bool{
"/autorizzaUtente": true,
"/aggiungiAdmin": true,
"/rimuoviAdmin": true,
}
var bot *tb.Bot
var botStatus botBool
var (
//ErrNilPointer is thrown when a pointer is nil
ErrNilPointer = errors.New("pointer is nil")
@@ -42,32 +65,7 @@ func botInit() error {
}
poller := &tb.LongPoller{Timeout: 15 * time.Second}
middlePoller := tb.NewMiddlewarePoller(poller, func(upd *tb.Update) bool {
if upd.Message == nil {
return true
}
if upd.Message.Sender != nil {
err := addUser(upd.Message.Sender)
if err != nil {
log.Printf("Error in adding user info: %v", err)
}
err = authorizeUser(upd.Message.Sender.ID, true)
if err != nil {
log.Printf("Error in authorizing user: %v", err)
}
} else {
log.Printf("%v", ErrIDFromMsg)
}
auth, err := isAuthrizedUser(upd.Message.Sender.ID)
if err != nil {
log.Printf("Error checking if user is authorized: %v", err)
}
if !auth {
return false
}
return true
})
middlePoller := tb.NewMiddlewarePoller(poller, setBotPoller)
bot, err = tb.NewBot(tb.Settings{
Token: token,
@@ -84,15 +82,35 @@ func botInit() error {
return ErrBotInit
}
err = setBotMenus()
if err != nil {
log.Printf("Error setting bot menus: %v", err)
return ErrBotInit
}
err = setBotCallbacks()
if err != nil {
log.Printf("Error setting bot callbacks: %v", err)
return ErrBotInit
}
err = addBotInfo(token, bot.Me.Username)
if err != nil {
log.Printf("Error: bot %s info couldn't be added: %v", bot.Me.Username, err)
return ErrBotInit
}
hasAdmin, err := hasBotAdmins()
if err != nil {
log.Printf("Error checking if bot has admins: %v", err)
return ErrBotInit
}
botStatus.hasAdmin = hasAdmin
return nil
}
func sendMessage(user *tb.User, msg string) error {
func sendMsg(user *tb.User, msg string) error {
_, err := bot.Send(user, msg)
if err != nil {
log.Printf("Error sending message to user: %v", err)
@@ -101,28 +119,97 @@ func sendMessage(user *tb.User, msg string) error {
return nil
}
func setBotHandlers() error {
if bot == nil {
return ErrNilPointer
func sendMsgWithMenu(user *tb.User, msg string) error {
var menu [][]tb.InlineButton
auth, err := isAuthrizedUser(user.ID)
if err != nil {
log.Printf("Error checking if user is authorized: %v", err)
}
admin, err := isBotAdmin(user.ID)
if err != nil {
log.Printf("Error checking if user is admin: %v", err)
}
bot.Handle("/hello", func(m *tb.Message) {
bot.Send(m.Sender, "hello world")
if admin {
menu = adminInlineMenu
} else if auth {
menu = authInlineMenu
} else {
menu = genericInlineMenu
}
_, err = bot.Send(user, msg, &tb.ReplyMarkup{
InlineKeyboard: menu,
})
bot.Handle("/userID", func(m *tb.Message) {
bot.Send(m.Sender, strconv.Itoa(m.Sender.ID))
})
if err != nil {
log.Printf("Error sending message to user: %v", err)
return ErrSendMsg
}
return nil
}
func sendMsgWithSpecificMenu(user *tb.User, msg string, menu [][]tb.InlineButton) error {
_, err := bot.Send(user, msg, &tb.ReplyMarkup{
InlineKeyboard: menu,
})
if err != nil {
log.Printf("Error sending message to user: %v", err)
return ErrSendMsg
}
return nil
}
func setBotPoller(upd *tb.Update) bool {
if upd.Message == nil {
return true
}
if upd.Message.Sender != nil {
err := addUser(upd.Message.Sender)
if err != nil {
log.Printf("Error in adding user info: %v", err)
}
} else {
log.Printf("%v", ErrIDFromMsg)
}
_, isGenericCmd := genericCommands[upd.Message.Text]
_, isAuthCmd := authCommands[upd.Message.Text]
_, isAdminCmd := adminCommands[upd.Message.Text]
started, err := isStartedUser(upd.Message.Sender.ID)
if err != nil {
log.Printf("Error checking if user is started: %v", err)
}
if !started && upd.Message.Text != "/start" {
return false
}
auth, err := isAuthrizedUser(upd.Message.Sender.ID)
if err != nil {
log.Printf("Error checking if user is authorized: %v", err)
}
admin, err := isBotAdmin(upd.Message.Sender.ID)
if err != nil {
log.Printf("Error checking if user is admin: %v", err)
}
if isAdminCmd && !admin {
return false
}
if isAuthCmd && !auth {
return false
}
if !isGenericCmd {
return false
}
return true
}
func botStart() error {
if bot == nil {
return ErrNilPointer
}
go bot.Start()
isStartedBot = true
botStatus.isStarted = true
log.Printf("Started %s", bot.Me.Username)
return nil
@@ -134,7 +221,7 @@ func botStop() error {
}
log.Printf("Stopping %s", bot.Me.Username)
bot.Stop()
isStartedBot = false
botStatus.isStarted = false
log.Println("Bot stopped")
return nil

79
src/telegramHandlers.go Normal file
View File

@@ -0,0 +1,79 @@
package main
import (
"log"
"strconv"
tb "gopkg.in/tucnak/telebot.v2"
)
func startHandler(m *tb.Message) {
var msg string
isUser, err := isUser(m.Sender.ID)
if err != nil {
log.Printf("Error checking if ID is bot user: %v", err)
}
started, err := isStartedUser(m.Sender.ID)
if err != nil {
log.Printf("Error checking if user is started: %v", err)
}
if !started {
err = startUser(m.Sender.ID, true)
if err != nil {
log.Printf("Error starting user: %v", err)
}
if isUser {
msg = restartMsg
} else {
msg = startMsg
}
} else {
msg = alreadyStartedMsg
}
err = sendMsgWithMenu(m.Sender, msg)
if err != nil {
log.Printf("Error sending message to started user: %v", err)
}
}
func stopHandler(m *tb.Message) {
admin, err := isBotAdmin(m.Sender.ID)
if err != nil {
log.Printf("Error checking if user is admin: %v", err)
}
if admin {
msg := "Non ci siamo... Io l'ho nominata AMMINISTRATORE, cosa crede?! Questo ruolo esige impegno! Non può certo bloccarmi!"
err := sendMsg(m.Sender, msg)
if err != nil {
log.Printf("Error sending message to unstoppable user: %v", err)
}
} else {
err = startUser(m.Sender.ID, false)
if err != nil {
log.Printf("Error starting user: %v", err)
}
err := sendMsgWithSpecificMenu(m.Sender, stopMsg, startMenu)
if err != nil {
log.Printf("Error sending message to stopped user: %v", err)
}
}
}
func setBotHandlers() error {
if bot == nil {
return ErrNilPointer
}
bot.Handle("/start", startHandler)
bot.Handle("/stop", stopHandler)
bot.Handle("/menu", func(m *tb.Message) {
bot.Send(m.Sender, "hello world")
})
bot.Handle("/userID", func(m *tb.Message) {
bot.Send(m.Sender, strconv.Itoa(m.Sender.ID))
})
return nil
}

87
src/telegramMenu.go Normal file
View File

@@ -0,0 +1,87 @@
package main
import (
"log"
tb "gopkg.in/tucnak/telebot.v2"
)
var (
adminInlineMenu [][]tb.InlineButton
authInlineMenu [][]tb.InlineButton
genericInlineMenu [][]tb.InlineButton
startMenu [][]tb.InlineButton
)
var (
startBtn = tb.InlineButton{
Unique: "start_btn",
Text: "\xE2\x96\xB6 Avvia il barandaBot",
}
stopBtn = tb.InlineButton{
Unique: "stop_btn",
Text: "\xF0\x9F\x9A\xAB Ferma il barandaBot",
}
infoBtn = tb.InlineButton{
Unique: "info_btn",
Text: "\xE2\x84\xB9 Info",
}
)
func setBotMenus() error {
adminInlineMenu = append(adminInlineMenu, []tb.InlineButton{stopBtn, infoBtn})
authInlineMenu = append(authInlineMenu, []tb.InlineButton{stopBtn, infoBtn})
genericInlineMenu = append(genericInlineMenu, []tb.InlineButton{stopBtn, infoBtn})
startMenu = append(startMenu, []tb.InlineButton{startBtn})
return nil
}
func setBotCallbacks() error {
if bot == nil {
return ErrNilPointer
}
bot.Handle(&startBtn, func(c *tb.Callback) {
bot.Respond(c, &tb.CallbackResponse{})
//TODO: save last message id per user so it's possible to hide inline keyboard
//bot.Edit(lastMsgID, tb.ReplyMarkup{})
err := startUser(c.Sender.ID, true)
if err != nil {
log.Printf("Error starting user: %v", err)
}
err = sendMsgWithMenu(c.Sender, restartMsg)
if err != nil {
log.Printf("Error sending message to started user: %v", err)
}
})
bot.Handle(&stopBtn, func(c *tb.Callback) {
bot.Respond(c, &tb.CallbackResponse{})
admin, err := isBotAdmin(c.Sender.ID)
if err != nil {
log.Printf("Error checking if user is admin: %v", err)
}
if admin {
msg := "Non ci siamo... Io l'ho nominata AMMINISTRATORE, cosa crede?! Questo ruolo esige impegno! Non può certo bloccarmi!"
err := sendMsg(c.Sender, msg)
if err != nil {
log.Printf("Error sending message to unstoppable user: %v", err)
}
} else {
err = startUser(c.Sender.ID, false)
if err != nil {
log.Printf("Error starting user: %v", err)
}
err := sendMsgWithSpecificMenu(c.Sender, stopMsg, startMenu)
if err != nil {
log.Printf("Error sending message to stopped user: %v", err)
}
}
})
return nil
}