2022-03-17 00:21:28 +01:00
package telegram
import (
"bytes"
"context"
"encoding/json"
"fmt"
"strings"
2022-03-31 23:29:58 +02:00
"github.com/LightningTipBot/LightningTipBot/internal/telegram/intercept"
2022-03-17 00:21:28 +01:00
"github.com/LightningTipBot/LightningTipBot/internal"
"github.com/LightningTipBot/LightningTipBot/internal/errors"
"github.com/LightningTipBot/LightningTipBot/internal/i18n"
"github.com/LightningTipBot/LightningTipBot/internal/lnbits"
"github.com/LightningTipBot/LightningTipBot/internal/runtime"
"github.com/LightningTipBot/LightningTipBot/internal/runtime/mutex"
"github.com/LightningTipBot/LightningTipBot/internal/storage"
"github.com/LightningTipBot/LightningTipBot/internal/str"
log "github.com/sirupsen/logrus"
"github.com/skip2/go-qrcode"
2022-03-27 22:19:38 +02:00
tb "gopkg.in/lightningtipbot/telebot.v3"
2022-03-17 00:21:28 +01:00
)
type Ticket struct {
2022-03-17 10:22:47 +01:00
Price int64 ` json:"price" `
Memo string ` json:"memo" `
Creator * lnbits . User ` gorm:"embedded;embeddedPrefix:creator_" `
Cut int64 ` json:"cut" ` // Percent to cut from ticket price
BaseFee int64 ` json:"base_fee" `
CutCheap int64 ` json:"cut_cheap" ` // Percent to cut from ticket price
BaseFeeCheap int64 ` json:"base_fee_cheap" `
2022-03-17 00:21:28 +01:00
}
type Group struct {
Name string ` json:"name" `
Title string ` json:"title" `
ID int64 ` json:"id" gorm:"primaryKey" `
Owner * tb . User ` gorm:"embedded;embeddedPrefix:owner_" `
// Chat *tb.Chat `gorm:"embedded;embeddedPrefix:chat_"`
Ticket * Ticket ` gorm:"embedded;embeddedPrefix:ticket_" `
}
type CreateChatInviteLink struct {
ChatID int64 ` json:"chat_id" `
Name string ` json:"name" `
ExpiryDate int ` json:"expiry_date" `
MemberLimit int ` json:"member_limit" `
CreatesJoinRequest bool ` json:"creates_join_request" `
}
type Creator struct {
ID int64 ` json:"id" `
IsBot bool ` json:"is_bot" `
Firstname string ` json:"first_name" `
Username string ` json:"username" `
}
type Result struct {
InviteLink string ` json:"invite_link" `
Name string ` json:"name" `
Creator Creator ` json:"creator" `
CreatesJoinRequest bool ` json:"creates_join_request" `
IsPrimary bool ` json:"is_primary" `
IsRevoked bool ` json:"is_revoked" `
}
type ChatInviteLink struct {
Ok bool ` json:"ok" `
Result Result ` json:"result" `
}
type TicketEvent struct {
* storage . Base
* InvoiceEvent
Group * Group ` gorm:"embedded;embeddedPrefix:group_" `
}
func ( ticketEvent TicketEvent ) Type ( ) EventType {
return EventTypeTicketInvoice
}
func ( ticketEvent TicketEvent ) Key ( ) string {
return ticketEvent . Base . ID
}
var (
2022-03-27 22:19:38 +02:00
ticketPayConfirmationMenu = & tb . ReplyMarkup { ResizeKeyboard : true }
2022-03-17 00:21:28 +01:00
btnPayTicket = paymentConfirmationMenu . Data ( "✅ Pay" , "pay_ticket" )
)
var (
2022-04-16 00:20:52 +02:00
groupInvoiceMemo = "🎟 Ticket for group %s"
2022-03-17 00:21:28 +01:00
)
2022-03-31 23:29:58 +02:00
// groupHandler is called if the /group <cmd> command is invoked. It then decides with other
// handler to call depending on the <cmd> passed.
2022-03-27 22:19:38 +02:00
func ( bot TipBot ) groupHandler ( ctx intercept . Context ) ( intercept . Context , error ) {
m := ctx . Message ( )
2022-03-17 00:21:28 +01:00
splits := strings . Split ( m . Text , " " )
2022-04-09 21:20:20 +02:00
user := LoadUser ( ctx )
2022-03-17 00:21:28 +01:00
if len ( splits ) == 1 {
2022-04-09 21:20:20 +02:00
if ctx . Message ( ) . Private ( ) {
bot . trySendMessage ( ctx . Message ( ) . Chat , fmt . Sprintf ( Translate ( ctx , "groupHelpMessage" ) , GetUserStr ( bot . Telegram . Me ) , GetUserStr ( bot . Telegram . Me ) ) )
} else {
if bot . isOwner ( ctx . Message ( ) . Chat , user . Telegram ) {
bot . trySendMessage ( ctx . Message ( ) . Chat , fmt . Sprintf ( Translate ( ctx , "commandPrivateMessage" ) , GetUserStr ( bot . Telegram . Me ) ) )
}
}
2022-03-17 00:21:28 +01:00
return ctx , nil
} else if len ( splits ) > 1 {
if splits [ 1 ] == "join" {
2022-03-27 22:19:38 +02:00
return bot . groupRequestJoinHandler ( ctx )
2022-03-17 00:21:28 +01:00
}
if splits [ 1 ] == "add" {
2022-03-27 22:19:38 +02:00
return bot . addGroupHandler ( ctx )
2022-03-17 00:21:28 +01:00
}
if splits [ 1 ] == "remove" {
// todo -- implement this
// return bot.addGroupHandler(ctx, m)
}
}
return ctx , nil
}
// groupRequestJoinHandler sends a payment request to the user who wants to join a group
2022-03-27 22:19:38 +02:00
func ( bot TipBot ) groupRequestJoinHandler ( ctx intercept . Context ) ( intercept . Context , error ) {
2022-03-17 00:21:28 +01:00
user := LoadUser ( ctx )
// // reply only in private message
2022-03-27 22:19:38 +02:00
if ctx . Chat ( ) . Type != tb . ChatPrivate {
2022-03-17 00:21:28 +01:00
return ctx , fmt . Errorf ( "not private chat" )
}
2022-03-27 22:19:38 +02:00
splits := strings . Split ( ctx . Message ( ) . Text , " " )
2022-03-17 00:21:28 +01:00
// if the command was /group join
splitIdx := 1
// we also have the simpler command /join that can be used
// also by users who don't have an account with the bot yet
if splits [ 0 ] == "/join" {
splitIdx = 0
}
2022-03-27 22:19:38 +02:00
if len ( splits ) != splitIdx + 2 || len ( ctx . Message ( ) . Text ) > 100 {
2022-04-09 21:20:20 +02:00
bot . trySendMessage ( ctx . Message ( ) . Chat , Translate ( ctx , "groupJoinGroupHelpMessage" ) )
2022-03-17 00:21:28 +01:00
return ctx , nil
}
groupName := strings . ToLower ( splits [ splitIdx + 1 ] )
group := & Group { }
2022-04-29 14:28:12 +02:00
tx := bot . DB . Groups . Where ( "name = ? COLLATE NOCASE" , groupName ) . First ( group )
2022-03-17 00:21:28 +01:00
if tx . Error != nil {
2022-04-09 21:20:20 +02:00
bot . trySendMessage ( ctx . Message ( ) . Chat , Translate ( ctx , "groupNotFoundMessage" ) )
2022-03-17 00:21:28 +01:00
return ctx , fmt . Errorf ( "group not found" )
}
// create tickets
id := fmt . Sprintf ( "ticket:%d" , group . ID )
invoiceEvent := & InvoiceEvent {
Base : storage . New ( storage . ID ( id ) ) ,
User : group . Ticket . Creator ,
LanguageCode : ctx . Value ( "publicLanguageCode" ) . ( string ) ,
Payer : user ,
Chat : & tb . Chat { ID : group . ID } ,
CallbackData : id ,
}
ticketEvent := & TicketEvent {
Base : storage . New ( storage . ID ( id ) ) ,
InvoiceEvent : invoiceEvent ,
Group : group ,
}
// if no price is set, then we don't need to pay
if group . Ticket . Price == 0 {
// save ticketevent for later
runtime . IgnoreError ( ticketEvent . Set ( ticketEvent , bot . Bunt ) )
bot . groupGetInviteLinkHandler ( invoiceEvent )
return ctx , nil
}
// create an invoice
memo := fmt . Sprintf ( groupInvoiceMemo , groupName )
var err error
invoiceEvent , err = bot . createGroupTicketInvoice ( ctx , user , group , memo , InvoiceCallbackGroupTicket , id )
if err != nil {
errmsg := fmt . Sprintf ( "[/invoice] Could not create an invoice: %s" , err . Error ( ) )
bot . trySendMessage ( user . Telegram , Translate ( ctx , "errorTryLaterMessage" ) )
log . Errorln ( errmsg )
return ctx , err
}
ticketEvent . InvoiceEvent = invoiceEvent
// save ticketevent for later
defer ticketEvent . Set ( ticketEvent , bot . Bunt )
// // if the user has enough balance, we send him a payment button
balance , err := bot . GetUserBalance ( user )
if err != nil {
errmsg := fmt . Sprintf ( "[/group] Error: Could not get user balance: %s" , err . Error ( ) )
log . Errorln ( errmsg )
2022-03-27 22:19:38 +02:00
bot . trySendMessage ( ctx . Message ( ) . Sender , Translate ( ctx , "errorTryLaterMessage" ) )
2022-03-17 00:21:28 +01:00
return ctx , errors . New ( errors . GetBalanceError , err )
}
if balance >= group . Ticket . Price {
2022-03-27 22:19:38 +02:00
return bot . groupSendPayButtonHandler ( ctx , * ticketEvent )
2022-03-17 00:21:28 +01:00
}
// otherwise we send a payment request
// create qr code
qr , err := qrcode . Encode ( invoiceEvent . PaymentRequest , qrcode . Medium , 256 )
if err != nil {
errmsg := fmt . Sprintf ( "[/invoice] Failed to create QR code for invoice: %s" , err . Error ( ) )
bot . trySendMessage ( user . Telegram , Translate ( ctx , "errorTryLaterMessage" ) )
log . Errorln ( errmsg )
return ctx , err
}
2022-03-27 22:19:38 +02:00
ticketEvent . Message = bot . trySendMessage ( ctx . Message ( ) . Sender , & tb . Photo { File : tb . File { FileReader : bytes . NewReader ( qr ) } , Caption : fmt . Sprintf ( "`%s`" , invoiceEvent . PaymentRequest ) } )
2022-04-09 21:20:20 +02:00
bot . trySendMessage ( ctx . Message ( ) . Sender , fmt . Sprintf ( Translate ( ctx , "groupPayInvoiceMessage" ) , groupName ) )
2022-03-17 00:21:28 +01:00
return ctx , nil
}
2022-03-31 23:29:58 +02:00
// groupSendPayButtonHandler is invoked if the user has enough balance so a message with a
// pay button is sent to the user.
2022-03-27 22:19:38 +02:00
func ( bot * TipBot ) groupSendPayButtonHandler ( ctx intercept . Context , ticket TicketEvent ) ( intercept . Context , error ) {
2022-03-17 00:21:28 +01:00
// object that holds all information about the send payment
// // // create inline buttons
btnPayTicket := ticketPayConfirmationMenu . Data ( Translate ( ctx , "payButtonMessage" ) , "pay_ticket" , ticket . Base . ID )
ticketPayConfirmationMenu . Inline (
ticketPayConfirmationMenu . Row (
btnPayTicket ) ,
)
confirmText := fmt . Sprintf ( Translate ( ctx , "confirmPayInvoiceMessage" ) , ticket . Group . Ticket . Price )
if len ( ticket . Group . Ticket . Memo ) > 0 {
confirmText = confirmText + fmt . Sprintf ( Translate ( ctx , "confirmPayAppendMemo" ) , str . MarkdownEscape ( ticket . Group . Ticket . Memo ) )
}
2022-03-27 22:19:38 +02:00
bot . trySendMessageEditable ( ctx . Message ( ) . Chat , confirmText , ticketPayConfirmationMenu )
2022-03-17 00:21:28 +01:00
return ctx , nil
}
2022-03-31 23:29:58 +02:00
// groupConfirmPayButtonHandler is invoked if th user clicks the pay button.
2022-03-27 22:19:38 +02:00
func ( bot * TipBot ) groupConfirmPayButtonHandler ( ctx intercept . Context ) ( intercept . Context , error ) {
c := ctx . Callback ( )
2022-03-17 00:29:06 +01:00
tx := & TicketEvent { Base : storage . New ( storage . ID ( c . Data ) ) }
2022-03-17 00:21:28 +01:00
mutex . LockWithContext ( ctx , tx . ID )
defer mutex . UnlockWithContext ( ctx , tx . ID )
sn , err := tx . Get ( tx , bot . Bunt )
// immediatelly set intransaction to block duplicate calls
if err != nil {
log . Errorf ( "[groupConfirmPayButtonHandler] %s" , err . Error ( ) )
return ctx , err
}
2022-03-17 00:29:06 +01:00
ticketEvent := sn . ( * TicketEvent )
2022-03-17 00:21:28 +01:00
// onnly the correct user can press
if ticketEvent . Payer . Telegram . ID != c . Sender . ID {
return ctx , errors . Create ( errors . UnknownError )
}
if ! ticketEvent . Active {
log . Errorf ( "[confirmPayHandler] send not active anymore" )
2022-03-27 22:19:38 +02:00
bot . tryEditMessage ( c , i18n . Translate ( ticketEvent . LanguageCode , "errorTryLaterMessage" ) , & tb . ReplyMarkup { } )
bot . tryDeleteMessage ( c )
2022-03-17 00:21:28 +01:00
return ctx , errors . Create ( errors . NotActiveError )
}
defer ticketEvent . Set ( ticketEvent , bot . Bunt )
user := LoadUser ( ctx )
if user . Wallet == nil {
2022-03-27 22:19:38 +02:00
bot . tryDeleteMessage ( c )
2022-03-17 00:21:28 +01:00
return ctx , errors . Create ( errors . UserNoWalletError )
}
log . Infof ( "[/pay] Attempting %s's invoice %s (%d sat)" , GetUserStr ( user . Telegram ) , ticketEvent . ID , ticketEvent . Group . Ticket . Price )
// // pay invoice
_ , err = user . Wallet . Pay ( lnbits . PaymentParams { Out : true , Bolt11 : ticketEvent . Invoice . PaymentRequest } , bot . Client )
if err != nil {
errmsg := fmt . Sprintf ( "[/pay] Could not pay invoice of %s: %s" , GetUserStr ( user . Telegram ) , err )
err = fmt . Errorf ( i18n . Translate ( ticketEvent . LanguageCode , "invoiceUndefinedErrorMessage" ) )
2022-03-27 22:19:38 +02:00
bot . tryEditMessage ( c , fmt . Sprintf ( i18n . Translate ( ticketEvent . LanguageCode , "invoicePaymentFailedMessage" ) , err . Error ( ) ) , & tb . ReplyMarkup { } )
2022-03-17 00:21:28 +01:00
log . Errorln ( errmsg )
return ctx , err
}
// update the message and remove the button
2022-03-27 22:19:38 +02:00
bot . tryEditMessage ( c , i18n . Translate ( ticketEvent . LanguageCode , "invoicePaidMessage" ) , & tb . ReplyMarkup { } )
2022-03-17 00:21:28 +01:00
return ctx , nil
}
// groupGetInviteLinkHandler is called when the invoice is paid and sends a one-time group invite link to the payer
func ( bot * TipBot ) groupGetInviteLinkHandler ( event Event ) {
invoiceEvent := event . ( * InvoiceEvent )
// take a cut
// amount_bot := int64(ticketEvent.Group.Ticket.Price * int64(ticketEvent.Group.Ticket.Cut) / 100)
log . Infof ( invoiceEvent . CallbackData )
ticketEvent := & TicketEvent { Base : storage . New ( storage . ID ( invoiceEvent . CallbackData ) ) }
err := bot . Bunt . Get ( ticketEvent )
if err != nil {
log . Errorf ( "[groupGetInviteLinkHandler] %s" , err . Error ( ) )
return
}
log . Infof ( "[groupGetInviteLinkHandler] group: %d" , ticketEvent . Chat . ID )
params := map [ string ] interface {
} {
"chat_id" : ticketEvent . Group . ID , // must be the chat ID of the group
"name" : fmt . Sprintf ( "%s link for %s" , GetUserStr ( bot . Telegram . Me ) , GetUserStr ( ticketEvent . Payer . Telegram ) ) , // the name of the invite link
"member_limit" : 1 , // only one user can join with this link
// "expire_date": time.Now().AddDate(0, 0, 1), // expiry date of the invite link, add one day
// "creates_join_request": false, // True, if users joining the chat via the link need to be approved by chat administrators. If True, member_limit can't be specified
}
data , err := bot . Telegram . Raw ( "createChatInviteLink" , params )
if err != nil {
return
}
var resp ChatInviteLink
if err := json . Unmarshal ( data , & resp ) ; err != nil {
return
}
if ticketEvent . Message != nil {
bot . tryDeleteMessage ( ticketEvent . Message )
// do balance check for keyboard update
_ , err = bot . GetUserBalance ( ticketEvent . Payer )
if err != nil {
errmsg := fmt . Sprintf ( "could not get balance of user %s" , GetUserStr ( ticketEvent . Payer . Telegram ) )
log . Errorln ( errmsg )
}
bot . trySendMessage ( ticketEvent . Payer . Telegram , i18n . Translate ( ticketEvent . LanguageCode , "invoicePaidText" ) )
}
2022-03-31 23:29:58 +02:00
// send confirmation text with the ticket to the user
2022-04-09 21:20:20 +02:00
bot . trySendMessage ( ticketEvent . Payer . Telegram , fmt . Sprintf ( i18n . Translate ( ticketEvent . LanguageCode , "groupClickToJoinMessage" ) , resp . Result . InviteLink , ticketEvent . Group . Title ) )
2022-03-17 00:21:28 +01:00
2022-03-31 23:29:58 +02:00
// send a notification to the group that sold the ticket
2022-08-19 22:07:58 +02:00
bot . trySendMessage ( & tb . Chat { ID : ticketEvent . Group . ID } , fmt . Sprintf ( i18n . Translate ( ticketEvent . LanguageCode , "groupTicketIssuedGroupMessage" ) , GetUserStrMd ( ticketEvent . Payer . Telegram ) ) )
2022-03-31 23:29:58 +02:00
2022-03-17 00:21:28 +01:00
// take a commission
ticketSat := ticketEvent . Group . Ticket . Price
2022-03-17 10:22:47 +01:00
if ticketEvent . Group . Ticket . Price > 20 {
2022-03-17 00:21:28 +01:00
me , err := GetUser ( bot . Telegram . Me , * bot )
if err != nil {
log . Errorf ( "[groupGetInviteLinkHandler] Could not get bot user from DB: %s" , err . Error ( ) )
return
}
2022-03-17 10:22:47 +01:00
// 2% cut + 100 sat base fee
commissionSat := ticketEvent . Group . Ticket . Price * ticketEvent . Group . Ticket . Cut / 100 + ticketEvent . Group . Ticket . BaseFee
if ticketEvent . Group . Ticket . Price <= 1000 {
// if < 1000, then 10% cut + 10 sat base fee
commissionSat = ticketEvent . Group . Ticket . Price * ticketEvent . Group . Ticket . CutCheap / 100 + ticketEvent . Group . Ticket . BaseFeeCheap
}
2022-03-17 00:21:28 +01:00
ticketSat = ticketEvent . Group . Ticket . Price - commissionSat
invoice , err := me . Wallet . Invoice (
lnbits . InvoiceParams {
Out : false ,
Amount : commissionSat ,
2022-04-16 00:20:52 +02:00
Memo : "🎟 Ticket commission for group " + ticketEvent . Group . Title ,
2022-03-17 00:21:28 +01:00
Webhook : internal . Configuration . Lnbits . WebhookServer } ,
bot . Client )
if err != nil {
errmsg := fmt . Sprintf ( "[/invoice] Could not create an invoice: %s" , err . Error ( ) )
log . Errorln ( errmsg )
return
}
_ , err = ticketEvent . User . Wallet . Pay ( lnbits . PaymentParams { Out : true , Bolt11 : invoice . PaymentRequest } , bot . Client )
if err != nil {
errmsg := fmt . Sprintf ( "[groupGetInviteLinkHandler] Could not pay commission of %s: %s" , GetUserStr ( ticketEvent . User . Telegram ) , err )
log . Errorln ( errmsg )
return
}
// do balance check for keyboard update
_ , err = bot . GetUserBalance ( ticketEvent . User )
if err != nil {
errmsg := fmt . Sprintf ( "could not get balance of user %s" , GetUserStr ( ticketEvent . Payer . Telegram ) )
log . Errorln ( errmsg )
}
2022-08-19 22:07:58 +02:00
bot . trySendMessage ( ticketEvent . User . Telegram , fmt . Sprintf ( i18n . Translate ( ticketEvent . LanguageCode , "groupReceiveTicketInvoiceCommission" ) , ticketSat , commissionSat , ticketEvent . Group . Title , GetUserStrMd ( ticketEvent . Payer . Telegram ) ) )
2022-03-17 00:21:28 +01:00
} else {
2022-08-19 22:07:58 +02:00
bot . trySendMessage ( ticketEvent . User . Telegram , fmt . Sprintf ( i18n . Translate ( ticketEvent . LanguageCode , "groupReceiveTicketInvoice" ) , ticketSat , ticketEvent . Group . Title , GetUserStrMd ( ticketEvent . Payer . Telegram ) ) )
2022-03-17 00:21:28 +01:00
}
}
2022-03-31 23:29:58 +02:00
// addGroupHandler is invoked if the user calls the "/group add" command
2022-03-27 22:19:38 +02:00
func ( bot TipBot ) addGroupHandler ( ctx intercept . Context ) ( intercept . Context , error ) {
m := ctx . Message ( )
2022-03-17 00:21:28 +01:00
if m . Chat . Type == tb . ChatPrivate {
2022-04-09 21:20:20 +02:00
bot . trySendMessage ( m . Chat , Translate ( ctx , "groupAddGroupHelpMessage" ) )
2022-03-17 00:21:28 +01:00
return ctx , fmt . Errorf ( "not in group" )
}
// parse command "/group add <grou_name> [<amount>]"
splits := strings . Split ( m . Text , " " )
if len ( splits ) < 3 || len ( m . Text ) > 100 {
2022-04-09 21:20:20 +02:00
bot . trySendMessage ( m . Chat , Translate ( ctx , "groupAddGroupHelpMessage" ) )
2022-03-17 00:21:28 +01:00
return ctx , nil
}
groupName := strings . ToLower ( splits [ 2 ] )
user := LoadUser ( ctx )
// check if the user is the owner of the group
if ! bot . isOwner ( m . Chat , user . Telegram ) {
return ctx , fmt . Errorf ( "not owner" )
}
if ! bot . isAdminAndCanInviteUsers ( m . Chat , bot . Telegram . Me ) {
2022-04-09 21:20:20 +02:00
bot . trySendMessage ( m . Chat , Translate ( ctx , "groupBotIsNotAdminMessage" ) )
2022-03-17 00:21:28 +01:00
return ctx , fmt . Errorf ( "bot is not admin" )
}
// check if the group with this name is already in db
// only if a group with this name is owned by this user, it can be overwritten
group := & Group { }
2022-04-29 14:28:12 +02:00
tx := bot . DB . Groups . Where ( "name = ? COLLATE NOCASE" , groupName ) . First ( group )
2022-03-17 00:21:28 +01:00
if tx . Error == nil {
// if it is already added, check if this user is the admin
if user . Telegram . ID != group . Owner . ID || group . ID != m . Chat . ID {
2022-04-09 21:20:20 +02:00
bot . trySendMessage ( m . Chat , Translate ( ctx , "groupNameExists" ) )
2022-03-17 00:21:28 +01:00
return ctx , fmt . Errorf ( "not owner" )
}
}
amount := int64 ( 0 ) // default amount is zero
if amount_str , err := getArgumentFromCommand ( m . Text , 3 ) ; err == nil {
amount , err = getAmount ( amount_str )
if err != nil {
bot . trySendMessage ( m . Sender , Translate ( ctx , "lnurlInvalidAmountMessage" ) )
return ctx , err
}
}
ticket := & Ticket {
2022-03-17 10:22:47 +01:00
Price : amount ,
Memo : "Ticket for group " + groupName ,
Creator : user ,
Cut : 2 ,
BaseFee : 100 ,
CutCheap : 10 ,
BaseFeeCheap : 10 ,
2022-03-17 00:21:28 +01:00
}
group = & Group {
Name : groupName ,
Title : m . Chat . Title ,
ID : m . Chat . ID ,
Owner : user . Telegram ,
Ticket : ticket ,
}
2022-04-29 14:28:12 +02:00
bot . DB . Groups . Save ( group )
2022-03-17 00:21:28 +01:00
log . Infof ( "[group] Ticket of %d sat added to group %s." , group . Ticket . Price , group . Name )
2022-04-09 21:20:20 +02:00
bot . trySendMessage ( m . Chat , fmt . Sprintf ( Translate ( ctx , "groupAddedMessage" ) , str . MarkdownEscape ( m . Chat . Title ) , group . Name , group . Ticket . Price , GetUserStrMd ( bot . Telegram . Me ) , group . Name ) )
2022-03-17 00:21:28 +01:00
return ctx , nil
}
2022-03-31 23:29:58 +02:00
// createGroupTicketInvoice produces an invoice for the group ticket with a
// callback that then calls groupGetInviteLinkHandler upton payment
2022-03-17 00:21:28 +01:00
func ( bot * TipBot ) createGroupTicketInvoice ( ctx context . Context , payer * lnbits . User , group * Group , memo string , callback int , callbackData string ) ( * InvoiceEvent , error ) {
invoice , err := group . Ticket . Creator . Wallet . Invoice (
lnbits . InvoiceParams {
Out : false ,
Amount : group . Ticket . Price ,
Memo : memo ,
Webhook : internal . Configuration . Lnbits . WebhookServer } ,
bot . Client )
if err != nil {
errmsg := fmt . Sprintf ( "[/invoice] Could not create an invoice: %s" , err . Error ( ) )
log . Errorln ( errmsg )
return & InvoiceEvent { } , err
}
// save the invoice event
id := fmt . Sprintf ( "invoice:%s" , invoice . PaymentHash )
invoiceEvent := & InvoiceEvent {
Base : storage . New ( storage . ID ( id ) ) ,
Invoice : & Invoice { PaymentHash : invoice . PaymentHash ,
PaymentRequest : invoice . PaymentRequest ,
Amount : group . Ticket . Price ,
Memo : memo } ,
User : group . Ticket . Creator ,
Callback : callback ,
CallbackData : callbackData ,
LanguageCode : ctx . Value ( "publicLanguageCode" ) . ( string ) ,
Payer : payer ,
Chat : & tb . Chat { ID : group . ID } ,
}
// add result to persistent struct
runtime . IgnoreError ( invoiceEvent . Set ( invoiceEvent , bot . Bunt ) )
return invoiceEvent , nil
}