2021-10-07 00:21:21 +03:00
package webhook
import (
"encoding/json"
"fmt"
2021-11-15 10:18:57 +01:00
"time"
2021-10-07 00:21:21 +03:00
"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"
2021-11-15 10:18:57 +01:00
"net/http"
2021-10-07 00:21:21 +03:00
"github.com/LightningTipBot/LightningTipBot/internal/storage"
"github.com/gorilla/mux"
2022-03-27 22:19:38 +02:00
tb "gopkg.in/lightningtipbot/telebot.v3"
2021-10-07 00:21:21 +03:00
"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 {
2021-12-19 14:41:01 +00:00
CheckingID string ` json:"checking_id" `
2021-12-22 02:35:00 +01:00
Pending bool ` json:"pending" `
Amount int64 ` json:"amount" `
Fee int64 ` json:"fee" `
2021-12-19 14:41:01 +00:00
Memo string ` json:"memo" `
2021-12-22 02:35:00 +01:00
Time int64 ` json:"time" `
2021-12-19 14:41:01 +00:00
Bolt11 string ` json:"bolt11" `
Preimage string ` json:"preimage" `
PaymentHash string ` json:"payment_hash" `
Extra struct { } ` json:"extra" `
2021-10-07 00:21:21 +03:00
WalletID string ` json:"wallet_id" `
Webhook string ` json:"webhook" `
WebhookStatus interface { } ` json:"webhook_status" `
}
func NewServer ( bot * telegram . TipBot ) * Server {
srv := & http . Server {
2021-12-19 14:41:01 +00:00
Addr : internal . Configuration . Lnbits . WebhookServerUrl . Host ,
2021-10-07 00:21:21 +03:00
WriteTimeout : 15 * time . Second ,
ReadTimeout : 15 * time . Second ,
}
apiServer := & Server {
c : bot . Client ,
2022-04-29 14:28:12 +02:00
database : bot . DB . Users ,
2021-10-07 00:21:21 +03:00
bot : bot . Telegram ,
httpServer : srv ,
buntdb : bot . Bunt ,
}
apiServer . httpServer . Handler = apiServer . newRouter ( )
go apiServer . httpServer . ListenAndServe ( )
log . Infof ( "[Webhook] Server started at %s" , internal . Configuration . Lnbits . WebhookServerUrl )
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
}
2021-12-19 14:41:01 +00:00
func ( w * Server ) receive ( writer http . ResponseWriter , request * http . Request ) {
2021-12-22 02:35:00 +01:00
log . Debugln ( "[Webhook] Received request" )
2021-12-19 14:41:01 +00:00
webhookEvent := Webhook { }
2021-10-07 00:21:21 +03:00
// need to delete the header otherwise the Decode will fail
request . Header . Del ( "content-length" )
2021-12-19 14:41:01 +00:00
err := json . NewDecoder ( request . Body ) . Decode ( & webhookEvent )
2021-10-07 00:21:21 +03:00
if err != nil {
2021-12-24 15:34:17 +01:00
log . Errorf ( "[Webhook] Error decoding request: %s" , err . Error ( ) )
2021-10-07 00:21:21 +03:00
writer . WriteHeader ( 400 )
return
}
2021-12-19 14:41:01 +00:00
user , err := w . GetUserByWalletId ( webhookEvent . WalletID )
2021-10-07 00:21:21 +03:00
if err != nil {
2021-12-24 15:34:17 +01:00
log . Errorf ( "[Webhook] Error getting user: %s" , err . Error ( ) )
2021-10-07 00:21:21 +03:00
writer . WriteHeader ( 400 )
return
}
2021-12-19 14:41:01 +00:00
log . Infoln ( fmt . Sprintf ( "[⚡️ WebHook] User %s (%d) received invoice of %d sat." , telegram . GetUserStr ( user . Telegram ) , user . Telegram . ID , webhookEvent . Amount / 1000 ) )
2021-12-17 20:41:13 +00:00
writer . WriteHeader ( 200 )
// trigger invoice events
2021-12-19 14:41:01 +00:00
txInvoiceEvent := & telegram . InvoiceEvent { Invoice : & telegram . Invoice { PaymentHash : webhookEvent . PaymentHash } }
2021-12-17 20:41:13 +00:00
err = w . buntdb . Get ( txInvoiceEvent )
if err != nil {
log . Errorln ( err )
} else {
// do something with the event
2022-03-17 00:21:28 +01:00
if c := telegram . InvoiceCallback [ txInvoiceEvent . Callback ] ; c . Function != nil {
if err := telegram . AssertEventType ( txInvoiceEvent , c . Type ) ; err != nil {
log . Errorln ( err )
return
}
c . Function ( txInvoiceEvent )
2021-12-17 20:41:13 +00:00
return
}
}
2021-12-19 14:41:01 +00:00
// 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 ) )
2021-10-07 00:21:21 +03:00
if err != nil {
log . Errorln ( err )
}
}