1
0
mirror of https://github.com/muety/wakapi.git synced 2023-08-10 21:12:56 +03:00

feat: implement badges endpoint and sharing functionality

This commit is contained in:
Ferdinand Mütsch
2020-09-12 16:09:23 +02:00
parent 19a8c61f77
commit d60dddb550
19 changed files with 409 additions and 102 deletions

View File

@ -0,0 +1,96 @@
package v1
import (
"github.com/gorilla/mux"
"github.com/muety/wakapi/models"
v1 "github.com/muety/wakapi/models/compat/shields/v1"
"github.com/muety/wakapi/services"
"github.com/muety/wakapi/utils"
"net/http"
"regexp"
)
const (
intervalPattern = `interval:([a-z0-9_]+)`
entityFilterPattern = `(project|os|editor|language|machine):([_a-zA-Z0-9-]+)`
)
type BadgeHandler struct {
userSrvc *services.UserService
summarySrvc *services.SummaryService
config *models.Config
}
func NewBadgeHandler(summaryService *services.SummaryService, userService *services.UserService) *BadgeHandler {
return &BadgeHandler{
summarySrvc: summaryService,
userSrvc: userService,
config: models.GetConfig(),
}
}
func (h *BadgeHandler) ApiGet(w http.ResponseWriter, r *http.Request) {
intervalReg := regexp.MustCompile(intervalPattern)
entityFilterReg := regexp.MustCompile(entityFilterPattern)
requestedUserId := mux.Vars(r)["user"]
user, err := h.userSrvc.GetUserById(requestedUserId)
if err != nil || !user.BadgesEnabled {
w.WriteHeader(http.StatusUnauthorized)
return
}
var filterEntity, filterKey string
if groups := entityFilterReg.FindStringSubmatch(r.URL.Path); len(groups) > 2 {
filterEntity, filterKey = groups[1], groups[2]
}
var interval = models.IntervalPast30Days
if groups := intervalReg.FindStringSubmatch(r.URL.Path); len(groups) > 1 {
interval = groups[1]
}
filters := &models.Filters{}
switch filterEntity {
case "project":
filters.Project = filterKey
case "os":
filters.OS = filterKey
case "editor":
filters.Editor = filterKey
case "language":
filters.Language = filterKey
case "machine":
filters.Machine = filterKey
}
summary, err, status := h.loadUserSummary(user, interval)
if err != nil {
w.WriteHeader(status)
w.Write([]byte(err.Error()))
return
}
vm := v1.NewBadgeDataFrom(summary, filters)
utils.RespondJSON(w, http.StatusOK, vm)
}
func (h *BadgeHandler) loadUserSummary(user *models.User, interval string) (*models.Summary, error, int) {
err, from, to := utils.ResolveInterval(interval)
if err != nil {
return nil, err, http.StatusBadRequest
}
summaryParams := &models.SummaryParams{
From: from,
To: to,
User: user,
}
summary, err := h.summarySrvc.Construct(summaryParams.From, summaryParams.To, summaryParams.User, summaryParams.Recompute)
if err != nil {
return nil, err, http.StatusInternalServerError
}
return summary, nil, http.StatusOK
}

View File

@ -3,7 +3,7 @@ package v1
import (
"github.com/gorilla/mux"
"github.com/muety/wakapi/models"
v1 "github.com/muety/wakapi/models/compat/v1"
v1 "github.com/muety/wakapi/models/compat/wakatime/v1"
"github.com/muety/wakapi/services"
"github.com/muety/wakapi/utils"
"net/http"
@ -11,19 +11,19 @@ import (
"time"
)
type CompatV1AllHandler struct {
type AllTimeHandler struct {
summarySrvc *services.SummaryService
config *models.Config
}
func NewCompatV1AllHandler(summaryService *services.SummaryService) *CompatV1AllHandler {
return &CompatV1AllHandler{
func NewAllTimeHandler(summaryService *services.SummaryService) *AllTimeHandler {
return &AllTimeHandler{
summarySrvc: summaryService,
config: models.GetConfig(),
}
}
func (h *CompatV1AllHandler) ApiGet(w http.ResponseWriter, r *http.Request) {
func (h *AllTimeHandler) ApiGet(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
values, _ := url.ParseQuery(r.URL.RawQuery)
@ -42,11 +42,11 @@ func (h *CompatV1AllHandler) ApiGet(w http.ResponseWriter, r *http.Request) {
return
}
vm := v1.NewAllTimeFrom(summary, &v1.Filters{Project: values.Get("project")})
vm := v1.NewAllTimeFrom(summary, &models.Filters{Project: values.Get("project")})
utils.RespondJSON(w, http.StatusOK, vm)
}
func (h *CompatV1AllHandler) loadUserSummary(user *models.User) (*models.Summary, error, int) {
func (h *AllTimeHandler) loadUserSummary(user *models.User) (*models.Summary, error, int) {
summaryParams := &models.SummaryParams{
From: time.Time{},
To: time.Now(),

View File

@ -4,7 +4,7 @@ import (
"errors"
"github.com/gorilla/mux"
"github.com/muety/wakapi/models"
v1 "github.com/muety/wakapi/models/compat/v1"
v1 "github.com/muety/wakapi/models/compat/wakatime/v1"
"github.com/muety/wakapi/services"
"github.com/muety/wakapi/utils"
"net/http"
@ -12,13 +12,13 @@ import (
"time"
)
type CompatV1SummariesHandler struct {
type SummariesHandler struct {
summarySrvc *services.SummaryService
config *models.Config
}
func NewCompatV1SummariesHandler(summaryService *services.SummaryService) *CompatV1SummariesHandler {
return &CompatV1SummariesHandler{
func NewSummariesHandler(summaryService *services.SummaryService) *SummariesHandler {
return &SummariesHandler{
summarySrvc: summaryService,
config: models.GetConfig(),
}
@ -30,7 +30,7 @@ https://wakatime.com/developers#summaries
timezone can be specified via an offset suffix (e.g. +02:00) in date strings
*/
func (h *CompatV1SummariesHandler) ApiGet(w http.ResponseWriter, r *http.Request) {
func (h *SummariesHandler) ApiGet(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
requestedUser := vars["user"]
authorizedUser := r.Context().Value(models.UserKey).(*models.User)
@ -47,11 +47,11 @@ func (h *CompatV1SummariesHandler) ApiGet(w http.ResponseWriter, r *http.Request
return
}
vm := v1.NewSummariesFrom(summaries, &v1.Filters{})
vm := v1.NewSummariesFrom(summaries, &models.Filters{})
utils.RespondJSON(w, http.StatusOK, vm)
}
func (h *CompatV1SummariesHandler) loadUserSummaries(r *http.Request) ([]*models.Summary, error, int) {
func (h *SummariesHandler) loadUserSummaries(r *http.Request) ([]*models.Summary, error, int) {
user := r.Context().Value(models.UserKey).(*models.User)
params := r.URL.Query()