mirror of
https://github.com/ChuckNorrison/LightningTipBot.git
synced 2026-08-13 12:33:14 +02:00
160 lines
4.7 KiB
Go
160 lines
4.7 KiB
Go
package webhook
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/LightningTipBot/LightningTipBot/internal"
|
|
"github.com/LightningTipBot/LightningTipBot/internal/lnbits"
|
|
"github.com/LightningTipBot/LightningTipBot/internal/telegram"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
"gorm.io/gorm"
|
|
|
|
"net/http"
|
|
|
|
"github.com/LightningTipBot/LightningTipBot/internal/storage"
|
|
|
|
"github.com/gorilla/mux"
|
|
tb "gopkg.in/lightningtipbot/telebot.v3"
|
|
|
|
"github.com/LightningTipBot/LightningTipBot/internal/i18n"
|
|
)
|
|
|
|
type Server struct {
|
|
httpServer *http.Server
|
|
bot *tb.Bot
|
|
c *lnbits.Client
|
|
database *gorm.DB
|
|
buntdb *storage.DB
|
|
}
|
|
|
|
type Webhook struct {
|
|
CheckingID string `json:"checking_id"`
|
|
Pending int `json:"pending"`
|
|
Amount int64 `json:"amount"`
|
|
Fee int64 `json:"fee"`
|
|
Memo string `json:"memo"`
|
|
Time int64 `json:"time"`
|
|
Bolt11 string `json:"bolt11"`
|
|
Preimage string `json:"preimage"`
|
|
PaymentHash string `json:"payment_hash"`
|
|
Extra struct{} `json:"extra"`
|
|
WalletID string `json:"wallet_id"`
|
|
Webhook string `json:"webhook"`
|
|
WebhookStatus interface{} `json:"webhook_status"`
|
|
}
|
|
|
|
func NewServer(bot *telegram.TipBot) *Server {
|
|
srv := &http.Server{
|
|
Addr: "0.0.0.0:5588",
|
|
WriteTimeout: 15 * time.Second,
|
|
ReadTimeout: 15 * time.Second,
|
|
}
|
|
apiServer := &Server{
|
|
c: bot.Client,
|
|
database: bot.DB.Users,
|
|
bot: bot.Telegram,
|
|
httpServer: srv,
|
|
buntdb: bot.Bunt,
|
|
}
|
|
apiServer.httpServer.Handler = apiServer.newRouter()
|
|
go apiServer.httpServer.ListenAndServe()
|
|
log.WithFields(log.Fields{
|
|
"module": "lnbits",
|
|
"func": "NewServer", "host": internal.Configuration.Lnbits.WebhookServerUrl.String()}).Infof("started webhook server")
|
|
return apiServer
|
|
}
|
|
|
|
func (w *Server) GetUserByWalletId(walletId string) (*lnbits.User, error) {
|
|
user := &lnbits.User{}
|
|
tx := w.database.Where("wallet_id = ?", walletId).First(user)
|
|
if tx.Error != nil {
|
|
return user, tx.Error
|
|
}
|
|
return user, nil
|
|
}
|
|
|
|
func (w *Server) newRouter() *mux.Router {
|
|
router := mux.NewRouter()
|
|
router.HandleFunc("/", w.receive).Methods(http.MethodPost)
|
|
return router
|
|
}
|
|
|
|
func (w *Server) receive(writer http.ResponseWriter, request *http.Request) {
|
|
log.WithFields(log.Fields{
|
|
"module": "webhook",
|
|
"func": "receive"}).Debugln("Received request")
|
|
webhookEvent := Webhook{}
|
|
// need to delete the header otherwise the Decode will fail
|
|
request.Header.Del("content-length")
|
|
err := json.NewDecoder(request.Body).Decode(&webhookEvent)
|
|
if err != nil {
|
|
log.WithFields(log.Fields{
|
|
"module": "webhook",
|
|
"func": "receive",
|
|
"error": err.Error()}).Errorf("Error decoding request")
|
|
writer.WriteHeader(400)
|
|
return
|
|
}
|
|
user, err := w.GetUserByWalletId(webhookEvent.WalletID)
|
|
if err != nil {
|
|
log.WithFields(log.Fields{
|
|
"module": "webhook",
|
|
"func": "receive",
|
|
"error": err.Error()}).Errorf("Error getting user")
|
|
writer.WriteHeader(400)
|
|
return
|
|
}
|
|
amount := webhookEvent.Amount / 1000
|
|
log.WithFields(log.Fields{
|
|
"module": "webhook",
|
|
"func": "receive",
|
|
"user": user.GetUserStr(),
|
|
"telegram_id": user.Telegram.ID,
|
|
"amount": amount}).Infoln(fmt.Sprintf("User received invoice"))
|
|
|
|
writer.WriteHeader(200)
|
|
|
|
// trigger invoice events
|
|
txInvoiceEvent := &telegram.InvoiceEvent{Invoice: &telegram.Invoice{PaymentHash: webhookEvent.PaymentHash}}
|
|
err = w.buntdb.Get(txInvoiceEvent)
|
|
if err != nil {
|
|
log.WithFields(log.Fields{
|
|
"module": "webhook",
|
|
"func": "receive",
|
|
"user": user.GetUserStr(),
|
|
"telegram_id": user.Telegram.ID,
|
|
"error": err.Error(),
|
|
"amount": amount}).Errorln(err)
|
|
} else {
|
|
// do something with the event
|
|
if c := telegram.InvoiceCallback[txInvoiceEvent.Callback]; c.Function != nil {
|
|
if err := telegram.AssertEventType(txInvoiceEvent, c.Type); err != nil {
|
|
log.WithFields(log.Fields{
|
|
"module": "webhook",
|
|
"func": "receive",
|
|
"user": user.GetUserStr(),
|
|
"telegram_id": user.Telegram.ID,
|
|
"error": err.Error(),
|
|
"amount": amount}).Errorln("invalid event type")
|
|
return
|
|
}
|
|
go c.Function(txInvoiceEvent)
|
|
return
|
|
}
|
|
}
|
|
|
|
// fallback: send a message to the user if there is no callback for this invoice
|
|
_, err = w.bot.Send(user.Telegram, fmt.Sprintf(i18n.Translate(user.Telegram.LanguageCode, "invoiceReceivedMessage"), webhookEvent.Amount/1000))
|
|
if err != nil {
|
|
log.WithFields(log.Fields{
|
|
"module": "webhook",
|
|
"func": "receive",
|
|
"user": user.GetUserStr(),
|
|
"telegram_id": user.Telegram.ID,
|
|
"error": err.Error(),
|
|
"amount": amount}).Errorln("could not send fallback message")
|
|
}
|
|
}
|