Concurrent menu/bot. Disappearing option in menu. User groups.
Signed-off-by: Ettore Dreucci <ettore.dreucci@gmail.com>
This commit is contained in:
@@ -12,13 +12,19 @@ func main() {
|
||||
}
|
||||
|
||||
err = redisInit(cmdFlags.redisAddr, cmdFlags.redisPwd, cmdFlags.redisDB)
|
||||
defer redisClient.Close()
|
||||
if err != nil {
|
||||
log.Fatalf("Error in initializing redis instance: %v", err)
|
||||
}
|
||||
defer redisClient.Close()
|
||||
|
||||
err = botInit()
|
||||
if err != nil {
|
||||
log.Fatalf("Error initializing bot: %v", err)
|
||||
}
|
||||
defer bot.Stop()
|
||||
|
||||
if cmdFlags.interactive {
|
||||
mainMenu()
|
||||
mainMenuLoop()
|
||||
} else if cmdFlags.token != "" {
|
||||
err = setBotToken(cmdFlags.token)
|
||||
if err == ErrAddToken {
|
||||
|
@@ -45,7 +45,7 @@ func removeBotAdmins() error {
|
||||
if redisClient == nil {
|
||||
return ErrNilPointer
|
||||
}
|
||||
botAdmins, err := redisClient.SMembers(adminSet).Result()
|
||||
botAdmins, err := redisClient.SMembers(adminUsers).Result()
|
||||
if err != nil {
|
||||
log.Printf("Couldn't retrieve admins: %v", err)
|
||||
return ErrRedisRetrieveSet
|
||||
@@ -120,13 +120,13 @@ func addBotAdmin(newAdminID string) error {
|
||||
return ErrAddAdmin
|
||||
}
|
||||
if !isUser {
|
||||
err = addUser(&tb.User{int(chat.ID), chat.FirstName, chat.LastName, chat.Username})
|
||||
err = addUser(&tb.User{ID: int(chat.ID), FirstName: chat.FirstName, LastName: chat.LastName, Username: chat.Username})
|
||||
if err != nil {
|
||||
log.Printf("Error adding user: %v", err)
|
||||
return ErrAddUser
|
||||
}
|
||||
}
|
||||
err = redisClient.SAdd(adminSet, adminID).Err()
|
||||
err = redisClient.SAdd(adminUsers, adminID).Err()
|
||||
if err != nil {
|
||||
log.Printf("Error in adding new admin ID: %v", err)
|
||||
return ErrRedisAddSet
|
||||
@@ -142,7 +142,7 @@ func addBotAdmin(newAdminID string) error {
|
||||
log.Printf("Error getting user info: %v", err)
|
||||
return ErrGetUser
|
||||
}
|
||||
err = sendMessage(user, "Sei stato aggiunto come amministratore del BarandaBot")
|
||||
err = sendMessage(user, newAdminMsg)
|
||||
if err != nil {
|
||||
log.Printf("Error sending message to new admin: %v", err)
|
||||
return ErrSendMsg
|
||||
@@ -155,10 +155,21 @@ func removeBotAdmin(adminID int) error {
|
||||
if redisClient == nil {
|
||||
return ErrNilPointer
|
||||
}
|
||||
err := redisClient.SRem(adminSet, strconv.Itoa(adminID)).Err()
|
||||
err := redisClient.SRem(adminUsers, strconv.Itoa(adminID)).Err()
|
||||
if err != nil {
|
||||
log.Printf("Error removing admin from set: %v", err)
|
||||
return ErrRedisRemSet
|
||||
}
|
||||
user, err := getUserInfo(adminID)
|
||||
if err != nil {
|
||||
log.Printf("Error getting user info: %v", err)
|
||||
return ErrGetUser
|
||||
}
|
||||
err = sendMessage(user, delAdminMsg)
|
||||
if err != nil {
|
||||
log.Printf("Error sending message to removed admin: %v", err)
|
||||
return ErrSendMsg
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@@ -2,14 +2,11 @@ package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
tb "gopkg.in/tucnak/telebot.v2"
|
||||
)
|
||||
|
||||
func setBotToken(newToken string) error {
|
||||
@@ -49,12 +46,12 @@ func getBotToken() (string, error) {
|
||||
if redisClient == nil {
|
||||
return "", ErrNilPointer
|
||||
}
|
||||
token, err := redisClient.Get(botToken).Result()
|
||||
tokenExists, err := redisClient.Exists(botToken).Result()
|
||||
if err != nil {
|
||||
log.Printf("Couldn't retrieve bot token: %v", err)
|
||||
return "", ErrRedisRetrieveSet
|
||||
log.Printf("Error checking if token exists in db: %v", err)
|
||||
return "", ErrRedisCheckSet
|
||||
}
|
||||
if token == "" {
|
||||
if tokenExists == 0 {
|
||||
fmt.Println("No bot token found.")
|
||||
err := setBotToken("")
|
||||
if err != nil {
|
||||
@@ -62,20 +59,19 @@ func getBotToken() (string, error) {
|
||||
return "", ErrAddToken
|
||||
}
|
||||
}
|
||||
|
||||
token, err := redisClient.Get(botToken).Result()
|
||||
if err != nil {
|
||||
log.Printf("Couldn't retrieve bot token: %v", err)
|
||||
return "", ErrRedisRetrieveSet
|
||||
}
|
||||
return token, nil
|
||||
}
|
||||
|
||||
func addBotInfo(botToken string, bot *tb.Bot) error {
|
||||
func addBotInfo(botToken string, botUser string) error {
|
||||
if redisClient == nil {
|
||||
return ErrNilPointer
|
||||
}
|
||||
jsonBot, err := json.Marshal(&bot)
|
||||
if err != nil {
|
||||
log.Printf("Error marshalling bot info: %v", err)
|
||||
return ErrJSONMarshall
|
||||
}
|
||||
err = redisClient.HSet(botHash, botToken, string(jsonBot)).Err()
|
||||
err := redisClient.HSet(botInfo, botToken, botUser).Err()
|
||||
if err != nil {
|
||||
log.Printf("Error in adding bot info: %v", err)
|
||||
return ErrRedisAddHash
|
||||
@@ -88,7 +84,7 @@ func removeBotInfo(botToken string) error {
|
||||
if redisClient == nil {
|
||||
return ErrNilPointer
|
||||
}
|
||||
err := redisClient.HDel(botHash, botToken).Err()
|
||||
err := redisClient.HDel(botInfo, botToken).Err()
|
||||
if err != nil {
|
||||
log.Printf("Error in removing bot info: %v", err)
|
||||
return ErrRedisDelHash
|
||||
|
@@ -4,15 +4,28 @@ import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
tb "gopkg.in/tucnak/telebot.v2"
|
||||
)
|
||||
|
||||
type userGroup int
|
||||
|
||||
const (
|
||||
ugSoprano userGroup = iota
|
||||
ugContralto
|
||||
ugTenore
|
||||
ugBasso
|
||||
ugCommissario
|
||||
ugReferente
|
||||
ugPreparatore
|
||||
)
|
||||
|
||||
func addUser(user *tb.User) error {
|
||||
if redisClient == nil {
|
||||
return ErrNilPointer
|
||||
}
|
||||
err := redisClient.SAdd(userSet, user.ID).Err()
|
||||
err := redisClient.SAdd(usersID, user.ID).Err()
|
||||
if err != nil {
|
||||
log.Printf("Error in adding user ID: %v", err)
|
||||
return ErrRedisAddSet
|
||||
@@ -22,7 +35,7 @@ func addUser(user *tb.User) error {
|
||||
log.Printf("Error in marshalling user to json: %v", err)
|
||||
return ErrJSONMarshall
|
||||
}
|
||||
err = redisClient.HSet(userHash, strconv.Itoa(user.ID), jsonUser).Err()
|
||||
err = redisClient.HSet(usersInfo, strconv.Itoa(user.ID), jsonUser).Err()
|
||||
if err != nil {
|
||||
log.Printf("Error adding user info in hash: %v", err)
|
||||
return ErrRedisAddHash
|
||||
@@ -35,7 +48,7 @@ func isUser(userID int) (bool, error) {
|
||||
if redisClient == nil {
|
||||
return false, ErrNilPointer
|
||||
}
|
||||
user, err := redisClient.SIsMember(userSet, strconv.Itoa(userID)).Result()
|
||||
user, err := redisClient.SIsMember(usersID, strconv.Itoa(userID)).Result()
|
||||
if err != nil {
|
||||
log.Printf("Error checking if ID is bot user: %v", err)
|
||||
return false, ErrRedisCheckSet
|
||||
@@ -47,7 +60,7 @@ func getUserInfo(userID int) (*tb.User, error) {
|
||||
if redisClient == nil {
|
||||
return nil, ErrNilPointer
|
||||
}
|
||||
user, err := redisClient.HGet(userHash, strconv.Itoa(userID)).Result()
|
||||
user, err := redisClient.HGet(usersInfo, strconv.Itoa(userID)).Result()
|
||||
if err != nil {
|
||||
log.Printf("Error retriving user info from hash: %v", err)
|
||||
return nil, ErrRedisRetrieveHash
|
||||
@@ -65,7 +78,7 @@ func isAuthrizedUser(userID int) (bool, error) {
|
||||
if redisClient == nil {
|
||||
return false, ErrNilPointer
|
||||
}
|
||||
auth, err := redisClient.SIsMember(authUserSet, strconv.Itoa(userID)).Result()
|
||||
auth, err := redisClient.SIsMember(authUsers, strconv.Itoa(userID)).Result()
|
||||
if err != nil {
|
||||
log.Printf("Error checking if user is authorized: %v", err)
|
||||
return false, ErrRedisCheckSet
|
||||
@@ -78,13 +91,13 @@ func authorizeUser(userID int, authorized bool) error {
|
||||
return ErrNilPointer
|
||||
}
|
||||
if authorized {
|
||||
err := redisClient.SAdd(authUserSet, strconv.Itoa(userID)).Err()
|
||||
err := redisClient.SAdd(authUsers, strconv.Itoa(userID)).Err()
|
||||
if err != nil {
|
||||
log.Printf("Error adding token to set: %v", err)
|
||||
return ErrRedisAddSet
|
||||
}
|
||||
} else {
|
||||
err := redisClient.SRem(authUserSet, strconv.Itoa(userID)).Err()
|
||||
err := redisClient.SRem(authUsers, strconv.Itoa(userID)).Err()
|
||||
if err != nil {
|
||||
log.Printf("Error removing token from set: %v", err)
|
||||
return ErrRedisRemSet
|
||||
@@ -92,3 +105,43 @@ func authorizeUser(userID int, authorized bool) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func setUserGroups(userID int, groups ...userGroup) error {
|
||||
if redisClient == nil {
|
||||
return ErrNilPointer
|
||||
}
|
||||
var csvGroups string
|
||||
for _, group := range groups {
|
||||
csvGroups += strconv.Itoa(int(group)) + ","
|
||||
}
|
||||
err := redisClient.HSet(usersGroups, strconv.Itoa(userID), csvGroups).Err()
|
||||
if err != nil {
|
||||
log.Printf("Error adding user groups to hash: %v", err)
|
||||
return ErrRedisAddHash
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getUserGroups(userID int) ([]userGroup, error) {
|
||||
if redisClient == nil {
|
||||
return nil, ErrNilPointer
|
||||
}
|
||||
|
||||
csvGroups, err := redisClient.HGet(usersGroups, strconv.Itoa(userID)).Result()
|
||||
if err != nil {
|
||||
log.Printf("Error retrieving user groups: %v", err)
|
||||
return nil, ErrRedisRetrieveHash
|
||||
}
|
||||
var retGroups []userGroup
|
||||
groups := strings.Split(csvGroups, ",")
|
||||
for _, group := range groups {
|
||||
intGroup, err := strconv.Atoi(group)
|
||||
if err != nil {
|
||||
log.Printf("Error converting user group: %v", err)
|
||||
return nil, ErrAtoiConv
|
||||
}
|
||||
retGroups = append(retGroups, userGroup(intGroup))
|
||||
}
|
||||
return retGroups, nil
|
||||
}
|
||||
|
@@ -9,11 +9,12 @@ import (
|
||||
|
||||
const (
|
||||
botToken = "botToken"
|
||||
botHash = "botInfo"
|
||||
userSet = "userID"
|
||||
userHash = "userInfo"
|
||||
authUserSet = "authUser"
|
||||
adminSet = "adminID"
|
||||
botInfo = "botInfo"
|
||||
usersID = "usersID"
|
||||
usersInfo = "usersInfo"
|
||||
usersGroups = "usersGroups"
|
||||
authUsers = "authUsers"
|
||||
adminUsers = "adminUsers"
|
||||
)
|
||||
|
||||
var redisClient *redis.Client
|
||||
|
56
src/sys.go
56
src/sys.go
@@ -5,6 +5,7 @@ import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/dixonwille/wmenu"
|
||||
@@ -23,7 +24,7 @@ type flags struct {
|
||||
var cmdFlags flags
|
||||
|
||||
var (
|
||||
welcomeMessage = "Welcome in barandaBot! Here you can control the bot(s) options and configurations."
|
||||
welcomeMessage = "Welcome! Here you can control the bot options and configurations."
|
||||
//ErrStdRead is thrown when it's not possible to read from the standard input
|
||||
ErrStdRead = errors.New("stdin: couldn't read string from stdin")
|
||||
//ErrMainMenu is thrown when a menu couldn't be started
|
||||
@@ -80,31 +81,62 @@ func getFlags() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func mainMenu() error {
|
||||
fmt.Println(welcomeMessage)
|
||||
func exit() error {
|
||||
if isStartedBot {
|
||||
log.Printf("Stopping %s", bot.Me.Username)
|
||||
bot.Stop()
|
||||
log.Println("Bot stopped")
|
||||
}
|
||||
log.Println("Closing redis instance")
|
||||
redisClient.Close()
|
||||
log.Println("Redis instance closed")
|
||||
log.Println("Exiting")
|
||||
os.Exit(0)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func mainMenu() *wmenu.Menu {
|
||||
menu := wmenu.NewMenu("What do you want to do?")
|
||||
menu.LoopOnInvalid()
|
||||
menu.Option("Start Bot", nil, true, func(opt wmenu.Opt) error {
|
||||
return botStart()
|
||||
})
|
||||
menu.Option("Set bot token", nil, false, func(opt wmenu.Opt) error {
|
||||
return setBotToken("")
|
||||
})
|
||||
if !isStartedBot {
|
||||
menu.Option("Start bot", nil, true, func(opt wmenu.Opt) error {
|
||||
return botStart()
|
||||
})
|
||||
menu.Option("Set bot token", nil, false, func(opt wmenu.Opt) error {
|
||||
return setBotToken("")
|
||||
})
|
||||
}
|
||||
if isStartedBot {
|
||||
menu.Option("Stop bot", nil, true, func(opt wmenu.Opt) error {
|
||||
return botStop()
|
||||
})
|
||||
}
|
||||
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()
|
||||
})
|
||||
menu.Option("Exit", nil, false, func(opt wmenu.Opt) error {
|
||||
return exit()
|
||||
})
|
||||
|
||||
var returnErr error
|
||||
return menu
|
||||
}
|
||||
|
||||
func mainMenuLoop() error {
|
||||
menu := mainMenu()
|
||||
botStatus := isStartedBot
|
||||
fmt.Println(welcomeMessage)
|
||||
for {
|
||||
err := menu.Run()
|
||||
if err != nil {
|
||||
log.Printf("Error in main menu: %v", err)
|
||||
returnErr = ErrMainMenu
|
||||
}
|
||||
if botStatus != isStartedBot {
|
||||
botStatus = isStartedBot
|
||||
menu = mainMenu()
|
||||
}
|
||||
}
|
||||
return returnErr
|
||||
}
|
||||
|
@@ -9,7 +9,13 @@ import (
|
||||
tb "gopkg.in/tucnak/telebot.v2"
|
||||
)
|
||||
|
||||
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."
|
||||
)
|
||||
|
||||
var bot *tb.Bot
|
||||
var isStartedBot bool
|
||||
|
||||
var (
|
||||
//ErrNilPointer is thrown when a pointer is nil
|
||||
@@ -18,15 +24,21 @@ var (
|
||||
ErrIDFromMsg = errors.New("telegram: couldn't retrieve user ID from message")
|
||||
//ErrSendMsg is thrown when the message couldn't be send
|
||||
ErrSendMsg = errors.New("telegram: cannot send message")
|
||||
//ErrChatRetrive is thrown when the chat cannot be retrieved
|
||||
//ErrChatRetrieve is thrown when the chat cannot be retrieved
|
||||
ErrChatRetrieve = errors.New("telegram: cannot retrieve chat")
|
||||
//ErrTokenMissing is thrown when neither a token is in the db nor one is passed with -t on program start
|
||||
ErrTokenMissing = errors.New("telegram: cannot start bot without a token")
|
||||
//ErrBotInit is thrown when a bot couldn't be initialized
|
||||
ErrBotInit = errors.New("telegram: error in bot initialization")
|
||||
//ErrBotConn is thrown when there is a connection problem
|
||||
ErrBotConn = errors.New("telegram: cannot connect to bot")
|
||||
)
|
||||
|
||||
func botInit() error {
|
||||
token, err := getBotToken()
|
||||
if err != nil {
|
||||
log.Printf("Error in retriving bot token: %v. Cannot start telebot without token.", err)
|
||||
return err
|
||||
return ErrTokenMissing
|
||||
}
|
||||
|
||||
poller := &tb.LongPoller{Timeout: 15 * time.Second}
|
||||
@@ -61,15 +73,22 @@ func botInit() error {
|
||||
Token: token,
|
||||
Poller: middlePoller,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
log.Printf("Error in enstablishing connection for bot %s: %v", bot.Me.Username, err)
|
||||
} else {
|
||||
err = addBotInfo(token, bot)
|
||||
if err != nil {
|
||||
log.Printf("Error: bot %s info couldn't be added: %v", bot.Me.Username, err)
|
||||
}
|
||||
return ErrBotConn
|
||||
}
|
||||
|
||||
err = setBotHandlers()
|
||||
if err != nil {
|
||||
log.Printf("Error setting bot handlers: %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 nil
|
||||
}
|
||||
|
||||
@@ -82,11 +101,11 @@ func sendMessage(user *tb.User, msg string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func botStart() error {
|
||||
func setBotHandlers() error {
|
||||
if bot == nil {
|
||||
return ErrNilPointer
|
||||
}
|
||||
log.Printf("Started %s", bot.Me.Username)
|
||||
|
||||
bot.Handle("/hello", func(m *tb.Message) {
|
||||
bot.Send(m.Sender, "hello world")
|
||||
})
|
||||
@@ -94,7 +113,29 @@ func botStart() error {
|
||||
bot.Send(m.Sender, strconv.Itoa(m.Sender.ID))
|
||||
})
|
||||
|
||||
bot.Start()
|
||||
return nil
|
||||
}
|
||||
|
||||
func botStart() error {
|
||||
if bot == nil {
|
||||
return ErrNilPointer
|
||||
}
|
||||
|
||||
go bot.Start()
|
||||
isStartedBot = true
|
||||
log.Printf("Started %s", bot.Me.Username)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func botStop() error {
|
||||
if bot == nil {
|
||||
return ErrNilPointer
|
||||
}
|
||||
log.Printf("Stopping %s", bot.Me.Username)
|
||||
bot.Stop()
|
||||
isStartedBot = false
|
||||
log.Println("Bot stopped")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user