Archived
1
0
Fork 0
This repository has been archived on 2024-12-18. You can view files and clone it, but cannot push or open issues or pull requests.
flexassistant/main.go
Julien Riou 632da28954
feat: Add notification templates (#2)
Signed-off-by: Julien Riou <julien@riou.xyz>
2021-10-13 15:09:59 +02:00

286 lines
7.1 KiB
Go

package main
import (
"flag"
"fmt"
"os"
log "github.com/sirupsen/logrus"
"gorm.io/gorm"
)
// AppName to store application name
var AppName string = "flexassistant"
// AppVersion to set version at compilation time
var AppVersion string = "9999"
// GitCommit to set git commit at compilation time (can be empty)
var GitCommit string
// GoVersion to set Go version at compilation time
var GoVersion string
// MaxPayments defaults
const MaxPayments = 10
// MaxBlocks defaults
const MaxBlocks = 50
// initialize logging
func init() {
log.SetOutput(os.Stdout)
}
func main() {
config := NewConfig()
version := flag.Bool("version", false, "Print version and exit")
quiet := flag.Bool("quiet", false, "Log errors only")
verbose := flag.Bool("verbose", false, "Print more logs")
debug := flag.Bool("debug", false, "Print even more logs")
configFileName := flag.String("config", AppName+".yaml", "Configuration file name")
flag.Parse()
if *version {
showVersion()
return
}
// Logs and configuration
log.SetLevel(log.WarnLevel)
if *debug {
log.SetLevel(log.DebugLevel)
}
if *verbose {
log.SetLevel(log.InfoLevel)
}
if *quiet {
log.SetLevel(log.ErrorLevel)
}
if *configFileName != "" {
err := config.ReadFile(*configFileName)
if err != nil {
log.Fatalf("Cannot parse configuration file: %v", err)
}
}
// Database
var db *gorm.DB
db, err := NewDatabase(config.DatabaseFile)
if err != nil {
log.Fatalf("Could not create database: %v", err)
}
if err := CreateDatabaseObjects(db); err != nil {
log.Fatalf("Could not create objects: %v", err)
}
if err := EnsureDatabaseRetention(db); err != nil {
log.Fatalf("Could not cleanup objects from database: %v", err)
}
// API client
client := NewFlexpoolClient()
// Notifications
notifier, err := NewTelegramNotifier(&config.TelegramConfig, &config.NotificationTemplates)
if err != nil {
log.Fatalf("Could not create notifier: %v", err)
}
// Limits
var maxPayments int
if config.MaxPayments > 0 {
maxPayments = config.MaxPayments
} else {
maxPayments = MaxPayments
}
var maxBlocks int
if config.MaxBlocks > 0 {
maxBlocks = config.MaxBlocks
} else {
maxBlocks = MaxBlocks
}
// Handle miners
for _, configuredMiner := range config.Miners {
miner, err := NewMiner(configuredMiner.Address)
if err != nil {
log.Warnf("Could not parse miner: %v", err)
continue
}
var dbMiner Miner
trx := db.Where(Miner{Address: miner.Address}).Attrs(Miner{Address: miner.Address, Coin: miner.Coin}).FirstOrCreate(&dbMiner)
if trx.Error != nil {
log.Warnf("Cannot fetch miner %s from database: %v", miner, trx.Error)
}
// Balance management
if configuredMiner.EnableBalance {
// Balance have never been persisted, skip notifications
notify := true
if dbMiner.Balance == 0 {
notify = false
}
log.Debugf("Fetching balance for %s", miner)
balance, err := client.MinerBalance(miner.Coin, miner.Address)
if err != nil {
log.Warnf("Could not fetch unpaid balance: %v", err)
continue
}
log.Debugf("Unpaid balance %d", balance)
miner.Balance = balance
if miner.Balance != dbMiner.Balance {
dbMiner.Balance = balance
if trx = db.Save(&dbMiner); trx.Error != nil {
log.Warnf("Cannot update miner: %v", trx.Error)
continue
}
if notify {
err = notifier.NotifyBalance(*miner)
if err != nil {
log.Warnf("Cannot send notification: %v", err)
continue
}
log.Infof("Balance notification sent for %s", miner)
}
}
}
// Payments management
if configuredMiner.EnablePayments {
// Payments have never been persisted, skip notifications
notify := true
if dbMiner.LastPaymentTimestamp == 0 {
notify = false
}
log.Debugf("Fetching payments for %s", miner)
payments, err := client.MinerPayments(miner.Coin, miner.Address, maxPayments)
if err != nil {
log.Warnf("Could not fetch payments: %v", err)
continue
}
for _, payment := range payments {
log.Debugf("Fetched %s", payment)
if dbMiner.LastPaymentTimestamp < payment.Timestamp {
dbMiner.LastPaymentTimestamp = payment.Timestamp
if trx = db.Save(&dbMiner); trx.Error != nil {
log.Warnf("Cannot update miner: %v", trx.Error)
continue
}
if notify {
err = notifier.NotifyPayment(*miner, *payment)
if err != nil {
log.Warnf("Cannot send notification: %v", err)
continue
}
log.Infof("Payment notification sent for %s", payment)
}
}
}
}
// Offline workers management
if configuredMiner.EnableOfflineWorkers {
log.Debugf("Fetching workers for %s", miner)
workers, err := client.MinerWorkers(miner.Coin, miner.Address)
if err != nil {
log.Warnf("Could not fetch workers: %v", err)
continue
}
for _, worker := range workers {
log.Debugf("Fetched %s", worker)
var dbWorker Worker
trx := db.Where(Worker{MinerAddress: miner.Address, Name: worker.Name}).Attrs(Worker{MinerAddress: miner.Address, Name: worker.Name}).FirstOrCreate(&dbWorker)
if trx.Error != nil {
log.Warnf("Cannot fetch worker %s from database: %v", worker, trx.Error)
continue
}
if dbWorker.IsOnline != worker.IsOnline {
// Skip first notification
notify := true
if dbWorker.LastSeen.IsZero() {
notify = false
}
dbWorker.IsOnline = worker.IsOnline
dbWorker.LastSeen = worker.LastSeen
if trx = db.Save(&dbWorker); trx.Error != nil {
log.Warnf("Cannot update worker: %v", trx.Error)
continue
}
if notify {
err = notifier.NotifyOfflineWorker(*worker)
if err != nil {
log.Warnf("Cannot send notification: %v", err)
continue
}
log.Infof("Offline worker notification sent for %s", worker)
}
}
}
}
}
// Handle pools
for _, configuredPool := range config.Pools {
pool := NewPool(configuredPool.Coin)
var dbPool Pool
trx := db.Where(Pool{Coin: pool.Coin}).Attrs(Pool{Coin: pool.Coin}).FirstOrCreate(&dbPool)
if trx.Error != nil {
log.Warnf("Cannot fetch pool %s from database: %v", pool, trx.Error)
}
// Blocks management
if configuredPool.EnableBlocks {
// Block number has never been persisted, skip notifications
notify := true
if dbPool.LastBlockNumber == 0 {
notify = false
}
log.Debugf("Fetching blocks for %s", pool)
blocks, err := client.PoolBlocks(pool.Coin, maxBlocks)
if err != nil {
log.Warnf("Could not fetch blocks: %v", err)
} else {
for _, block := range blocks {
log.Debugf("Fetched %s", block)
if dbPool.LastBlockNumber < block.Number {
dbPool.LastBlockNumber = block.Number
if trx = db.Save(&dbPool); trx.Error != nil {
log.Warnf("Cannot update pool: %v", trx.Error)
continue
}
if notify {
err = notifier.NotifyBlock(*pool, *block)
if err != nil {
log.Warnf("Cannot send notification: %v", err)
continue
}
log.Infof("Block notification sent for %s", block)
}
}
}
}
}
}
}
func showVersion() {
if GitCommit != "" {
AppVersion = fmt.Sprintf("%s-%s", AppVersion, GitCommit)
}
fmt.Printf("%s version %s (compiled with %s)\n", AppName, AppVersion, GoVersion)
}