From 773318a079debcb8a4863feb51485d3382c498e3 Mon Sep 17 00:00:00 2001 From: Seraphim Strub Date: Fri, 12 Jul 2024 13:51:36 +0000 Subject: [PATCH] feature: switch domaincheckbot to sqlite kv --- cmd/domaincheckbot/dns/domain.go | 12 ++- cmd/domaincheckbot/main.go | 61 +++++++---- cmd/domaincheckbot/repository/repository.go | 108 -------------------- 3 files changed, 48 insertions(+), 133 deletions(-) delete mode 100644 cmd/domaincheckbot/repository/repository.go diff --git a/cmd/domaincheckbot/dns/domain.go b/cmd/domaincheckbot/dns/domain.go index 51b5374..dbd73a7 100644 --- a/cmd/domaincheckbot/dns/domain.go +++ b/cmd/domaincheckbot/dns/domain.go @@ -1,21 +1,25 @@ package dns import ( - "grow.rievo.dev/discordBots/cmd/domaincheckbot/repository" "net" "sort" ) -func CheckDomain(domain string) repository.Domain { +type Domain struct { + Name string + NS []string +} + +func CheckDomain(domain string) Domain { nameservers, err := net.LookupNS(domain) if len(nameservers) > 0 && err == nil { - return repository.Domain{ + return Domain{ Name: domain, NS: nsToArray(nameservers), } } - return repository.Domain{ + return Domain{ Name: domain, NS: []string{}, } diff --git a/cmd/domaincheckbot/main.go b/cmd/domaincheckbot/main.go index 609af67..1e920bf 100644 --- a/cmd/domaincheckbot/main.go +++ b/cmd/domaincheckbot/main.go @@ -2,23 +2,27 @@ package main import ( "context" + "database/sql" + "encoding/json" "errors" "fmt" - "github.com/dgraph-io/badger/v4" "github.com/disgoorg/disgo" "github.com/disgoorg/disgo/discord" "github.com/disgoorg/disgo/rest" "github.com/disgoorg/disgo/webhook" "github.com/disgoorg/snowflake/v2" + "grow.rievo.dev/discordBots" "grow.rievo.dev/discordBots/cmd/domaincheckbot/config" "grow.rievo.dev/discordBots/cmd/domaincheckbot/dns" - "grow.rievo.dev/discordBots/cmd/domaincheckbot/repository" + "grow.rievo.dev/discordBots/pkg/db" "log/slog" "os" "os/signal" "reflect" "syscall" "time" + + _ "modernc.org/sqlite" ) var ( @@ -39,11 +43,22 @@ func main() { client := webhook.New(webhookID, webhookToken) defer client.Close(context.TODO()) - repo := repository.InitDb() - defer repo.Close() + ctx := context.Background() + con, err := sql.Open("sqlite", "file:db/domain.db?cache=shared") + if err != nil { + logger.Error("error opening db", slog.Any("error", err)) + panic(err) + } + defer con.Close() - ticker := time.NewTicker(10 * time.Minute) - tickerGC := time.NewTicker(15 * time.Minute) + // create tables + if _, err := con.ExecContext(ctx, discordBots.Schema); err != nil { + logger.Error("error creating db schema", slog.Any("error", err)) + panic(err) + } + query := db.New(con) + + ticker := time.NewTicker(1 * time.Minute) quit := make(chan struct{}) go func() { @@ -51,20 +66,11 @@ func main() { select { case <-ticker.C: for _, d := range config.Domains { - go checkDomain(0, d, repo, client) - } - - case <-tickerGC.C: - err := repo.RunGC() - if err != nil && !errors.Is(err, badger.ErrNoRewrite) { - logger.Error("GC failed", slog.Any("error", err)) - } else { - logger.Debug("GC successful") + go checkDomain(0, d, query, client) } case <-quit: ticker.Stop() - tickerGC.Stop() return } } @@ -77,9 +83,13 @@ func main() { <-s } -func checkDomain(counter int, d string, repo *repository.DomainRepository, client webhook.Client) { +func checkDomain(counter int, d string, query *db.Queries, client webhook.Client) { domain := dns.CheckDomain(d) - retrievedDomain, _ := repo.GetValue(d) + retrievedDomainJson, dbErr := query.GetItem(context.TODO(), d) + retrievedDomain := dns.Domain{} + if err := json.Unmarshal(retrievedDomainJson.Data, &retrievedDomain); !errors.Is(dbErr, sql.ErrNoRows) && err != nil { + logger.Error("failed unmarshalling deal", slog.Any("error", err)) + } if reflect.DeepEqual(domain, retrievedDomain) { logger.Debug("domain did not change", slog.String("domain", d)) return @@ -88,14 +98,23 @@ func checkDomain(counter int, d string, repo *repository.DomainRepository, clien counter += 1 if counter >= 2 { go sendWebhook(client, domain, retrievedDomain) - repo.SetValue(domain) + + domainJson, _ := json.Marshal(domain) + err := query.CreateItem(context.TODO(), db.CreateItemParams{ + ID: domain.Name, + Data: domainJson, + }) + + if err != nil { + logger.Error("failed saving domain", slog.Any("error", err)) + } return } time.Sleep(1 * time.Minute) - checkDomain(counter, d, repo, client) + checkDomain(counter, d, query, client) } -func sendWebhook(client webhook.Client, domain repository.Domain, oldDomain repository.Domain) { +func sendWebhook(client webhook.Client, domain dns.Domain, oldDomain dns.Domain) { var status string status = fmt.Sprintf("```md\n# %v", domain.Name) diff --git a/cmd/domaincheckbot/repository/repository.go b/cmd/domaincheckbot/repository/repository.go deleted file mode 100644 index c589fb2..0000000 --- a/cmd/domaincheckbot/repository/repository.go +++ /dev/null @@ -1,108 +0,0 @@ -package repository - -import ( - "encoding/json" - "github.com/dgraph-io/badger/v4" - "log" -) - -type Domain struct { - Name string - NS []string -} - -type Repository interface { - GetAll() ([]Domain, error) - GetValue(domainName string) Domain - SetValue(domain Domain) error - DeleteValue(domainName string) error - Close() error -} - -type DomainRepository struct { - db *badger.DB -} - -func InitDb() *DomainRepository { - opts := badger.DefaultOptions("./badger") - opts.Logger = nil - db, err := badger.Open(opts) - if err != nil { - log.Fatal(err) - } - return &DomainRepository{db} -} - -func (d *DomainRepository) Close() error { - return d.db.Close() -} - -func (d *DomainRepository) RunGC() error { - return d.db.RunValueLogGC(0.7) -} - -func (d *DomainRepository) GetAll() ([]Domain, error) { - var domains []Domain - err := d.db.View(func(txn *badger.Txn) error { - opts := badger.DefaultIteratorOptions - opts.PrefetchSize = 10 - it := txn.NewIterator(opts) - defer it.Close() - for it.Rewind(); it.Valid(); it.Next() { - item := it.Item() - err := item.Value(func(val []byte) error { - retrievedDomain := Domain{} - err := json.Unmarshal(val, &retrievedDomain) - domains = append(domains, retrievedDomain) - return err - }) - if err != nil { - return err - } - } - return nil - }) - return domains, err -} - -func (d *DomainRepository) GetValue(domainName string) (Domain, error) { - retrievedDomain := Domain{} - err := d.db.View(func(txn *badger.Txn) error { - item, err := txn.Get([]byte(domainName)) - if err != nil { - return err - } - err = item.Value(func(val []byte) error { - err = json.Unmarshal(val, &retrievedDomain) - return err - }) - return err - }) - if err != nil { - return Domain{}, err - } - return retrievedDomain, nil -} - -func (d *DomainRepository) SetValue(domain Domain) error { - jsonBytes, err := json.Marshal(domain) - if err != nil { - return err - } - err = d.db.Update(func(txn *badger.Txn) error { - err := txn.Set([]byte(domain.Name), jsonBytes) - return err - }) - if err != nil { - return err - } - return nil -} - -func (d *DomainRepository) DeleteValue(domainName string) error { - err := d.db.Update(func(txn *badger.Txn) error { - err := txn.Delete([]byte(domainName)) - return err - }) - return err -}