This commit is contained in:
callebtc 2022-02-09 11:09:27 +01:00
parent afcbca28f2
commit 1d510fca45
5 changed files with 182 additions and 1 deletions

3
go.mod
View file

@ -20,7 +20,8 @@ require (
github.com/sirupsen/logrus v1.6.0
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
github.com/tidwall/buntdb v1.2.7
github.com/tidwall/gjson v1.10.2
github.com/tidwall/gjson v1.12.1
github.com/tidwall/sjson v1.2.4 // indirect
golang.org/x/text v0.3.5
golang.org/x/time v0.0.0-20191024005414-555d28b269f0
gopkg.in/lightningtipbot/telebot.v2 v2.4.2-0.20211217193303-c005cce171ac

4
go.sum
View file

@ -508,6 +508,8 @@ github.com/tidwall/gjson v1.6.1 h1:LRbvNuNuvAiISWg6gxLEFuCe72UKy5hDqhxW/8183ws=
github.com/tidwall/gjson v1.6.1/go.mod h1:BaHyNc5bjzYkPqgLq7mdVzeiRtULKULXLgZFKsxEHI0=
github.com/tidwall/gjson v1.10.2 h1:APbLGOM0rrEkd8WBw9C24nllro4ajFuJu0Sc9hRz8Bo=
github.com/tidwall/gjson v1.10.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/gjson v1.12.1 h1:ikuZsLdhr8Ws0IdROXUS1Gi4v9Z4pGqpX/CvJkxvfpo=
github.com/tidwall/gjson v1.12.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/grect v0.1.3 h1:z9YwQAMUxVSBde3b7Sl8Da37rffgNfZ6Fq6h9t6KdXE=
github.com/tidwall/grect v0.1.3/go.mod h1:8GMjwh3gPZVpLBI/jDz9uslCe0dpxRpWDdtN0lWAS/E=
github.com/tidwall/lotsa v1.0.2 h1:dNVBH5MErdaQ/xd9s769R31/n2dXavsQ0Yf4TMEHHw8=
@ -523,6 +525,8 @@ github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/rtred v0.1.2 h1:exmoQtOLvDoO8ud++6LwVsAMTu0KPzLTUrMln8u1yu8=
github.com/tidwall/rtred v0.1.2/go.mod h1:hd69WNXQ5RP9vHd7dqekAz+RIdtfBogmglkZSRxCHFQ=
github.com/tidwall/sjson v1.2.4 h1:cuiLzLnaMeBhRmEv00Lpk3tkYrcxpmbU81tAY4Dw0tc=
github.com/tidwall/sjson v1.2.4/go.mod h1:098SZ494YoMWPmMO6ct4dcFnqxwj9r/gF0Etp19pSNM=
github.com/tidwall/tinyqueue v0.1.1 h1:SpNEvEggbpyN5DIReaJ2/1ndroY8iyEGxPYxoSaymYE=
github.com/tidwall/tinyqueue v0.1.1/go.mod h1:O/QNHwrnjqr6IHItYrzoHAKYhBkLI67Q096fQP5zMYw=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=

View file

@ -0,0 +1,129 @@
package satdress
import (
"bytes"
"crypto/tls"
"crypto/x509"
"encoding/base64"
"encoding/hex"
"errors"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"strings"
"time"
"github.com/tidwall/gjson"
"github.com/tidwall/sjson"
)
// from github.com/fiatjaf/makeinvoice
var TorProxyURL = "socks5://127.0.0.1:9050"
var Client = &http.Client{
Timeout: 10 * time.Second,
}
type LNDParams struct {
Cert string
Host string
Macaroon string
}
func (l LNDParams) getCert() string { return l.Cert }
func (l LNDParams) isTor() bool { return strings.Index(l.Host, ".onion") != -1 }
type BackendParams interface {
getCert() string
isTor() bool
}
type Params struct {
Backend BackendParams
Msatoshi int64
Description string
DescriptionHash []byte
Label string // only used for c-lightning
}
func GetInvoice(params Params) (string, error) {
defer func(prevTransport http.RoundTripper) {
Client.Transport = prevTransport
}(Client.Transport)
specialTransport := &http.Transport{}
// use a cert or skip TLS verification?
if params.Backend.getCert() != "" {
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM([]byte(params.Backend.getCert()))
specialTransport.TLSClientConfig = &tls.Config{RootCAs: caCertPool}
} else {
specialTransport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
}
// use a tor proxy?
if params.Backend.isTor() {
torURL, _ := url.Parse(TorProxyURL)
specialTransport.Proxy = http.ProxyURL(torURL)
}
Client.Transport = specialTransport
// description hash?
var _, b64h string
if params.DescriptionHash != nil {
_ = hex.EncodeToString(params.DescriptionHash)
b64h = base64.StdEncoding.EncodeToString(params.DescriptionHash)
}
switch backend := params.Backend.(type) {
case LNDParams:
body, _ := sjson.Set("{}", "value_msat", params.Msatoshi)
if params.DescriptionHash == nil {
body, _ = sjson.Set(body, "memo", params.Description)
} else {
body, _ = sjson.Set(body, "description_hash", b64h)
}
req, err := http.NewRequest("POST",
backend.Host+"/v1/invoices",
bytes.NewBufferString(body),
)
if err != nil {
return "", err
}
// macaroon must be hex, so if it is on base64 we adjust that
if b, err := base64.StdEncoding.DecodeString(backend.Macaroon); err == nil {
backend.Macaroon = hex.EncodeToString(b)
}
req.Header.Set("Grpc-Metadata-macaroon", backend.Macaroon)
resp, err := Client.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
if resp.StatusCode >= 300 {
body, _ := ioutil.ReadAll(resp.Body)
text := string(body)
if len(text) > 300 {
text = text[:300]
}
return "", fmt.Errorf("call to lnd failed (%d): %s", resp.StatusCode, text)
}
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", err
}
return gjson.ParseBytes(b).Get("payment_request").String(), nil
}
return "", errors.New("missing backend params")
}

