glance/internal/feed/changedetection.go
2024-05-08 11:47:25 +02:00

80 lines
1.6 KiB
Go

package feed
import (
"fmt"
"log/slog"
"net/http"
"time"
)
type changeDetectionResponseJson struct {
Name string `json:"title"`
Url string `json:"url"`
LastChanged int `json:"last_changed"`
}
func parseLastChangeTime(t int) time.Time {
parsedTime := time.Unix(int64(t), 0)
return parsedTime
}
func FetchLatestDetectedChanges(watches []string, token string) (ChangeWatches, error) {
changeWatches := make(ChangeWatches, 0, len(watches))
if len(watches) == 0 {
return changeWatches, nil
}
requests := make([]*http.Request, len(watches))
for i, repository := range watches {
request, _ := http.NewRequest("GET", fmt.Sprintf("https://changedetection.knhash.in/api/v1/watch/%s", repository), nil)
if token != "" {
request.Header.Add("x-api-key", token)
}
requests[i] = request
}
task := decodeJsonFromRequestTask[changeDetectionResponseJson](defaultClient)
job := newJob(task, requests).withWorkers(15)
responses, errs, err := workerPoolDo(job)
if err != nil {
return nil, err
}
var failed int
for i := range responses {
if errs[i] != nil {
failed++
slog.Error("Failed to fetch or parse change detections", "error", errs[i], "url", requests[i].URL)
continue
}
watch := responses[i]
changeWatches = append(changeWatches, ChangeWatch{
Name: watch.Name,
Url: watch.Url,
LastChanged: parseLastChangeTime(watch.LastChanged),
})
}
if len(changeWatches) == 0 {
return nil, ErrNoContent
}
changeWatches.SortByNewest()
if failed > 0 {
return changeWatches, fmt.Errorf("%w: could not get %d watches", ErrPartialContent, failed)
}
return changeWatches, nil
}