299 lines
6.5 KiB
Go
299 lines
6.5 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"html"
|
|
"log"
|
|
"net/http"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
var updateCommunity = make(chan struct{})
|
|
|
|
func handleMediNET(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
_ = r.ParseForm()
|
|
|
|
// Authenticate (signin)
|
|
// Send key, client will then call (connect)
|
|
token := r.FormValue("token")
|
|
if token != "" {
|
|
a, err := db.authenticate(token)
|
|
if err != nil {
|
|
log.Printf("ERROR! failed to authenticate token: %s", err)
|
|
return
|
|
} else if a == nil {
|
|
log.Printf("ERROR! failed to retrieve authenticated account")
|
|
return
|
|
}
|
|
|
|
go trackActiveAccount(a.ID)
|
|
w.Header().Set("x-MediNET", "connected")
|
|
w.Header().Set("x-MediNET-Key", a.Key)
|
|
|
|
return
|
|
}
|
|
|
|
key := r.URL.Query().Get("x")
|
|
if key == "" {
|
|
key = r.FormValue("x")
|
|
}
|
|
|
|
a, err := db.getAccount(key)
|
|
if err != nil {
|
|
log.Printf("ERROR! %v", err)
|
|
return
|
|
}
|
|
if a == nil {
|
|
w.Header().Set("x-MediNET", "signin")
|
|
logDebugf("Asking to sign in %s %q", key, html.EscapeString(r.URL.RequestURI()))
|
|
|
|
return
|
|
}
|
|
go trackActiveAccount(a.ID)
|
|
|
|
data := make(map[string]interface{})
|
|
data["status"] = "success"
|
|
|
|
action := r.FormValue("action")
|
|
|
|
tz, err := time.LoadLocation(r.URL.Query().Get("tz"))
|
|
if err != nil {
|
|
tz, err = time.LoadLocation("UTC")
|
|
if err != nil {
|
|
log.Printf("ERROR! %v", err)
|
|
return
|
|
}
|
|
}
|
|
|
|
apiver, err := strconv.Atoi(r.URL.Query().Get("v"))
|
|
if err != nil {
|
|
apiver = 0
|
|
}
|
|
|
|
appver := 0
|
|
streakbuffer := -1
|
|
|
|
av := r.URL.Query().Get("av")
|
|
match := regexpMarket.FindStringSubmatch(av)
|
|
if len(match) == 2 {
|
|
match := regexpNumbers.FindAllString(av[0:len(av)-len(match[1])], -1)
|
|
if match != nil {
|
|
appver, err = strconv.Atoi(strings.Join(match, ""))
|
|
if err != nil {
|
|
appver = 0
|
|
}
|
|
}
|
|
} else {
|
|
av = "x-" + av
|
|
}
|
|
|
|
appmarket := r.URL.Query().Get("am")
|
|
|
|
sb := r.URL.Query().Get("buf")
|
|
if sb != "" {
|
|
streakbuffer, err = strconv.Atoi(sb)
|
|
if err != nil {
|
|
streakbuffer = -1
|
|
}
|
|
}
|
|
|
|
if streakbuffer >= 0 {
|
|
if a.StreakBuffer != streakbuffer {
|
|
a.StreakBuffer = streakbuffer
|
|
go db.updateStreakBuffer(a.ID, streakbuffer)
|
|
}
|
|
}
|
|
|
|
// TODO: read from announcement table on successful connect
|
|
//data["announce"] = "First line\n\nSecond line"
|
|
|
|
switch action {
|
|
case "deletesession":
|
|
data["result"] = "notdeleted"
|
|
|
|
st := r.FormValue("session")
|
|
if st == "" {
|
|
break
|
|
}
|
|
started, err := strconv.Atoi(st)
|
|
if err != nil || started == 0 {
|
|
log.Printf("failed to read session started when deleting session: %s", err)
|
|
return
|
|
}
|
|
|
|
deleted, err := db.deleteSession(started, a.ID)
|
|
if err != nil {
|
|
log.Printf("ERROR! %v", err)
|
|
return
|
|
} else if deleted {
|
|
data["result"] = "deleted"
|
|
}
|
|
case "downloadsessions":
|
|
sessions, err := db.getAllSessions(a.ID)
|
|
if err != nil {
|
|
log.Printf("ERROR! %v", err)
|
|
return
|
|
}
|
|
|
|
data["downloadsessions"] = sessions
|
|
case "uploadsessions":
|
|
data["result"] = "corrupt"
|
|
|
|
u := r.FormValue("uploadsessions")
|
|
if u == "" {
|
|
break
|
|
}
|
|
|
|
postsession := r.FormValue("postsession")
|
|
updateSessionStarted, _ := strconv.Atoi(r.FormValue("editstarted"))
|
|
|
|
var uploadsessions []session
|
|
err = json.Unmarshal([]byte(u), &uploadsessions)
|
|
if err != nil {
|
|
log.Printf("ERROR! %v", err)
|
|
return
|
|
}
|
|
|
|
data["result"] = "uploaded"
|
|
uploaded := false
|
|
sessionsuploaded := 0
|
|
|
|
for _, session := range uploadsessions {
|
|
uploaded, err = db.addSession(session, updateSessionStarted, a.ID, av, appmarket)
|
|
if err != nil {
|
|
log.Printf("ERROR! %v", err)
|
|
return
|
|
}
|
|
|
|
if uploaded {
|
|
sessionsuploaded++
|
|
}
|
|
}
|
|
data["sessionsuploaded"] = sessionsuploaded
|
|
|
|
if sessionsuploaded > 0 {
|
|
started := 0
|
|
streakday := 0
|
|
for _, session := range uploadsessions {
|
|
if session.Started > started {
|
|
started = session.Started
|
|
if action != "editposting" {
|
|
streakday = session.StreakDay
|
|
}
|
|
}
|
|
}
|
|
|
|
t := time.Now().In(tz)
|
|
if beforeWindowStart(t, streakbuffer) {
|
|
t = t.AddDate(0, 0, -1)
|
|
}
|
|
t = atWindowStart(t, streakbuffer)
|
|
if int64(started) >= t.Unix() { // A session was recorded after the start of today's streak window
|
|
streak, err := db.calculateStreak(a.ID, a.StreakBuffer, tz)
|
|
if err != nil {
|
|
log.Printf("ERROR! %v", err)
|
|
return
|
|
}
|
|
|
|
logDebugf("NEW SESSION %v - CALCULATED: %d, SUBMITTED: %d", t, streak, streakday)
|
|
|
|
if streak < streakday {
|
|
streak = streakday
|
|
} else if streak > streakday {
|
|
err = db.setSessionStreakDay(started, streak, a.ID)
|
|
if err != nil {
|
|
log.Printf("ERROR! %v", err)
|
|
return
|
|
}
|
|
}
|
|
|
|
err = db.setStreak(streak, a.ID, a.StreakBuffer, tz)
|
|
if err != nil {
|
|
log.Printf("ERROR! %v", err)
|
|
return
|
|
}
|
|
}
|
|
|
|
stats.SessionsPosted++
|
|
if streakday > stats.TopStreak {
|
|
stats.TopStreak = streakday
|
|
}
|
|
}
|
|
|
|
if postsession != "" {
|
|
if sessionsuploaded > 0 {
|
|
data["result"] = "posted"
|
|
} else {
|
|
data["result"] = "alreadyposted"
|
|
}
|
|
}
|
|
}
|
|
|
|
w.Header().Set("x-MediNET", "connected")
|
|
|
|
// Send streak
|
|
if action == "connect" || action == "downloadsessions" || action == "uploadsessions" {
|
|
streakday, streakend, topstreak, err := db.getStreak(a.ID)
|
|
if err != nil {
|
|
log.Printf("ERROR! %v", err)
|
|
return
|
|
}
|
|
w.Header().Set("x-MediNET-Streak", fmt.Sprintf("%d,%d", streakday, streakend))
|
|
w.Header().Set("x-MediNET-MaxStreak", fmt.Sprintf("%d", topstreak))
|
|
}
|
|
|
|
err = json.NewEncoder(w).Encode(data)
|
|
if err != nil {
|
|
log.Printf("ERROR! %v", err)
|
|
return
|
|
}
|
|
|
|
j, err := json.Marshal(data)
|
|
if err != nil {
|
|
log.Printf("ERROR! %v", err)
|
|
return
|
|
}
|
|
|
|
logDebugf("App: %d API: %d Action: %s - %q", appver, apiver, action, html.EscapeString(r.URL.RequestURI()))
|
|
logDebugf("Account ID: %d, JSON: %s", a.ID, string(j))
|
|
|
|
if action == "uploadsessions" || action == "deletesession" {
|
|
updateCommunity <- struct{}{}
|
|
}
|
|
}
|
|
|
|
func initWeb() {
|
|
http.HandleFunc("/om/sessions", func(w http.ResponseWriter, r *http.Request) {
|
|
// TODO
|
|
})
|
|
|
|
http.HandleFunc("/om/account", func(w http.ResponseWriter, r *http.Request) {
|
|
// TODO
|
|
})
|
|
|
|
http.HandleFunc("/om/forum", func(w http.ResponseWriter, r *http.Request) {
|
|
// TODO
|
|
})
|
|
|
|
http.HandleFunc("/om/groups", func(w http.ResponseWriter, r *http.Request) {
|
|
// TODO
|
|
})
|
|
|
|
http.HandleFunc("/om/status", func(w http.ResponseWriter, r *http.Request) {
|
|
fmt.Fprintf(w, "MediNET ONLINE<br><br>Accounts: %d (%d new)<br>Sessions: %d<br>Top streak: %d", len(stats.ActiveAccounts), stats.AccountsCreated, stats.SessionsPosted, stats.TopStreak)
|
|
})
|
|
|
|
http.HandleFunc("/om", handleMediNET)
|
|
|
|
go handleUpdateCommunity()
|
|
updateCommunity <- struct{}{}
|
|
}
|
|
|
|
func listenWeb() {
|
|
log.Fatal(http.ListenAndServe(config.Om, nil))
|
|
}
|