From 890448ce81f4db8e2eeed8205221ea000019bce7 Mon Sep 17 00:00:00 2001 From: callebtc <93376500+callebtc@users.noreply.github.com> Date: Tue, 30 Aug 2022 17:16:38 +0200 Subject: [PATCH] ux --- internal/lnbits/types.go | 1 + internal/telegram/generate.go | 71 ++++++++++++++++++++++++++++++----- internal/telegram/state.go | 1 + translations/en.toml | 8 +++- 4 files changed, 71 insertions(+), 10 deletions(-) diff --git a/internal/lnbits/types.go b/internal/lnbits/types.go index 770359a..52fa7a9 100644 --- a/internal/lnbits/types.go +++ b/internal/lnbits/types.go @@ -65,6 +65,7 @@ const ( UserStateShopItemSendPrice UserStateShopItemSendItemFile UserEnterShopsDescription + UserEnterDallePrompt ) type UserStateKey int diff --git a/internal/telegram/generate.go b/internal/telegram/generate.go index 50cb27f..81cef2e 100644 --- a/internal/telegram/generate.go +++ b/internal/telegram/generate.go @@ -4,31 +4,81 @@ import ( "bytes" "context" "fmt" + "io" + "os" + "strings" + "time" + "github.com/LightningTipBot/LightningTipBot/internal/dalle" + "github.com/LightningTipBot/LightningTipBot/internal/lnbits" "github.com/LightningTipBot/LightningTipBot/internal/runtime" "github.com/LightningTipBot/LightningTipBot/internal/telegram/intercept" log "github.com/sirupsen/logrus" "github.com/skip2/go-qrcode" tb "gopkg.in/lightningtipbot/telebot.v3" - "io" - "os" - "time" ) +const DALLE2PRICE = 100 // satoshis + +// generateImages is called when the user enters /generate or /generate +// asks the user for a prompt if not given func (bot *TipBot) generateImages(ctx intercept.Context) (intercept.Context, error) { user := LoadUser(ctx) if user.Wallet == nil { return ctx, fmt.Errorf("user has no wallet") } + + if len(strings.Split(ctx.Message().Text, " ")) < 2 { + // We need to save the pay state in the user state so we can load the payment in the next handler + SetUserState(user, bot, lnbits.UserEnterDallePrompt, "") + bot.trySendMessage(ctx.Message().Sender, "⌨️ Enter image prompt.", tb.ForceReply) + return ctx, nil + } + // write the prompt into the command and call confirm + m := ctx.Message() + m.Text = GetMemoFromCommand(m.Text, 1) + return bot.confirmGenerateImages(ctx) +} + +// confirmGenerateImages is called when the user has entered a prompt through /generate +// or because he answered to the request to enter it in generateImages() +// confirmGenerateImages will create an invoice that the user can pay and if they pay +// generateDalleImages will fetch the images and send it to the user +func (bot *TipBot) confirmGenerateImages(ctx intercept.Context) (intercept.Context, error) { + user := LoadUser(ctx) + + ResetUserState(user, bot) + m := ctx.Message() + prompt := m.Text + if user.Wallet == nil { + return ctx, fmt.Errorf("user has no wallet") + } me, err := GetUser(bot.Telegram.Me, *bot) if err != nil { return ctx, err } - invoice, err := bot.createInvoiceWithEvent(ctx, me, 1, fmt.Sprintf("DALLE2 %s", GetUserStr(user.Telegram)), InvoiceCallbackGenerateDalle, "") + invoice, err := bot.createInvoiceWithEvent(ctx, me, DALLE2PRICE, fmt.Sprintf("DALLE2 %s", GetUserStr(user.Telegram)), InvoiceCallbackGenerateDalle, prompt) invoice.Payer = user if err != nil { return ctx, err } + + runtime.IgnoreError(bot.Bunt.Set(invoice)) + + balance, err := bot.GetUserBalance(user) + if err != nil { + errmsg := fmt.Sprintf("[inlineReceive] Error: Could not get user balance: %s", err.Error()) + log.Warnln(errmsg) + } + + bot.trySendMessage(ctx.Message().Sender, Translate(ctx, "generateDallePayInvoiceMessage")) + + // invoke internal pay if enough balance + if balance > DALLE2PRICE { + m.Text = fmt.Sprintf("/pay %s", invoice.PaymentRequest) + return bot.payHandler(ctx) + } + // create qr code qr, err := qrcode.Encode(invoice.PaymentRequest, qrcode.Medium, 256) if err != nil { @@ -43,15 +93,16 @@ func (bot *TipBot) generateImages(ctx intercept.Context) (intercept.Context, err return ctx, nil } +// generateDalleImages is called by the invoice event when the user has paid func (bot *TipBot) generateDalleImages(event Event) { invoiceEvent := event.(*InvoiceEvent) user := invoiceEvent.Payer - if user.Wallet == nil { + if user == nil || user.Wallet == nil { return } // create the client with the bearer token api key - dalleClient, err := dalle.NewHTTPClient("") + dalleClient, err := dalle.NewHTTPClient("API KEY") // handle err if err != nil { return @@ -60,8 +111,10 @@ func (bot *TipBot) generateDalleImages(event Event) { ctx, cancel := context.WithTimeout(context.Background(), time.Minute*5) defer cancel() // generate a task to create an image with a prompt - task, err := dalleClient.Generate(ctx, "humanoid robot standing on a skyscraper at night looking down on the dark rainy metropolis in vaporware style oil painting") - // handle err + task, err := dalleClient.Generate(ctx, invoiceEvent.CallbackData) + if err != nil { + + } // poll the task.ID until status is succeeded var t *dalle.Task @@ -103,7 +156,7 @@ func (bot *TipBot) generateDalleImages(event Event) { if err != nil { return } - bot.trySendMessage(invoiceEvent.Payer.Telegram, &tb.Photo{File: tb.File{FileReader: f}, Caption: fmt.Sprintf("Result")}) + bot.trySendMessage(invoiceEvent.Payer.Telegram, &tb.Photo{File: tb.File{FileReader: f}}) } // handle err and close readCloser diff --git a/internal/telegram/state.go b/internal/telegram/state.go index f3135c2..3839d94 100644 --- a/internal/telegram/state.go +++ b/internal/telegram/state.go @@ -20,5 +20,6 @@ func initializeStateCallbackMessage(bot *TipBot) { lnbits.UserStateShopItemSendTitle: bot.enterShopItemTitleHandler, lnbits.UserStateShopItemSendItemFile: bot.addItemFileHandler, lnbits.UserEnterShopsDescription: bot.enterShopsDescriptionHandler, + lnbits.UserEnterDallePrompt: bot.confirmGenerateImages, } } diff --git a/translations/en.toml b/translations/en.toml index 19cd7c3..6d3d5bd 100644 --- a/translations/en.toml +++ b/translations/en.toml @@ -133,6 +133,7 @@ advancedMessage = """%s enterAmountRangeMessage = """💯 Enter an amount between %d and %d sat.""" enterAmountMessage = """💯 Enter an amount.""" enterUserMessage = """👤 Enter a user.""" +enterTextMessage = """⌨️ Enter text.""" errorReasonMessage = """🚫 Error: %s""" # START @@ -393,4 +394,9 @@ To join a group, talk to %s and write in a private message `/join `. 📖 *Usage:* *For admins (in group chat):* `/group add []`\nExample: `/group add TheBestBitcoinGroup 1000` -*For users (in private chat):* `/join `\nExample: `/join TheBestBitcoinGroup`""" \ No newline at end of file +*For users (in private chat):* `/join `\nExample: `/join TheBestBitcoinGroup`""" + +# DALLE GENERATE +generateDalleHelpMessage = """Generate images using OpenAI DALLE 2.\nUsage: `/generate `\nPrice: 1000 sat""" +generateDallePayInvoiceMessage = """Pay this invoice to generate four images 👇""" +generateDalleGeneratingMessage = """Your images are being generated...""" \ No newline at end of file