View file

@ -168,6 +168,22 @@ func (bot TipBot) getHandler() []Handler {
},
},
},
{
Endpoints: []interface{}{"/inv"},
Handler: bot.invHandler,
Interceptor: &Interceptor{
Type: MessageInterceptor,
Before: []intercept.Func{
bot.localizerInterceptor,
bot.logMessageInterceptor,
bot.requireUserInterceptor,
bot.lockInterceptor,
},
OnDefer: []intercept.Func{
bot.unlockInterceptor,
},
},
},
{
Endpoints: []interface{}{"/shops"},
Handler: bot.shopsHandler,

View file

@ -8,6 +8,7 @@ import (
"time"
"github.com/LightningTipBot/LightningTipBot/internal/errors"
"github.com/LightningTipBot/LightningTipBot/internal/satdress"
"github.com/LightningTipBot/LightningTipBot/internal"
@ -200,3 +201,33 @@ func (bot *TipBot) lnurlReceiveEvent(invoiceEvent *InvoiceEvent) {
}
}
}
// TODO -- move somewhere else
func (bot *TipBot) invHandler(ctx context.Context, m *tb.Message) (context.Context, error) {
// check and print all commands
bot.anyTextHandler(ctx, m)
user := LoadUser(ctx)
if user.Wallet == nil {
return ctx, errors.Create(errors.UserNoWalletError)
}
// get invoice from user node
pr, err := satdress.GetInvoice(
satdress.Params{
Backend: satdress.LNDParams{
Cert: "2d2d2d2d2d424547494e2043455254494649434154452d2d2d2d2d0a4d494943496a4343416369674177494241674952414f68774131694b486b4d704b3654734a797836794b4177436759494b6f5a497a6a3045417749774d4445660a4d4230474131554543684d576247356b494746316447396e5a57356c636d46305a575167593256796444454e4d4173474131554541784d455a4746325a5441650a467730794d5445794d4463794d6a51314d544e61467730794d7a41794d4445794d6a51314d544e614d444178487a416442674e5642416f54466d78755a4342680a645852765a3256755a584a686447566b49474e6c636e51784454414c42674e5642414d5442475268646d55775754415442676371686b6a4f50514942426767710a686b6a4f50514d4242774e4341415350514146462f586838655666496d43414f7a6a456d57596d2f736470632b616a535a50654245333342305369787a3433350a30427976344e317033396d54527a4f783848647332777562326e6d505958636d2b6263506f3448434d49472f4d41344741315564447745422f775145417749430a7044415442674e56485355454444414b4267677242674546425163444154415042674e5648524d4241663845425441444151482f4d42304741315564446751570a424254734732594c32666a6744467954366c2b474f777671762b38634d44426f42674e5648524545595442666767526b59585a6c67676c7362324e68624768760a6333534342475268646d574344584276624746794c5734794c575268646d57434248567561586943436e56756158687759574e725a58534342324a315a6d4e760a626d36484248384141414748454141414141414141414141414141414141414141414748424b775741415977436759494b6f5a497a6a304541774944534141770a52514968414f6437436c716e4a3258735571716b5953756e4937777147736e4b596d57334668353045765877775a44394169424e4c6e575a4342416a343664780a726f5a392f435563595a78754756432f6d666b2b38325a2b5073777977413d3d0a2d2d2d2d2d454e442043455254494649434154452d2d2d2d2d0a",
Host: "https://127.0.0.1:8082",
Macaroon: "AgEDbG5kAlgDChBdAmYXLaSkDZ+jUNXkXedBEgEwGhYKB2FkZHJlc3MSBHJlYWQSBXdyaXRlGhcKCGludm9pY2VzEgRyZWFkEgV3cml0ZRoPCgdvbmNoYWluEgRyZWFkAAAGIBevooGKO6xo8c0Q2fj14DYYx95b+jah0rfMj+JJ6pf3",
},
Msatoshi: 1000,
},
)
if err != nil {
log.Errorln(err.Error())
return ctx, err
}
log.Infof(pr)
return ctx, nil
}