2020-09-12 17:09:23 +03:00
package v1
import (
2021-03-24 23:49:42 +03:00
"fmt"
2023-03-03 22:40:50 +03:00
"github.com/go-chi/chi/v5"
2022-12-01 12:57:07 +03:00
"github.com/muety/wakapi/helpers"
2022-04-18 12:39:26 +03:00
routeutils "github.com/muety/wakapi/routes/utils"
2022-01-02 03:22:58 +03:00
"net/http"
"time"
2020-11-08 12:12:49 +03:00
conf "github.com/muety/wakapi/config"
2020-09-12 17:09:23 +03:00
"github.com/muety/wakapi/models"
v1 "github.com/muety/wakapi/models/compat/shields/v1"
"github.com/muety/wakapi/services"
2021-03-24 23:49:42 +03:00
"github.com/patrickmn/go-cache"
2020-09-12 17:09:23 +03:00
)
type BadgeHandler struct {
2020-11-08 12:12:49 +03:00
config * conf . Config
userSrvc services . IUserService
summarySrvc services . ISummaryService
2021-03-24 23:49:42 +03:00
cache * cache . Cache
2020-09-12 17:09:23 +03:00
}
2020-11-08 12:12:49 +03:00
func NewBadgeHandler ( summaryService services . ISummaryService , userService services . IUserService ) * BadgeHandler {
2020-09-12 17:09:23 +03:00
return & BadgeHandler {
summarySrvc : summaryService ,
userSrvc : userService ,
2021-03-24 23:49:42 +03:00
cache : cache . New ( time . Hour , time . Hour ) ,
2020-11-08 12:12:49 +03:00
config : conf . Get ( ) ,
2020-09-12 17:09:23 +03:00
}
}
2023-03-03 22:40:50 +03:00
func ( h * BadgeHandler ) RegisterRoutes ( router chi . Router ) {
2021-02-06 22:09:08 +03:00
// no auth middleware here, handler itself resolves the user
2023-03-03 22:40:50 +03:00
router . Get ( "/compat/shields/v1/{user}/*" , h . Get )
2021-01-30 12:34:52 +03:00
}
2021-02-07 13:54:07 +03:00
// @Summary Get badge data
// @Description Retrieve total time for a given entity (e.g. a project) within a given range (e.g. one week) in a format compatible with [Shields.io](https://shields.io/endpoint). Requires public data access to be allowed.
// @ID get-badge
// @Tags badges
// @Produce json
// @Param user path string true "User ID to fetch data for"
2022-08-19 18:14:00 +03:00
// @Param interval path string true "Interval to aggregate data for" Enums(today, yesterday, week, month, year, 7_days, last_7_days, 30_days, last_30_days, 6_months, last_6_months, 12_months, last_12_months, last_year, any, all_time)
2021-02-07 13:54:07 +03:00
// @Param filter path string true "Filter to apply (e.g. 'project:wakapi' or 'language:Go')"
// @Success 200 {object} v1.BadgeData
2022-01-02 03:22:58 +03:00
// @Router /compat/shields/v1/{user}/{interval}/{filter} [get]
2021-02-03 23:28:02 +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" ) )
2021-02-07 00:32:03 +03:00
if err != nil {
w . WriteHeader ( http . StatusNotFound )
return
}
2022-04-18 12:39:26 +03:00
interval , filters , err := routeutils . GetBadgeParams ( r , user )
if err != nil {
2021-06-11 17:02:28 +03:00
w . WriteHeader ( http . StatusForbidden )
2022-04-18 12:39:26 +03:00
w . Write ( [ ] byte ( err . Error ( ) ) )
2021-06-11 17:02:28 +03:00
return
}
2022-04-18 12:39:26 +03:00
cacheKey := fmt . Sprintf ( "%s_%v_%s" , user . ID , * interval . Key , filters . Hash ( ) )
2021-03-24 23:49:42 +03:00
if cacheResult , ok := h . cache . Get ( cacheKey ) ; ok {
2022-12-01 12:57:07 +03:00
helpers . RespondJSON ( w , r , http . StatusOK , cacheResult . ( * v1 . BadgeData ) )
2021-03-24 23:49:42 +03:00
return
}
2022-04-18 12:39:26 +03:00
params := & models . SummaryParams {
From : interval . Start ,
To : interval . End ,
User : user ,
Filters : filters ,
}
summary , err , status := routeutils . LoadUserSummaryByParams ( h . summarySrvc , params )
2020-09-12 17:09:23 +03:00
if err != nil {
w . WriteHeader ( status )
w . Write ( [ ] byte ( err . Error ( ) ) )
return
}
2021-12-26 19:02:14 +03:00
vm := v1 . NewBadgeDataFrom ( summary )
2021-03-24 23:49:42 +03:00
h . cache . SetDefault ( cacheKey , vm )
2022-12-01 12:57:07 +03:00
helpers . RespondJSON ( w , r , http . StatusOK , vm )
2020-09-12 17:09:23 +03:00
}
2021-12-26 19:02:14 +03:00
func ( h * BadgeHandler ) loadUserSummary ( user * models . User , interval * models . IntervalKey , filters * models . Filters ) ( * models . Summary , error , int ) {
2022-12-01 12:57:07 +03:00
err , from , to := helpers . ResolveIntervalTZ ( interval , user . TZ ( ) )
2020-09-12 17:09:23 +03:00
if err != nil {
return nil , err , http . StatusBadRequest
}
summaryParams := & models . SummaryParams {
From : from ,
To : to ,
User : user ,
}
2020-11-07 14:01:35 +03:00
var retrieveSummary services . SummaryRetriever = h . summarySrvc . Retrieve
if summaryParams . Recompute {
retrieveSummary = h . summarySrvc . Summarize
}
2021-12-26 19:02:14 +03:00
summary , err := h . summarySrvc . Aliased (
summaryParams . From ,
summaryParams . To ,
summaryParams . User ,
retrieveSummary ,
filters ,
summaryParams . Recompute ,
)
2020-09-12 17:09:23 +03:00
if err != nil {
return nil , err , http . StatusInternalServerError
}
return summary , nil , http . StatusOK
}