Update random daily seed logic
parent
2cb7be52eb
commit
be04408336
|
@ -1,4 +1,4 @@
|
||||||
|
|
||||||
pokerogue-server.exe
|
pokerogue-server.exe
|
||||||
userdata/*
|
userdata/*
|
||||||
key
|
secret.key
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
61
api/daily.go
61
api/daily.go
|
@ -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")
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
20
api/utils.go
20
api/utils.go
|
@ -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)
|
|
||||||
}
|
|
|
@ -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 {
|
||||||
|
|
18
db/daily.go
18
db/daily.go
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue