From c0bf3b2b36eb7c6d59821428b498f17115fc0345 Mon Sep 17 00:00:00 2001 From: Ettore Dreucci Date: Sun, 5 Apr 2020 01:25:43 +0200 Subject: [PATCH] Further development Signed-off-by: Ettore Dreucci --- go.mod | 8 +-- go.sum | 8 +++ src/manageBot.go | 12 ++-- src/manageUser.go | 2 +- src/redisAPI.go | 4 ++ src/telegramAPI.go | 4 +- src/telegramCommands.go | 144 ++++++++++++++++++++++++++++++------- src/telegramHandlers.go | 2 +- src/telegramMenus.go | 155 +++++++++++----------------------------- todo | 13 ++-- 10 files changed, 190 insertions(+), 162 deletions(-) diff --git a/go.mod b/go.mod index e361339..50c4793 100644 --- a/go.mod +++ b/go.mod @@ -3,12 +3,10 @@ module github.com/noettore/barandaBot go 1.14 require ( - github.com/daviddengcn/go-colortext v0.0.0-20180409174941-186a3d44e920 + github.com/daviddengcn/go-colortext v1.0.0 // indirect github.com/dixonwille/wmenu v4.0.2+incompatible github.com/go-redis/redis v6.15.7+incompatible - github.com/mattn/go-isatty v0.0.12 - github.com/pkg/errors v0.9.1 - golang.org/x/sys v0.0.0-20200327173247-9dae0f8f5775 - gopkg.in/dixonwille/wlog.v2 v2.0.0 + github.com/mattn/go-isatty v0.0.12 // indirect + gopkg.in/dixonwille/wlog.v2 v2.0.0 // indirect gopkg.in/tucnak/telebot.v2 v2.0.0-20200329125927-3458aeb2e7be ) diff --git a/go.sum b/go.sum index 3986328..eade657 100644 --- a/go.sum +++ b/go.sum @@ -1,22 +1,30 @@ github.com/daviddengcn/go-colortext v0.0.0-20180409174941-186a3d44e920 h1:d/cVoZOrJPJHKH1NdeUjyVAWKp4OpOT+Q+6T1sH7jeU= github.com/daviddengcn/go-colortext v0.0.0-20180409174941-186a3d44e920/go.mod h1:dv4zxwHi5C/8AeI+4gX4dCWOIvNi7I6JCSX0HvlKPgE= +github.com/daviddengcn/go-colortext v1.0.0 h1:ANqDyC0ys6qCSvuEK7l3g5RaehL/Xck9EX8ATG8oKsE= +github.com/daviddengcn/go-colortext v1.0.0/go.mod h1:zDqEI5NVUop5QPpVJUxE9UO10hRnmkD5G4Pmri9+m4c= github.com/dixonwille/wmenu v4.0.2+incompatible h1:lxrPJsx9LpdUFD5T+dOfl6gPKLbBmiAtEdACLT1I2/w= github.com/dixonwille/wmenu v4.0.2+incompatible/go.mod h1:DnajdZEKFQksxBctWekpWaQXQrDUHRBco6b8MyZnR1s= github.com/go-redis/redis v6.12.1-0.20180601000436-026926344199+incompatible h1:gJTncm0Synkcv4HV+nn6wWxv5udP8gcHe19SPW3kmyI= github.com/go-redis/redis v6.12.1-0.20180601000436-026926344199+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= github.com/go-redis/redis v6.15.7+incompatible h1:3skhDh95XQMpnqeqNftPkQD9jL9e5e36z/1SUm6dy1U= github.com/go-redis/redis v6.15.7+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= +github.com/golangplus/bytes v0.0.0-20160111154220-45c989fe5450/go.mod h1:Bk6SMAONeMXrxql8uvOKuAZSu8aM5RUGv+1C6IJaEho= +github.com/golangplus/bytes v1.0.0/go.mod h1:AdRaCFwmc/00ZzELMWb01soso6W1R/++O1XL80yAn+A= +github.com/golangplus/fmt v1.0.0/go.mod h1:zpM0OfbMCjPtd2qkTD/jX2MgiFCqklhSUFyDW44gVQE= +github.com/golangplus/testing v1.0.0/go.mod h1:ZDreixUV3YzhoVraIDyOzHrr76p6NUh6k/pPg/Q3gYA= github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/pkg/errors v0.8.1-0.20180311214515-816c9085562c h1:SZvPVPsWE261bl8uxQ6Siq+ExNmYomz4CTU9E0ALgj4= github.com/pkg/errors v0.8.1-0.20180311214515-816c9085562c/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= golang.org/x/sys v0.0.0-20180616030259-6c888cc515d3 h1:FCfAlbS73+IQQJktaKGHldMdL2bGDVpm+OrCEbVz1f4= golang.org/x/sys v0.0.0-20180616030259-6c888cc515d3/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200327173247-9dae0f8f5775 h1:TC0v2RSO1u2kn1ZugjrFXkRZAEaqMN/RW+OTZkBzmLE= golang.org/x/sys v0.0.0-20200327173247-9dae0f8f5775/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/src/manageBot.go b/src/manageBot.go index 5159842..733e88a 100644 --- a/src/manageBot.go +++ b/src/manageBot.go @@ -67,27 +67,27 @@ func getBotToken() (string, error) { return token, nil } -func addBotInfo(botToken string, botUser string) error { +func addBotInfo(botUser string) error { if redisClient == nil { return ErrNilPointer } - err := redisClient.HSet(botInfo, botToken, botUser).Err() + err := redisClient.Set(botInfo, botUser, 0).Err() if err != nil { log.Printf("Error in adding bot info: %v", err) - return ErrRedisAddHash + return ErrRedisAddString } return nil } -func removeBotInfo(botToken string) error { +func removeBotInfo() error { if redisClient == nil { return ErrNilPointer } - err := redisClient.HDel(botInfo, botToken).Err() + err := redisClient.Del(botInfo).Err() if err != nil { log.Printf("Error in removing bot info: %v", err) - return ErrRedisDelHash + return ErrRedisDelString } return nil } diff --git a/src/manageUser.go b/src/manageUser.go index e1fd66d..e1d525e 100644 --- a/src/manageUser.go +++ b/src/manageUser.go @@ -143,7 +143,7 @@ func authorizeUser(userID int, authorize bool) error { log.Printf("Error adding token to set: %v", err) return ErrRedisAddSet } - err = sendMsg(user, newAuthMsg, true) + err = sendMsgWithMenu(user, newAuthMsg, true) if err != nil { log.Printf("Error sending message to new authorized user: %v", err) return ErrSendMsg diff --git a/src/redisAPI.go b/src/redisAPI.go index 15be144..5fb4b78 100644 --- a/src/redisAPI.go +++ b/src/redisAPI.go @@ -37,6 +37,10 @@ var ( 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 = errors.New("redis: couldn't remove key from hash") + //ErrRedisAddString is thrown when it's not possible to add a string + ErrRedisAddString = errors.New("redis: couldn't add string") + //ErrRedisDelString is thrown when it's not possible to remove a string + ErrRedisDelString = errors.New("redis: couldn't remove string") //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 diff --git a/src/telegramAPI.go b/src/telegramAPI.go index 8825314..77ca3e6 100644 --- a/src/telegramAPI.go +++ b/src/telegramAPI.go @@ -21,7 +21,7 @@ const ( unstoppableMsg string = "Non ci siamo... Io l'ho nominata AMMINISTRATORE, cosa crede?! Questo ruolo esige impegno! Non può certo bloccarmi!" wrongCmdMsg string = "Non capisco, si spieghi meglio! Per cortesia, basta basta! La prego! Non so di cosa sta parlando!" authHowToMsg string = "Per autorizzare un utente invia un messaggio con scritto \n`/authUser ID_UTENTE`\n sostituendo `ID_UTENTE` con l'ID che ti é stato comunicato dall'utente da autorizzare" - deAuthHowToMsg string = "Per deautorizzare un utente invia un messaggio con scritto \n`/authUser USERNAME`\n sostituendo `USERNAME` con il nome utente da deautorizzare" + deAuthHowToMsg string = "Per deautorizzare un utente invia un messaggio con scritto \n`/deAuthUser ID_UTENTE`\n sostituendo `ID_UTENTE` con il nome utente da deautorizzare" newAuthMsg string = "Benvenuto! Da ora in poi lei fa ufficialmente parte del magnifico *Coro dell'Università di Pisa*! Deve sentirsi onorato." delAuthMsg string = "Capisco, quindi se ne sta andando... Beh un po' mi dispiace, devo ammetterlo. Se ripassa da queste parti sarà sempre il benvenuto! Arrivederci." newAdminMsg string = "Beh allora, vediamo... Ah si, la nomino amministratore! Da grandi poteri derivano grandi responsabilità. Mi raccomando, non me ne faccia pentire!" @@ -94,7 +94,7 @@ func botInit() error { return ErrBotInit } - err = addBotInfo(token, bot.Me.Username) + err = addBotInfo(bot.Me.Username) if err != nil { log.Printf("Error: bot %s info couldn't be added: %v", bot.Me.Username, err) return ErrBotInit diff --git a/src/telegramCommands.go b/src/telegramCommands.go index b958a91..669f321 100644 --- a/src/telegramCommands.go +++ b/src/telegramCommands.go @@ -18,8 +18,10 @@ var genericCommands = map[string]bool{ "/prossimoEvento": true, } var authCommands = map[string]bool{ + "/prossimaProva": true, "/prossimaProvaSezione": true, "/prossimaProvaInsieme": true, + "/ultimaMail": true, } var adminCommands = map[string]bool{ "/authUser": true, @@ -87,27 +89,62 @@ func stopCmd(u *tb.User) { } } -func authUserCmd(u *tb.User, payload string) { +func authUserCmd(sender *tb.User, payload string) { if payload == "" { - err := sendMsg(u, authHowToMsg, true) + err := sendMsgWithMenu(sender, authHowToMsg, true) if err != nil { log.Printf("Error in sending message: %v", err) } } else { - //TODO check if payload is valid ID - desc, err := getUserDescription(u) + userID, err := strconv.Atoi(payload) + if err != nil { + log.Printf("Error converting string to int: %v", err) + } + user, err := getUserInfo(userID) + if err != nil { + log.Printf("Error getting user info: %v", err) + return + } + + desc, err := getUserDescription(user) if err != nil { log.Printf("Error retriving user description: %v", err) } + + userGroups, err := getUserGroups(user.ID) + if err != nil { + log.Printf("Error retriving user groups: %v", err) + } + menu := authUserMenu - menu[0][0].Data = payload - menu[0][1].Data = payload - menu[1][0].Data = payload - menu[1][1].Data = payload - menu[2][0].Data = payload - menu[2][1].Data = payload - menu[2][2].Data = payload - err = sendMsgWithSpecificMenu(u, "Stai per autorizzare il seguente utente:\n"+ + menu[0][0].Data = strconv.Itoa(user.ID) + menu[0][1].Data = strconv.Itoa(user.ID) + menu[1][0].Data = strconv.Itoa(user.ID) + menu[1][1].Data = strconv.Itoa(user.ID) + menu[2][0].Data = strconv.Itoa(user.ID) + menu[2][1].Data = strconv.Itoa(user.ID) + menu[2][2].Data = strconv.Itoa(user.ID) + + for _, group := range userGroups { + switch group { + case ugSoprano: + menu[0][0].Text = "" + case ugContralto: + menu[0][1].Text = "" + case ugTenore: + menu[1][0].Text = "" + case ugBasso: + menu[1][1].Text = "" + case ugCommissario: + menu[2][0].Text = "" + case ugReferente: + menu[2][1].Text = "" + case ugPreparatore: + menu[2][2].Text = "" + } + } + + err = sendMsgWithSpecificMenu(sender, "Stai per autorizzare il seguente utente:\n"+ desc+ "\nSe le informazioni sono corrette fai 'tap' sui gruppi di appartenenza dell'utente da autorizzare, altrimenti *torna al menù principale ed annulla l'autorizzazione*", menu, true) @@ -117,9 +154,9 @@ func authUserCmd(u *tb.User, payload string) { } } -func deAuthUserCmd(u *tb.User, payload string) { +func deAuthUserCmd(sender *tb.User, payload string) { if payload == "" { - err := sendMsg(u, deAuthHowToMsg, true) + err := sendMsgWithMenu(sender, deAuthHowToMsg, true) if err != nil { log.Printf("Error in sending message: %v", err) } @@ -128,29 +165,86 @@ func deAuthUserCmd(u *tb.User, payload string) { if err != nil { log.Printf("Error converting string to int: %v", err) } - authorizeUser(userID, false) - //TODO + user, err := getUserInfo(userID) + if err != nil { + log.Printf("Error getting user info: %v", err) + return + } + + desc, err := getUserDescription(user) + if err != nil { + log.Printf("Error retriving user description: %v", err) + } + + menu := authUserMenu + menu[0][0].Data = strconv.Itoa(user.ID) + "+remove" + menu[0][1].Data = strconv.Itoa(user.ID) + "+remove" + menu[1][0].Data = strconv.Itoa(user.ID) + "+remove" + menu[1][1].Data = strconv.Itoa(user.ID) + "+remove" + menu[2][0].Data = strconv.Itoa(user.ID) + "+remove" + menu[2][1].Data = strconv.Itoa(user.ID) + "+remove" + menu[2][2].Data = strconv.Itoa(user.ID) + "+remove" + + if is, _ := isUserInGroup(user.ID, ugSoprano); !is { + menu[0][0].Text = "" + } + if is, _ := isUserInGroup(user.ID, ugContralto); !is { + menu[0][1].Text = "" + } + if is, _ := isUserInGroup(user.ID, ugTenore); !is { + menu[1][0].Text = "" + } + if is, _ := isUserInGroup(user.ID, ugBasso); !is { + menu[1][1].Text = "" + } + if is, _ := isUserInGroup(user.ID, ugCommissario); !is { + menu[2][0].Text = "" + } + if is, _ := isUserInGroup(user.ID, ugReferente); !is { + menu[2][1].Text = "" + } + if is, _ := isUserInGroup(user.ID, ugPreparatore); !is { + menu[2][2].Text = "" + } + + err = sendMsgWithSpecificMenu(sender, "Stai per deautorizzare il seguente utente:\n"+ + desc+ + "\nSe le informazioni sono corrette fai 'tap' sui gruppi da cui deautorizzare l'utente, altrimenti *torna al menù principale ed annulla l'autorizzazione*", + menu, true) + if err != nil { + log.Printf("Error in sending message: %v", err) + } + } } -func addUserGroupCmd(userID int, group userGroup) error { +func addUserGroupCmd(userID int, group userGroup, add bool) error { userGroups, err := getUserGroups(userID) if err != nil { log.Printf("Error retriving user groups: %v", err) + return ErrAddAuthUser } is, err := isUserInGroup(userID, group) if err != nil { log.Printf("Error checking if user is in group: %v", err) - } - if is { - return ErrAddUser - } - userGroups = append(userGroups, group) - err = setUserGroups(userID, userGroups...) - if err != nil { - log.Printf("Error adding user in group: %v", err) return ErrAddAuthUser } + if is && !add { + //REMOVE USER FROM GROUP + //TODO + } else if !is && add { + userGroups = append(userGroups, group) + err = setUserGroups(userID, userGroups...) + if err != nil { + log.Printf("Error adding user in group: %v", err) + return ErrAddAuthUser + } + err = authorizeUser(userID, true) + if err != nil { + log.Printf("Error authorizing user: %v", err) + return ErrAddAuthUser + } + } return nil } diff --git a/src/telegramHandlers.go b/src/telegramHandlers.go index 406ca7e..9d23513 100644 --- a/src/telegramHandlers.go +++ b/src/telegramHandlers.go @@ -35,7 +35,7 @@ func setBotHandlers() error { authUserCmd(m.Sender, m.Payload) }) bot.Handle("/deAuthUser", func(m *tb.Message) { - + deAuthUserCmd(m.Sender, m.Payload) }) bot.Handle(tb.OnText, func(m *tb.Message) { diff --git a/src/telegramMenus.go b/src/telegramMenus.go index 7722a75..10176e7 100644 --- a/src/telegramMenus.go +++ b/src/telegramMenus.go @@ -3,6 +3,7 @@ package main import ( "log" "strconv" + "strings" tb "gopkg.in/tucnak/telebot.v2" ) @@ -118,6 +119,38 @@ func setBotMenus() error { return nil } +func groupCallback(c *tb.Callback, groupName string) { + dataContent := strings.Split(c.Data, "+") + userID, err := strconv.Atoi(dataContent[0]) + if err != nil { + log.Printf("Error converting string to int: %v", err) + return + } + var errAlert, authAlert string + var add bool + if len(dataContent) > 1 && dataContent[1] == "remove" { + add = false + errAlert = "Impossibile deautorizzare l'utente per il gruppo " + groupName + authAlert = "Utente " + dataContent[0] + " rimosso dal gruppo " + groupName + } else { + add = true + errAlert = "Impossibile aggiungere l'utente al gruppo " + groupName + authAlert = "Utente " + dataContent[0] + " aggiunto al gruppo " + groupName + } + err = addUserGroupCmd(userID, ugContralto, add) + if err != nil { + bot.Respond(c, &tb.CallbackResponse{ + Text: errAlert, + ShowAlert: true, + }) + } else { + bot.Respond(c, &tb.CallbackResponse{ + Text: authAlert, + ShowAlert: true, + }) + } +} + func setBotCallbacks() error { if bot == nil { return ErrNilPointer @@ -154,6 +187,7 @@ func setBotCallbacks() error { }) bot.Handle(&deAuthBtn, func(c *tb.Callback) { bot.Respond(c, &tb.CallbackResponse{}) + sendMsgWithMenu(c.Sender, deAuthHowToMsg, false) }) bot.Handle(&sendMsgBtn, func(c *tb.Callback) { @@ -161,132 +195,25 @@ func setBotCallbacks() error { }) bot.Handle(&authUGSopranoBtn, func(c *tb.Callback) { - userID, err := strconv.Atoi(c.Data) - if err != nil { - log.Printf("Error converting string to int: %v", err) - } - err = addUserGroupCmd(userID, ugSoprano) - if err != nil { - bot.Respond(c, &tb.CallbackResponse{ - Text: "Impossibile autorizzare l'utente", - ShowAlert: true, - }) - } else { - bot.Respond(c, &tb.CallbackResponse{ - Text: "Autorizzato utente " + c.Data + "e aggiunto al gruppo Soprani", - ShowAlert: true, - }) - } + groupCallback(c, "Soprani") }) bot.Handle(&authUGContraltoBtn, func(c *tb.Callback) { - userID, err := strconv.Atoi(c.Data) - if err != nil { - log.Printf("Error converting string to int: %v", err) - } - err = addUserGroupCmd(userID, ugContralto) - if err != nil { - bot.Respond(c, &tb.CallbackResponse{ - Text: "Impossibile autorizzare l'utente", - ShowAlert: true, - }) - } else { - bot.Respond(c, &tb.CallbackResponse{ - Text: "Autorizzato utente " + c.Data + "e aggiunto al gruppo Contralti", - ShowAlert: true, - }) - } - + groupCallback(c, "Contralti") }) bot.Handle(&authUGTenoreBtn, func(c *tb.Callback) { - userID, err := strconv.Atoi(c.Data) - if err != nil { - log.Printf("Error converting string to int: %v", err) - } - err = addUserGroupCmd(userID, ugTenore) - if err != nil { - bot.Respond(c, &tb.CallbackResponse{ - Text: "Impossibile autorizzare l'utente", - ShowAlert: true, - }) - } else { - bot.Respond(c, &tb.CallbackResponse{ - Text: "Autorizzato utente " + c.Data + "e aggiunto al gruppo Tenori", - ShowAlert: true, - }) - } + groupCallback(c, "Tenori") }) bot.Handle(&authUGBassoBtn, func(c *tb.Callback) { - userID, err := strconv.Atoi(c.Data) - if err != nil { - log.Printf("Error converting string to int: %v", err) - } - err = addUserGroupCmd(userID, ugBasso) - if err != nil { - bot.Respond(c, &tb.CallbackResponse{ - Text: "Impossibile autorizzare l'utente", - ShowAlert: true, - }) - } else { - bot.Respond(c, &tb.CallbackResponse{ - Text: "Autorizzato utente " + c.Data + "e aggiunto al gruppo Bassi", - ShowAlert: true, - }) - } + groupCallback(c, "Bassi") }) bot.Handle(&authUGCommissarioBtn, func(c *tb.Callback) { - userID, err := strconv.Atoi(c.Data) - if err != nil { - log.Printf("Error converting string to int: %v", err) - } - err = addUserGroupCmd(userID, ugCommissario) - if err != nil { - bot.Respond(c, &tb.CallbackResponse{ - Text: "Impossibile autorizzare l'utente", - ShowAlert: true, - }) - } else { - bot.Respond(c, &tb.CallbackResponse{ - Text: "Autorizzato utente " + c.Data + "e aggiunto al gruppo Commissari", - ShowAlert: true, - }) - } - + groupCallback(c, "Commissari") }) bot.Handle(&authUGReferenteBtn, func(c *tb.Callback) { - userID, err := strconv.Atoi(c.Data) - if err != nil { - log.Printf("Error converting string to int: %v", err) - } - err = addUserGroupCmd(userID, ugReferente) - if err != nil { - bot.Respond(c, &tb.CallbackResponse{ - Text: "Impossibile autorizzare l'utente", - ShowAlert: true, - }) - } else { - bot.Respond(c, &tb.CallbackResponse{ - Text: "Autorizzato utente " + c.Data + "e aggiunto al gruppo Referenti", - ShowAlert: true, - }) - } + groupCallback(c, "Referenti") }) bot.Handle(&authUGPreparatoreBtn, func(c *tb.Callback) { - userID, err := strconv.Atoi(c.Data) - if err != nil { - log.Printf("Error converting string to int: %v", err) - } - err = addUserGroupCmd(userID, ugPreparatore) - if err != nil { - bot.Respond(c, &tb.CallbackResponse{ - Text: "Impossibile autorizzare l'utente", - ShowAlert: true, - }) - } else { - bot.Respond(c, &tb.CallbackResponse{ - Text: "Autorizzato utente " + c.Data + "e aggiunto al gruppo Preparatori", - ShowAlert: true, - }) - } + groupCallback(c, "Preparatori") }) return nil diff --git a/todo b/todo index 6918670..6ce6ece 100644 --- a/todo +++ b/todo @@ -1,10 +1,7 @@ -menu con gorutine: - start bot - stop bot - stop daemon - info bot - delete bot -> per nome e non per token (segreto) - redis hash per bot (si puó usare la struct tb.Bot come interface?): rinnovare info ad ogni start del bot - visualizzare info bot \ No newline at end of file + visualizzare info bot. Tipo? + +SuperAdmin? Menú giá presente + +Controllare stoppedUser anche se comando inviato tramite menu. Dove farlo? \ No newline at end of file