2022-04-18 12:39:26 +03:00
|
|
|
package api
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"github.com/duke-git/lancet/v2/maputil"
|
|
|
|
"github.com/duke-git/lancet/v2/slice"
|
2023-03-03 22:40:50 +03:00
|
|
|
"github.com/go-chi/chi/v5"
|
2022-04-18 12:39:26 +03:00
|
|
|
conf "github.com/muety/wakapi/config"
|
|
|
|
"github.com/muety/wakapi/models"
|
|
|
|
v1 "github.com/muety/wakapi/models/compat/shields/v1"
|
|
|
|
routeutils "github.com/muety/wakapi/routes/utils"
|
|
|
|
"github.com/muety/wakapi/services"
|
|
|
|
"github.com/muety/wakapi/utils"
|
|
|
|
"github.com/narqo/go-badge"
|
|
|
|
"github.com/patrickmn/go-cache"
|
|
|
|
"net/http"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
type BadgeHandler struct {
|
|
|
|
config *conf.Config
|
|
|
|
cache *cache.Cache
|
|
|
|
userSrvc services.IUserService
|
|
|
|
summarySrvc services.ISummaryService
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewBadgeHandler(userService services.IUserService, summaryService services.ISummaryService) *BadgeHandler {
|
|
|
|
return &BadgeHandler{
|
|
|
|
config: conf.Get(),
|
|
|
|
cache: cache.New(time.Hour, time.Hour),
|
|
|
|
userSrvc: userService,
|
|
|
|
summarySrvc: summaryService,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-03 22:40:50 +03:00
|
|
|
func (h *BadgeHandler) RegisterRoutes(router chi.Router) {
|
2023-03-15 23:47:12 +03:00
|
|
|
router.Get("/badge/{user}/*", h.Get)
|
2022-04-18 12:39:26 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
func (h *BadgeHandler) Get(w http.ResponseWriter, r *http.Request) {
|
2023-03-03 22:40:50 +03:00
|
|
|
user, err := h.userSrvc.GetUserById(chi.URLParam(r, "user"))
|
2022-04-18 12:39:26 +03:00
|
|
|
if err != nil {
|
|
|
|
w.WriteHeader(http.StatusNotFound)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
interval, filters, err := routeutils.GetBadgeParams(r, user)
|
|
|
|
if err != nil {
|
|
|
|
w.WriteHeader(http.StatusForbidden)
|
|
|
|
w.Write([]byte(err.Error()))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
cacheKey := fmt.Sprintf("%s_%v_%s", user.ID, *interval.Key, filters.Hash())
|
|
|
|
noCache := utils.IsNoCache(r, 1*time.Hour)
|
|
|
|
if cacheResult, ok := h.cache.Get(cacheKey); ok && !noCache {
|
|
|
|
respondSvg(w, cacheResult.([]byte))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
params := &models.SummaryParams{
|
|
|
|
From: interval.Start,
|
|
|
|
To: interval.End,
|
|
|
|
User: user,
|
|
|
|
Filters: filters,
|
|
|
|
}
|
|
|
|
|
|
|
|
summary, err, status := routeutils.LoadUserSummaryByParams(h.summarySrvc, params)
|
|
|
|
if err != nil {
|
|
|
|
w.WriteHeader(status)
|
|
|
|
w.Write([]byte(err.Error()))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
badgeData := v1.NewBadgeDataFrom(summary)
|
|
|
|
if customLabel := r.URL.Query().Get("label"); customLabel != "" {
|
|
|
|
badgeData.Label = customLabel
|
|
|
|
}
|
|
|
|
if customColor := r.URL.Query().Get("color"); customColor != "" {
|
|
|
|
badgeData.Color = customColor
|
|
|
|
}
|
|
|
|
|
|
|
|
if badgeData.Color[0:1] != "#" && !slice.Contain(maputil.Keys(badge.ColorScheme), badgeData.Color) {
|
|
|
|
badgeData.Color = "#" + badgeData.Color
|
|
|
|
}
|
|
|
|
|
|
|
|
badgeSvg, err := badge.RenderBytes(badgeData.Label, badgeData.Message, badge.Color(badgeData.Color))
|
|
|
|
h.cache.SetDefault(cacheKey, badgeSvg)
|
|
|
|
respondSvg(w, badgeSvg)
|
|
|
|
}
|
|
|
|
|
|
|
|
func respondSvg(w http.ResponseWriter, data []byte) {
|
|
|
|
w.Header().Set("Content-Type", "image/svg+xml")
|
|
|
|
w.Header().Set("Cache-Control", "max-age=3600")
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
|
|
w.Write(data)
|
|
|
|
}
|