-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfunction.go
More file actions
101 lines (88 loc) · 2.95 KB
/
Copy pathfunction.go
File metadata and controls
101 lines (88 loc) · 2.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
package dca
import (
"context"
"errors"
"fmt"
"net/http"
"os"
"strconv"
"strings"
"time"
"github.com/line/line-bot-sdk-go/v8/linebot"
"github.com/pomadev/dollar-cost-averaging-bot/client/bitbank"
)
type Config struct {
BitbankAccessKey string
BitbankAPISecret string
LineChannelSecret string
LineChannelAccessToken string
LineUserID string
BTCCostYen int64
DryRun bool
}
func Run(ctx context.Context) error {
cfg, err := loadConfig()
if err != nil {
return err
}
httpClient := &http.Client{Timeout: 10 * time.Second}
exchangeClient := bitbank.NewClient(cfg.BitbankAccessKey, cfg.BitbankAPISecret, httpClient)
order, err := exchangeClient.BuyBTC(ctx, cfg.BTCCostYen, cfg.DryRun)
if err != nil {
return fmt.Errorf("buy BTC: %w", err)
}
bot, err := linebot.New(cfg.LineChannelSecret, cfg.LineChannelAccessToken, linebot.WithHTTPClient(httpClient))
if err != nil {
return fmt.Errorf("create LINE client: %w", err)
}
messagePrefix := "BTCを積み立てました。"
if order.DryRun {
messagePrefix = "DRY RUN: BTCの積み立て予定を計算しました。"
}
message := fmt.Sprintf("%s\n\n[BTC]\n価格: %d円\n数量: %.4fBTC\n投入額: %d円", messagePrefix, order.PriceYen, order.AmountBTC, cfg.BTCCostYen)
if _, err := bot.PushMessage(cfg.LineUserID, linebot.NewTextMessage(message)).Do(); err != nil {
return fmt.Errorf("push LINE message: %w", err)
}
return nil
}
func loadConfig() (Config, error) {
btcCostYen, err := strconv.ParseInt(os.Getenv("BTC_YEN"), 10, 64)
if err != nil {
return Config{}, fmt.Errorf("parse BTC_YEN: %w", err)
}
if btcCostYen <= 0 {
return Config{}, errors.New("BTC_YEN must be greater than 0")
}
dryRun, err := strconv.ParseBool(defaultValue(os.Getenv("DRY_RUN"), "false"))
if err != nil {
return Config{}, fmt.Errorf("parse DRY_RUN: %w", err)
}
cfg := Config{
BitbankAccessKey: strings.TrimSpace(os.Getenv("BITBANK_ACCESS_KEY")),
BitbankAPISecret: strings.TrimSpace(os.Getenv("BITBANK_API_SECRET")),
LineChannelSecret: strings.TrimSpace(os.Getenv("LINE_CHANNEL_SECRET")),
LineChannelAccessToken: strings.TrimSpace(os.Getenv("LINE_CHANNEL_ACCESS_TOKEN")),
LineUserID: strings.TrimSpace(os.Getenv("LINE_USER_ID")),
BTCCostYen: btcCostYen,
DryRun: dryRun,
}
switch {
case cfg.BitbankAccessKey == "":
return Config{}, errors.New("BITBANK_ACCESS_KEY is not set")
case cfg.BitbankAPISecret == "":
return Config{}, errors.New("BITBANK_API_SECRET is not set")
case cfg.LineChannelSecret == "":
return Config{}, errors.New("LINE_CHANNEL_SECRET is not set")
case cfg.LineChannelAccessToken == "":
return Config{}, errors.New("LINE_CHANNEL_ACCESS_TOKEN is not set")
case cfg.LineUserID == "":
return Config{}, errors.New("LINE_USER_ID is not set")
}
return cfg, nil
}
func defaultValue(value, fallback string) string {
if value == "" {
return fallback
}
return value
}