diff --git a/Gopkg.lock b/Gopkg.lock index c87572f..edc0e84 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -144,6 +144,17 @@ pruneopts = "UT" revision = "b3ddf786825de56a4178401b7e174ee332173b66" +[[projects]] + digest = "1:be8d49b32733c83fafd4b8480400857e1964ddbba224b9c9e861f562b75b71aa" + name = "gopkg.in/gographics/imagick.v2" + packages = [ + "imagick", + "imagick/types", + ] + pruneopts = "UT" + revision = "589a8ef16fd4f08a29ad26afe5c33fb5673e4efc" + version = "v2.5.0" + [solve-meta] analyzer-name = "dep" analyzer-version = 1 @@ -157,6 +168,7 @@ "google.golang.org/grpc", "google.golang.org/grpc/credentials", "google.golang.org/grpc/metadata", + "gopkg.in/gographics/imagick.v2/imagick", ] solver-name = "gps-cdcl" solver-version = 1 diff --git a/Makefile b/Makefile index c2ad95c..de511f1 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,9 @@ PKG := github.com/michael1011/lightningtip -GOBUILD := go build -v -GOINSTALL := go install -v +# Enable image support via ImageMagicks MagickWand API. Requires MagickWand C API to be installed +# IMAGICK := -tags imagick +GOBUILD := go build -v ${IMAGICK} +GOINSTALL := go install -v ${IMAGICK} GO_BIN := ${GOPATH}/bin DEP_BIN := $(GO_BIN)/dep diff --git a/README.md b/README.md index 2fc898e..de1216b 100644 --- a/README.md +++ b/README.md @@ -35,10 +35,17 @@ That's it! The only two things you need to take care about is keeping the LND no First of all make sure [Golang](https://golang.org/) and [Dep](https://github.com/golang/dep) are both correctly installed. Golang version 1.10 or newer is recommended. +If you want to return a picture, make sure you install ImageMagick MagickWand C API. For example (Ubuntu/Debian): + +sudo apt-get install libmagickwand-dev + + +To enable it, edit Makefile and enable the line with IMAGICK : = -tags imagick ``` go get -d github.com/michael1011/lightningtip cd $GOPATH/src/github.com/michael1011/lightningtip + make && make install ``` diff --git a/backends/backend.go b/backends/backend.go index 8c551c5..ebe466a 100644 --- a/backends/backend.go +++ b/backends/backend.go @@ -11,7 +11,7 @@ type Backend interface { Connect() error // The amount is denominated in satoshis and the expiry in seconds - GetInvoice(description string, amount int64, expiry int64) (invoice string, rHash string, err error) + GetInvoice(description string, amount int64, expiry int64) (invoice string, rHash string, picture string, err error) InvoiceSettled(rHash string) (settled bool, err error) diff --git a/backends/lnd.go b/backends/lnd.go index 6bb9803..233fd68 100644 --- a/backends/lnd.go +++ b/backends/lnd.go @@ -8,6 +8,7 @@ import ( "io/ioutil" "github.com/lightningnetwork/lnd/lnrpc" + "github.com/michael1011/lightningtip/image" "google.golang.org/grpc" "google.golang.org/grpc/credentials" "google.golang.org/grpc/metadata" @@ -64,7 +65,7 @@ func (lnd *LND) Connect() error { } // GetInvoice gets and invoice from a node -func (lnd *LND) GetInvoice(message string, amount int64, expiry int64) (invoice string, rHash string, err error) { +func (lnd *LND) GetInvoice(message string, amount int64, expiry int64) (invoice string, rHash string, picture string, err error) { var response *lnrpc.AddInvoiceResponse response, err = lnd.client.AddInvoice(lnd.ctx, &lnrpc.Invoice{ @@ -74,10 +75,10 @@ func (lnd *LND) GetInvoice(message string, amount int64, expiry int64) (invoice }) if err != nil { - return "", "", err + return "", "", "", err } - return response.PaymentRequest, hex.EncodeToString(response.RHash), err + return response.PaymentRequest, hex.EncodeToString(response.RHash), image.GetImagePath(hex.EncodeToString(response.RHash)), err } // InvoiceSettled checks if an invoice is settled by looking it up @@ -93,7 +94,7 @@ func (lnd *LND) InvoiceSettled(rHash string) (settled bool, err error) { if err != nil { return false, err } - + _ = image.GenerateImage(hex.EncodeToString(invoice.RHash), invoice.AmtPaid/1000) return invoice.Settled, err } @@ -128,6 +129,8 @@ func (lnd *LND) SubscribeInvoices(publish PublishInvoiceSettled, rescan RescanPe } if invoice.Settled { + _ = image.GenerateImage(hex.EncodeToString(invoice.RHash), invoice.AmtPaid/1000) + log.Debug("Payment request settled: ", invoice.PaymentRequest) go publish(invoice.PaymentRequest) } diff --git a/config.go b/config.go index be012ef..2932baf 100644 --- a/config.go +++ b/config.go @@ -13,6 +13,7 @@ import ( "github.com/jessevdk/go-flags" "github.com/michael1011/lightningtip/backends" "github.com/michael1011/lightningtip/database" + "github.com/michael1011/lightningtip/image" "github.com/michael1011/lightningtip/notifications" "github.com/michael1011/lightningtip/version" "github.com/op/go-logging" @@ -50,6 +51,16 @@ const ( defaultSTMPSSL = false defaultSTMPUser = "" defaultSTMPPassword = "" + + defaultImageDir = "" + defaultImageURLDir = "" + defaultImageFile = "" + defaultImageText = "I paid a random dude {Amount} satoshi\nbut all I got was this picture of his dog" + defaultImageTextX = 25 + defaultImageTextY = 165 + defaultImageTextColor = "black" + defaultImageTextFont = "Verdana-Bold-Italic" + defaultImageTextSize = 150 ) type helpOptions struct { @@ -78,7 +89,8 @@ type config struct { ReconnectInterval int64 `long:"reconnectinterval" description:"Reconnect interval to LND in seconds"` KeepAliveInterval int64 `long:"keepaliveinterval" description:"Send a dummy request to LND to prevent timeouts "` - LND *backends.LND `group:"LND" namespace:"lnd"` + LND *backends.LND `group:"LND" namespace:"lnd"` + Image *image.Image `group:"Image" namespace:"image"` Mail *notifications.Mail `group:"Mail" namespace:"mail"` @@ -117,6 +129,18 @@ func initConfig() { MacaroonFile: getDefaultMacaroon(), }, + Image: &image.Image{ + ImageDir: defaultImageDir, + ImageURLDir: defaultImageURLDir, + ImageFile: defaultImageFile, + ImageText: defaultImageText, + ImageTextX: defaultImageTextX, + ImageTextY: defaultImageTextY, + ImageTextColor: defaultImageTextColor, + ImageTextFont: defaultImageTextFont, + ImageTextSize: defaultImageTextSize, + }, + Mail: ¬ifications.Mail{ Recipient: defaultRecipient, Sender: defaultSender, @@ -133,6 +157,9 @@ func initConfig() { parser.Parse() errFile := flags.IniParse(cfg.ConfigFile, &cfg) + if cfg.Image.ImageDir != "" { + image.SetImageCfg(*cfg.Image) + } // If the user just wants to see the version initializing everything else is irrelevant if cfg.Help.ShowVersion { diff --git a/frontend/lightningTip.js b/frontend/lightningTip.js index 1ec4ce6..72cf935 100644 --- a/frontend/lightningTip.js +++ b/frontend/lightningTip.js @@ -1,6 +1,6 @@ // Edit this variable if you are not running LightningTip on the same domain or IP address as your webserver or not on port 8081 // Don't forget the "/" at the end! -var requestUrl = window.location.protocol + "//" + window.location.hostname + ":8081/"; +var requestUrl = window.location.protocol + "//" + window.location.hostname + "/tiprest/"; // To prohibit multiple requests at the same time var requestPending = false; @@ -69,7 +69,7 @@ function getInvoice() { console.log("Starting listening for invoice to get settled"); - listenInvoiceSettled(json.RHash); + listenInvoiceSettled(json.RHash, json.Picture); invoice = json.Invoice; @@ -135,7 +135,7 @@ function getInvoice() { } -function listenInvoiceSettled(rHash) { +function listenInvoiceSettled(rHash, picture) { try { var eventSrc = new EventSource(requestUrl + "eventsource"); @@ -145,7 +145,7 @@ function listenInvoiceSettled(rHash) { eventSrc.close(); - showThankYouScreen(); + showThankYouScreen(picture); } }; @@ -170,7 +170,7 @@ function listenInvoiceSettled(rHash) { clearInterval(interval); - showThankYouScreen(); + showThankYouScreen(json.Picture); } } @@ -190,11 +190,14 @@ function listenInvoiceSettled(rHash) { } -function showThankYouScreen() { +function showThankYouScreen(picture) { var wrapper = document.getElementById("lightningTip"); wrapper.innerHTML = "
⚡
"; wrapper.innerHTML += "Thank you for your tip!"; + if (picture !== "") { + wrapper.innerHTML += "