justlog/api/logrequest.go
2022-06-21 18:25:32 +02:00

190 lines
5 KiB
Go

package api
import (
"errors"
"fmt"
"net/http"
"regexp"
"strconv"
"strings"
"time"
log "github.com/sirupsen/logrus"
)
type logRequest struct {
channel string
user string
channelid string
userid string
time logTime
reverse bool
responseType string
redirectPath string
isUserRequest bool
isChannelRequest bool
}
// userRandomMessageRequest /channel/pajlada/user/gempir/random
type logTime struct {
from string
to string
year string
month string
day string
random bool
}
var (
pathRegex = regexp.MustCompile(`\/(channel|channelid)\/(\w+)(?:\/(user|userid)\/(\w+))?(?:(?:\/(\d{4})\/(\d{1,2})(?:\/(\d{1,2}))?)|(?:\/(random)))?`)
)
func (s *Server) newLogRequestFromURL(r *http.Request) (logRequest, error) {
path := r.URL.EscapedPath()
if path != strings.ToLower(path) {
return logRequest{redirectPath: fmt.Sprintf("%s?%s", strings.ToLower(path), r.URL.Query().Encode())}, nil
}
if !strings.HasPrefix(path, "/channel") && !strings.HasPrefix(path, "/channelid") {
return logRequest{}, errors.New("route not found")
}
url := strings.TrimRight(path, "/")
matches := pathRegex.FindAllStringSubmatch(url, -1)
if len(matches) == 0 || len(matches[0]) < 5 {
return logRequest{}, errors.New("route not found")
}
request := logRequest{
time: logTime{},
}
params := []string{}
for _, match := range matches[0] {
if match != "" {
params = append(params, match)
}
}
request.isUserRequest = len(params) > 4 && (params[3] == "user" || params[3] == "userid")
request.isChannelRequest = len(params) < 4 || (len(params) >= 4 && params[3] != "user" && params[3] != "userid")
if params[1] == "channel" {
request.channel = params[2]
}
if params[1] == "channelid" {
request.channelid = params[2]
}
if request.isUserRequest && params[3] == "user" {
request.user = params[4]
}
if request.isUserRequest && params[3] == "userid" {
request.userid = params[4]
}
var err error
request, err = s.fillIds(request)
if err != nil {
log.Error(err)
return logRequest{}, nil
}
if request.isUserRequest && len(params) == 7 {
request.time.year = params[5]
request.time.month = params[6]
} else if request.isUserRequest && len(params) == 8 {
return logRequest{}, errors.New("route not found")
} else if request.isChannelRequest && len(params) == 6 {
request.time.year = params[3]
request.time.month = params[4]
request.time.day = params[5]
} else if request.isUserRequest && len(params) == 6 && params[5] == "random" {
request.time.random = true
} else if request.isChannelRequest && len(params) == 4 && params[3] == "random" {
request.time.random = true
} else {
if request.isChannelRequest {
request.time.year = fmt.Sprintf("%d", time.Now().Year())
request.time.month = fmt.Sprintf("%d", time.Now().Month())
} else {
year, month, err := s.fileLogger.GetLastLogYearAndMonthForUser(request.channelid, request.userid)
if err == nil {
request.time.year = fmt.Sprintf("%d", year)
request.time.month = fmt.Sprintf("%d", month)
} else {
request.time.year = fmt.Sprintf("%d", time.Now().Year())
request.time.month = fmt.Sprintf("%d", time.Now().Month())
}
}
timePath := request.time.year + "/" + request.time.month
if request.isChannelRequest {
request.time.day = fmt.Sprintf("%d", time.Now().Day())
timePath += "/" + request.time.day
}
query := r.URL.Query()
encodedQuery := ""
if query.Encode() != "" {
encodedQuery = "?" + query.Encode()
}
return logRequest{redirectPath: fmt.Sprintf("%s/%s%s", params[0], timePath, encodedQuery)}, nil
}
if r.URL.Query().Get("from") != "" || r.URL.Query().Get("to") != "" {
request.time.from = r.URL.Query().Get("from")
if request.time.from == "" {
request.time.from = strconv.FormatInt(time.Now().Unix(), 10)
}
request.time.to = r.URL.Query().Get("to")
if request.time.to == "" {
request.time.to = strconv.FormatInt(time.Now().Unix(), 10)
}
}
if _, ok := r.URL.Query()["reverse"]; ok {
request.reverse = true
} else {
request.reverse = false
}
if _, ok := r.URL.Query()["json"]; ok || r.URL.Query().Get("type") == "json" || r.Header.Get("Content-Type") == "application/json" {
request.responseType = responseTypeJSON
} else if _, ok := r.URL.Query()["raw"]; ok || r.URL.Query().Get("type") == "raw" {
request.responseType = responseTypeRaw
} else {
request.responseType = responseTypeText
}
return request, nil
}
func (s *Server) fillIds(request logRequest) (logRequest, error) {
usernames := []string{}
if request.channelid == "" && request.channel != "" {
usernames = append(usernames, request.channel)
}
if request.userid == "" && request.user != "" {
usernames = append(usernames, request.user)
}
ids, err := s.helixClient.GetUsersByUsernames(usernames)
if err != nil {
return request, err
}
if request.channelid == "" {
request.channelid = ids[strings.ToLower(request.channel)].ID
}
if request.userid == "" {
request.userid = ids[strings.ToLower(request.user)].ID
}
return request, nil
}