From d8a6c8acd11fad1aa42769f2322bb9b9dd1d952c Mon Sep 17 00:00:00 2001 From: zomo Date: Fri, 9 Dec 2022 23:26:38 -0600 Subject: [PATCH] more --- discord/get.go | 6 +- discord/structs.go | 42 +++++++ endpoints/access.go | 16 +++ endpoints/authorization.go | 15 +-- endpoints/bots.go | 69 +++++++++++ endpoints/endpoints.go | 22 ++-- endpoints/login.go | 11 +- endpoints/tokens.go | 68 +++++++++++ go.mod | 4 +- go.sum | 2 + storage/bots.go | 132 ++++++++++++++++++--- storage/login.go | 58 +++++++--- storage/storage.go | 4 +- storage/tokens.go | 229 +++++++++++++++++++++++++++++++++++++ util/rand.go | 21 +++- 15 files changed, 643 insertions(+), 56 deletions(-) create mode 100644 endpoints/access.go create mode 100644 endpoints/bots.go create mode 100644 endpoints/tokens.go create mode 100644 storage/tokens.go diff --git a/discord/get.go b/discord/get.go index 0cab18c..8cb5b72 100644 --- a/discord/get.go +++ b/discord/get.go @@ -6,8 +6,8 @@ import ( "net/http" ) -func getDiscordUser(token string) User { - req, err := http.NewRequest("GET", "https://discord.com/api/v19/users/@me", nil) +func GetDiscordUser(token string) User { + req, err := http.NewRequest("GET", "https://discord.com/api/v10/users/@me", nil) if err != nil { panic(err) } @@ -24,7 +24,7 @@ func getDiscordUser(token string) User { panic(err) } - var respObj = User{} + var respObj User err = json.Unmarshal(respBody, &respObj) if err != nil { panic(err) diff --git a/discord/structs.go b/discord/structs.go index a30736d..fdcef9c 100644 --- a/discord/structs.go +++ b/discord/structs.go @@ -1,5 +1,7 @@ package discord +import "encoding/json" + type User struct { ID string `json:"id"` Username string `json:"username"` @@ -16,4 +18,44 @@ type User struct { Flags int `json:"flags"` Premium_type int `json:"premium_type"` Public_flags int `json:"public_flags"` +} + +type SimpleUser struct { + ID string `json:"id"` + Username string `json:"username"` + Discriminator string `json:"discriminator"` + Avatar string `json:"avatar"` + Bot bool `json:"bot"` + Banner string `json:"banner"` + AccentColor int `json:"accent_color"` + Verified bool `json:"verified"` +} + +func (u User) Simplify() SimpleUser { + return SimpleUser{ + ID: u.ID, + Username: u.Username, + Discriminator: u.Discriminator, + Avatar: u.Avatar, + Bot: u.Bot, + Banner: u.Banner, + AccentColor: u.Accent_color, + Verified: u.Verified, + } +} + +func (u User) MarshalBinary() ([]byte, error) { + return json.Marshal(u) +} + +func (u *User) UnmarshalBinary(data []byte) error { + return json.Unmarshal(data, u) +} + +func (u SimpleUser) MarshalBinary() ([]byte, error) { + return json.Marshal(u) +} + +func (u *SimpleUser) UnmarshalBinary(data []byte) error { + return json.Unmarshal(data, u) } \ No newline at end of file diff --git a/endpoints/access.go b/endpoints/access.go new file mode 100644 index 0000000..475b36f --- /dev/null +++ b/endpoints/access.go @@ -0,0 +1,16 @@ +package endpoints + +import ( + "git.zomo.dev/zomo/discord-retokenizer/storage" + "github.com/gin-gonic/gin" +) + +func access(c *gin.Context) { + authType, token := getAuthorization(c) + if authType != AuthorizationScopeBot { + c.AbortWithStatus(401) + } + + _, botToken := storage.BotTokenFromToken(token) + c.String(200, botToken) +} \ No newline at end of file diff --git a/endpoints/authorization.go b/endpoints/authorization.go index 6ffdc2f..3aa1400 100644 --- a/endpoints/authorization.go +++ b/endpoints/authorization.go @@ -23,15 +23,16 @@ func getAuthorization(c *gin.Context) (AuthorizationScope, string) { if len(headerSpl) != 2 { return AuthorizationScopeNone, "" } - if headerSpl[0] == "Bearer" { - if storage.CheckLoginToken(headerSpl[1], c.ClientIP()) { - return AuthorizationScopeUser, headerSpl[1] + prefix := headerSpl[0] + token := strings.ToLower(headerSpl[1]) + if prefix == "Bearer" { + if storage.CheckLoginToken(token, c.ClientIP()) { + return AuthorizationScopeUser, token } } - if headerSpl[0] == "Bot" { - // TODO check bot token - if true { - return AuthorizationScopeBot, headerSpl[1] + if prefix == "Bot" { + if found, _ := storage.BotTokenFromToken(token); found { + return AuthorizationScopeBot, token } } return AuthorizationScopeNone, "" diff --git a/endpoints/bots.go b/endpoints/bots.go new file mode 100644 index 0000000..f6b1e9e --- /dev/null +++ b/endpoints/bots.go @@ -0,0 +1,69 @@ +package endpoints + +import ( + "fmt" + + "git.zomo.dev/zomo/discord-retokenizer/storage" + "github.com/gin-gonic/gin" +) + +type SimpleDiscordUser struct { + Username string `json:"username"` + Discriminator string `json:"discriminator"` + Avatar string `json:"avatar"` + Banner string `json:"banner"` + Accent_color int `json:"accent_color"` + Verified bool `json:"verified"` +} + +type BotData struct { + Token string + ID string + Loaded SimpleDiscordUser +} + +// one array of just bot ids +// `bot:(id):token` +// `bot:(id):data` +// SimpleDiscordUser + +func bots(c *gin.Context) { + bots := storage.GetBots() + c.JSON(200, bots) +} + +func bot(c *gin.Context) { + id := c.Param("id") + bot := storage.GetBot(id) + c.JSON(200, bot) +} + +type addBotBody struct { + Token string `json:"token" binding:"required"` +} + +func addBot(c *gin.Context) { + var tokenBody addBotBody + if err := c.BindJSON(&tokenBody); err != nil { + fmt.Println(err) + return + } + didSet := storage.AddBot(tokenBody.Token) + if didSet { + c.JSON(200, gin.H{ + "success": true, + }) + } else { + c.JSON(400, gin.H{ + "success": false, + }) + } +} + +func removeBot(c *gin.Context) { + id := c.Param("id") + storage.RemoveBot(id) + c.JSON(200, gin.H{ + "success": true, + }) +} \ No newline at end of file diff --git a/endpoints/endpoints.go b/endpoints/endpoints.go index c5ebdde..3ca2c4d 100644 --- a/endpoints/endpoints.go +++ b/endpoints/endpoints.go @@ -10,23 +10,25 @@ func Run() { public := r.Group("/") public.POST("/login", login) //web login - public.POST("/access", func(c *gin.Context) {}) //access token + public.GET("/access", access) //access token private := r.Group("/") private.Use(userIsAuthorized) private.PATCH("/login", updateLogin) //change username/password (required before adding bots) + private.GET("/login/tokens", getLoginTokens) //list of login tokens + private.DELETE("/login/tokens", clearLoginTokens) //clears all login tokens - private.GET("/bots", func(c *gin.Context) {}) //generalized list of bots - private.GET("/bot/:bot", func(c *gin.Context) {}) //specific bot - private.POST("/bot/", func(c *gin.Context) {}) //add bot given token - private.DELETE("/bot/:bot", func(c *gin.Context) {}) //remove bot + private.GET("/bots", bots) //generalized list of bots + private.GET("/bot/:id", bot) //specific bot + private.POST("/bot", addBot) //add bot given token + private.DELETE("/bot/:id", removeBot) //remove bot - private.GET("/tokens", func(c *gin.Context) {}) //generalized list of tokens - private.GET("/token/:token", func(c *gin.Context) {}) //specific token - private.POST("/token/", func(c *gin.Context) {}) //new token given bot (so you cant add a token if theres no bots) - private.DELETE("/token/:token", func(c *gin.Context) {}) //remove token - private.PATCH("/token/:token", func(c *gin.Context) {}) //update token given bot + private.GET("/tokens", getTokens) //generalized list of tokens + private.GET("/token/:id", getToken) //specific token + private.POST("/token", addToken) //new token given bot (so you cant add a token if theres no bots) + private.DELETE("/token/:id", deleteToken) //remove token + private.PATCH("/token/:id", updateToken) //update token given bot r.Run() } \ No newline at end of file diff --git a/endpoints/login.go b/endpoints/login.go index 334831a..c72a02b 100644 --- a/endpoints/login.go +++ b/endpoints/login.go @@ -13,7 +13,6 @@ type LoginBody struct { } func login(c *gin.Context) { - var loginBody LoginBody if err := c.BindJSON(&loginBody); err != nil { fmt.Println(err) @@ -31,7 +30,6 @@ func login(c *gin.Context) { "error": "invalid username or password", }) } - } func updateLogin(c *gin.Context) { @@ -43,3 +41,12 @@ func updateLogin(c *gin.Context) { storage.UpdateUsername(updateLogin.Username) storage.UpdatePassword(updateLogin.Password) } + +func getLoginTokens(c *gin.Context) { + tokens := storage.GetLoginTokensSimple() + c.JSON(200, tokens) +} + +func clearLoginTokens(c *gin.Context) { + storage.ClearLoginTokens() +} \ No newline at end of file diff --git a/endpoints/tokens.go b/endpoints/tokens.go new file mode 100644 index 0000000..9def7af --- /dev/null +++ b/endpoints/tokens.go @@ -0,0 +1,68 @@ +package endpoints + +import ( + "fmt" + + "git.zomo.dev/zomo/discord-retokenizer/storage" + "github.com/gin-gonic/gin" +) + +func getTokens(c *gin.Context) { + tokens := storage.GetTokens() + c.JSON(200, tokens) +} + +func getToken(c *gin.Context) { + id := c.Param("id") + token := storage.GetToken(id) + c.JSON(200, token) +} + +type TokenBody struct { + BotID string `json:"bot_id" binding:"required"` +} + +func addToken(c *gin.Context) { + var tokenBody TokenBody + if err := c.BindJSON(&tokenBody); err != nil { + fmt.Println(err) + return + } + token := storage.GenerateToken(tokenBody.BotID) + if token == "" { + c.JSON(400, gin.H{ + "message": "bot id not found", + }) + return + } + c.JSON(200, gin.H{ + "token": token, + }) +} + +func deleteToken(c *gin.Context) { + id := c.Param("id") + storage.DeleteToken(id) + c.JSON(200, gin.H{ + "message": "success", + }) +} + +func updateToken(c *gin.Context) { + id := c.Param("id") + var tokenBody TokenBody + if err := c.BindJSON(&tokenBody); err != nil { + fmt.Println(err) + return + } + didSet := storage.UpdateToken(id, tokenBody.BotID) + if !didSet { + c.JSON(400, gin.H{ + "message": "token or bot id not found", + }) + return + } + c.JSON(200, gin.H{ + "message": "success", + }) +} \ No newline at end of file diff --git a/go.mod b/go.mod index 4a36f05..2625939 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,10 @@ module git.zomo.dev/zomo/discord-retokenizer go 1.19 +require github.com/joho/godotenv v1.4.0 + require ( + github.com/bwmarrin/snowflake v0.3.0 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/gin-contrib/sse v0.1.0 // indirect @@ -12,7 +15,6 @@ require ( github.com/go-playground/validator/v10 v10.11.1 // indirect github.com/go-redis/redis/v9 v9.0.0-rc.2 // indirect github.com/goccy/go-json v0.10.0 // indirect - github.com/joho/godotenv v1.4.0 github.com/json-iterator/go v1.1.12 // indirect github.com/leodido/go-urn v1.2.1 // indirect github.com/mattn/go-isatty v0.0.16 // indirect diff --git a/go.sum b/go.sum index 31ad526..0448b04 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +github.com/bwmarrin/snowflake v0.3.0 h1:xm67bEhkKh6ij1790JB83OujPR5CzNe8QuQqAgISZN0= +github.com/bwmarrin/snowflake v0.3.0/go.mod h1:NdZxfVWX+oR6y2K0o6qAYv6gIOP9rjG0/E9WsDpxqwE= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= diff --git a/storage/bots.go b/storage/bots.go index 1791d8e..fc274dc 100644 --- a/storage/bots.go +++ b/storage/bots.go @@ -1,27 +1,125 @@ package storage -type SimpleDiscordUser struct { - Username string `json:"username"` - Discriminator string `json:"discriminator"` - Avatar string `json:"avatar"` - Banner string `json:"banner"` - Accent_color int `json:"accent_color"` - Verified bool `json:"verified"` +import ( + "fmt" + + "git.zomo.dev/zomo/discord-retokenizer/discord" + "github.com/go-redis/redis/v9" +) + +func BotExists(id string) bool { + exist, err := client.SMIsMember(ctx, "bots", id).Result() + if err != nil { + if err == redis.Nil { + return false + } + panic(err) + } + for _, b := range exist { + if !b { + return false + } + } + return true } -type BotData struct { - Token string - ID string - Loaded SimpleDiscordUser +func GetBots() []discord.SimpleUser { + botIDs, err := client.SMembers(ctx, "bots").Result() + if err != nil && err != redis.Nil { + panic(err) + } + bots := make([]discord.SimpleUser, 0) + for _, id := range botIDs { + bots = append(bots, GetBot(id).Simplify()) + } + return bots } -// one array of just bot ids -// `bot:(id):token` -// `bot:(id):data` -// SimpleDiscordUser +func GetBot(id string) discord.User { + var bot discord.User + key := fmt.Sprintf("bot:%s:data", id) + err := client.Get(ctx, key).Scan(&bot) + if err != nil && err != redis.Nil { + panic(err) + } + return bot +} -func GetBots() { +func ExistsBot(id string) bool { + exist, err := client.SIsMember(ctx, "bots", id).Result() + if err != nil { + if err == redis.Nil { + return false + } + panic(err) + } + return exist +} - +func RemoveBot(id string) { + err := client.SRem(ctx, "bots", id).Err() + if err != nil { + panic(err) + } + keyPrefix := fmt.Sprintf("bot:%s:", id) + err = client.Del(ctx, keyPrefix + "token").Err() + if err != nil { + panic(err) + } + err = client.Del(ctx, keyPrefix + "data").Err() + if err != nil { + panic(err) + } +} +func getBotToken(id string) string { + if !BotExists(id) { + return "" + } + key := fmt.Sprintf("bot:%s:token", id) + token, err := client.Get(ctx, key).Result() + if err != nil { + panic(err) + } + return token +} + +func RefreshBot(id string) discord.User { + token := getBotToken(id) + bot := discord.GetDiscordUser(token) + + key := fmt.Sprintf("bot:%s:data", id) + err := client.Set(ctx, key, bot, 0).Err() + if err != nil { + panic(err) + } + return bot +} + +func AddBot(token string) bool { + user := discord.GetDiscordUser(token) + + if user.ID == "" { + return false + } + + err := client.SAdd(ctx, "bots", user.ID).Err() + if err != nil { + panic(err) + } + + userID := user.ID + keyPrefix := fmt.Sprintf("bot:%s:", userID) + + err = client.Set(ctx, keyPrefix + "token", token, 0).Err() + if err != nil { + panic(err) + } + + err = client.Set(ctx, keyPrefix + "data", user, 0).Err() + if err != nil { + panic(err) + } + + return true } \ No newline at end of file diff --git a/storage/login.go b/storage/login.go index 396a185..6f38f6f 100644 --- a/storage/login.go +++ b/storage/login.go @@ -41,8 +41,6 @@ func CheckLogin(username string, password string, ip string) (bool, string) { panic(err) } - fmt.Println(user, username) - if user != username { return false, "" } @@ -56,11 +54,27 @@ func CheckLogin(username string, password string, ip string) (bool, string) { } type LoginToken struct { - Token string `json:"token"` + ID string `json:"id"` + TokenHash string `json:"token"` + IP string `json:"ip"` + End string `json:"end"` +} + + +type LoginTokenSimple struct { + ID string `json:"id"` IP string `json:"ip"` End string `json:"end"` } +func (t LoginToken) Simplify() LoginTokenSimple { + return LoginTokenSimple{ + ID: t.ID, + IP: t.IP, + End: t.End, + } +} + func (t LoginToken) MarshalBinary() ([]byte, error) { return json.Marshal(t) } @@ -70,21 +84,22 @@ func (t *LoginToken) UnmarshalBinary(data []byte) error { } func createLoginToken(ip string) string { - token := util.GeneratePassword(32) + token := util.GenerateToken() tokenHash, err := bcrypt.GenerateFromPassword([]byte(token), bcrypt.DefaultCost) if err != nil { panic(err) } - + tokenData := LoginToken{ - Token: string(tokenHash), - IP: ip, - End: token[len(token) - 4:], + ID: util.GenerateID(), + TokenHash: string(tokenHash), + IP: ip, + End: util.GetEnd(token), } member := redis.Z{ - Score: float64(time.Now().Unix() + 4 * 60 * 60), + Score: float64(time.Now().Unix() + 4 * 60 * 60), Member: tokenData, } @@ -96,8 +111,7 @@ func createLoginToken(ip string) string { return token } -func CheckLoginToken(token string, ip string) bool { - +func getLoginTokens() []LoginToken { expired, err := client.ZRangeByScore(ctx, "loginTokens", &redis.ZRangeBy{ Min: "-inf", Max: fmt.Sprintf("%d", time.Now().Unix()), @@ -118,10 +132,28 @@ func CheckLoginToken(token string, ip string) bool { panic(err) } - fmt.Printf("%v\n", current) + return current +} + +func GetLoginTokensSimple() []LoginTokenSimple { + simple := make([]LoginTokenSimple, 0) + + for _, c := range getLoginTokens() { + simple = append(simple, c.Simplify()) + } + + return simple +} + +func ClearLoginTokens() { + client.Del(ctx, "loginTokens") +} + +func CheckLoginToken(token string, ip string) bool { + current := getLoginTokens() for _, c := range current { - err = bcrypt.CompareHashAndPassword([]byte(c.Token), []byte(token)) + err := bcrypt.CompareHashAndPassword([]byte(c.TokenHash), []byte(token)) if err == nil && ip == c.IP { return true } diff --git a/storage/storage.go b/storage/storage.go index 445b1f2..3027bcf 100644 --- a/storage/storage.go +++ b/storage/storage.go @@ -15,9 +15,9 @@ var client *redis.Client = nil func initializeRedis() { username := "default" - UpdateUsername( username) + UpdateUsername(username) password := util.GeneratePassword(16) - UpdatePassword( password) + UpdatePassword(password) fmt.Printf("FIRST TIME SETUP\nusername: %s\npassword: %s\n\n\n", username, password) } diff --git a/storage/tokens.go b/storage/tokens.go new file mode 100644 index 0000000..94d0ea6 --- /dev/null +++ b/storage/tokens.go @@ -0,0 +1,229 @@ +package storage + +import ( + "encoding/json" + + "git.zomo.dev/zomo/discord-retokenizer/discord" + "git.zomo.dev/zomo/discord-retokenizer/util" + "golang.org/x/crypto/bcrypt" +) + +type TokenTiny struct { + ID string `json:"id"` + TokenHash string `json:"token"` +} + +type TokenBot struct { + ID string `json:"id"` + BotID string `json:"bot_id"` + End string `json:"end"` + TokenHash string `json:"token"` +} + +type SimpleTokenBot struct { + ID string `json:"id"` + BotID string `json:"bot_id"` + End string `json:"end"` +} + +func (t TokenBot) Simplify() SimpleTokenBot { + return SimpleTokenBot{ + ID: t.ID, + BotID: t.BotID, + End: t.End, + } +} + +func (t TokenTiny) MarshalBinary() ([]byte, error) { + return json.Marshal(t) +} + +func (t *TokenTiny) UnmarshalBinary(data []byte) error { + return json.Unmarshal(data, t) +} + +func (t TokenBot) MarshalBinary() ([]byte, error) { + return json.Marshal(t) +} + +func (t *TokenBot) UnmarshalBinary(data []byte) error { + return json.Unmarshal(data, t) +} + +func (t SimpleTokenBot) MarshalBinary() ([]byte, error) { + return json.Marshal(t) +} + +func (t *SimpleTokenBot) UnmarshalBinary(data []byte) error { + return json.Unmarshal(data, t) +} + +func GenerateToken(botID string) string { + if !ExistsBot(botID) { + return "" + } + + // Generate a token + token := util.GenerateToken() + tokenID := util.GenerateID() + tokenHash, err := bcrypt.GenerateFromPassword([]byte(token), bcrypt.DefaultCost) + if err != nil { + panic(err) + } + + tinyToken := TokenTiny{ + ID: tokenID, + TokenHash: string(tokenHash), + } + + err = client.SAdd(ctx, "tokens", tinyToken).Err() + if err != nil { + panic(err) + } + + botToken := TokenBot{ + ID: tokenID, + BotID: botID, + End: util.GetEnd(token), + TokenHash: string(tokenHash), + } + + err = client.Set(ctx, "token:" + tokenID, botToken, 0).Err() + if err != nil { + panic(err) + } + + return token +} + +func getTokenBot(token string) (bool, TokenBot) { + var tokens []TokenTiny + err := client.SMembers(ctx, "tokens").ScanSlice(&tokens) + if err != nil { + panic(err) + } + for _, t := range tokens { + err = bcrypt.CompareHashAndPassword([]byte(t.TokenHash), []byte(token)) + if err == nil { + var botToken TokenBot + err := client.Get(ctx, "token:" + t.ID).Scan(&botToken) + if err != nil { + panic(err) + } + return true, botToken + } + } + return false, TokenBot{} +} + +func DeleteToken(token string) { + foundToken, botToken := getTokenBot(token) + if !foundToken { + return + } + err := client.SRem(ctx, "tokens", botToken.TokenHash).Err() + if err != nil { + panic(err) + } + err = client.Del(ctx, "token:" + botToken.ID).Err() + if err != nil { + panic(err) + } +} + +func UpdateToken(token string, botID string) bool { + if !ExistsBot(botID) { + return false + } + + foundToken, botToken := getTokenBot(token) + if !foundToken { + return false + } + + err := client.Set(ctx, "token:" + botToken.ID, botToken, 0).Err() + if err != nil { + panic(err) + } + return true +} + +type TokenUserBot struct { + ID string `json:"id"` + End string `json:"token_end"` + User discord.User `json:"user"` +} + +type SimpleTokenUserBot struct { + ID string `json:"id"` + End string `json:"token_end"` + User discord.SimpleUser `json:"user"` +} + +func (t TokenBot) WithUser() TokenUserBot { + return TokenUserBot{ + ID: t.ID, + End: t.End, + User: GetBot(t.BotID), + } +} + +func (t TokenUserBot) Simplify() SimpleTokenUserBot { + return SimpleTokenUserBot{ + ID: t.ID, + End: t.End, + User: t.User.Simplify(), + } +} + +func (t TokenUserBot) MarshalBinary() ([]byte, error) { + return json.Marshal(t) +} + +func (t *TokenUserBot) UnmarshalBinary(data []byte) error { + return json.Unmarshal(data, t) +} + +func (t SimpleTokenUserBot) MarshalBinary() ([]byte, error) { + return json.Marshal(t) +} + +func (t *SimpleTokenUserBot) UnmarshalBinary(data []byte) error { + return json.Unmarshal(data, t) +} + +func GetTokens() []SimpleTokenUserBot { + var tokens []TokenTiny + err := client.SMembers(ctx, "tokens").ScanSlice(&tokens) + if err != nil { + panic(err) + } + + simpleTokens := make([]SimpleTokenUserBot, 0) + for _, t := range tokens { + var tokenBot TokenBot + err := client.Get(ctx, "token:" + t.ID).Scan(&tokenBot) + if err != nil { + panic(err) + } + simpleTokens = append(simpleTokens, tokenBot.WithUser().Simplify()) + } + return simpleTokens +} + +func GetToken(id string) TokenUserBot { + var tokenBot TokenBot + err := client.Get(ctx, "token:" + id).Scan(&tokenBot) + if err != nil { + panic(err) + } + return tokenBot.WithUser() +} + +func BotTokenFromToken(token string) (bool, string) { + foundBot, tokenBot := getTokenBot(token) + if !foundBot { + return false, "" + } + return true, getBotToken(tokenBot.BotID) +} \ No newline at end of file diff --git a/util/rand.go b/util/rand.go index e63d444..591ffe1 100644 --- a/util/rand.go +++ b/util/rand.go @@ -4,9 +4,12 @@ import ( "encoding/hex" "math/rand" "time" + + "github.com/bwmarrin/snowflake" ) -var passwordChars = []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-=_+!@#$%^&*()[]{}|;:,.<>/?") +// var passwordChars = []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-=_+!@#$%^&*()[]{}|;:,.<>/?") +var passwordChars = []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-=_+!@#$%^&*?") func GeneratePassword(length int) string { rand.Seed(time.Now().UnixNano()) @@ -26,4 +29,20 @@ func GenerateToken() string { return "" } return hex.EncodeToString(b) +} + +var snowflakeNodeIndex int64 = 0 +func GenerateID() string { + node, err := snowflake.NewNode(snowflakeNodeIndex) + if err != nil { + panic(err) + } + return node.Generate().String() +} + +func GetEnd(token string) string { + if len(token) < 8 { + return "" + } + return token[len(token)-8:] } \ No newline at end of file