bbgo/examples/interact/main.go

152 lines
3.3 KiB
Go
Raw Normal View History

package main
import (
"context"
"fmt"
"os"
"strconv"
"strings"
"syscall"
"time"
log "github.com/sirupsen/logrus"
prefixed "github.com/x-cray/logrus-prefixed-formatter"
tb "gopkg.in/tucnak/telebot.v2"
"git.qtrade.icu/lychiyu/bbgo/pkg/cmd/cmdutil"
"git.qtrade.icu/lychiyu/bbgo/pkg/interact"
)
func parseFloatPercent(s string, bitSize int) (f float64, err error) {
i := strings.Index(s, "%")
if i < 0 {
return strconv.ParseFloat(s, bitSize)
}
f, err = strconv.ParseFloat(s[:i], bitSize)
if err != nil {
return 0, err
}
return f / 100.0, nil
}
type closePositionTask struct {
symbol string
percentage float64
confirmed bool
}
type positionInteraction struct {
closePositionTask closePositionTask
}
// Commands implements the custom interaction
func (m *positionInteraction) Commands(i *interact.Interact) {
i.Command("/closePosition", "", func(reply interact.Reply) error {
// send symbol options
reply.Message("Choose your position")
for _, symbol := range []string{"BTCUSDT", "ETHUSDT"} {
reply.AddButton(symbol, symbol, symbol)
}
return nil
}).Next(func(reply interact.Reply, symbol string) error {
// get symbol from user
if len(symbol) == 0 {
reply.Message("Please enter a symbol")
return fmt.Errorf("empty symbol")
}
switch symbol {
case "BTCUSDT", "ETHUSDT":
default:
reply.Message("Invalid symbol")
return fmt.Errorf("invalid symbol")
}
m.closePositionTask.symbol = symbol
reply.Message("Choose or enter the percentage to close")
for _, symbol := range []string{"25%", "50%", "100%"} {
reply.AddButton(symbol, symbol, symbol)
}
// send percentage options
return nil
}).Next(func(reply interact.Reply, percentageStr string) error {
p, err := parseFloatPercent(percentageStr, 64)
if err != nil {
reply.Message("Not a valid percentage string")
return err
}
// get percentage from user
m.closePositionTask.percentage = p
// send confirmation
reply.Message("Are you sure to close the position?")
reply.AddButton("Yes", "confirm", "yes")
return nil
}).Next(func(reply interact.Reply, confirm string) error {
switch strings.ToLower(confirm) {
case "yes":
m.closePositionTask.confirmed = true
reply.Message(fmt.Sprintf("Your %s position is closed", m.closePositionTask.symbol))
default:
}
// call position close
if kc, ok := reply.(interact.KeyboardController); ok {
kc.RemoveKeyboard()
}
// reply result
return nil
})
}
func main() {
log.SetFormatter(&prefixed.TextFormatter{})
b, err := tb.NewBot(tb.Settings{
// You can also set custom API URL.
// If field is empty it equals to "https://api.telegram.org".
// URL: "http://195.129.111.17:8012",
Token: os.Getenv("TELEGRAM_BOT_TOKEN"),
Poller: &tb.LongPoller{Timeout: 10 * time.Second},
// Synchronous: false,
// Verbose: true,
// ParseMode: "",
// Reporter: nil,
// Client: nil,
// Offline: false,
})
if err != nil {
log.Fatal(err)
return
}
ctx := context.Background()
interact.AddMessenger(&interact.Telegram{
Private: true,
Bot: b,
})
interact.AddCustomInteraction(&interact.AuthInteract{
Strict: true,
Mode: interact.AuthModeToken,
Token: "123",
})
interact.AddCustomInteraction(&positionInteraction{})
if err := interact.Start(ctx); err != nil {
log.Fatal(err)
}
cmdutil.WaitForSignal(ctx, syscall.SIGINT, syscall.SIGTERM)
}