Update random daily seed logic

pull/1/head
Flashfyre 2024-03-18 19:55:02 -04:00
parent 2cb7be52eb
commit be04408336
9 changed files with 63 additions and 66 deletions

2
.gitignore vendored
View File

@ -1,4 +1,4 @@
pokerogue-server.exe pokerogue-server.exe
userdata/* userdata/*
key secret.key

View File

@ -22,7 +22,7 @@ func GetUsernameFromRequest(request *http.Request) (string, error) {
return "", fmt.Errorf("invalid token length: got %d, expected 32", len(token)) return "", fmt.Errorf("invalid token length: got %d, expected 32", len(token))
} }
username, err := db.GetUsernameFromToken(token) username, err := db.FetchUsernameFromToken(token)
if err != nil { if err != nil {
return "", fmt.Errorf("failed to validate token: %s", err) return "", fmt.Errorf("failed to validate token: %s", err)
} }
@ -44,7 +44,7 @@ func GetUuidFromRequest(request *http.Request) ([]byte, error) {
return nil, fmt.Errorf("invalid token length: got %d, expected 32", len(token)) return nil, fmt.Errorf("invalid token length: got %d, expected 32", len(token))
} }
uuid, err := db.GetUuidFromToken(token) uuid, err := db.FetchUuidFromToken(token)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to validate token: %s", err) return nil, fmt.Errorf("failed to validate token: %s", err)
} }

View File

@ -144,7 +144,7 @@ func (s *Server) HandleAccountLogin(w http.ResponseWriter, r *http.Request) {
return return
} }
key, salt, err := db.GetAccountKeySaltFromUsername(request.Username) key, salt, err := db.FetchAccountKeySaltFromUsername(request.Username)
if err != nil { if err != nil {
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
http.Error(w, "account doesn't exist", http.StatusBadRequest) http.Error(w, "account doesn't exist", http.StatusBadRequest)

View File

@ -1,17 +1,26 @@
package api package api
import ( import (
"crypto/md5"
"crypto/rand"
"encoding/base64"
"encoding/binary"
"encoding/json" "encoding/json"
"fmt" "fmt"
"log" "log"
"net/http" "net/http"
"os"
"strconv" "strconv"
"time"
"github.com/Flashfyre/pokerogue-server/db" "github.com/Flashfyre/pokerogue-server/db"
) )
const secondsPerDay = 60 * 60 * 24
var ( var (
dailyRunSeed string dailyRunSecret []byte
dailyRunSeed string
) )
func ScheduleDailyRunRefresh() { func ScheduleDailyRunRefresh() {
@ -21,24 +30,48 @@ func ScheduleDailyRunRefresh() {
} }
func InitDailyRun() { func InitDailyRun() {
var err error secret, err := os.ReadFile("secret.key")
dailyRunSeed, err = db.GetDailyRunSeed()
if err != nil { if err != nil {
log.Printf("failed to generated daily run seed: %s", err.Error()) if !os.IsNotExist(err) {
log.Fatalf("failed to read daily seed secret: %s", err)
}
newSecret := make([]byte, 32)
_, err := rand.Read(newSecret)
if err != nil {
log.Fatalf("failed to generate daily seed secret: %s", err)
}
err = os.WriteFile("secret.key", newSecret, 0400)
if err != nil {
log.Fatalf("failed to write daily seed secret: %s", err)
}
secret = newSecret
} }
if dailyRunSeed == "" { dailyRunSecret = secret
dailyRunSeed = RandString(24)
err := db.TryAddDailyRun(dailyRunSeed) dailyRunSeed = base64.StdEncoding.EncodeToString(DeriveDailyRunSeed(time.Now().UTC()))
if err != nil {
log.Print(err.Error()) err = db.TryAddDailyRun(dailyRunSeed)
} else { if err != nil {
log.Printf("Daily Run Seed: %s", dailyRunSeed) log.Print(err.Error())
} } else {
log.Printf("Daily Run Seed: %s", dailyRunSeed)
} }
} }
// /daily/seed - get daily run seed func DeriveDailyRunSeed(seedTime time.Time) []byte {
day := make([]byte, 8)
binary.BigEndian.PutUint64(day, uint64(seedTime.Unix()/secondsPerDay))
hashedSeed := md5.Sum(append(day, dailyRunSecret...))
return hashedSeed[:]
}
// /daily/seed - fetch daily run seed
func (s *Server) HandleSeed(w http.ResponseWriter, r *http.Request) { func (s *Server) HandleSeed(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(dailyRunSeed)) w.Write([]byte(dailyRunSeed))
@ -60,7 +93,7 @@ func (s *Server) HandleRankings(w http.ResponseWriter, r *http.Request) {
page = 1 page = 1
} }
rankings, err := db.GetRankings(page) rankings, err := db.FetchRankings(page)
if err != nil { if err != nil {
log.Print("failed to retrieve rankings") log.Print("failed to retrieve rankings")
} }

View File

@ -12,7 +12,7 @@ import (
"github.com/klauspost/compress/zstd" "github.com/klauspost/compress/zstd"
) )
func GetSystemSaveData(uuid []byte) (defs.SystemSaveData, error) { func ReadSystemSaveData(uuid []byte) (defs.SystemSaveData, error) {
var system defs.SystemSaveData var system defs.SystemSaveData
save, err := os.ReadFile("userdata/" + hex.EncodeToString(uuid) + "/system.pzs") save, err := os.ReadFile("userdata/" + hex.EncodeToString(uuid) + "/system.pzs")
@ -40,7 +40,7 @@ func GetSystemSaveData(uuid []byte) (defs.SystemSaveData, error) {
return system, nil return system, nil
} }
func GetSessionSaveData(uuid []byte, slotId int) (defs.SessionSaveData, error) { func ReadSessionSaveData(uuid []byte, slotId int) (defs.SessionSaveData, error) {
var session defs.SessionSaveData var session defs.SessionSaveData
fileName := "session" fileName := "session"
@ -76,9 +76,9 @@ func GetSessionSaveData(uuid []byte, slotId int) (defs.SessionSaveData, error) {
func ValidateSessionCompleted(session defs.SessionSaveData) bool { func ValidateSessionCompleted(session defs.SessionSaveData) bool {
switch session.GameMode { switch session.GameMode {
case 0: case 0:
return session.WaveIndex == 200 return session.BattleType == 2 && session.WaveIndex == 200
case 3: case 3:
return session.WaveIndex == 50 return session.BattleType == 2 && session.WaveIndex == 50
} }
return false return false
} }

View File

@ -29,7 +29,7 @@ func (s *Server) HandleSavedataGet(w http.ResponseWriter, r *http.Request) {
switch r.URL.Query().Get("datatype") { switch r.URL.Query().Get("datatype") {
case "0": // System case "0": // System
system, err := GetSystemSaveData(uuid) system, err := ReadSystemSaveData(uuid)
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
@ -54,7 +54,7 @@ func (s *Server) HandleSavedataGet(w http.ResponseWriter, r *http.Request) {
return return
} }
session, err := GetSessionSaveData(uuid, slotId) session, err := ReadSessionSaveData(uuid, slotId)
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
@ -276,12 +276,12 @@ func (s *Server) HandleSavedataClear(w http.ResponseWriter, r *http.Request) {
return return
} }
sessionCompleted := session.BattleType == 2 && ValidateSessionCompleted(session) sessionCompleted := ValidateSessionCompleted(session)
newCompletion := false newCompletion := false
if session.GameMode == 3 { if session.GameMode == 3 {
waveCompleted := session.WaveIndex waveCompleted := session.WaveIndex
if session.BattleType != 2 { if !sessionCompleted {
waveCompleted-- waveCompleted--
} }
err = db.AddOrUpdateAccountDailyRun(uuid, session.Score, waveCompleted) err = db.AddOrUpdateAccountDailyRun(uuid, session.Score, waveCompleted)

View File

@ -1,20 +0,0 @@
package api
import (
"crypto/rand"
)
const randRunes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
const lenRandRunes = len(randRunes)
func RandString(length int) string {
b := make([]byte, length)
rand.Read(b)
for i := range b {
b[i] = randRunes[int(b[i])%lenRandRunes]
}
return string(b)
}

View File

@ -38,7 +38,7 @@ func UpdateAccountLastActivity(uuid []byte) error {
return nil return nil
} }
func GetUsernameFromToken(token []byte) (string, error) { func FetchUsernameFromToken(token []byte) (string, error) {
var username string var username string
err := handle.QueryRow("SELECT a.username FROM accounts a JOIN sessions s ON s.uuid = a.uuid WHERE s.token = ? AND s.expire > UTC_TIMESTAMP()", token).Scan(&username) err := handle.QueryRow("SELECT a.username FROM accounts a JOIN sessions s ON s.uuid = a.uuid WHERE s.token = ? AND s.expire > UTC_TIMESTAMP()", token).Scan(&username)
if err != nil { if err != nil {
@ -48,7 +48,7 @@ func GetUsernameFromToken(token []byte) (string, error) {
return username, nil return username, nil
} }
func GetAccountKeySaltFromUsername(username string) ([]byte, []byte, error) { func FetchAccountKeySaltFromUsername(username string) ([]byte, []byte, error) {
var key, salt []byte var key, salt []byte
err := handle.QueryRow("SELECT hash, salt FROM accounts WHERE username = ?", username).Scan(&key, &salt) err := handle.QueryRow("SELECT hash, salt FROM accounts WHERE username = ?", username).Scan(&key, &salt)
if err != nil { if err != nil {
@ -58,7 +58,7 @@ func GetAccountKeySaltFromUsername(username string) ([]byte, []byte, error) {
return key, salt, nil return key, salt, nil
} }
func GetUuidFromToken(token []byte) ([]byte, error) { func FetchUuidFromToken(token []byte) ([]byte, error) {
var uuid []byte var uuid []byte
err := handle.QueryRow("SELECT uuid FROM sessions WHERE token = ? AND expire > UTC_TIMESTAMP()", token).Scan(&uuid) err := handle.QueryRow("SELECT uuid FROM sessions WHERE token = ? AND expire > UTC_TIMESTAMP()", token).Scan(&uuid)
if err != nil { if err != nil {

View File

@ -1,8 +1,6 @@
package db package db
import ( import (
"database/sql"
"github.com/Flashfyre/pokerogue-server/defs" "github.com/Flashfyre/pokerogue-server/defs"
) )
@ -15,20 +13,6 @@ func TryAddDailyRun(seed string) error {
return nil return nil
} }
func GetDailyRunSeed() (string, error) {
var seed string
err := handle.QueryRow("SELECT seed FROM dailyRuns WHERE date = UTC_DATE()").Scan(&seed)
if err != nil {
if err == sql.ErrNoRows {
return "", err
}
return "", err
}
return seed, nil
}
func AddOrUpdateAccountDailyRun(uuid []byte, score int, wave int) error { func AddOrUpdateAccountDailyRun(uuid []byte, score int, wave int) error {
_, err := handle.Exec("INSERT INTO accountDailyRuns (uuid, date, score, wave, timestamp) VALUES (?, UTC_DATE(), ?, ?, UTC_TIMESTAMP()) ON DUPLICATE KEY UPDATE score = ?, wave = GREATEST(wave, ?), timestamp = IF(score < ?, UTC_TIMESTAMP(), timestamp)", uuid, score, wave, score, wave, score) _, err := handle.Exec("INSERT INTO accountDailyRuns (uuid, date, score, wave, timestamp) VALUES (?, UTC_DATE(), ?, ?, UTC_TIMESTAMP()) ON DUPLICATE KEY UPDATE score = ?, wave = GREATEST(wave, ?), timestamp = IF(score < ?, UTC_TIMESTAMP(), timestamp)", uuid, score, wave, score, wave, score)
if err != nil { if err != nil {
@ -38,7 +22,7 @@ func AddOrUpdateAccountDailyRun(uuid []byte, score int, wave int) error {
return nil return nil
} }
func GetRankings(page int) ([]defs.DailyRanking, error) { func FetchRankings(page int) ([]defs.DailyRanking, error) {
var rankings []defs.DailyRanking var rankings []defs.DailyRanking
offset := (page - 1) * 10 offset := (page - 1) * 10