mi-v1/switchcounter/switch.go

215 lines
4.2 KiB
Go

package switchcounter
import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"path"
"strconv"
"time"
"github.com/celrenheit/sandflake"
r "gopkg.in/rethinkdb/rethinkdb-go.v6"
"within.website/ln"
)
func (s *Switches) ByID(ctx context.Context, id string) (*Switch, error) {
var result Switch
res, err := r.Table("switches").
Get(id).
Run(s.session)
if err != nil {
return nil, err
}
err = res.One(&result)
if err != nil {
return nil, err
}
return &result, nil
}
func (s *Switches) Get(ctx context.Context, limit, page int) ([]Switch, error) {
var result []Switch
res, err := r.Table("switches").
OrderBy(r.Desc("started_at")).
Skip(page * limit).
Limit(limit).
Run(s.session)
if err != nil {
return nil, err
}
err = res.All(&result)
if err != nil {
return nil, err
}
return result, nil
}
func (s *Switches) Switch(ctx context.Context, who string) (Switch, Switch, error) {
var lastSw Switch
var currentSw Switch
ln.Log(ctx, ln.Info("getting last switch"))
res, err := r.Table("switches").
OrderBy(r.Desc("started_at")).
Limit(1).
Run(s.session)
if err != nil {
return lastSw, currentSw, err
}
err = res.One(&lastSw)
if err != nil {
return lastSw, currentSw, err
}
f := ln.F{
"from": lastSw.Who,
"to": who,
}
ln.Log(ctx, f, ln.Info("got last switch"))
now := time.Now().UTC()
lastSw.EndedAt = &now
lastSw.Duration = now.Sub(lastSw.StartedAt).Round(time.Second)
err = r.Table("switches").
Update(lastSw).
Exec(s.session)
if err != nil {
return lastSw, currentSw, err
}
currentSw = Switch{
ID: sandflake.Next().String(),
Who: who,
StartedAt: now,
}
err = r.Table("switches").
Insert(currentSw).
Exec(s.session)
if err != nil {
return lastSw, currentSw, err
}
go func(who string) {
err = replicateToPluralKit(who)
if err != nil {
ln.Error(ctx, err, ln.Action("while switching"), ln.F{"to": who, "at": "pluralkit"})
}
err = replicateToSwitchCounter(who)
if err != nil {
ln.Error(ctx, err, ln.Action("while switching"), ln.F{"to": who, "at": "switcounter"})
}
}(who)
ln.Log(ctx, f, ln.Info("switched"))
return lastSw, currentSw, nil
}
func (s *Switches) GetID(rw http.ResponseWriter, req *http.Request) {
id := path.Base(req.URL.Path)
sw, err := s.ByID(req.Context(), id)
if err != nil {
ln.Error(req.Context(), err)
http.Error(rw, "can't get data", http.StatusInternalServerError)
return
}
json.NewEncoder(rw).Encode(sw)
}
func (s *Switches) Current(rw http.ResponseWriter, req *http.Request) {
var result Switch
res, err := r.Table("switches").
OrderBy(r.Desc("started_at")).
Limit(1).
Run(s.session)
if err != nil {
ln.Error(req.Context(), err)
http.Error(rw, "can't get data", http.StatusInternalServerError)
return
}
err = res.One(&result)
if err != nil {
panic(err)
}
switch req.Header.Get("Accept") {
case "text/plain":
rw.WriteHeader(http.StatusOK)
fmt.Fprint(rw, result.Who)
return
default:
json.NewEncoder(rw).Encode(result)
}
}
func (s *Switches) GetSwitches(rw http.ResponseWriter, req *http.Request) {
var (
limit = 40
page = 0
)
q := req.URL.Query()
if val := q.Get("limit"); val != "" {
i, err := strconv.Atoi(val)
if err != nil {
http.Error(rw, "limit is bad: "+err.Error(), http.StatusBadRequest)
return
}
limit = i
}
if val := q.Get("page"); val != "" {
i, err := strconv.Atoi(val)
if err != nil {
http.Error(rw, "page is bad: "+err.Error(), http.StatusBadRequest)
return
}
page = i
}
switches, err := s.Get(req.Context(), limit, page)
if err != nil {
ln.Error(req.Context(), err)
http.Error(rw, "can't get data", http.StatusInternalServerError)
return
}
json.NewEncoder(rw).Encode(switches)
}
func (s *Switches) RegisterSwitch(rw http.ResponseWriter, req *http.Request) {
who, err := ioutil.ReadAll(req.Body)
defer req.Body.Close()
if err != nil {
http.Error(rw, err.Error(), http.StatusBadRequest)
return
}
last, current, err := s.Switch(req.Context(), string(who))
if err != nil {
ln.Error(req.Context(), err)
http.Error(rw, err.Error(), http.StatusInternalServerError)
return
}
json.NewEncoder(rw).Encode(struct {
Last Switch `json:"last"`
Current Switch `json:"current"`
}{
Last: last,
Current: current,
})
}