MVP
This commit is contained in:
		
							parent
							
								
									72177679f4
								
							
						
					
					
						commit
						05127ef72b
					
				
					 9 changed files with 97 additions and 7 deletions
				
			
		
							
								
								
									
										1
									
								
								.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					*.db
 | 
				
			||||||
							
								
								
									
										2
									
								
								Justfile
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								Justfile
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,2 @@
 | 
				
			||||||
 | 
					run:
 | 
				
			||||||
 | 
					    go run src/*.go
 | 
				
			||||||
							
								
								
									
										5
									
								
								go.mod
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								go.mod
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,5 @@
 | 
				
			||||||
 | 
					module beretta
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					go 1.22.7
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					require github.com/mattn/go-sqlite3 v1.14.23 // indirect
 | 
				
			||||||
							
								
								
									
										2
									
								
								go.sum
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								go.sum
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,2 @@
 | 
				
			||||||
 | 
					github.com/mattn/go-sqlite3 v1.14.23 h1:gbShiuAP1W5j9UOksQ06aiiqPMxYecovVGwmTxWtuw0=
 | 
				
			||||||
 | 
					github.com/mattn/go-sqlite3 v1.14.23/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
 | 
				
			||||||
							
								
								
									
										49
									
								
								src/db.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								src/db.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,49 @@
 | 
				
			||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						_ "embed"
 | 
				
			||||||
 | 
						_ "github.com/mattn/go-sqlite3"
 | 
				
			||||||
 | 
						"database/sql"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//go:embed init.sql
 | 
				
			||||||
 | 
					var initSQL string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Db interface {
 | 
				
			||||||
 | 
						// CheckAndStore checks if the tag is already stored in the database and stores it if it's not.
 | 
				
			||||||
 | 
						CheckAndStore(repo, tag string) (bool, error)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type SQLiteDb struct {
 | 
				
			||||||
 | 
						DB *sql.DB
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s SQLiteDb) CheckAndStore(repo, tag string) (bool, error) {
 | 
				
			||||||
 | 
						var count int
 | 
				
			||||||
 | 
						err := s.DB.QueryRow("SELECT COUNT(*) FROM tags WHERE repo = ? AND tag = ?", repo, tag).Scan(&count)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return false, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if count > 0 {
 | 
				
			||||||
 | 
							return false, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						_, err = s.DB.Exec("INSERT INTO tags (repo, tag) VALUES (?, ?)", repo, tag)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return false, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return true, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewSQLiteDb creates a new SQLite database connection.
 | 
				
			||||||
 | 
					// The database is created if it doesn't exist.
 | 
				
			||||||
 | 
					func NewSQLiteDb(file string) (SQLiteDb, error) {
 | 
				
			||||||
 | 
						db, err := sql.Open("sqlite3", file)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return SQLiteDb{}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						_, err = db.Exec(initSQL)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return SQLiteDb{}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return SQLiteDb{DB: db}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										5
									
								
								src/init.sql
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/init.sql
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,5 @@
 | 
				
			||||||
 | 
					CREATE TABLE IF NOT EXISTS tags (
 | 
				
			||||||
 | 
					    id INTEGER PRIMARY KEY AUTOINCREMENT,
 | 
				
			||||||
 | 
					    repo TEXT NOT NULL,
 | 
				
			||||||
 | 
					    tag TEXT NOT NULL
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
							
								
								
									
										23
									
								
								src/main.go
									
										
									
									
									
								
							
							
						
						
									
										23
									
								
								src/main.go
									
										
									
									
									
								
							| 
						 | 
					@ -7,7 +7,17 @@ import (
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func main() {
 | 
					func main() {
 | 
				
			||||||
	// Load configuration
 | 
						// Load configuration
 | 
				
			||||||
	config := loadConfig("config.json")
 | 
						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)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						_ = db
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	notifier := NtfyNotifier{Topic: config.NtfyTopic}
 | 
						notifier := NtfyNotifier{Topic: config.NtfyTopic}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,11 +32,22 @@ func main() {
 | 
				
			||||||
			if tag.Name == "" {
 | 
								if tag.Name == "" {
 | 
				
			||||||
				log.Printf("No tags found for %s", repo.Repo)
 | 
									log.Printf("No tags found for %s", repo.Repo)
 | 
				
			||||||
				continue
 | 
									continue
 | 
				
			||||||
 | 
									_ = notifier
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Check and store tag
 | 
				
			||||||
 | 
								stored, err := db.CheckAndStore(repo.Repo, tag.Name)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									log.Printf("Failed to store tag for %s: %v", repo.Repo, err)
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if stored {
 | 
				
			||||||
 | 
									log.Printf("New tag stored for %s: %s", repo.Repo, tag.Name)
 | 
				
			||||||
				if notifier.Notify(repo, tag.Name) {
 | 
									if notifier.Notify(repo, tag.Name) {
 | 
				
			||||||
					log.Printf("Notified for %s/%s: %s", repo.Owner, repo.Repo, tag.Name)
 | 
										log.Printf("Notified for %s/%s: %s", repo.Owner, repo.Repo, tag.Name)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		time.Sleep(time.Duration(config.Interval) * time.Second)
 | 
							time.Sleep(time.Duration(config.Interval) * time.Second)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,7 +19,7 @@ type RepoConfig struct {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (r RepoConfig) GetLatestTag() (Tag, error) {
 | 
					func (r RepoConfig) GetLatestTag() (Tag, error) {
 | 
				
			||||||
	url := fmt.Sprintf("https://api.github.com/repos/%s/%s/tags", r.Owner, r.Repo)
 | 
						url := fmt.Sprintf("https://api.github.com/repos/%s/%s/tags", r.Owner, r.Repo)
 | 
				
			||||||
	fmt.Printf(url)
 | 
					
 | 
				
			||||||
	resp, err := http.Get(url)
 | 
						resp, err := http.Get(url)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		log.Printf("Failed to fetch releases for %s/%s: %v", r.Owner, r.Repo, err)
 | 
							log.Printf("Failed to fetch releases for %s/%s: %v", r.Owner, r.Repo, err)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										11
									
								
								src/types.go
									
										
									
									
									
								
							
							
						
						
									
										11
									
								
								src/types.go
									
										
									
									
									
								
							| 
						 | 
					@ -16,20 +16,25 @@ type Config struct {
 | 
				
			||||||
	NtfyTopic string       `json:"ntfy_topic"`
 | 
						NtfyTopic string       `json:"ntfy_topic"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func loadConfig(file string) Config {
 | 
					func loadConfig(file string) (Config, error) {
 | 
				
			||||||
 | 
						var config Config
 | 
				
			||||||
	fh, err := os.OpenFile(file, os.O_RDONLY, 0644)
 | 
						fh, err := os.OpenFile(file, os.O_RDONLY, 0644)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		log.Fatalf("Failed to open config file: %v", err)
 | 
							log.Fatalf("Failed to open config file: %v", err)
 | 
				
			||||||
 | 
							return Config{}, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	data, err := io.ReadAll(fh)
 | 
						data, err := io.ReadAll(fh)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		log.Fatalf("Failed to read config file: %v", err)
 | 
							log.Fatalf("Failed to read config file: %v", err)
 | 
				
			||||||
 | 
							return Config{}, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	var config Config
 | 
					 | 
				
			||||||
	if err := json.Unmarshal(data, &config); err != nil {
 | 
						if err := json.Unmarshal(data, &config); err != nil {
 | 
				
			||||||
		log.Fatalf("Failed to parse config file: %v", err)
 | 
							log.Fatalf("Failed to parse config file: %v", err)
 | 
				
			||||||
 | 
							return Config{}, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return config
 | 
					
 | 
				
			||||||
 | 
						return config, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Notifier interface {
 | 
					type Notifier interface {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue