lightningtipbot/internal/telegram/users.go
2022-07-26 15:12:01 +02:00

144 lines
4 KiB
Go

package telegram
import (
"errors"
"fmt"
"strings"
"time"
"github.com/LightningTipBot/LightningTipBot/internal/lnbits"
"github.com/LightningTipBot/LightningTipBot/internal/str"
"github.com/eko/gocache/store"
log "github.com/sirupsen/logrus"
tb "gopkg.in/lightningtipbot/telebot.v3"
"gorm.io/gorm"
)
func SetUserState(user *lnbits.User, bot *TipBot, stateKey lnbits.UserStateKey, stateData string) {
user.StateKey = stateKey
user.StateData = stateData
UpdateUserRecord(user, *bot)
}
func ResetUserState(user *lnbits.User, bot *TipBot) {
user.ResetState()
UpdateUserRecord(user, *bot)
}
func GetUserStr(user *tb.User) string {
userStr := fmt.Sprintf("@%s", user.Username)
// if user does not have a username
if len(userStr) < 2 && user.FirstName != "" {
userStr = fmt.Sprintf("%s", user.FirstName)
} else if len(userStr) < 2 {
userStr = fmt.Sprintf("%d", user.ID)
}
return userStr
}
func GetUserStrMd(user *tb.User) string {
userStr := fmt.Sprintf("@%s", user.Username)
// if user does not have a username
if len(userStr) < 2 && user.FirstName != "" {
userStr = fmt.Sprintf("[%s](tg://user?id=%d)", user.FirstName, user.ID)
return userStr
} else if len(userStr) < 2 {
userStr = fmt.Sprintf("[%d](tg://user?id=%d)", user.ID, user.ID)
return userStr
} else {
// escape only if user has a username
return str.MarkdownEscape(userStr)
}
}
func appendUinqueUsersToSlice(slice []*tb.User, i *tb.User) []*tb.User {
for _, ele := range slice {
if ele.ID == i.ID {
return slice
}
}
return append(slice, i)
}
func (bot *TipBot) GetUserBalanceCached(user *lnbits.User) (amount int64, err error) {
u, err := bot.Cache.Get(fmt.Sprintf("%s_balance", user.Name))
if err != nil {
return bot.GetUserBalance(user)
}
cachedBalance := u.(int64)
return cachedBalance, nil
}
func (bot *TipBot) GetUserBalance(user *lnbits.User) (amount int64, err error) {
if user.Wallet == nil {
return 0, errors.New("User has no wallet")
}
wallet, err := bot.Client.Info(*user.Wallet)
if err != nil {
errmsg := fmt.Sprintf("[GetUserBalance] Error: Couldn't fetch user %s's info from LNbits: %s", GetUserStr(user.Telegram), err.Error())
log.Errorln(errmsg)
return
}
user.Wallet.Balance = wallet.Balance
err = UpdateUserRecord(user, *bot)
if err != nil {
return
}
// msat to sat
amount = int64(wallet.Balance) / 1000
log.Debugf("[GetUserBalance] %s's balance: %d sat\n", GetUserStr(user.Telegram), amount)
// update user balance in cache
bot.Cache.Set(
fmt.Sprintf("%s_balance", user.Name),
amount,
&store.Options{Expiration: 1 * time.Hour},
)
return
}
func (bot *TipBot) CreateWalletForTelegramUser(tbUser *tb.User) (*lnbits.User, error) {
// failsafe: do not create wallet for existing user
if _, exists := bot.UserExists(tbUser); exists {
return nil, fmt.Errorf("user already exists")
}
user := &lnbits.User{Telegram: tbUser}
userStr := GetUserStr(tbUser)
log.Printf("[CreateWalletForTelegramUser] Creating wallet for user %s ... ", userStr)
err := bot.createWallet(user)
if err != nil {
errmsg := fmt.Sprintf("[CreateWalletForTelegramUser] Error: Could not create wallet for user %s", userStr)
log.Errorln(errmsg)
return user, err
}
// todo: remove this. we're doing this already in bot.createWallet().
err = UpdateUserRecord(user, *bot)
if err != nil {
return nil, err
}
log.Printf("[CreateWalletForTelegramUser] Wallet created for user %s. ", userStr)
return user, nil
}
func (bot *TipBot) UserExists(user *tb.User) (*lnbits.User, bool) {
lnbitUser, err := GetUser(user, *bot)
if err != nil || errors.Is(err, gorm.ErrRecordNotFound) {
return nil, false
}
return lnbitUser, true
}
func (bot *TipBot) UserIsBanned(user *lnbits.User) bool {
// do not respond to banned users
if user.Wallet == nil {
log.Tracef("[UserIsBanned] User %s has no wallet.\n", GetUserStr(user.Telegram))
return false
}
if strings.HasPrefix(user.Wallet.Adminkey, "banned") || strings.Contains(user.Wallet.Adminkey, "_") {
log.Debugf("[UserIsBanned] User %s is banned. Not responding.", GetUserStr(user.Telegram))
return true
}
return false
}