diff --git a/internal/lnbits/lnbits.go b/internal/lnbits/lnbits.go index 1419af74..259954bd 100644 --- a/internal/lnbits/lnbits.go +++ b/internal/lnbits/lnbits.go @@ -7,6 +7,20 @@ import ( "github.com/imroc/req" ) +// parseLNbitsError extracts a meaningful error from an LNbits HTTP response. +func parseLNbitsError(resp *req.Resp) Error { + statusCode := resp.Response().StatusCode + rawBody := resp.String() + + var reqErr Error + resp.ToJSON(&reqErr) + reqErr.StatusCode = statusCode + if reqErr.Detail == "" && reqErr.Message == "" { + reqErr.RawBody = rawBody + } + return reqErr +} + // NewClient returns a new lnbits api client. Pass your API key and url here. func NewClient(key, url string) *Client { return &Client{ @@ -31,9 +45,7 @@ func (c *Client) GetUser(userId string) (user User, err error) { } if resp.Response().StatusCode >= 300 { - var reqErr Error - resp.ToJSON(&reqErr) - err = reqErr + err = parseLNbitsError(resp) return } @@ -54,9 +66,7 @@ func (c *Client) CreateUserWithInitialWallet(userName, walletName, adminId strin } if resp.Response().StatusCode >= 300 { - var reqErr Error - resp.ToJSON(&reqErr) - err = reqErr + err = parseLNbitsError(resp) return } err = resp.ToJSON(&wal) @@ -75,9 +85,7 @@ func (c *Client) CreateWallet(userId, walletName, adminId string) (wal Wallet, e } if resp.Response().StatusCode >= 300 { - var reqErr Error - resp.ToJSON(&reqErr) - err = reqErr + err = parseLNbitsError(resp) return } err = resp.ToJSON(&wal) @@ -98,9 +106,7 @@ func (w Wallet) Invoice(params InvoiceParams, c *Client) (lntx Invoice, err erro } if resp.Response().StatusCode >= 300 { - var reqErr Error - resp.ToJSON(&reqErr) - err = reqErr + err = parseLNbitsError(resp) return } @@ -122,9 +128,7 @@ func (c Client) Info(w Wallet) (wtx Wallet, err error) { } if resp.Response().StatusCode >= 300 { - var reqErr Error - resp.ToJSON(&reqErr) - err = reqErr + err = parseLNbitsError(resp) return } @@ -146,9 +150,7 @@ func (c Client) Payments(w Wallet) (wtx Payments, err error) { } if resp.Response().StatusCode >= 300 { - var reqErr Error - resp.ToJSON(&reqErr) - err = reqErr + err = parseLNbitsError(resp) return } @@ -170,9 +172,7 @@ func (c Client) Payment(w Wallet, payment_hash string) (payment LNbitsPayment, e } if resp.Response().StatusCode >= 300 { - var reqErr Error - resp.ToJSON(&reqErr) - err = reqErr + err = parseLNbitsError(resp) return } @@ -188,9 +188,7 @@ func (c Client) Wallets(w User) (wtx []Wallet, err error) { } if resp.Response().StatusCode >= 300 { - var reqErr Error - resp.ToJSON(&reqErr) - err = reqErr + err = parseLNbitsError(resp) return } @@ -214,9 +212,7 @@ func (w Wallet) Pay(params PaymentParams, c *Client) (wtx Invoice, err error) { } if resp.Response().StatusCode >= 300 { - var reqErr Error - resp.ToJSON(&reqErr) - err = reqErr + err = parseLNbitsError(resp) return } diff --git a/internal/lnbits/types.go b/internal/lnbits/types.go index ae14ab60..6cdb15e3 100644 --- a/internal/lnbits/types.go +++ b/internal/lnbits/types.go @@ -111,11 +111,26 @@ type TransferParams struct { } type Error struct { - Detail string `json:"detail"` + Detail string `json:"detail"` + Message string `json:"message"` + StatusCode int `json:"-"` + RawBody string `json:"-"` } func (err Error) Error() string { - return err.Detail + if err.Detail != "" { + return err.Detail + } + if err.Message != "" { + return err.Message + } + if err.RawBody != "" { + return fmt.Sprintf("LNbits HTTP %d: %s", err.StatusCode, err.RawBody) + } + if err.StatusCode != 0 { + return fmt.Sprintf("LNbits HTTP %d: unknown error", err.StatusCode) + } + return "unknown LNbits error" } type Wallet struct { diff --git a/internal/telegram/error_logger.go b/internal/telegram/error_logger.go index ad3fb56a..b2616b74 100644 --- a/internal/telegram/error_logger.go +++ b/internal/telegram/error_logger.go @@ -52,8 +52,11 @@ func (el *ErrorLogger) LogError(err error, context string, userInfo ...interface return } - // Filter out annoying/irrelevant error messages + // Filter out empty/ghost errors and irrelevant messages errorMsg := err.Error() + if errorMsg == "" || errorMsg == `{"message":"","Err":{},"code":0}` { + return // Skip empty/meaningless errors + } if strings.Contains(errorMsg, "[requirePrivateChatInterceptor]") { return // Skip logging this specific interceptor error } diff --git a/main.go b/main.go index 158613cd..ad630248 100644 --- a/main.go +++ b/main.go @@ -50,18 +50,29 @@ func main() { func startApiServer(bot *telegram.TipBot) { // log errors from interceptors bot.Telegram.OnError = func(err error, ctx tb.Context) { + if err == nil { + return + } + + errMsg := err.Error() + + // Filter out empty/ghost errors from telebot (code:0, empty message) + if errMsg == "" || errMsg == `{"message":"","Err":{},"code":0}` { + return + } + // Filter out annoying interceptor errors - if err != nil && strings.Contains(err.Error(), "[requirePrivateChatInterceptor]") { - return // Skip logging this specific error + if strings.Contains(errMsg, "[requirePrivateChatInterceptor]") { + return } // Log errors to Telegram group if bot.ErrorLogger != nil { userInfo := []interface{}{} - if ctx.Sender() != nil { + if ctx != nil && ctx.Sender() != nil { userInfo = append(userInfo, ctx.Sender()) } - if ctx.Chat() != nil { + if ctx != nil && ctx.Chat() != nil { userInfo = append(userInfo, ctx.Chat()) } bot.ErrorLogger.LogError(err, "Telegram Bot Error", userInfo...) @@ -72,6 +83,11 @@ func startApiServer(bot *telegram.TipBot) { // start external api server s := api.NewServer(internal.Configuration.Bot.LNURLServerUrl.Host) + s.AppendRoute("/health", func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + w.Write([]byte("OK")) + }, http.MethodGet) + // append lnurl ctx functions lnUrl := lnurl.New(bot) s.AppendRoute("/.well-known/lnurlp/{username}", lnUrl.Handle, http.MethodGet)