// usernameExistsForChat checks if a username exists for a given chat. // This returns false if the userID exists but the username has changed. func (j *JarvisBot) usernameExistsForChat(chat, sender *telebot.User) bool { res := false // Guard against possibility that chat isn't a group chat. // We're lazy here, returning true implies that we don't want to run a save. if !chat.IsGroupChat() { return true } groupID, senderID, username := strconv.Itoa(chat.ID), strconv.Itoa(sender.ID), sender.Username j.db.View(func(tx *bolt.Tx) error { b := tx.Bucket(group_usernames_bucket_name) gb := b.Bucket([]byte(groupID)) if gb == nil { return nil } v := gb.Get([]byte(senderID)) if v != nil && string(v) == username { res = true return nil } return nil }) return res }
// getAllUsernamesForChat returns all usernames for a chat, sans the sender's. func (j *JarvisBot) getAllUsernamesForChat(chat, sender *telebot.User) (string, error) { uArray, groupID, senderID := []string{}, strconv.Itoa(chat.ID), strconv.Itoa(sender.ID) if !chat.IsGroupChat() { return "", fmt.Errorf("chat %s is not a group chat!", groupID) } err := j.db.View(func(tx *bolt.Tx) error { b := tx.Bucket(group_usernames_bucket_name) gb := b.Bucket([]byte(groupID)) if gb == nil { return fmt.Errorf("error retrieving bucket for group ID %s", groupID) } gb.ForEach(func(k, v []byte) error { key, curr := string(k), string(v) if key != senderID && key != timestampKey && key != countKey { uArray = append(uArray, curr) } return nil }) return nil }) if err != nil { return "", err } res := "" for _, v := range uArray { res = res + "@" + v + " " } return res, nil }
// saveUsernameSafely checks if a user exists in a given group chat, and saves if he/she // doesn't currently exist. // We try as much as possible to avoid opening a Read-Write transaction, because // Bolt can only have one Read-Write transaction at any time. func (j *JarvisBot) saveUsernameSafely(chat, sender *telebot.User) { if sender.Username == "" || !chat.IsGroupChat() { return } if !j.usernameExistsForChat(chat, sender) { err := j.saveUserToDB(chat, sender) if err != nil { j.log.Printf("[%s] error saving user %s to group %s: %s", time.Now().Format(time.RFC3339), sender.Username, chat.Title, err) } } }
// updateLastSentTime updates the last sent time for a given chat. func (j *JarvisBot) updateLastSentTime(chat *telebot.User) error { if !chat.IsGroupChat() { return fmt.Errorf("chat is not a group chat!") } groupID := strconv.Itoa(chat.ID) err := j.db.Update(func(tx *bolt.Tx) error { b := tx.Bucket(group_usernames_bucket_name) gb := b.Bucket([]byte(groupID)) if gb == nil { return fmt.Errorf("invariant error - group bucket does not exist, yet attempt to update timestamp") } timeString := gb.Get([]byte(timestampKey)) if timeString == nil { return resetTime(gb) } else { lastTime, err := time.Parse(time.RFC3339, string(timeString)) if err != nil { return err } if time.Since(lastTime) > time.Hour { return resetTime(gb) } else { countBytes := gb.Get([]byte(countKey)) if countBytes == nil { return fmt.Errorf("invariant error - timestamp was saved but no count exists") } lastCount, err := strconv.Atoi(string(countBytes)) if err != nil { return err } newCount := strconv.Itoa(lastCount + 1) err = gb.Put([]byte(countKey), []byte(newCount)) if err != nil { return err } } } return nil }) return err }