Gestione utenti, admin. Eliminato multibot
Signed-off-by: Ettore Dreucci <ettore.dreucci@gmail.com>
This commit is contained in:
@@ -19,8 +19,8 @@ func main() {
|
|||||||
|
|
||||||
if cmdFlags.interactive {
|
if cmdFlags.interactive {
|
||||||
mainMenu()
|
mainMenu()
|
||||||
} else if cmdFlags.tokens != nil {
|
} else if cmdFlags.token != "" {
|
||||||
err = addBotTokens(cmdFlags.tokens)
|
err = setBotToken(cmdFlags.token)
|
||||||
if err == ErrAddToken {
|
if err == ErrAddToken {
|
||||||
log.Printf("Error in adding bot tokens: %v", err)
|
log.Printf("Error in adding bot tokens: %v", err)
|
||||||
}
|
}
|
||||||
|
164
src/manageAdmin.go
Normal file
164
src/manageAdmin.go
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/dixonwille/wmenu"
|
||||||
|
tb "gopkg.in/tucnak/telebot.v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func addBotAdmins(newAdminIDs []string) error {
|
||||||
|
if redisClient == nil {
|
||||||
|
return ErrNilPointer
|
||||||
|
}
|
||||||
|
errNum := 0
|
||||||
|
if newAdminIDs == nil && cmdFlags.interactive {
|
||||||
|
fmt.Println("Add the new admin IDs, comma-separated:")
|
||||||
|
reader := bufio.NewReader(os.Stdin)
|
||||||
|
line, err := reader.ReadString('\n')
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error in reading new admin IDs: %v", err)
|
||||||
|
return ErrStdRead
|
||||||
|
}
|
||||||
|
newAdminIDs = strings.Split(line, ",")
|
||||||
|
}
|
||||||
|
for _, newAdminID := range newAdminIDs {
|
||||||
|
err := addBotAdmin(newAdminID)
|
||||||
|
if err != nil {
|
||||||
|
errNum++
|
||||||
|
log.Printf("Error in adding new admin ID %s: %v", newAdminID, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if errNum == len(newAdminIDs) {
|
||||||
|
return ErrAddAdmin
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func removeBotAdmins() error {
|
||||||
|
if redisClient == nil {
|
||||||
|
return ErrNilPointer
|
||||||
|
}
|
||||||
|
botAdmins, err := redisClient.SMembers(adminSet).Result()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Couldn't retrieve admins: %v", err)
|
||||||
|
return ErrRedisRetrieveSet
|
||||||
|
}
|
||||||
|
menu := wmenu.NewMenu("Select the admin(s) you want to remove:")
|
||||||
|
menu.AllowMultiple()
|
||||||
|
menu.LoopOnInvalid()
|
||||||
|
menu.Action(func(opts []wmenu.Opt) error {
|
||||||
|
var returnErr error
|
||||||
|
for _, opt := range opts {
|
||||||
|
if opt.Value == nil {
|
||||||
|
log.Println("Couldn't remove admin: nil token")
|
||||||
|
returnErr = ErrNilPointer
|
||||||
|
} else {
|
||||||
|
err := removeBotAdmin(opt.Value.(int))
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Couldn't remove bot admin: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnErr
|
||||||
|
})
|
||||||
|
//for _, token := range tokens {
|
||||||
|
for _, botAdmin := range botAdmins {
|
||||||
|
adminID, err := strconv.Atoi(botAdmin)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error converting adminID from string to int: %v", err)
|
||||||
|
return ErrAtoiConv
|
||||||
|
}
|
||||||
|
adminInfo, err := getUserInfo(adminID)
|
||||||
|
menu.Option(adminInfo.Username+": "+adminInfo.FirstName+" "+adminInfo.LastName, adminID, false, nil)
|
||||||
|
}
|
||||||
|
err = menu.Run()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error in removeToken menu: %v", err)
|
||||||
|
return ErrRemoveAdmin
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func addBotAdmin(newAdminID string) error {
|
||||||
|
if redisClient == nil {
|
||||||
|
return ErrNilPointer
|
||||||
|
}
|
||||||
|
adminID := strings.TrimSpace(newAdminID)
|
||||||
|
matched, err := regexp.MatchString("^\\d+$", adminID)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error in parsing admin ID: %v", err)
|
||||||
|
return ErrIDParsing
|
||||||
|
}
|
||||||
|
if !matched {
|
||||||
|
return ErrIDInvalid
|
||||||
|
}
|
||||||
|
|
||||||
|
ID, err := strconv.Atoi(adminID)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error converting user ID: %v", err)
|
||||||
|
return ErrAtoiConv
|
||||||
|
}
|
||||||
|
chat, err := bot.ChatByID(adminID)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error retriving chat by id: %v", err)
|
||||||
|
return ErrChatRetrieve
|
||||||
|
}
|
||||||
|
if chat.Type != tb.ChatPrivate {
|
||||||
|
log.Printf("Admin must be a user!")
|
||||||
|
return ErrAddAdmin
|
||||||
|
}
|
||||||
|
isUser, err := isUser(ID)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error checking if ID is bot user: %v", err)
|
||||||
|
return ErrAddAdmin
|
||||||
|
}
|
||||||
|
if !isUser {
|
||||||
|
err = addUser(&tb.User{int(chat.ID), chat.FirstName, chat.LastName, chat.Username})
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error adding user: %v", err)
|
||||||
|
return ErrAddUser
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err = redisClient.SAdd(adminSet, adminID).Err()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error in adding new admin ID: %v", err)
|
||||||
|
return ErrRedisAddSet
|
||||||
|
}
|
||||||
|
|
||||||
|
err = authorizeUser(ID, true)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error in adding new admin ID in authorized users: %v", err)
|
||||||
|
return ErrAddAuthUser
|
||||||
|
}
|
||||||
|
user, err := getUserInfo(ID)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error getting user info: %v", err)
|
||||||
|
return ErrGetUser
|
||||||
|
}
|
||||||
|
err = sendMessage(user, "Sei stato aggiunto come amministratore del BarandaBot")
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error sending message to new admin: %v", err)
|
||||||
|
return ErrSendMsg
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func removeBotAdmin(adminID int) error {
|
||||||
|
if redisClient == nil {
|
||||||
|
return ErrNilPointer
|
||||||
|
}
|
||||||
|
err := redisClient.SRem(adminSet, strconv.Itoa(adminID)).Err()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error removing admin from set: %v", err)
|
||||||
|
return ErrRedisRemSet
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
97
src/manageBot.go
Normal file
97
src/manageBot.go
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
tb "gopkg.in/tucnak/telebot.v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func setBotToken(newToken string) error {
|
||||||
|
var err error
|
||||||
|
if redisClient == nil {
|
||||||
|
return ErrNilPointer
|
||||||
|
}
|
||||||
|
if newToken == "" && cmdFlags.interactive {
|
||||||
|
fmt.Println("Add the new token:")
|
||||||
|
reader := bufio.NewReader(os.Stdin)
|
||||||
|
newToken, err = reader.ReadString('\n')
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error in reading new bot token: %v", err)
|
||||||
|
return ErrStdRead
|
||||||
|
}
|
||||||
|
}
|
||||||
|
token := strings.TrimSpace(newToken)
|
||||||
|
matched, err := regexp.MatchString("^\\d+\\:([0-9]|[A-z]|\\_|\\-)+", token)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error in parsing bot token: %v", err)
|
||||||
|
return ErrTokenParsing
|
||||||
|
}
|
||||||
|
if !matched {
|
||||||
|
return ErrTokenInvalid
|
||||||
|
}
|
||||||
|
|
||||||
|
err = redisClient.Set(botToken, token, 0).Err()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error in adding new bot token: %v", err)
|
||||||
|
return ErrRedisAddSet
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getBotToken() (string, error) {
|
||||||
|
if redisClient == nil {
|
||||||
|
return "", ErrNilPointer
|
||||||
|
}
|
||||||
|
token, err := redisClient.Get(botToken).Result()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Couldn't retrieve bot token: %v", err)
|
||||||
|
return "", ErrRedisRetrieveSet
|
||||||
|
}
|
||||||
|
if token == "" {
|
||||||
|
fmt.Println("No bot token found.")
|
||||||
|
err := setBotToken("")
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Couldn't add new bot tokens: %v", err)
|
||||||
|
return "", ErrAddToken
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return token, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func addBotInfo(botToken string, bot *tb.Bot) 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()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error in adding bot info: %v", err)
|
||||||
|
return ErrRedisAddHash
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func removeBotInfo(botToken string) error {
|
||||||
|
if redisClient == nil {
|
||||||
|
return ErrNilPointer
|
||||||
|
}
|
||||||
|
err := redisClient.HDel(botHash, botToken).Err()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error in removing bot info: %v", err)
|
||||||
|
return ErrRedisDelHash
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
94
src/manageUser.go
Normal file
94
src/manageUser.go
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"log"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
tb "gopkg.in/tucnak/telebot.v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func addUser(user *tb.User) error {
|
||||||
|
if redisClient == nil {
|
||||||
|
return ErrNilPointer
|
||||||
|
}
|
||||||
|
err := redisClient.SAdd(userSet, user.ID).Err()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error in adding user ID: %v", err)
|
||||||
|
return ErrRedisAddSet
|
||||||
|
}
|
||||||
|
jsonUser, err := json.Marshal(&user)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error in marshalling user to json: %v", err)
|
||||||
|
return ErrJSONMarshall
|
||||||
|
}
|
||||||
|
err = redisClient.HSet(userHash, strconv.Itoa(user.ID), jsonUser).Err()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error adding user info in hash: %v", err)
|
||||||
|
return ErrRedisAddHash
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func isUser(userID int) (bool, error) {
|
||||||
|
if redisClient == nil {
|
||||||
|
return false, ErrNilPointer
|
||||||
|
}
|
||||||
|
user, err := redisClient.SIsMember(userSet, strconv.Itoa(userID)).Result()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error checking if ID is bot user: %v", err)
|
||||||
|
return false, ErrRedisCheckSet
|
||||||
|
}
|
||||||
|
return user, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getUserInfo(userID int) (*tb.User, error) {
|
||||||
|
if redisClient == nil {
|
||||||
|
return nil, ErrNilPointer
|
||||||
|
}
|
||||||
|
user, err := redisClient.HGet(userHash, strconv.Itoa(userID)).Result()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error retriving user info from hash: %v", err)
|
||||||
|
return nil, ErrRedisRetrieveHash
|
||||||
|
}
|
||||||
|
jsonUser := &tb.User{}
|
||||||
|
err = json.Unmarshal([]byte(user), jsonUser)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error unmarshalling user info: %v", err)
|
||||||
|
return nil, ErrJSONUnmarshall
|
||||||
|
}
|
||||||
|
return jsonUser, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func isAuthrizedUser(userID int) (bool, error) {
|
||||||
|
if redisClient == nil {
|
||||||
|
return false, ErrNilPointer
|
||||||
|
}
|
||||||
|
auth, err := redisClient.SIsMember(authUserSet, strconv.Itoa(userID)).Result()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error checking if user is authorized: %v", err)
|
||||||
|
return false, ErrRedisCheckSet
|
||||||
|
}
|
||||||
|
return auth, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func authorizeUser(userID int, authorized bool) error {
|
||||||
|
if redisClient == nil {
|
||||||
|
return ErrNilPointer
|
||||||
|
}
|
||||||
|
if authorized {
|
||||||
|
err := redisClient.SAdd(authUserSet, 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()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error removing token from set: %v", err)
|
||||||
|
return ErrRedisRemSet
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
255
src/redisAPI.go
255
src/redisAPI.go
@@ -1,27 +1,19 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
|
||||||
"regexp"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/dixonwille/wmenu"
|
|
||||||
"github.com/go-redis/redis"
|
"github.com/go-redis/redis"
|
||||||
tb "gopkg.in/tucnak/telebot.v2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
tkSet = "botToken"
|
botToken = "botToken"
|
||||||
botHash = "botInfo"
|
botHash = "botInfo"
|
||||||
userSet = "userID"
|
userSet = "userID"
|
||||||
userHash = "userInfo"
|
userHash = "userInfo"
|
||||||
authUserSet = "authUser"
|
authUserSet = "authUser"
|
||||||
|
adminSet = "adminID"
|
||||||
)
|
)
|
||||||
|
|
||||||
var redisClient *redis.Client
|
var redisClient *redis.Client
|
||||||
@@ -33,24 +25,34 @@ var (
|
|||||||
ErrRedisAddSet = errors.New("redis: couldn't add key in set")
|
ErrRedisAddSet = errors.New("redis: couldn't add key in set")
|
||||||
//ErrRedisRemSet is thrown when it's not possible to remove a key from a given set
|
//ErrRedisRemSet is thrown when it's not possible to remove a key from a given set
|
||||||
ErrRedisRemSet = errors.New("redis: couldn't remove key from set")
|
ErrRedisRemSet = errors.New("redis: couldn't remove key from set")
|
||||||
//ErrRedisRetriveSet is thrown when it's not possible to retrive keys from a set
|
//ErrRedisRetrieveSet is thrown when it's not possible to retrieve keys from a set
|
||||||
ErrRedisRetriveSet = errors.New("redis: couldn't retrive keys from set")
|
ErrRedisRetrieveSet = errors.New("redis: couldn't retrieve keys from set")
|
||||||
//ErrRedisCheckSet is thrown when it's not possible to check if a key is in a given set
|
//ErrRedisCheckSet is thrown when it's not possible to check if a key is in a given set
|
||||||
ErrRedisCheckSet = errors.New("redis: couldn't check if key is in set")
|
ErrRedisCheckSet = errors.New("redis: couldn't check if key is in set")
|
||||||
//ErrRedisAddHash is thrown when it's not possible to add a key in a hash
|
//ErrRedisAddHash is thrown when it's not possible to add a key in a hash
|
||||||
ErrRedisAddHash = errors.New("redis: couldn't add key in hash")
|
ErrRedisAddHash = errors.New("redis: couldn't add key in hash")
|
||||||
//ErrRedisDelHash is thrown when it's not possible to remove a key from a hash
|
//ErrRedisDelHash is thrown when it's not possible to remove a key from a hash
|
||||||
ErrRedisDelHash = errors.New("redis: couldn't remove key from hash")
|
ErrRedisDelHash = errors.New("redis: couldn't remove key from hash")
|
||||||
|
//ErrRedisRetrieveHash is thrown when it's not possible to retrieve a key from a hash
|
||||||
|
ErrRedisRetrieveHash = errors.New("redis: couldn't retrieve key from hash")
|
||||||
//ErrTokenParsing is thrown when it's not possible to parse the bot token
|
//ErrTokenParsing is thrown when it's not possible to parse the bot token
|
||||||
ErrTokenParsing = errors.New("botToken: cannot parse token")
|
ErrTokenParsing = errors.New("botToken: cannot parse token")
|
||||||
//ErrTokenInvalid is thrown when the string parsed isn't a valid telegram bot token
|
//ErrTokenInvalid is thrown when the string parsed isn't a valid telegram bot token
|
||||||
ErrTokenInvalid = errors.New("botToken: string isn't a valid telegram bot token")
|
ErrTokenInvalid = errors.New("botToken: string isn't a valid telegram bot token")
|
||||||
|
//ErrIDParsing is thrown when it's not possible to parse the user ID
|
||||||
|
ErrIDParsing = errors.New("userID: cannot parse ID")
|
||||||
|
//ErrIDInvalid is thrown when the string parsed isn't a valid telegram user ID
|
||||||
|
ErrIDInvalid = errors.New("userID: string isn't a valid telegram user ID")
|
||||||
//ErrAddToken is thrown when one or more bot token hasn't been added
|
//ErrAddToken is thrown when one or more bot token hasn't been added
|
||||||
ErrAddToken = errors.New("couldn't add one or more tokens")
|
ErrAddToken = errors.New("couldn't add one or more tokens")
|
||||||
//ErrRemoveToken is thrown when one or more bot tokens hasn't been removed
|
//ErrAddUser is thrown when one or more user hasn't been added
|
||||||
ErrRemoveToken = errors.New("couldn't remove one or more tokens")
|
ErrAddUser = errors.New("couldn't add one or more users")
|
||||||
//ErrJSONMarshall is thrown when it's impossible to marshall a given struct
|
//ErrAddAdmin is thrown when one or more admin IDs hasn't been added
|
||||||
ErrJSONMarshall = errors.New("json: couldn't marshall struct")
|
ErrAddAdmin = errors.New("couldn't add one or more admins")
|
||||||
|
//ErrAddAuthUser is thrown when one or more users cannot be authorized
|
||||||
|
ErrAddAuthUser = errors.New("couldn't authorize one or more users")
|
||||||
|
//ErrGetUser is thrown when user info couldn't be retrieven
|
||||||
|
ErrGetUser = errors.New("couldn't retrieve user info")
|
||||||
)
|
)
|
||||||
|
|
||||||
func redisInit(addr string, pwd string, db int) error {
|
func redisInit(addr string, pwd string, db int) error {
|
||||||
@@ -66,224 +68,3 @@ func redisInit(addr string, pwd string, db int) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func addBotToken(newToken string) error {
|
|
||||||
if redisClient == nil {
|
|
||||||
return ErrNilPointer
|
|
||||||
}
|
|
||||||
token := strings.TrimSpace(newToken)
|
|
||||||
matched, err := regexp.MatchString("^\\d+\\:([0-9]|[A-z]|\\_|\\-)+", token)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Error in parsing bot token: %v", err)
|
|
||||||
return ErrTokenParsing
|
|
||||||
}
|
|
||||||
if !matched {
|
|
||||||
return ErrTokenInvalid
|
|
||||||
}
|
|
||||||
|
|
||||||
err = redisClient.SAdd(tkSet, token).Err()
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Error in adding new bot token: %v", err)
|
|
||||||
return ErrRedisAddSet
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func addBotTokens(newTokens []string) error {
|
|
||||||
if redisClient == nil {
|
|
||||||
return ErrNilPointer
|
|
||||||
}
|
|
||||||
errNum := 0
|
|
||||||
if newTokens == nil && cmdFlags.interactive {
|
|
||||||
fmt.Println("Add the new tokens, comma-separated:")
|
|
||||||
reader := bufio.NewReader(os.Stdin)
|
|
||||||
line, err := reader.ReadString('\n')
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Error in reading new bot tokens: %v", err)
|
|
||||||
return ErrStdRead
|
|
||||||
}
|
|
||||||
newTokens = strings.Split(line, ",")
|
|
||||||
}
|
|
||||||
for _, newToken := range newTokens {
|
|
||||||
err := addBotToken(newToken)
|
|
||||||
if err != nil {
|
|
||||||
errNum++
|
|
||||||
log.Printf("Error in adding new bot token %s: %v", newToken, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if errNum == len(newTokens) {
|
|
||||||
return ErrAddToken
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func removeBotToken(token string) error {
|
|
||||||
if redisClient == nil {
|
|
||||||
return ErrNilPointer
|
|
||||||
}
|
|
||||||
err := redisClient.SRem(tkSet, token).Err()
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Error in removing bot token %s: %v", token, err)
|
|
||||||
return ErrRemoveToken
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func removeBotTokens() error {
|
|
||||||
if redisClient == nil {
|
|
||||||
return ErrNilPointer
|
|
||||||
}
|
|
||||||
//tokens, err := redisClient.SMembers(tkSet).Result()
|
|
||||||
botsInfo, err := redisClient.HGetAll(botHash).Result()
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Couldn't retrive bot info: %v", err)
|
|
||||||
return ErrRedisRetriveSet
|
|
||||||
}
|
|
||||||
menu := wmenu.NewMenu("Select the token(s) you want to remove:")
|
|
||||||
menu.AllowMultiple()
|
|
||||||
menu.LoopOnInvalid()
|
|
||||||
menu.Action(func(opts []wmenu.Opt) error {
|
|
||||||
var returnErr error
|
|
||||||
for _, opt := range opts {
|
|
||||||
if opt.Value == nil {
|
|
||||||
log.Println("Couldn't remove bot: nil token")
|
|
||||||
returnErr = ErrNilPointer
|
|
||||||
} else {
|
|
||||||
err := removeBotToken(opt.Value.(string))
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Couldn't remove bot token: %v", err)
|
|
||||||
}
|
|
||||||
err = removeBotInfo(opt.Value.(string))
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Couldn't remove bot info: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return returnErr
|
|
||||||
})
|
|
||||||
//for _, token := range tokens {
|
|
||||||
for token, jsonBotInfo := range botsInfo {
|
|
||||||
botInfo := &tb.Bot{}
|
|
||||||
json.Unmarshal([]byte(jsonBotInfo), &botInfo)
|
|
||||||
menu.Option(botInfo.Me.Username, token, false, nil)
|
|
||||||
}
|
|
||||||
err = menu.Run()
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Error in removeToken menu: %v", err)
|
|
||||||
return ErrRemoveToken
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getBotTokens() ([]string, error) {
|
|
||||||
if redisClient == nil {
|
|
||||||
return nil, ErrNilPointer
|
|
||||||
}
|
|
||||||
tkNum, err := redisClient.SCard(tkSet).Result()
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Couldn't retrive number of bot tokens: %v", err)
|
|
||||||
return nil, ErrRedisRetriveSet
|
|
||||||
}
|
|
||||||
if tkNum == 0 {
|
|
||||||
fmt.Println("No bot token found.")
|
|
||||||
err := addBotTokens(nil)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Couldn't add new bot tokens: %v", err)
|
|
||||||
return nil, ErrAddToken
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tokens, err := redisClient.SMembers(tkSet).Result()
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Couldn't retrive bot tokens: %v", err)
|
|
||||||
return nil, ErrRedisRetriveSet
|
|
||||||
}
|
|
||||||
|
|
||||||
return tokens, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func addBotInfo(botToken string, bot *tb.Bot) 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()
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Error in adding bot info: %v", err)
|
|
||||||
return ErrRedisAddHash
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func removeBotInfo(botToken string) error {
|
|
||||||
if redisClient == nil {
|
|
||||||
return ErrNilPointer
|
|
||||||
}
|
|
||||||
err := redisClient.HDel(botHash, botToken).Err()
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Error in removing bot info: %v", err)
|
|
||||||
return ErrRedisDelHash
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func addUser(user *tb.User) error {
|
|
||||||
if redisClient == nil {
|
|
||||||
return ErrNilPointer
|
|
||||||
}
|
|
||||||
err := redisClient.SAdd(userSet, user.ID).Err()
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Error in adding user ID: %v", err)
|
|
||||||
return ErrRedisAddSet
|
|
||||||
}
|
|
||||||
jsonUser, err := json.Marshal(&user)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Error in marshalling user to json: %v", err)
|
|
||||||
return ErrJSONMarshall
|
|
||||||
}
|
|
||||||
err = redisClient.HSet(userHash, strconv.Itoa(user.ID), jsonUser).Err()
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Error adding user info in hash: %v", err)
|
|
||||||
return ErrRedisAddHash
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func isAuthrizedUser(userID int) (bool, error) {
|
|
||||||
if redisClient == nil {
|
|
||||||
return false, ErrNilPointer
|
|
||||||
}
|
|
||||||
auth, err := redisClient.SIsMember(authUserSet, strconv.Itoa(userID)).Result()
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Error checking if user is authorized: %v", err)
|
|
||||||
return false, ErrRedisCheckSet
|
|
||||||
}
|
|
||||||
return auth, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func authorizeUser(userID int, authorized bool) error {
|
|
||||||
if redisClient == nil {
|
|
||||||
return ErrNilPointer
|
|
||||||
}
|
|
||||||
if authorized {
|
|
||||||
err := redisClient.SAdd(authUserSet, 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()
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Error removing token from set: %v", err)
|
|
||||||
return ErrRedisRemSet
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
30
src/sys.go
30
src/sys.go
@@ -17,7 +17,7 @@ type flags struct {
|
|||||||
redisAddr string
|
redisAddr string
|
||||||
redisPwd string
|
redisPwd string
|
||||||
redisDB int
|
redisDB int
|
||||||
tokens stringSlice
|
token string
|
||||||
}
|
}
|
||||||
|
|
||||||
var cmdFlags flags
|
var cmdFlags flags
|
||||||
@@ -28,6 +28,14 @@ var (
|
|||||||
ErrStdRead = errors.New("stdin: couldn't read string from stdin")
|
ErrStdRead = errors.New("stdin: couldn't read string from stdin")
|
||||||
//ErrMainMenu is thrown when a menu couldn't be started
|
//ErrMainMenu is thrown when a menu couldn't be started
|
||||||
ErrMainMenu = errors.New("menu: couldn't start menu")
|
ErrMainMenu = errors.New("menu: couldn't start menu")
|
||||||
|
//ErrAtoiConv is thrown when a string couldn't be converted to int
|
||||||
|
ErrAtoiConv = errors.New("atoi: couldn't convert string to int")
|
||||||
|
//ErrJSONMarshall is thrown when it's impossible to marshall a given struct
|
||||||
|
ErrJSONMarshall = errors.New("json: couldn't marshall struct")
|
||||||
|
//ErrJSONUnmarshall is thworn when it's impossible to unmarshall a given struct
|
||||||
|
ErrJSONUnmarshall = errors.New("json: couldn't unmarshall struct")
|
||||||
|
//ErrRemoveAdmin is thrown when it's impossible to remove an admin
|
||||||
|
ErrRemoveAdmin = errors.New("menu: cannot remove admin")
|
||||||
)
|
)
|
||||||
|
|
||||||
func (i *stringSlice) String() string {
|
func (i *stringSlice) String() string {
|
||||||
@@ -52,6 +60,7 @@ func getFlags() error {
|
|||||||
pwdUsage = "The password of the redis instance"
|
pwdUsage = "The password of the redis instance"
|
||||||
defaultDB = 0
|
defaultDB = 0
|
||||||
dbUsage = "The database to be selected after connecting to redis instance"
|
dbUsage = "The database to be selected after connecting to redis instance"
|
||||||
|
defaultToken = ""
|
||||||
tokenUsage = "A bot token to be added to the set of tokens"
|
tokenUsage = "A bot token to be added to the set of tokens"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -63,8 +72,8 @@ func getFlags() error {
|
|||||||
flag.StringVar(&(cmdFlags.redisPwd), "p", defaultPwd, pwdUsage+"(shorthand)")
|
flag.StringVar(&(cmdFlags.redisPwd), "p", defaultPwd, pwdUsage+"(shorthand)")
|
||||||
flag.IntVar(&(cmdFlags.redisDB), "redisDB", defaultDB, dbUsage)
|
flag.IntVar(&(cmdFlags.redisDB), "redisDB", defaultDB, dbUsage)
|
||||||
flag.IntVar(&(cmdFlags.redisDB), "d", defaultDB, dbUsage+"(shorthand)")
|
flag.IntVar(&(cmdFlags.redisDB), "d", defaultDB, dbUsage+"(shorthand)")
|
||||||
flag.Var(&(cmdFlags.tokens), "token", tokenUsage)
|
flag.StringVar(&(cmdFlags.token), "token", defaultToken, tokenUsage)
|
||||||
flag.Var(&(cmdFlags.tokens), "t", tokenUsage+"(shorthand")
|
flag.StringVar(&(cmdFlags.token), "t", defaultToken, tokenUsage+"(shorthand")
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
@@ -75,14 +84,17 @@ func mainMenu() error {
|
|||||||
fmt.Println(welcomeMessage)
|
fmt.Println(welcomeMessage)
|
||||||
menu := wmenu.NewMenu("What do you want to do?")
|
menu := wmenu.NewMenu("What do you want to do?")
|
||||||
menu.LoopOnInvalid()
|
menu.LoopOnInvalid()
|
||||||
menu.Option("Start Bot(s)", nil, true, func(opt wmenu.Opt) error {
|
menu.Option("Start Bot", nil, true, func(opt wmenu.Opt) error {
|
||||||
return botsStart()
|
return botStart()
|
||||||
})
|
})
|
||||||
menu.Option("Add bot token(s)", nil, false, func(opt wmenu.Opt) error {
|
menu.Option("Set bot token", nil, false, func(opt wmenu.Opt) error {
|
||||||
return addBotTokens(nil)
|
return setBotToken("")
|
||||||
})
|
})
|
||||||
menu.Option("Remove bot token(s)", nil, false, func(opt wmenu.Opt) error {
|
menu.Option("Add bot admin(s)", nil, false, func(opt wmenu.Opt) error {
|
||||||
return removeBotTokens()
|
return addBotAdmins(nil)
|
||||||
|
})
|
||||||
|
menu.Option("Remove bot admin(s)", nil, false, func(opt wmenu.Opt) error {
|
||||||
|
return removeBotAdmins()
|
||||||
})
|
})
|
||||||
|
|
||||||
var returnErr error
|
var returnErr error
|
||||||
|
@@ -4,104 +4,85 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"log"
|
"log"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
tb "gopkg.in/tucnak/telebot.v2"
|
tb "gopkg.in/tucnak/telebot.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var bots []*tb.Bot
|
var bot *tb.Bot
|
||||||
|
|
||||||
var (
|
var (
|
||||||
//ErrNilPointer is thrown when a pointer is nil
|
//ErrNilPointer is thrown when a pointer is nil
|
||||||
ErrNilPointer = errors.New("pointer is nil")
|
ErrNilPointer = errors.New("pointer is nil")
|
||||||
//ErrIDFromMsg is thrown when the message doesn't contain user infos
|
//ErrIDFromMsg is thrown when the message doesn't contain user infos
|
||||||
ErrIDFromMsg = errors.New("telegram: couldn't retrive user ID from message")
|
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 = errors.New("telegram: cannot retrieve chat")
|
||||||
)
|
)
|
||||||
|
|
||||||
func botsInit() error {
|
func botInit() error {
|
||||||
tokens, err := getBotTokens()
|
token, err := getBotToken()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error in retriving bot tokens: %v. Cannot start telebot without tokens.", err)
|
log.Printf("Error in retriving bot token: %v. Cannot start telebot without token.", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if tokens == nil {
|
poller := &tb.LongPoller{Timeout: 15 * time.Second}
|
||||||
log.Println("Error: pointer is nil")
|
middlePoller := tb.NewMiddlewarePoller(poller, func(upd *tb.Update) bool {
|
||||||
return ErrNilPointer
|
if upd.Message == nil {
|
||||||
}
|
|
||||||
|
|
||||||
for _, token := range tokens {
|
|
||||||
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
|
return true
|
||||||
})
|
}
|
||||||
|
if upd.Message.Sender != nil {
|
||||||
bot, err := tb.NewBot(tb.Settings{
|
err := addUser(upd.Message.Sender)
|
||||||
Token: token,
|
|
||||||
Poller: middlePoller,
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Error in enstablishing connection for bot %s: %v", bot.Me.Username, err)
|
|
||||||
} else {
|
|
||||||
bots = append(bots, bot)
|
|
||||||
err = addBotInfo(token, bot)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error: bot %s info couldn't be added: %v", bot.Me.Username, err)
|
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 nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func botsStart() error {
|
return true
|
||||||
err := botsInit()
|
})
|
||||||
|
|
||||||
|
bot, err = tb.NewBot(tb.Settings{
|
||||||
|
Token: token,
|
||||||
|
Poller: middlePoller,
|
||||||
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error in initializing bots: %v", err)
|
log.Printf("Error in enstablishing connection for bot %s: %v", bot.Me.Username, err)
|
||||||
}
|
} else {
|
||||||
|
err = addBotInfo(token, bot)
|
||||||
for _, bot := range bots {
|
if err != nil {
|
||||||
defer bot.Stop()
|
log.Printf("Error: bot %s info couldn't be added: %v", bot.Me.Username, err)
|
||||||
}
|
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
|
||||||
for i := range bots {
|
|
||||||
if bots[i] != nil {
|
|
||||||
wg.Add(1)
|
|
||||||
go botStart(bots[i], &wg)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wg.Wait()
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func botStart(bot *tb.Bot, wg *sync.WaitGroup) error {
|
func sendMessage(user *tb.User, msg string) error {
|
||||||
defer wg.Done()
|
_, err := bot.Send(user, msg)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error sending message to user: %v", err)
|
||||||
|
return ErrSendMsg
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func botStart() error {
|
||||||
if bot == nil {
|
if bot == nil {
|
||||||
return ErrNilPointer
|
return ErrNilPointer
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user