package realDynDns import ( "fmt" "time" "realdnydns/pkg/config" "realdnydns/pkg/dnsProvider" "realdnydns/pkg/externalIpProvider" "realdnydns/pkg/notificationProvider" "github.com/go-co-op/gocron" ) type ChangeDetector struct { externalIpProvider externalIpProvider.ExternalIpProvider dnsProvider dnsProvider.DNSProvider notificationProvider notificationProvider.NotificationProvider domains []config.DomainConfig } func New( externalIpProvider externalIpProvider.ExternalIpProvider, dnsProvider dnsProvider.DNSProvider, notificationProvider notificationProvider.NotificationProvider, domains []config.DomainConfig, ) ChangeDetector { return ChangeDetector{ externalIpProvider: externalIpProvider, dnsProvider: dnsProvider, notificationProvider: notificationProvider, domains: domains, } } func (c *ChangeDetector) RunWithSchedule(checkInterval string) (*gocron.Scheduler, *gocron.Job, error) { s := gocron.NewScheduler(time.UTC) s.SingletonMode() s.CronWithSeconds(checkInterval) job, err := s.DoWithJobDetails(func(job gocron.Job) { numberChanged, err := c.detectAndApplyChanges() if err != nil { panic(err) } fmt.Printf("Number of changes: %d\n", numberChanged) fmt.Println("Next run:", job.NextRun()) }) if err != nil { return nil, nil, err } return s, job, nil } func (c *ChangeDetector) RunOnce() (int, error) { return c.detectAndApplyChanges() } func (c *ChangeDetector) detectAndApplyChanges() (int, error) { externalIp, err := c.externalIpProvider.GetExternalIp() if err != nil { return 0, err } var numberUpdated int for _, domain := range c.domains { for _, subdomain := range domain.Subdomains { currentRecord, err := c.dnsProvider.GetRecord(domain.TLD, subdomain) if err != nil { return numberUpdated, err } if currentRecord.IP != externalIp.String() { err = c.notificationProvider.SendNotification( fmt.Sprintf("Update %s.%s", subdomain, domain.TLD), fmt.Sprintf("The IP of %s has changed from %s to %s", domain.TLD, currentRecord.IP, externalIp.String()), ) if err != nil { return numberUpdated, err } _, err = c.dnsProvider.UpdateRecord(domain.TLD, subdomain, externalIp, currentRecord.TTL, currentRecord.Prio, currentRecord.Disabled) numberUpdated++ if err != nil { return numberUpdated, err } } } } return numberUpdated, nil }