This commit is contained in:
Ferdinand Mütsch 2019-05-05 22:36:49 +02:00
commit 0bd71b7708
6 changed files with 178 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
launch.json
.vscode

38
handlers.go Normal file
View File

@ -0,0 +1,38 @@
package main
import (
"encoding/json"
"net/http"
"os"
_ "github.com/go-sql-driver/mysql"
"github.com/n1try/wakapi/models"
)
func Authenticate(w http.ResponseWriter, r *http.Request) {
}
func HeartbeatHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
w.WriteHeader(415)
return
}
dec := json.NewDecoder(r.Body)
var heartbeats []models.Heartbeat
err := dec.Decode(&heartbeats)
if err != nil {
w.WriteHeader(400)
w.Write([]byte(err.Error()))
return
}
err = HeartbeatSrvc.InsertMulti(heartbeats)
if err != nil {
w.WriteHeader(500)
os.Stderr.WriteString(err.Error())
return
}
w.WriteHeader(201)
}

56
main.go Normal file
View File

@ -0,0 +1,56 @@
package main
import (
"database/sql"
"flag"
"fmt"
"net/http"
"os"
"strconv"
"time"
_ "github.com/go-sql-driver/mysql"
"github.com/n1try/wakapi/models"
"github.com/n1try/wakapi/services"
)
var HeartbeatSrvc services.HeartbeatService
func getConfig() models.Config {
portPtr := flag.Int("port", 8080, "Port for the webserver to listen on")
flag.Parse()
return models.Config{
Port: *portPtr,
}
}
func main() {
// Read Config
config := getConfig()
// Connect Database
db, _ := sql.Open("mysql", "fakatime_user:eB2zyLt2heqWj5Y9@tcp(muetsch.io:3306)/fakatime")
defer db.Close()
err := db.Ping()
if err != nil {
fmt.Println("Could not connect to database.")
os.Exit(1)
}
// Init Services
HeartbeatSrvc = services.HeartbeatService{db}
// Define Routes
http.HandleFunc("/api/heartbeat", HeartbeatHandler)
// Listen HTTP
portString := ":" + strconv.Itoa(config.Port)
s := &http.Server{
Addr: portString,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
}
fmt.Printf("Listening on %+s\n", portString)
s.ListenAndServe()
}

5
models/config.go Normal file
View File

@ -0,0 +1,5 @@
package models
type Config struct {
Port int
}

37
models/heartbeat.go Normal file
View File

@ -0,0 +1,37 @@
package models
import (
"strconv"
"strings"
"time"
)
type HeartbeatReqTime time.Time
type Heartbeat struct {
User string `json:"user"`
Entity string `json:"entity"`
Type string `json:"type"`
Category string `json:"category"`
Project string `json:"project"`
Branch string `json:"branch"`
Language string `json:"language"`
IsWrite bool `json:"is_write"`
Time HeartbeatReqTime `json:"time"`
}
func (j *HeartbeatReqTime) UnmarshalJSON(b []byte) error {
s := strings.Split(strings.Trim(string(b), "\""), ".")[0]
i, err := strconv.ParseInt(s, 10, 64)
if err != nil {
return err
}
t := time.Unix(i, 0)
*j = HeartbeatReqTime(t)
return nil
}
func (j HeartbeatReqTime) String() string {
t := time.Time(j)
return t.Format("2006-01-02 15:04:05")
}

40
services/heartbeat.go Normal file
View File

@ -0,0 +1,40 @@
package services
import (
"database/sql"
"errors"
"fmt"
"github.com/n1try/wakapi/models"
)
const (
TableName = "heartbeat"
)
type HeartbeatService struct {
Db *sql.DB
}
func (srv *HeartbeatService) InsertMulti(heartbeats []models.Heartbeat) error {
qTpl := "INSERT INTO %+s (user, time, entity, type, category, is_write, project, branch, language) VALUES %+s;"
qFill := ""
vals := []interface{}{}
for _, h := range heartbeats {
qFill = "(?, ?, ?, ?, ?, ?, ?, ?, ?),"
vals = append(vals, h.User, h.Time.String(), h.Entity, h.Type, h.Category, h.IsWrite, h.Project, h.Branch, h.Language)
}
q := fmt.Sprintf(qTpl, TableName, qFill[0:len(qFill)-1])
stmt, _ := srv.Db.Prepare(q)
result, err := stmt.Exec(vals...)
if err != nil {
return err
}
n, err := result.RowsAffected()
if err != nil || n != int64(len(heartbeats)) {
return errors.New(fmt.Sprintf("Failed to insert %+v rows.", len(heartbeats)))
}
return nil
}