Add regex fetcher

Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
Knut Ahlers 2021-11-29 14:55:28 +01:00
parent b824da5c1d
commit f1f5b405c4
Signed by: luzifer
GPG key ID: 0066F03ED215AD7D

89
internal/fetcher/regex.go Normal file
View file

@ -0,0 +1,89 @@
package fetcher
import (
"context"
"io/ioutil"
"net/http"
"regexp"
"time"
"github.com/pkg/errors"
"github.com/Luzifer/go-latestver/internal/database"
"github.com/Luzifer/go_helpers/v2/fieldcollection"
)
const (
httpStatus3xx = 300
regexpFetcherExpectedLength = 2
)
type (
RegexFetcher struct{}
)
func init() { registerFetcher("regex", func() Fetcher { return &RegexFetcher{} }) }
func (h RegexFetcher) FetchVersion(ctx context.Context, attrs *fieldcollection.FieldCollection) (string, time.Time, error) {
req, err := http.NewRequestWithContext(ctx, http.MethodGet, attrs.MustString("url", nil), 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 resp.Body.Close()
if resp.StatusCode >= httpStatus3xx {
return "", time.Time{}, errors.Errorf("HTTP status %d", resp.StatusCode)
}
data, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", time.Time{}, errors.Wrap(err, "reading response body")
}
matches := regexp.MustCompile(attrs.MustString("regex", nil)).FindStringSubmatch(string(data))
if matches == nil {
return "", time.Time{}, errors.New("regex did not match the response")
}
if l := len(matches); l != regexpFetcherExpectedLength {
return "", time.Time{}, errors.Errorf("unpexected number of matches: %d != 2", l)
}
return matches[1], time.Now(), nil
}
func (h RegexFetcher) Links(attrs *fieldcollection.FieldCollection) []database.CatalogLink {
return []database.CatalogLink{
{
IconClass: "fas fa-globe",
Name: "Website",
URL: attrs.MustString("url", nil),
},
}
}
func (h RegexFetcher) Validate(attrs *fieldcollection.FieldCollection) error {
if v, err := attrs.String("url"); err != nil || v == "" {
return errors.New("url is expected to be non-empty string")
}
if v, err := attrs.String("regex"); err != nil || v == "" {
return errors.New("regex is expected to be non-empty string")
}
r, err := regexp.Compile(attrs.MustString("regex", nil))
if err != nil {
return errors.Wrap(err, "compiling regex expression")
}
if n := r.NumSubexp(); n != 1 {
return errors.Errorf("regex must have 1 submatch, has %d", n)
}
return nil
}