package main import ( "log" "math/rand" "time" ) type RepoUpdate struct { repo RepoConfig Tag string } func notifierThread(c chan RepoUpdate, n Notifier) { update := <-c log.Printf("New tag stored for %s: %s", update.repo.Repo, update.Tag) if n.Notify(update.repo, update.Tag) { log.Printf("Notified for %s/%s: %s", update.repo.Owner, update.repo.Repo, update.Tag) } notifierThread(c, n) } func repoThread(c chan RepoUpdate, repo RepoConfig, avgInterval int, db Db) { log.Println("Checking", repo.Repo) tag, err := repo.GetLatestTag() isNewVersion, err_2 := db.CheckAndStore(repo.Owner, repo.Repo) if err != nil { log.Printf("Failed to fetch latest tag for %s: %v", repo.Repo, err) } else if err_2 != nil { log.Printf("Failed to store latest tag for %s: %v", repo.Repo, err_2) } else if isNewVersion { c <- RepoUpdate{repo, tag.Name} } sleepTime := time.Duration(rand.Intn(avgInterval)) * time.Second time.Sleep(sleepTime) repoThread(c, repo, avgInterval, db) } func main() { // Load configuration config, err := loadConfig("config.json") if err != nil { log.Fatalf("Failed to load configuration: %v", err) } // Create database db, err := NewSQLiteDb("tags.db") if err != nil { log.Fatalf("Failed to create database: %v", err) } notifier := NtfyNotifier{Topic: config.NtfyTopic} c := make(chan RepoUpdate) // Spawn a goroutine for each repository for _, repo := range config.Repos { go repoThread(c, repo, config.Interval, db) } notifierThread(c, notifier) }