mirror of
https://github.com/ChuckNorrison/LightningTipBot.git
synced 2026-08-19 13:18:12 +02:00
anonymous user ID for lnurl (#107)
* anonymous user ID for lnurl * anonymous lnurl * migrate at every start, not good * anon id at user creation * migrations file * fix database migration task * remove comment * anon label Co-authored-by: lngohumble <lngohumble@gmail.com>
This commit is contained in:
parent
bb00253122
commit
fd9ad39b0c
10 changed files with 113 additions and 37 deletions
26
internal/database/migrations.go
Normal file
26
internal/database/migrations.go
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
package database
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/LightningTipBot/LightningTipBot/internal/lnbits"
|
||||
"github.com/LightningTipBot/LightningTipBot/internal/str"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func MigrateAnonIdHash(db *gorm.DB) error {
|
||||
users := []lnbits.User{}
|
||||
_ = db.Find(&users)
|
||||
for _, u := range users {
|
||||
log.Info(u.ID, str.Int32Hash(u.ID))
|
||||
u.AnonID = fmt.Sprint(str.Int32Hash(u.ID))
|
||||
tx := db.Save(u)
|
||||
if tx.Error != nil {
|
||||
errmsg := fmt.Sprintf("[MigrateAnonIdHash] Error: Couldn't migrate user %s (%d)", u.Telegram.Username, u.Telegram.ID)
|
||||
log.Errorln(errmsg)
|
||||
return tx.Error
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -24,6 +24,7 @@ type User struct {
|
|||
StateData string `json:"stateData"`
|
||||
CreatedAt time.Time `json:"created"`
|
||||
UpdatedAt time.Time `json:"updated"`
|
||||
AnonID string `jsin:"anonid"`
|
||||
}
|
||||
|
||||
const (
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ func (w Server) serveLNURLpSecond(username string, amount int64, comment string)
|
|||
tx := w.database
|
||||
if err == nil {
|
||||
// asume it's a user ID
|
||||
tx = w.database.Where("telegram_id = ?", fmt.Sprint(id)).First(user)
|
||||
tx = w.database.Where("anon_id = ?", fmt.Sprint(id)).First(user)
|
||||
} else {
|
||||
// assume it's a string @username
|
||||
tx = w.database.Where("telegram_username = ?", strings.ToLower(username)).First(user)
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package str
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"hash/fnv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
|
@ -25,3 +26,15 @@ func MarkdownEscape(s string) string {
|
|||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func Int32Hash(s string) uint32 {
|
||||
h := fnv.New32a()
|
||||
h.Write([]byte(s))
|
||||
return h.Sum32()
|
||||
}
|
||||
|
||||
func Int64Hash(s string) uint64 {
|
||||
h := fnv.New64a()
|
||||
h.Write([]byte(s))
|
||||
return h.Sum64()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@ package telegram
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/LightningTipBot/LightningTipBot/internal"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/LightningTipBot/LightningTipBot/internal"
|
||||
"github.com/LightningTipBot/LightningTipBot/internal/lnbits"
|
||||
"github.com/LightningTipBot/LightningTipBot/internal/storage"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
|
@ -30,7 +30,7 @@ var (
|
|||
// NewBot migrates data and creates a new bot
|
||||
func NewBot() TipBot {
|
||||
// create sqlite databases
|
||||
db, txLogger := migration()
|
||||
db, txLogger := AutoMigration()
|
||||
return TipBot{
|
||||
Database: db,
|
||||
Client: lnbits.NewClient(internal.Configuration.Lnbits.AdminKey, internal.Configuration.Lnbits.Url),
|
||||
|
|
|
|||
|
|
@ -2,14 +2,16 @@ package telegram
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/LightningTipBot/LightningTipBot/internal"
|
||||
"github.com/LightningTipBot/LightningTipBot/internal/storage"
|
||||
"github.com/tidwall/buntdb"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/LightningTipBot/LightningTipBot/internal"
|
||||
"github.com/LightningTipBot/LightningTipBot/internal/database"
|
||||
"github.com/LightningTipBot/LightningTipBot/internal/storage"
|
||||
"github.com/tidwall/buntdb"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/LightningTipBot/LightningTipBot/internal/lnbits"
|
||||
|
|
@ -33,21 +35,41 @@ func createBunt() *storage.DB {
|
|||
}
|
||||
return bunt
|
||||
}
|
||||
func migration() (db *gorm.DB, txLogger *gorm.DB) {
|
||||
txLogger, err := gorm.Open(sqlite.Open(internal.Configuration.Database.TransactionsPath), &gorm.Config{DisableForeignKeyConstraintWhenMigrating: true, FullSaveAssociations: true})
|
||||
if err != nil {
|
||||
panic("Initialize orm failed.")
|
||||
}
|
||||
|
||||
func ColumnMigrationTasks(db *gorm.DB) error {
|
||||
var err error
|
||||
if !db.Migrator().HasColumn(&lnbits.User{}, "anon_id") {
|
||||
// first we need to auto migrate the user. This will create anon_id column
|
||||
err = db.AutoMigrate(&lnbits.User{})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
log.Info("Running ano_id database migrations ...")
|
||||
// run the migration on anon_id
|
||||
err = database.MigrateAnonIdHash(db)
|
||||
}
|
||||
// todo -- add more database field migrations here in the future
|
||||
return err
|
||||
}
|
||||
|
||||
func AutoMigration() (db *gorm.DB, txLogger *gorm.DB) {
|
||||
orm, err := gorm.Open(sqlite.Open(internal.Configuration.Database.DbPath), &gorm.Config{DisableForeignKeyConstraintWhenMigrating: true, FullSaveAssociations: true})
|
||||
if err != nil {
|
||||
panic("Initialize orm failed.")
|
||||
}
|
||||
|
||||
err = ColumnMigrationTasks(orm)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
err = orm.AutoMigrate(&lnbits.User{})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
txLogger, err = gorm.Open(sqlite.Open(internal.Configuration.Database.TransactionsPath), &gorm.Config{DisableForeignKeyConstraintWhenMigrating: true, FullSaveAssociations: true})
|
||||
if err != nil {
|
||||
panic("Initialize orm failed.")
|
||||
}
|
||||
err = txLogger.AutoMigrate(&Transaction{})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
|
@ -93,7 +115,7 @@ func GetUser(u *tb.User, bot TipBot) (*lnbits.User, error) {
|
|||
return user, err
|
||||
}
|
||||
go func() {
|
||||
userCopy := bot.copyLowercaseUser(u)
|
||||
userCopy := bot.CopyLowercaseUser(u)
|
||||
if !reflect.DeepEqual(userCopy, user.Telegram) {
|
||||
// update possibly changed user details in Database
|
||||
user.Telegram = userCopy
|
||||
|
|
@ -107,7 +129,7 @@ func GetUser(u *tb.User, bot TipBot) (*lnbits.User, error) {
|
|||
}
|
||||
|
||||
func UpdateUserRecord(user *lnbits.User, bot TipBot) error {
|
||||
user.Telegram = bot.copyLowercaseUser(user.Telegram)
|
||||
user.Telegram = bot.CopyLowercaseUser(user.Telegram)
|
||||
user.UpdatedAt = time.Now()
|
||||
tx := bot.Database.Save(user)
|
||||
if tx.Error != nil {
|
||||
|
|
|
|||
|
|
@ -8,13 +8,14 @@ import (
|
|||
)
|
||||
|
||||
func (bot TipBot) makeHelpMessage(ctx context.Context, m *tb.Message) string {
|
||||
fromUser := LoadUser(ctx)
|
||||
dynamicHelpMessage := ""
|
||||
// user has no username set
|
||||
if len(m.Sender.Username) == 0 {
|
||||
// return fmt.Sprintf(helpMessage, fmt.Sprintf("%s\n\n", helpNoUsernameMessage))
|
||||
dynamicHelpMessage = dynamicHelpMessage + "\n" + Translate(ctx, "helpNoUsernameMessage")
|
||||
}
|
||||
lnaddr, _ := bot.UserGetLightningAddress(m.Sender)
|
||||
lnaddr, _ := bot.UserGetLightningAddress(fromUser)
|
||||
if len(lnaddr) > 0 {
|
||||
dynamicHelpMessage = dynamicHelpMessage + "\n" + fmt.Sprintf(Translate(ctx, "infoYourLightningAddress"), lnaddr)
|
||||
}
|
||||
|
|
@ -48,18 +49,19 @@ func (bot TipBot) basicsHandler(ctx context.Context, m *tb.Message) {
|
|||
}
|
||||
|
||||
func (bot TipBot) makeAdvancedHelpMessage(ctx context.Context, m *tb.Message) string {
|
||||
|
||||
fromUser := LoadUser(ctx)
|
||||
dynamicHelpMessage := "ℹ️ *Info*\n"
|
||||
// user has no username set
|
||||
if len(m.Sender.Username) == 0 {
|
||||
// return fmt.Sprintf(helpMessage, fmt.Sprintf("%s\n\n", helpNoUsernameMessage))
|
||||
dynamicHelpMessage = dynamicHelpMessage + fmt.Sprintf("%s", Translate(ctx, "helpNoUsernameMessage")) + "\n"
|
||||
}
|
||||
lnaddr, err := bot.UserGetLightningAddress(m.Sender)
|
||||
// we print the anonymous ln address in the advanced help
|
||||
lnaddr, err := bot.UserGetAnonLightningAddress(fromUser)
|
||||
if err == nil {
|
||||
dynamicHelpMessage = dynamicHelpMessage + fmt.Sprintf("Lightning Address: `%s`\n", lnaddr)
|
||||
dynamicHelpMessage = dynamicHelpMessage + fmt.Sprintf("Anonymous lightning address: `%s`\n", lnaddr)
|
||||
}
|
||||
lnurl, err := UserGetLNURL(m.Sender)
|
||||
lnurl, err := UserGetLNURL(fromUser)
|
||||
if err == nil {
|
||||
dynamicHelpMessage = dynamicHelpMessage + fmt.Sprintf("LNURL: `%s`", lnurl)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -114,23 +114,30 @@ func (bot TipBot) lnurlHandler(ctx context.Context, m *tb.Message) {
|
|||
}
|
||||
}
|
||||
|
||||
func (bot *TipBot) UserGetLightningAddress(user *tb.User) (string, error) {
|
||||
if len(user.Username) > 0 {
|
||||
return fmt.Sprintf("%s@%s", strings.ToLower(user.Username), strings.ToLower(internal.Configuration.Bot.LNURLHostUrl.Hostname())), nil
|
||||
func (bot *TipBot) UserGetLightningAddress(user *lnbits.User) (string, error) {
|
||||
if len(user.Telegram.Username) > 0 {
|
||||
return fmt.Sprintf("%s@%s", strings.ToLower(user.Telegram.Username), strings.ToLower(internal.Configuration.Bot.LNURLHostUrl.Hostname())), nil
|
||||
} else {
|
||||
return fmt.Sprintf("%s@%s", fmt.Sprint(user.ID), strings.ToLower(internal.Configuration.Bot.LNURLHostUrl.Hostname())), nil
|
||||
// return "", fmt.Errorf("user has no username")
|
||||
lnaddr, err := bot.UserGetAnonLightningAddress(user)
|
||||
return lnaddr, err
|
||||
}
|
||||
}
|
||||
|
||||
func UserGetLNURL(user *tb.User) (string, error) {
|
||||
name := strings.ToLower(strings.ToLower(user.Username))
|
||||
if len(name) == 0 {
|
||||
name = fmt.Sprint(user.ID)
|
||||
// return "", fmt.Errorf("user has no username.")
|
||||
}
|
||||
func (bot *TipBot) UserGetAnonLightningAddress(user *lnbits.User) (string, error) {
|
||||
return fmt.Sprintf("%s@%s", fmt.Sprint(user.AnonID), strings.ToLower(internal.Configuration.Bot.LNURLHostUrl.Hostname())), nil
|
||||
}
|
||||
|
||||
func UserGetLNURL(user *lnbits.User) (string, error) {
|
||||
// before: we used the username for the LNURL
|
||||
// name := strings.ToLower(strings.ToLower(user.Telegram.Username))
|
||||
// if len(name) == 0 {
|
||||
// name = fmt.Sprint(user.AnonID)
|
||||
// // return "", fmt.Errorf("user has no username.")
|
||||
// }
|
||||
// now: use only the anon ID as LNURL
|
||||
name := fmt.Sprint(user.AnonID)
|
||||
callback := fmt.Sprintf("%s/.well-known/lnurlp/%s", internal.Configuration.Bot.LNURLHostName, name)
|
||||
log.Debugf("[lnurlReceiveHandler] %s's LNURL: %s", GetUserStr(user), callback)
|
||||
log.Debugf("[lnurlReceiveHandler] %s's LNURL: %s", GetUserStr(user.Telegram), callback)
|
||||
|
||||
lnurlEncode, err := lnurl.LNURLEncode(callback)
|
||||
if err != nil {
|
||||
|
|
@ -141,7 +148,8 @@ func UserGetLNURL(user *tb.User) (string, error) {
|
|||
|
||||
// lnurlReceiveHandler outputs the LNURL of the user
|
||||
func (bot TipBot) lnurlReceiveHandler(ctx context.Context, m *tb.Message) {
|
||||
lnurlEncode, err := UserGetLNURL(m.Sender)
|
||||
fromUser := LoadUser(ctx)
|
||||
lnurlEncode, err := UserGetLNURL(fromUser)
|
||||
if err != nil {
|
||||
errmsg := fmt.Sprintf("[lnurlReceiveHandler] Failed to get LNURL: %s", err)
|
||||
log.Errorln(errmsg)
|
||||
|
|
|
|||
|
|
@ -4,13 +4,15 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/LightningTipBot/LightningTipBot/internal"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/LightningTipBot/LightningTipBot/internal"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/LightningTipBot/LightningTipBot/internal/lnbits"
|
||||
"github.com/LightningTipBot/LightningTipBot/internal/str"
|
||||
tb "gopkg.in/tucnak/telebot.v2"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
|
@ -97,6 +99,7 @@ func (bot TipBot) createWallet(user *lnbits.User) error {
|
|||
return err
|
||||
}
|
||||
user.Wallet = &wallet[0]
|
||||
user.AnonID = fmt.Sprint(str.Int32Hash(user.ID))
|
||||
user.Initialized = false
|
||||
user.CreatedAt = time.Now()
|
||||
err = UpdateUserRecord(user, bot)
|
||||
|
|
|
|||
|
|
@ -3,9 +3,10 @@ package telegram
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/LightningTipBot/LightningTipBot/internal/str"
|
||||
"strings"
|
||||
|
||||
"github.com/LightningTipBot/LightningTipBot/internal/str"
|
||||
|
||||
"github.com/LightningTipBot/LightningTipBot/internal/lnbits"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
|
|
@ -78,15 +79,15 @@ func (bot *TipBot) GetUserBalance(user *lnbits.User) (amount int, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
// copyLowercaseUser will create a coy user and cast username to lowercase.
|
||||
func (bot *TipBot) copyLowercaseUser(u *tb.User) *tb.User {
|
||||
// CopyLowercaseUser will create a coy user and cast username to lowercase.
|
||||
func (bot *TipBot) CopyLowercaseUser(u *tb.User) *tb.User {
|
||||
userCopy := *u
|
||||
userCopy.Username = strings.ToLower(u.Username)
|
||||
return &userCopy
|
||||
}
|
||||
|
||||
func (bot *TipBot) CreateWalletForTelegramUser(tbUser *tb.User) (*lnbits.User, error) {
|
||||
userCopy := bot.copyLowercaseUser(tbUser)
|
||||
userCopy := bot.CopyLowercaseUser(tbUser)
|
||||
user := &lnbits.User{Telegram: userCopy}
|
||||
userStr := GetUserStr(tbUser)
|
||||
log.Printf("[CreateWalletForTelegramUser] Creating wallet for user %s ... ", userStr)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue