2018-10-09 10:45:25 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"net/http"
|
|
|
|
"net/url"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/pkg/errors"
|
2023-09-08 12:23:22 +00:00
|
|
|
"github.com/sirupsen/logrus"
|
2018-10-09 10:45:25 +00:00
|
|
|
"golang.org/x/net/context"
|
|
|
|
)
|
|
|
|
|
2023-09-08 12:23:22 +00:00
|
|
|
const aurCacheDuration = 10 * time.Minute
|
|
|
|
|
2018-10-09 10:45:25 +00:00
|
|
|
func init() {
|
|
|
|
registerServiceHandler("aur", aurServiceHandler{})
|
|
|
|
}
|
|
|
|
|
|
|
|
type aurServiceHandler struct{}
|
|
|
|
|
|
|
|
type aurInfoResult struct {
|
|
|
|
Version int `json:"version"`
|
|
|
|
Type string `json:"type"`
|
|
|
|
Resultcount int `json:"resultcount"`
|
|
|
|
Results []struct {
|
|
|
|
ID int `json:"ID"`
|
|
|
|
Name string `json:"Name"`
|
|
|
|
PackageBaseID int `json:"PackageBaseID"`
|
|
|
|
PackageBase string `json:"PackageBase"`
|
|
|
|
Version string `json:"Version"`
|
|
|
|
Description string `json:"Description"`
|
|
|
|
URL string `json:"URL"`
|
|
|
|
NumVotes int `json:"NumVotes"`
|
|
|
|
Popularity float64 `json:"Popularity"`
|
|
|
|
OutOfDate int `json:"OutOfDate"`
|
|
|
|
Maintainer string `json:"Maintainer"`
|
|
|
|
FirstSubmitted int `json:"FirstSubmitted"`
|
|
|
|
LastModified int `json:"LastModified"`
|
|
|
|
URLPath string `json:"URLPath"`
|
|
|
|
Depends []string `json:"Depends"`
|
|
|
|
License []string `json:"License"`
|
|
|
|
Keywords []string `json:"Keywords"`
|
|
|
|
MakeDepends []string `json:"MakeDepends,omitempty"`
|
|
|
|
} `json:"results"`
|
|
|
|
}
|
|
|
|
|
2023-09-08 12:23:22 +00:00
|
|
|
func (aurServiceHandler) GetDocumentation() serviceHandlerDocumentationList {
|
2018-10-09 10:45:25 +00:00
|
|
|
return serviceHandlerDocumentationList{
|
|
|
|
{
|
|
|
|
ServiceName: "AUR package version",
|
|
|
|
DemoPath: "/aur/version/yay",
|
|
|
|
Arguments: []string{"version", "<package name>"},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ServiceName: "AUR package votes",
|
|
|
|
DemoPath: "/aur/votes/yay",
|
|
|
|
Arguments: []string{"votes", "<package name>"},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ServiceName: "AUR package license",
|
|
|
|
DemoPath: "/aur/license/yay",
|
|
|
|
Arguments: []string{"license", "<package name>"},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ServiceName: "AUR package last update",
|
|
|
|
DemoPath: "/aur/updated/yay",
|
|
|
|
Arguments: []string{"updated", "<package name>"},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-11 10:16:15 +00:00
|
|
|
func (aurServiceHandler) IsEnabled() bool { return true }
|
|
|
|
|
2018-10-09 10:45:25 +00:00
|
|
|
func (a aurServiceHandler) Handle(ctx context.Context, params []string) (title, text, color string, err error) {
|
2023-09-08 12:23:22 +00:00
|
|
|
if len(params) < 2 { //nolint:gomnd
|
2018-10-09 10:45:25 +00:00
|
|
|
return title, text, color, errors.New("No service-command / parameters were given")
|
|
|
|
}
|
|
|
|
|
|
|
|
switch params[0] {
|
2023-09-08 12:23:22 +00:00
|
|
|
case "license": //nolint:goconst
|
2018-10-09 10:45:25 +00:00
|
|
|
return a.handleAURLicense(ctx, params[1:])
|
|
|
|
case "updated":
|
|
|
|
return a.handleAURUpdated(ctx, params[1:])
|
|
|
|
case "version":
|
|
|
|
return a.handleAURVersion(ctx, params[1:])
|
|
|
|
case "votes":
|
|
|
|
return a.handleAURVotes(ctx, params[1:])
|
|
|
|
default:
|
|
|
|
return title, text, color, errors.New("An unknown service command was called")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (a aurServiceHandler) handleAURLicense(ctx context.Context, params []string) (title, text, color string, err error) {
|
|
|
|
title = params[0]
|
|
|
|
text, err = cacheStore.Get("aur_license", title)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
info, err := a.fetchAURInfo(ctx, params[0])
|
|
|
|
if err != nil {
|
|
|
|
return title, text, color, err
|
|
|
|
}
|
|
|
|
|
|
|
|
text = strings.Join(info.Results[0].License, ", ")
|
|
|
|
|
2023-09-08 12:23:22 +00:00
|
|
|
logErr(cacheStore.Set("aur_license", title, text, aurCacheDuration), "writing AUR license to cache")
|
2018-10-09 10:45:25 +00:00
|
|
|
}
|
|
|
|
|
2023-09-08 12:23:22 +00:00
|
|
|
return "license", text, colorNameBlue, nil
|
2018-10-09 10:45:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (a aurServiceHandler) handleAURVersion(ctx context.Context, params []string) (title, text, color string, err error) {
|
|
|
|
title = params[0]
|
|
|
|
text, err = cacheStore.Get("aur_version", title)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
info, err := a.fetchAURInfo(ctx, params[0])
|
|
|
|
if err != nil {
|
|
|
|
return title, text, color, err
|
|
|
|
}
|
|
|
|
|
|
|
|
text = info.Results[0].Version
|
|
|
|
|
2023-09-08 12:23:22 +00:00
|
|
|
logErr(cacheStore.Set("aur_version", title, text, aurCacheDuration), "writing AUR version to cache")
|
2018-10-09 10:45:25 +00:00
|
|
|
}
|
|
|
|
|
2023-09-08 12:23:22 +00:00
|
|
|
return title, text, colorNameBlue, nil
|
2018-10-09 10:45:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (a aurServiceHandler) handleAURUpdated(ctx context.Context, params []string) (title, text, color string, err error) {
|
|
|
|
title = params[0]
|
|
|
|
text, err = cacheStore.Get("aur_updated", title)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
info, err := a.fetchAURInfo(ctx, params[0])
|
|
|
|
if err != nil {
|
|
|
|
return title, text, color, err
|
|
|
|
}
|
|
|
|
|
|
|
|
update := time.Unix(int64(info.Results[0].LastModified), 0)
|
|
|
|
text = update.Format("2006-01-02 15:04:05")
|
|
|
|
|
|
|
|
if info.Results[0].OutOfDate > 0 {
|
2023-09-08 12:23:22 +00:00
|
|
|
text += " (outdated)"
|
2018-10-09 10:45:25 +00:00
|
|
|
}
|
|
|
|
|
2023-09-08 12:23:22 +00:00
|
|
|
logErr(cacheStore.Set("aur_updated", title, text, aurCacheDuration), "writing AUR updated to cache")
|
2018-10-09 10:45:25 +00:00
|
|
|
}
|
|
|
|
|
2023-09-08 12:23:22 +00:00
|
|
|
color = colorNameBlue
|
2018-10-09 10:45:25 +00:00
|
|
|
if strings.Contains(text, "outdated") {
|
|
|
|
color = "red"
|
|
|
|
}
|
|
|
|
|
|
|
|
return "last updated", text, color, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (a aurServiceHandler) handleAURVotes(ctx context.Context, params []string) (title, text, color string, err error) {
|
|
|
|
title = params[0]
|
|
|
|
text, err = cacheStore.Get("aur_votes", title)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
info, err := a.fetchAURInfo(ctx, params[0])
|
|
|
|
if err != nil {
|
|
|
|
return title, text, color, err
|
|
|
|
}
|
|
|
|
|
|
|
|
text = strconv.Itoa(info.Results[0].NumVotes) + " votes"
|
|
|
|
|
2023-09-08 12:23:22 +00:00
|
|
|
logErr(cacheStore.Set("aur_votes", title, text, aurCacheDuration), "writing AUR votes to cache")
|
2018-10-09 10:45:25 +00:00
|
|
|
}
|
|
|
|
|
2023-09-08 12:23:22 +00:00
|
|
|
return title, text, colorNameBrightGreen, nil
|
2018-10-09 10:45:25 +00:00
|
|
|
}
|
|
|
|
|
2023-09-08 12:23:22 +00:00
|
|
|
func (aurServiceHandler) fetchAURInfo(ctx context.Context, pkg string) (*aurInfoResult, error) {
|
2018-10-09 10:45:25 +00:00
|
|
|
params := url.Values{
|
|
|
|
"v": []string{"5"},
|
|
|
|
"type": []string{"info"},
|
|
|
|
"arg": []string{pkg},
|
|
|
|
}
|
2023-09-08 12:23:22 +00:00
|
|
|
u := "https://aur.archlinux.org/rpc/?" + params.Encode()
|
2018-10-09 10:45:25 +00:00
|
|
|
|
2023-09-08 12:23:22 +00:00
|
|
|
req, _ := http.NewRequest("GET", u, nil)
|
2018-10-09 10:45:25 +00:00
|
|
|
resp, err := http.DefaultClient.Do(req.WithContext(ctx))
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrap(err, "Failed to fetch AUR info")
|
|
|
|
}
|
2023-09-08 12:23:22 +00:00
|
|
|
defer func() {
|
|
|
|
if err := resp.Body.Close(); err != nil {
|
|
|
|
logrus.WithError(err).Error("closing response body (leaked fd)")
|
|
|
|
}
|
|
|
|
}()
|
2018-10-09 10:45:25 +00:00
|
|
|
|
|
|
|
out := &aurInfoResult{}
|
|
|
|
if err := json.NewDecoder(resp.Body).Decode(out); err != nil {
|
|
|
|
return nil, errors.Wrap(err, "Failed to parse AUR info")
|
|
|
|
}
|
|
|
|
|
|
|
|
if out.Resultcount == 0 {
|
|
|
|
return nil, errors.New("No package was found")
|
|
|
|
}
|
|
|
|
|
|
|
|
return out, nil
|
|
|
|
}
|