mirror of
https://github.com/Luzifer/go-latestver.git
synced 2024-12-20 10:31:16 +00:00
122 lines
3.7 KiB
Go
122 lines
3.7 KiB
Go
package fetcher
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"sort"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
"github.com/Luzifer/go-latestver/internal/database"
|
|
"github.com/Luzifer/go-latestver/internal/helpers"
|
|
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
|
)
|
|
|
|
/*
|
|
* @module atlassian
|
|
* @module_desc Fetches latest version of an Atlassian product
|
|
*/
|
|
|
|
var (
|
|
atlassianDefaultEdition = ""
|
|
atlassianDefaultSearch = "TAR.GZ"
|
|
)
|
|
|
|
type (
|
|
// AtlassianFetcher implements the fetcher interface to monitor Atlassian products
|
|
AtlassianFetcher struct{}
|
|
)
|
|
|
|
func init() { registerFetcher("atlassian", func() Fetcher { return &AtlassianFetcher{} }) }
|
|
|
|
// FetchVersion retrieves the latest version for the catalog entry
|
|
func (AtlassianFetcher) FetchVersion(ctx context.Context, attrs *fieldcollection.FieldCollection) (string, time.Time, error) {
|
|
url := fmt.Sprintf("https://my.atlassian.com/download/feeds/current/%s.json", attrs.MustString("product", nil))
|
|
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
|
if err != nil {
|
|
return "", time.Time{}, errors.Wrap(err, "creating request")
|
|
}
|
|
|
|
resp, err := http.DefaultClient.Do(req)
|
|
if err != nil {
|
|
return "", time.Time{}, errors.Wrap(err, "executing request")
|
|
}
|
|
defer func() { helpers.LogIfErr(resp.Body.Close(), "closing response body after read") }()
|
|
|
|
body, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return "", time.Time{}, errors.Wrap(err, "reading response body")
|
|
}
|
|
|
|
matches := jsonpStripRegex.FindSubmatch(body)
|
|
if matches == nil {
|
|
return "", time.Time{}, errors.New("document does not match jsonp syntax")
|
|
}
|
|
|
|
var payload []struct {
|
|
Description string `json:"description"`
|
|
Edition string `json:"edition"`
|
|
Zipurl string `json:"zipUrl"`
|
|
Md5 string `json:"md5"`
|
|
Size string `json:"size"`
|
|
Released string `json:"released"`
|
|
Type string `json:"type"`
|
|
Platform string `json:"platform"`
|
|
Version string `json:"version"`
|
|
Releasenotes string `json:"releaseNotes"`
|
|
Upgradenotes string `json:"upgradeNotes"`
|
|
}
|
|
|
|
if err = json.Unmarshal(matches[1], &payload); err != nil {
|
|
return "", time.Time{}, errors.Wrap(err, "parsing response JSON")
|
|
}
|
|
|
|
sort.Slice(payload, func(j, i int) bool { // j, i -> Reverse sort, biggest date at the top
|
|
iRelease, _ := time.Parse("02-Jan-2006", payload[i].Released)
|
|
jRelease, _ := time.Parse("02-Jan-2006", payload[j].Released)
|
|
return iRelease.Before(jRelease)
|
|
})
|
|
|
|
var (
|
|
// @attr edition optional string "" Filter down the versions according to its edition (e.g. "Enterprise" or "Standard" for Confluence)
|
|
edition = attrs.MustString("edition", &atlassianDefaultEdition)
|
|
// @attr search optional string "TAR.GZ" What to search in the download description: default is to search for the standalone .tar.gz file
|
|
search = attrs.MustString("search", &atlassianDefaultSearch)
|
|
)
|
|
|
|
for _, r := range payload {
|
|
if edition != "" && !strings.Contains(r.Edition, edition) {
|
|
continue
|
|
}
|
|
|
|
if search != "" && !strings.Contains(r.Description, search) {
|
|
continue
|
|
}
|
|
|
|
rt, _ := time.Parse("02-Jan-2006", r.Released)
|
|
return r.Version, rt, nil
|
|
}
|
|
|
|
return "", time.Time{}, ErrNoVersionFound
|
|
}
|
|
|
|
// Links retrieves a collection of links for the fetcher
|
|
func (AtlassianFetcher) Links(_ *fieldcollection.FieldCollection) []database.CatalogLink {
|
|
return nil
|
|
}
|
|
|
|
// Validate validates the configuration given to the fetcher
|
|
func (AtlassianFetcher) Validate(attrs *fieldcollection.FieldCollection) error {
|
|
// @attr product required string "" Lowercase name of the product to fetch (e.g. confluence, crowd, jira-software, ...)
|
|
if v, err := attrs.String("product"); err != nil || v == "" {
|
|
return errors.New("product is expected to be non-empty string")
|
|
}
|
|
|
|
return nil
|
|
}
|