1
0
Fork 0
mirror of https://github.com/FrankerFaceZ/FrankerFaceZ.git synced 2025-08-06 14:20:56 +00:00

Add documentation to ProcessSingleGetRequest

Make a collectError() function to reduce repetitiveness
This commit is contained in:
Kane York 2016-01-17 14:09:09 -08:00
parent a327f6cf57
commit aca50d9de5
4 changed files with 152 additions and 53 deletions

View file

@ -1,9 +1,9 @@
package main package main
import ( import (
"os"
"fmt"
"encoding/json" "encoding/json"
"fmt"
"os"
) )
type ConfigFile struct { type ConfigFile struct {

View file

@ -1,10 +1,10 @@
package main package main
import ( import (
"bitbucket.org/stendec/frankerfacez/socketserver/server"
"html/template" "html/template"
"net/http" "net/http"
"time" "time"
"bitbucket.org/stendec/frankerfacez/socketserver/server"
) )
type CalendarData struct { type CalendarData struct {

View file

@ -0,0 +1,70 @@
package main
type serverFilter struct {
// Mode is false for blacklist, true for whitelist
Mode bool
Special string[]
}
const serverFilterModeBlacklist = false
const serverFilterModeWhitelist = true
func (sf *serverFilter) IsServerAllowed(server string) {
for _, v := range sf.Special {
if server == v {
return sf.Mode
}
}
return !sf.Mode
}
func (sf *serverFilter) Remove(server string) {
if sf.Mode == serverFilterModeWhitelist {
var idx int = -1
for i, v := range sf.Special {
if server == v {
idx = i
break
}
}
if idx != -1 {
var lenMinusOne = len(sf.Special)-1
sf.Special[idx] = sf.Special[lenMinusOne]
sf.Special = sf.Special[:lenMinusOne]
}
} else {
for _, v := range sf.Special {
if server == v {
return
}
}
sf.Special = append(sf.Special, server)
}
}
func (sf *serverFilter) Add(server string) {
if sf.Mode == serverFilterModeBlacklist {
var idx int = -1
for i, v := range sf.Special {
if server == v {
idx = i
break
}
}
if idx != -1 {
var lenMinusOne = len(sf.Special)-1
sf.Special[idx] = sf.Special[lenMinusOne]
sf.Special = sf.Special[:lenMinusOne]
}
} else {
for _, v := range sf.Special {
if server == v {
return
}
}
sf.Special = append(sf.Special, server)
}
}
const serverFilterAll serverFilter = serverFilter{Mode: serverFilterModeBlacklist}
const serverFilterNone serverFilter = serverFilter{Mode: serverFilterModeWhitelist}

View file

@ -30,13 +30,14 @@ func main() {
loadConfig() loadConfig()
http.HandleFunc("/api", ServeAPI) http.HandleFunc("/api/get", ServeAPIGet)
http.ListenAndServe(config.ListenAddr, http.DefaultServeMux) http.ListenAndServe(config.ListenAddr, http.DefaultServeMux)
} }
const RequestURIName = "q" const RequestURIName = "q"
const separatorRange = "~" const separatorRange = "~"
const separatorAdd = " " const separatorAdd = " "
const separatorServer = "@"
const jsonErrMalformedRequest = `{"status":"error","error":"malformed request uri"}` const jsonErrMalformedRequest = `{"status":"error","error":"malformed request uri"}`
const jsonErrBlankRequest = `{"status":"error","error":"no queries given"}` const jsonErrBlankRequest = `{"status":"error","error":"no queries given"}`
const statusError = "error" const statusError = "error"
@ -53,15 +54,7 @@ type requestResponse struct {
Count uint64 `json:"count,omitempty"` Count uint64 `json:"count,omitempty"`
} }
type serverFilter struct { func ServeAPIGet(w http.ResponseWriter, r *http.Request) {
// TODO
}
func (sf *serverFilter) IsServerAllowed(server string) {
return true
}
const serverFilterAll serverFilter
func ServeAPI(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
u, err := url.ParseRequestURI(r.RequestURI) u, err := url.ParseRequestURI(r.RequestURI)
@ -82,7 +75,10 @@ func ServeAPI(w http.ResponseWriter, r *http.Request) {
resp := apiResponse{Status: statusOk} resp := apiResponse{Status: statusOk}
resp.Responses = make([]requestResponse, reqCount) resp.Responses = make([]requestResponse, reqCount)
for i, v := range query[RequestURIName] { for i, v := range query[RequestURIName] {
resp.Responses[i] = processSingleRequest(v) if len(v) == 0 {
continue
}
resp.Responses[i] = ProcessSingleGetRequest(v)
} }
for _, v := range resp.Responses { for _, v := range resp.Responses {
if v.Status == statusError { if v.Status == statusError {
@ -96,20 +92,61 @@ func ServeAPI(w http.ResponseWriter, r *http.Request) {
enc.Encode(resp) enc.Encode(resp)
} }
const errRangeFormatIncorrect = "incorrect range format, must be yyyy-mm-dd~yyyy-mm-dd" const errRangeFormatIncorrect = errors.New("incorrect range format, must be yyyy-mm-dd~yyyy-mm-dd")
func processSingleRequest(req string) (result requestResponse) { // ProcessSingleGetRequest takes a request string and pulls the unique user data for the given dates and filters.
// Forms: //
// Single: 2016-01-02 // The request string is in the following format:
// Range: 2016-01-03~2016-01-09 //
// Add disparate: 2016-01-02 2016-01-03 2016-01-09 2016-01-10 // Request = AddDateRanges [ "@" ServerFilter ] .
// NOTE: Spaces are uri-encoded as + // ServerFilter = [ "!" ] ServerName { " " ServerName } .
// Add ranges: 2016-01-04~2016-01-08 2016-01-11~2016-01-15 // ServerName = { "a" … "z" } .
// AddDateRanges = DateMaybeRange { " " DateMaybeRange } .
// DateMaybeRange = DateRange | Date .
// DateRange = Date "~" Date .
// Date = Year "-" Month "-" Day .
// Year = number number number number .
// Month = number number .
// Day = number number .
// number = "0" … "9" .
//
// Example of a well-formed request:
//
// 2016-01-04~2016-01-08 2016-01-11~2016-01-15@andknuckles tuturu
//
// Remember that spaces are urlencoded as "+", so the HTTP request to send to retrieve that data would be this:
//
// /api/get?q=2016-01-04~2016-01-08+2016-01-11~2016-01-15%40andknuckles+tuturu
//
// If a ServerFilter is specified, only users connecting to the specified servers will be included in the count.
//
// It does not matter if a date is specified multiple times, due to the data format used.
func ProcessSingleGetRequest(req string) (result requestResponse) {
var hll hyperloglog.HyperLogLogPlus, _ = hyperloglog.NewPlus(server.CounterPrecision) var hll hyperloglog.HyperLogLogPlus, _ = hyperloglog.NewPlus(server.CounterPrecision)
addSplit := strings.Split(req, separatorAdd)
result.Request = req result.Request = req
result.Status = statusOk result.Status = statusOk
filter := serverFilterAll
collectError := func(err error) bool {
if err != nil {
result.Status = statusError
result.Error = err.Error()
return true
}
return false
}
serverSplit := strings.Split(req, separatorServer)
if len(serverSplit) == 2 {
filter = serverFilterNone
serversOnly := strings.Split(serverSplit[1], separatorAdd)
for _, v := range serversOnly {
filter.Add(v)
}
}
addSplit := strings.Split(serverSplit[0], separatorAdd)
outerLoop: outerLoop:
for _, split1 := range addSplit { for _, split1 := range addSplit {
@ -119,40 +156,31 @@ func processSingleRequest(req string) (result requestResponse) {
rangeSplit := strings.Split(split1, separatorRange) rangeSplit := strings.Split(split1, separatorRange)
if len(rangeSplit) == 1 { if len(rangeSplit) == 1 {
at, err := parseDate(rangeSplit[0]) at, err := parseDateFromRequest(rangeSplit[0])
if err != nil { if collectError(err) {
result.Status = statusError
result.Error = err.Error()
break outerLoop break outerLoop
} }
err = addSingleDate(at, serverFilterAll, &hll)
if err != nil { err = addSingleDate(at, filter, &hll)
result.Status = statusError if collectError(err) {
result.Error = err.Error()
break outerLoop break outerLoop
} }
} else if len(rangeSplit) == 2 { } else if len(rangeSplit) == 2 {
from, err := parseDate(rangeSplit[0]) from, err := parseDateFromRequest(rangeSplit[0])
if err != nil { if collectError(err) {
result.Status = statusError
result.Error = err.Error()
break outerLoop break outerLoop
} }
to, err := parseDate(rangeSplit[1]) to, err := parseDateFromRequest(rangeSplit[1])
if err != nil { if collectError(err) {
result.Status = statusError
result.Error = err.Error()
break outerLoop break outerLoop
} }
err = addRange(from, to, serverFilterAll, &hll)
if err != nil { err = addRange(from, to, filter, &hll)
result.Status = statusError if collectError(err) {
result.Error = err.Error()
break outerLoop break outerLoop
} }
} else { } else {
result.Status = statusError collectError(errRangeFormatIncorrect)
result.Error = errRangeFormatIncorrect
break outerLoop break outerLoop
} }
} }
@ -166,7 +194,7 @@ func processSingleRequest(req string) (result requestResponse) {
var errBadDate = errors.New("bad date format, must be yyyy-mm-dd") var errBadDate = errors.New("bad date format, must be yyyy-mm-dd")
var zeroTime = time.Unix(0, 0) var zeroTime = time.Unix(0, 0)
func parseDate(dateStr string) (time.Time, error) { func parseDateFromRequest(dateStr string) (time.Time, error) {
var year, month, day int var year, month, day int
n, err := fmt.Sscanf(dateStr, "%d-%d-%d", &year, &month, &day) n, err := fmt.Sscanf(dateStr, "%d-%d-%d", &year, &month, &day)
if err != nil || n != 3 { if err != nil || n != 3 {
@ -182,6 +210,7 @@ func addSingleDate(at time.Time, filter serverFilter, dest *hyperloglog.HyperLog
func addRange(start time.Time, end time.Time, filter serverFilter, dest *hyperloglog.HyperLogLogPlus) error { func addRange(start time.Time, end time.Time, filter serverFilter, dest *hyperloglog.HyperLogLogPlus) error {
return nil
} }
func combineDateRange(from time.Time, to time.Time, dest *hyperloglog.HyperLogLogPlus) error { func combineDateRange(from time.Time, to time.Time, dest *hyperloglog.HyperLogLogPlus) error {