Compare commits
8 commits
416145dfaa
...
c0e643f299
Author | SHA1 | Date | |
---|---|---|---|
![]() |
c0e643f299 | ||
![]() |
73507c3e7f | ||
![]() |
adda00508e | ||
![]() |
a6ac787270 | ||
![]() |
573e8e3617 | ||
![]() |
9d2eec5250 | ||
![]() |
64553bb153 | ||
![]() |
0b11ac87cd |
9 changed files with 112 additions and 12 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1,2 +1,3 @@
|
||||||
*.db
|
*.db
|
||||||
beretta*
|
data
|
||||||
|
bin
|
||||||
|
|
16
Containerfile
Normal file
16
Containerfile
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
FROM docker.io/golang:1.24 AS builder
|
||||||
|
WORKDIR /app
|
||||||
|
COPY go.mod go.sum ./
|
||||||
|
RUN go mod download
|
||||||
|
COPY src src
|
||||||
|
RUN GOOS=linux go build -o beretta src/*.go
|
||||||
|
# FROM docker.io/alpine:3
|
||||||
|
FROM docker.io/debian:bookworm-slim
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y \
|
||||||
|
ca-certificates \
|
||||||
|
sqlite3 \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
COPY --from=builder /app/beretta /beretta
|
||||||
|
ENTRYPOINT ["/beretta"]
|
7
Makefile
7
Makefile
|
@ -1,8 +1,11 @@
|
||||||
|
build:
|
||||||
|
go build -o bin/beretta src/*.go
|
||||||
|
|
||||||
run:
|
run:
|
||||||
go run src/*.go
|
go run src/*.go
|
||||||
|
|
||||||
build:
|
build-container:
|
||||||
go build -o beretta src/*.go
|
podman build -t beretta .
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm beretta
|
rm beretta
|
||||||
|
|
14
beretta.service
Normal file
14
beretta.service
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Beretta Service
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
ExecStart=/usr/local/bin/beretta
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=5
|
||||||
|
User=beretta
|
||||||
|
WorkingDirectory=/usr/local/bin
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
11
docker-compose.yml
Normal file
11
docker-compose.yml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
services:
|
||||||
|
beretta:
|
||||||
|
image: beretta:latest
|
||||||
|
name: beretta-server
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
command: >
|
||||||
|
-config /data/beretta.json
|
||||||
|
-db /data/cache.db
|
||||||
|
volumes:
|
||||||
|
- ./data:/data:Z
|
|
@ -10,6 +10,6 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"interval": 1200,
|
"interval": 1200,
|
||||||
"ntfy_topic": "hee4waeNguch"
|
"ntfy_topic": "{{.TopicToken}}"
|
||||||
}
|
}
|
||||||
|
|
48
src/main.go
48
src/main.go
|
@ -1,12 +1,18 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
_ "embed"
|
||||||
"flag"
|
"flag"
|
||||||
"log"
|
"log"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
"os"
|
||||||
|
"text/template"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//go:embed beretta.json
|
||||||
|
var defconfig string
|
||||||
|
|
||||||
type RepoUpdate struct {
|
type RepoUpdate struct {
|
||||||
repo Repo
|
repo Repo
|
||||||
Tag string
|
Tag string
|
||||||
|
@ -22,7 +28,7 @@ func notifierThread(c chan RepoUpdate, n Notifier) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func repoThread(c chan RepoUpdate, repo Repo, avgInterval int, db Db) {
|
func repoThread(c chan RepoUpdate, repo Repo, avgInterval int, db Db) {
|
||||||
log.Println("Checking", repo.IdTuple())
|
log.Println("Checking: ", repo.IdTuple())
|
||||||
tag, err := repo.GetLatestTag()
|
tag, err := repo.GetLatestTag()
|
||||||
isNewVersion, err_2 := db.CheckAndStore(repo.IdTuple(), tag.Name)
|
isNewVersion, err_2 := db.CheckAndStore(repo.IdTuple(), tag.Name)
|
||||||
|
|
||||||
|
@ -33,6 +39,7 @@ func repoThread(c chan RepoUpdate, repo Repo, avgInterval int, db Db) {
|
||||||
} else if isNewVersion {
|
} else if isNewVersion {
|
||||||
c <- RepoUpdate{repo, tag.Name}
|
c <- RepoUpdate{repo, tag.Name}
|
||||||
}
|
}
|
||||||
|
log.Println("Checking done: ", repo.IdTuple())
|
||||||
|
|
||||||
sleepTime := time.Duration(rand.Intn(avgInterval)) * time.Second
|
sleepTime := time.Duration(rand.Intn(avgInterval)) * time.Second
|
||||||
time.Sleep(sleepTime)
|
time.Sleep(sleepTime)
|
||||||
|
@ -41,25 +48,54 @@ func repoThread(c chan RepoUpdate, repo Repo, avgInterval int, db Db) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
conf_path := flag.String("config", "beretta.json", "The path to the config file")
|
||||||
conf := flag.String("config", "./beretta.json", "The path to the config file")
|
db_path := flag.String("db", "cache.db", "The path to the cache database")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
log.Printf("Using config path: %s", *conf)
|
tmpl, err := template.New("config").Parse(defconfig)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
randtk, err := randToken(8)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
data := map[string]any{
|
||||||
|
"TopicToken": randtk,
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := os.Stat(*conf_path); os.IsNotExist(err) {
|
||||||
|
log.Printf("Writing new config file: %s", *conf_path)
|
||||||
|
file, err := os.Create(*conf_path)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
err = tmpl.Execute(file, data)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Error writing config file: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Using config path: %s", *conf_path)
|
||||||
|
log.Printf("Using db path: %s", *db_path)
|
||||||
|
|
||||||
// Load configuration
|
// Load configuration
|
||||||
config, err := loadConfig(*conf)
|
config, err := loadConfig(*conf_path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to load configuration: %v", err)
|
log.Fatalf("Failed to load configuration: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create database
|
// Create database
|
||||||
db, err := NewSQLiteDb("tags.db")
|
db, err := NewSQLiteDb(*db_path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to create database: %v", err)
|
log.Fatalf("Failed to create database: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
notifier := NtfyNotifier{Topic: config.NtfyTopic}
|
notifier := NtfyNotifier{Topic: config.NtfyTopic}
|
||||||
|
log.Printf("Sending notifications to: %s", notifier.Url())
|
||||||
|
|
||||||
c := make(chan RepoUpdate)
|
c := make(chan RepoUpdate)
|
||||||
|
|
||||||
|
|
14
src/random_token.go
Normal file
14
src/random_token.go
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/hex"
|
||||||
|
)
|
||||||
|
|
||||||
|
func randToken(n int) (string, error) {
|
||||||
|
bytes := make([]byte, n)
|
||||||
|
if _, err := rand.Read(bytes); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return hex.EncodeToString(bytes), nil
|
||||||
|
}
|
|
@ -39,6 +39,7 @@ func loadConfig(file string) (Config, error) {
|
||||||
|
|
||||||
type Notifier interface {
|
type Notifier interface {
|
||||||
Notify(repo Repo, tag string) bool
|
Notify(repo Repo, tag string) bool
|
||||||
|
Url() string
|
||||||
}
|
}
|
||||||
|
|
||||||
type NtfyNotifier struct {
|
type NtfyNotifier struct {
|
||||||
|
@ -46,10 +47,10 @@ type NtfyNotifier struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n NtfyNotifier) Notify(repo Repo, tag string) bool {
|
func (n NtfyNotifier) Notify(repo Repo, tag string) bool {
|
||||||
ntfyURL := fmt.Sprintf("https://ntfy.sh/%s", n.Topic)
|
// ntfyURL := fmt.Sprintf("https://ntfy.sh/%s", n.Topic)
|
||||||
message := fmt.Sprintf("New release for %s/%s: %s", repo.Owner(), repo.Name(), tag)
|
message := fmt.Sprintf("New release for %s/%s: %s", repo.Owner(), repo.Name(), tag)
|
||||||
|
|
||||||
_, err := http.Post(ntfyURL, "text/plain", bytes.NewBuffer([]byte(message)))
|
_, err := http.Post(n.Url(), "text/plain", bytes.NewBuffer([]byte(message)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed to send notification: %v", err)
|
log.Printf("Failed to send notification: %v", err)
|
||||||
return false
|
return false
|
||||||
|
@ -57,3 +58,7 @@ func (n NtfyNotifier) Notify(repo Repo, tag string) bool {
|
||||||
log.Printf("Notification sent: %s", message)
|
log.Printf("Notification sent: %s", message)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n NtfyNotifier) Url() string {
|
||||||
|
return fmt.Sprintf("https://ntfy.sh/%s", n.Topic)
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue