2022-10-03 11:53:27 +03:00
|
|
|
package routes
|
|
|
|
|
|
|
|
import (
|
2022-10-03 21:38:19 +03:00
|
|
|
"fmt"
|
2022-10-05 22:52:10 +03:00
|
|
|
"github.com/duke-git/lancet/v2/slice"
|
2022-10-04 00:52:22 +03:00
|
|
|
"github.com/emvi/logbuch"
|
2022-10-03 11:53:27 +03:00
|
|
|
"github.com/gorilla/mux"
|
|
|
|
conf "github.com/muety/wakapi/config"
|
|
|
|
"github.com/muety/wakapi/middlewares"
|
|
|
|
"github.com/muety/wakapi/models"
|
|
|
|
"github.com/muety/wakapi/models/view"
|
|
|
|
"github.com/muety/wakapi/services"
|
|
|
|
"net/http"
|
2022-10-03 21:38:19 +03:00
|
|
|
"strings"
|
2022-10-03 11:53:27 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
type LeaderboardHandler struct {
|
|
|
|
config *conf.Config
|
|
|
|
userService services.IUserService
|
|
|
|
leaderboardService services.ILeaderboardService
|
|
|
|
}
|
|
|
|
|
2022-10-03 21:38:19 +03:00
|
|
|
var allowedAggregations = map[string]uint8{
|
|
|
|
"language": models.SummaryLanguage,
|
|
|
|
}
|
|
|
|
|
2022-10-03 11:53:27 +03:00
|
|
|
func NewLeaderboardHandler(userService services.IUserService, leaderboardService services.ILeaderboardService) *LeaderboardHandler {
|
|
|
|
return &LeaderboardHandler{
|
|
|
|
config: conf.Get(),
|
|
|
|
userService: userService,
|
|
|
|
leaderboardService: leaderboardService,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h *LeaderboardHandler) RegisterRoutes(router *mux.Router) {
|
|
|
|
r := router.PathPrefix("/leaderboard").Subrouter()
|
|
|
|
r.Use(
|
|
|
|
middlewares.NewAuthenticateMiddleware(h.userService).
|
|
|
|
WithRedirectTarget(defaultErrorRedirectTarget()).
|
|
|
|
WithOptionalFor([]string{"/"}).
|
|
|
|
Handler,
|
|
|
|
)
|
|
|
|
r.Methods(http.MethodGet).HandlerFunc(h.GetIndex)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h *LeaderboardHandler) GetIndex(w http.ResponseWriter, r *http.Request) {
|
|
|
|
if h.config.IsDev() {
|
|
|
|
loadTemplates()
|
|
|
|
}
|
2022-10-04 00:52:22 +03:00
|
|
|
if err := templates[conf.LeaderboardTemplate].Execute(w, h.buildViewModel(r)); err != nil {
|
|
|
|
logbuch.Error(err.Error())
|
|
|
|
}
|
2022-10-03 11:53:27 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
func (h *LeaderboardHandler) buildViewModel(r *http.Request) *view.LeaderboardViewModel {
|
|
|
|
user := middlewares.GetPrincipal(r)
|
2022-10-03 21:38:19 +03:00
|
|
|
byParam := strings.ToLower(r.URL.Query().Get("by"))
|
2022-10-04 00:52:22 +03:00
|
|
|
keyParam := strings.ToLower(r.URL.Query().Get("key"))
|
2022-10-03 11:53:27 +03:00
|
|
|
|
2022-10-03 21:38:19 +03:00
|
|
|
var err error
|
2022-10-04 00:52:22 +03:00
|
|
|
var leaderboard models.Leaderboard
|
2022-10-05 22:52:10 +03:00
|
|
|
var userLanguages map[string][]string
|
2022-10-04 00:52:22 +03:00
|
|
|
var topKeys []string
|
2022-10-03 11:53:27 +03:00
|
|
|
|
2022-10-03 21:38:19 +03:00
|
|
|
if byParam == "" {
|
2022-10-04 00:52:22 +03:00
|
|
|
leaderboard, err = h.leaderboardService.GetByInterval(models.IntervalPast7Days, true)
|
2022-10-03 21:38:19 +03:00
|
|
|
if err != nil {
|
|
|
|
conf.Log().Request(r).Error("error while fetching general leaderboard items - %v", err)
|
|
|
|
return &view.LeaderboardViewModel{Error: criticalError}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if by, ok := allowedAggregations[byParam]; ok {
|
2022-10-04 00:52:22 +03:00
|
|
|
leaderboard, err = h.leaderboardService.GetAggregatedByInterval(models.IntervalPast7Days, &by, true)
|
2022-10-03 21:38:19 +03:00
|
|
|
if err != nil {
|
|
|
|
conf.Log().Request(r).Error("error while fetching general leaderboard items - %v", err)
|
|
|
|
return &view.LeaderboardViewModel{Error: criticalError}
|
|
|
|
}
|
2022-10-04 00:52:22 +03:00
|
|
|
|
2022-10-05 22:52:10 +03:00
|
|
|
userLeaderboards := slice.GroupWith[*models.LeaderboardItem, string](leaderboard, func(item *models.LeaderboardItem) string {
|
|
|
|
return item.UserID
|
|
|
|
})
|
|
|
|
userLanguages = map[string][]string{}
|
|
|
|
for u, items := range userLeaderboards {
|
|
|
|
userLanguages[u] = models.Leaderboard(items).TopKeysByUser(models.SummaryLanguage, u)
|
|
|
|
}
|
|
|
|
|
2022-10-04 00:52:22 +03:00
|
|
|
topKeys = leaderboard.TopKeys(by)
|
|
|
|
if len(topKeys) > 0 {
|
|
|
|
if keyParam == "" {
|
|
|
|
keyParam = strings.ToLower(topKeys[0])
|
|
|
|
}
|
|
|
|
leaderboard = leaderboard.TopByKey(by, keyParam)
|
|
|
|
}
|
2022-10-03 21:38:19 +03:00
|
|
|
} else {
|
|
|
|
return &view.LeaderboardViewModel{Error: fmt.Sprintf("unsupported aggregation '%s'", byParam)}
|
|
|
|
}
|
2022-10-03 11:53:27 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
var apiKey string
|
|
|
|
if user != nil {
|
|
|
|
apiKey = user.ApiKey
|
|
|
|
}
|
|
|
|
|
|
|
|
return &view.LeaderboardViewModel{
|
2022-10-05 22:52:10 +03:00
|
|
|
User: user,
|
|
|
|
By: byParam,
|
|
|
|
Key: keyParam,
|
|
|
|
Items: leaderboard,
|
|
|
|
UserLanguages: userLanguages,
|
|
|
|
TopKeys: topKeys,
|
|
|
|
ApiKey: apiKey,
|
|
|
|
Success: r.URL.Query().Get("success"),
|
|
|
|
Error: r.URL.Query().Get("error"),
|
2022-10-03 11:53:27 +03:00
|
|
|
}
|
|
|
|
}
|