Author SHA1 Message Date
Matthew Olker 9bc8cd2b28 Need a login check 2024-05-06 14:02:25 -04:00
29 changed files with 373 additions and 689 deletions

No files matched your search

-10
View File
@@ -1,10 +0,0 @@
/.github/
Dockerfile*
docker-compose*.yml
/.data/
/secret.key
/rogueserver*
!/rogueserver.go
-46
View File
@@ -1,46 +0,0 @@
name: Build
on:
push:
pull_request:
jobs:
build:
name: Build (${{ matrix.os_name }})
env:
GO_VERSION: 1.22
GOOS: ${{ matrix.os_name }}
GOARCH: ${{ matrix.arch }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
os_name: linux
arch: amd64
- os: windows-latest
os_name: windows
arch: amd64
# TODO macos needs universal binary!
# - os: macos-latest
# os_name: macos
steps:
- uses: actions/checkout@v4
- name: Set up Go ${{ env.GO_VERSION }}
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
- name: Install dependencies
run: go mod download
- name: Test
run: go test -v
- name: Build
run: go build -v
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: rogueserver-${{ matrix.os_name }}-${{ matrix.arch }}-${{ github.sha }}
path: |
rogueserver*
!rogueserver.go
-38
View File
@@ -1,38 +0,0 @@
name: Publish to GHCR
on:
push:
jobs:
build:
name: Build and publish to GHCR
if: github.repository == 'pagefaultgames/rogueserver'
env:
GO_VERSION: 1.22
runs-on: ubuntu-latest
steps:
- name: Setup Docker BuildX
uses: docker/setup-buildx-action@v3
- name: Log into container registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ github.token }}
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository }}
- name: Build Docker image
uses: docker/build-push-action@v5
with:
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
GO_VERSION=${{ env.GO_VERSION }}
VERSION=${{ github.ref_name }}-SNAPSHOT
COMMIT_SHA=${{ env.GITHUB_SHA_SHORT }}
+1 -12
View File
@@ -1,16 +1,5 @@
# no extension on linux, .exe on windows
rogueserver*
!/rogueserver/*
/userdata/*
userdata/*
secret.key
# local testing
/.data/
# Jetbrains IDEs
/.idea/
*.iml
*.ipr
*.iws
.vscode/launch.json
-29
View File
@@ -1,29 +0,0 @@
ARG GO_VERSION=1.22
FROM golang:${GO_VERSION} AS builder
WORKDIR /src
COPY ./go.mod /src/
COPY ./go.sum /src/
RUN go mod download && go mod verify
COPY . /src/
RUN CGO_ENABLED=0 \
go build -o rogueserver
RUN chmod +x /src/rogueserver
# ---------------------------------------------
FROM scratch
WORKDIR /app
COPY --from=builder /src/rogueserver .
EXPOSE 8001
ENTRYPOINT ["./rogueserver"]
+2 -3
View File
@@ -19,7 +19,6 @@ package account
import (
"regexp"
"runtime"
"golang.org/x/crypto/argon2"
)
@@ -35,13 +34,13 @@ const (
ArgonKeySize = 32
ArgonSaltSize = 16
ArgonMaxInstances = 16
UUIDSize = 16
TokenSize = 32
)
var (
ArgonMaxInstances = runtime.NumCPU()
isValidUsername = regexp.MustCompile(`^\w{1,16}$`).MatchString
semaphore = make(chan bool, ArgonMaxInstances)
)
+17 -13
View File
@@ -18,7 +18,11 @@
package account
import (
"github.com/pagefaultgames/rogueserver/db"
"fmt"
"os"
"strconv"
"time"
"github.com/pagefaultgames/rogueserver/defs"
)
@@ -29,24 +33,24 @@ type InfoResponse struct {
// /account/info - get account info
func Info(username string, uuid []byte) (InfoResponse, error) {
response := InfoResponse{Username: username, LastSessionSlot: -1}
var latestSave time.Time
latestSaveID := -1
for id := range defs.SessionSlotCount {
fileName := "session"
if id != 0 {
fileName += strconv.Itoa(id)
}
highest := -1
for i := 0; i < defs.SessionSlotCount; i++ {
data, err := db.ReadSessionSaveData(uuid, i)
stat, err := os.Stat(fmt.Sprintf("userdata/%x/%s.pzs", uuid, fileName))
if err != nil {
continue
}
if data.Timestamp > highest {
highest = data.Timestamp
response.LastSessionSlot = i
if stat.ModTime().After(latestSave) {
latestSave = stat.ModTime()
latestSaveID = id
}
}
if response.LastSessionSlot < 0 || response.LastSessionSlot >= defs.SessionSlotCount {
response.LastSessionSlot = -1
}
return response, nil
return InfoResponse{Username: username, LastSessionSlot: latestSaveID}, nil
}
+7
View File
@@ -20,6 +20,8 @@ package account
import (
"crypto/rand"
"fmt"
"os"
"github.com/pagefaultgames/rogueserver/db"
)
@@ -50,5 +52,10 @@ func Register(username, password string) error {
return fmt.Errorf("failed to add account record: %s", err)
}
err = os.MkdirAll(fmt.Sprintf("userdata/%x", uuid), 0755)
if err != nil && !os.IsExist(err) {
return fmt.Errorf(fmt.Sprintf("failed to create userdata folder: %s", err))
}
return nil
}
+30
View File
@@ -0,0 +1,30 @@
package api
import (
"github.com/gorilla/sessions"
"github.com/markbates/goth"
"github.com/markbates/goth/gothic"
"github.com/markbates/goth/providers/discord"
)
// TODO: actual randomized key for sessions
const (
key = "randomString"
MaxAge = 86400 * 30 // 30 days
IsProd = false
)
func InitAuth(discordClientId string, discordClientSecret string, discordCallbackURI string) {
store := sessions.NewCookieStore([]byte(key))
store.MaxAge(MaxAge)
store.Options.Path = "/"
store.Options.HttpOnly = true
store.Options.Secure = IsProd
gothic.Store = store
goth.UseProviders(
discord.New(discordClientId, discordClientSecret, discordCallbackURI, discord.ScopeIdentify),
)
}
+6 -1
View File
@@ -40,6 +40,7 @@ func Init(mux *http.ServeMux) {
mux.HandleFunc("GET /account/logout", handleAccountLogout)
// game
mux.HandleFunc("GET /game/playercount", handleGamePlayerCount)
mux.HandleFunc("GET /game/titlestats", handleGameTitleStats)
mux.HandleFunc("GET /game/classicsessioncount", handleGameClassicSessionCount)
@@ -48,12 +49,16 @@ func Init(mux *http.ServeMux) {
mux.HandleFunc("POST /savedata/update", handleSaveData)
mux.HandleFunc("GET /savedata/delete", handleSaveData)
mux.HandleFunc("POST /savedata/clear", handleSaveData)
mux.HandleFunc("GET /savedata/newclear", handleNewClear)
// daily
mux.HandleFunc("GET /daily/seed", handleDailySeed)
mux.HandleFunc("GET /daily/rankings", handleDailyRankings)
mux.HandleFunc("GET /daily/rankingpagecount", handleDailyRankingPageCount)
// auth
mux.HandleFunc("/auth/{provider}/callback", handleProviderCallback)
mux.HandleFunc("/auth/{provider}/link", handleProviderLink)
mux.HandleFunc("/auth/{provider}/logout", handleProviderLogout)
}
func tokenFromRequest(r *http.Request) ([]byte, error) {
+11 -11
View File
@@ -61,26 +61,21 @@ func Init() error {
secret = newSecret
}
seed, err := recordNewDaily()
err = recordNewDaily()
if err != nil {
log.Print(err)
}
log.Printf("Daily Run Seed: %s", seed)
log.Printf("Daily Run Seed: %s", Seed())
_, err = scheduler.AddFunc("@daily", func() {
scheduler.AddFunc("@daily", func() {
time.Sleep(time.Second)
seed, err = recordNewDaily()
err := recordNewDaily()
if err != nil {
log.Printf("error while recording new daily: %s", err)
} else {
log.Printf("Daily Run Seed: %s", seed)
}
})
if err != nil {
return err
}
scheduler.Start()
@@ -100,6 +95,11 @@ func deriveSeed(seedTime time.Time) []byte {
return hashedSeed[:]
}
func recordNewDaily() (string, error) {
return db.TryAddDailyRun(Seed())
func recordNewDaily() error {
err := db.TryAddDailyRun(Seed())
if err != nil {
return err
}
return nil
}
+67 -49
View File
@@ -18,12 +18,13 @@
package api
import (
"database/sql"
"encoding/json"
"fmt"
"log"
"net/http"
"strconv"
"github.com/markbates/goth/gothic"
"github.com/pagefaultgames/rogueserver/api/account"
"github.com/pagefaultgames/rogueserver/api/daily"
"github.com/pagefaultgames/rogueserver/api/savedata"
@@ -37,6 +38,10 @@ import (
Handlers should not return serialized JSON, instead return the struct itself.
*/
var (
user = string("")
)
// account
func handleAccountInfo(w http.ResponseWriter, r *http.Request) {
@@ -145,6 +150,10 @@ func handleAccountLogout(w http.ResponseWriter, r *http.Request) {
// game
func handleGamePlayerCount(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(strconv.Itoa(playerCount)))
}
func handleGameTitleStats(w http.ResponseWriter, r *http.Request) {
err := json.NewEncoder(w).Encode(defs.TitleStats{
PlayerCount: playerCount,
@@ -281,10 +290,6 @@ func handleSaveData(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case "/savedata/get":
save, err = savedata.Get(uuid, datatype, slot)
if err == sql.ErrNoRows {
http.Error(w, err.Error(), http.StatusNotFound)
return
}
case "/savedata/update":
err = savedata.Update(uuid, slot, save)
case "/savedata/delete":
@@ -296,15 +301,14 @@ func handleSaveData(w http.ResponseWriter, r *http.Request) {
break
}
var seed string
seed, err = db.GetDailyRunSeed()
if err != nil {
httpError(w, r, err, http.StatusInternalServerError)
return
s, ok := save.(defs.SessionSaveData)
if !ok {
err = fmt.Errorf("save data is not type SessionSaveData")
break
}
// doesn't return a save, but it works
save, err = savedata.Clear(uuid, slot, seed, save.(defs.SessionSaveData))
save, err = savedata.Clear(uuid, slot, daily.Seed(), s)
}
if err != nil {
httpError(w, r, err, http.StatusInternalServerError)
@@ -325,47 +329,10 @@ func handleSaveData(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
}
func handleNewClear(w http.ResponseWriter, r *http.Request) {
uuid, err := uuidFromRequest(r)
if err != nil {
httpError(w, r, err, http.StatusBadRequest)
return
}
var slot int
if r.URL.Query().Has("slot") {
slot, err = strconv.Atoi(r.URL.Query().Get("slot"))
if err != nil {
httpError(w, r, err, http.StatusBadRequest)
return
}
}
newClear, err := savedata.NewClear(uuid, slot)
if err != nil {
httpError(w, r, fmt.Errorf("failed to read new clear: %s", err), http.StatusInternalServerError)
return
}
err = json.NewEncoder(w).Encode(newClear)
if err != nil {
httpError(w, r, fmt.Errorf("failed to encode response json: %s", err), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
}
// daily
func handleDailySeed(w http.ResponseWriter, r *http.Request) {
seed, err := db.GetDailyRunSeed()
if err != nil {
httpError(w, r, err, http.StatusInternalServerError)
return
}
w.Write([]byte(seed))
w.Write([]byte(daily.Seed()))
}
func handleDailyRankings(w http.ResponseWriter, r *http.Request) {
@@ -422,3 +389,54 @@ func handleDailyRankingPageCount(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(strconv.Itoa(count)))
}
// redirect link after authorizing application link
func handleProviderCallback(w http.ResponseWriter, r *http.Request) {
gothic.GetProviderName = func(r *http.Request) (string, error) { return r.PathValue("provider"), nil }
// called again with code after authorization
code := r.URL.Query().Get("code")
if code != "" {
userId, err := db.FetchDiscordIdByUsername(user)
if err != nil {
}
defer http.Redirect(w, r, "http://localhost:8000", http.StatusSeeOther)
}
gothUser, err := gothic.CompleteUserAuth(w, r)
if err != nil {
log.Println("callback err", w, r)
return
} else {
err := db.AddDiscordAuthByUsername(gothUser.UserID, user)
if err != nil {
log.Println("error adding Discord Auth to database")
return
}
}
log.Println("user", gothUser.UserID)
}
func handleProviderLink(w http.ResponseWriter, r *http.Request) {
gothic.GetProviderName = func(r *http.Request) (string, error) { return r.PathValue("provider"), nil }
username := r.URL.Query().Get("username")
// username recorded prior to authorization
if username != "" {
user = username
}
// try to get the user without re-authenticating
if gothUser, err := gothic.CompleteUserAuth(w, r); err == nil {
log.Print("gothUser:", gothUser.Name)
} else {
gothic.BeginAuthHandler(w, r)
}
}
func handleProviderLogout(w http.ResponseWriter, r *http.Request) {
gothic.GetProviderName = func(r *http.Request) (string, error) { return r.PathValue("provider"), nil }
gothic.Logout(w, r)
w.Header().Set("Location", "/")
w.WriteHeader(http.StatusTemporaryRedirect)
}
+12 -4
View File
@@ -18,8 +18,11 @@
package savedata
import (
"encoding/hex"
"fmt"
"log"
"os"
"strconv"
"github.com/pagefaultgames/rogueserver/db"
"github.com/pagefaultgames/rogueserver/defs"
@@ -57,15 +60,20 @@ func Clear(uuid []byte, slot int, seed string, save defs.SessionSaveData) (Clear
}
if sessionCompleted {
response.Success, err = db.TryAddSeedCompletion(uuid, save.Seed, int(save.GameMode))
response.Success, err = db.TryAddDailyRunCompletion(uuid, save.Seed, int(save.GameMode))
if err != nil {
log.Printf("failed to mark seed as completed: %s", err)
}
}
err = db.DeleteSessionSaveData(uuid, slot)
if err != nil {
log.Printf("failed to delete session save data: %s", err)
fileName := "session"
if slot != 0 {
fileName += strconv.Itoa(slot)
}
err = os.Remove(fmt.Sprintf("userdata/%s/%s.pzs", hex.EncodeToString(uuid), fileName))
if err != nil && !os.IsNotExist(err) {
return response, fmt.Errorf("failed to delete save file: %s", err)
}
return response, nil
+62
View File
@@ -18,9 +18,71 @@
package savedata
import (
"encoding/gob"
"encoding/hex"
"fmt"
"os"
"strconv"
"github.com/klauspost/compress/zstd"
"github.com/pagefaultgames/rogueserver/defs"
)
func readSystemSaveData(uuid []byte) (defs.SystemSaveData, error) {
var system defs.SystemSaveData
file, err := os.Open("userdata/" + hex.EncodeToString(uuid) + "/system.pzs")
if err != nil {
return system, fmt.Errorf("failed to open save file for reading: %s", err)
}
defer file.Close()
zstdDecoder, err := zstd.NewReader(file)
if err != nil {
return system, fmt.Errorf("failed to create zstd decoder: %s", err)
}
defer zstdDecoder.Close()
err = gob.NewDecoder(zstdDecoder).Decode(&system)
if err != nil {
return system, fmt.Errorf("failed to deserialize save: %s", err)
}
return system, nil
}
func readSessionSaveData(uuid []byte, slotID int) (defs.SessionSaveData, error) {
var session defs.SessionSaveData
fileName := "session"
if slotID != 0 {
fileName += strconv.Itoa(slotID)
}
file, err := os.Open(fmt.Sprintf("userdata/%s/%s.pzs", hex.EncodeToString(uuid), fileName))
if err != nil {
return session, fmt.Errorf("failed to open save file for reading: %s", err)
}
defer file.Close()
zstdDecoder, err := zstd.NewReader(file)
if err != nil {
return session, fmt.Errorf("failed to create zstd decoder: %s", err)
}
defer zstdDecoder.Close()
err = gob.NewDecoder(zstdDecoder).Decode(&session)
if err != nil {
return session, fmt.Errorf("failed to deserialize save: %s", err)
}
return session, nil
}
func validateSessionCompleted(session defs.SessionSaveData) bool {
switch session.GameMode {
case 0:
+19 -3
View File
@@ -19,9 +19,12 @@ package savedata
import (
"fmt"
"log"
"os"
"strconv"
"github.com/pagefaultgames/rogueserver/db"
"github.com/pagefaultgames/rogueserver/defs"
"log"
)
// /savedata/delete - delete save data
@@ -33,14 +36,27 @@ func Delete(uuid []byte, datatype, slot int) error {
switch datatype {
case 0: // System
return db.DeleteSystemSaveData(uuid)
err := os.Remove(fmt.Sprintf("userdata/%x/system.pzs", uuid))
if err != nil && !os.IsNotExist(err) {
return fmt.Errorf("failed to delete save file: %s", err)
}
case 1: // Session
if slot < 0 || slot >= defs.SessionSlotCount {
return fmt.Errorf("slot id %d out of range", slot)
}
return db.DeleteSessionSaveData(uuid, slot)
fileName := "session"
if slot != 0 {
fileName += strconv.Itoa(slot)
}
err = os.Remove(fmt.Sprintf("userdata/%x/%s.pzs", uuid, fileName))
if err != nil && !os.IsNotExist(err) {
return fmt.Errorf("failed to delete save file: %s", err)
}
default:
return fmt.Errorf("invalid data type")
}
return nil
}
+2 -6
View File
@@ -29,11 +29,7 @@ import (
func Get(uuid []byte, datatype, slot int) (any, error) {
switch datatype {
case 0: // System
if slot != 0 {
return nil, fmt.Errorf("invalid slot id for system data")
}
system, err := db.ReadSystemSaveData(uuid)
system, err := readSystemSaveData(uuid)
if err != nil {
return nil, err
}
@@ -53,7 +49,7 @@ func Get(uuid []byte, datatype, slot int) (any, error) {
return nil, fmt.Errorf("slot id %d out of range", slot)
}
session, err := db.ReadSessionSaveData(uuid, slot)
session, err := readSessionSaveData(uuid, slot)
if err != nil {
return nil, err
}
-44
View File
@@ -1,44 +0,0 @@
/*
Copyright (C) 2024 Pagefault Games
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package savedata
import (
"fmt"
"github.com/pagefaultgames/rogueserver/db"
"github.com/pagefaultgames/rogueserver/defs"
)
// /savedata/newclear - return whether a session is a new clear for its seed
func NewClear(uuid []byte, slot int) (bool, error) {
if slot < 0 || slot >= defs.SessionSlotCount {
return false, fmt.Errorf("slot id %d out of range", slot)
}
session, err := db.ReadSessionSaveData(uuid, slot)
if err != nil {
return false, err
}
completed, err := db.ReadSeedCompleted(uuid, session.Seed)
if err != nil {
return false, fmt.Errorf("failed to read seed completed: %s", err)
}
return !completed, nil
}
+30 -10
View File
@@ -18,8 +18,11 @@
package savedata
import (
"bytes"
"encoding/gob"
"fmt"
"log"
"os"
"strconv"
"github.com/klauspost/compress/zstd"
@@ -36,6 +39,13 @@ func Update(uuid []byte, slot int, save any) error {
log.Print("failed to update account last activity")
}
// ideally should have been done at account creation
err = os.MkdirAll(fmt.Sprintf("userdata/%x", uuid), 0755)
if err != nil && !os.IsExist(err) {
return fmt.Errorf(fmt.Sprintf("failed to create userdata folder: %s", err))
}
var filename string
switch save := save.(type) {
case defs.SystemSaveData: // System
if save.TrainerId == 0 && save.SecretId == 0 {
@@ -51,26 +61,36 @@ func Update(uuid []byte, slot int, save any) error {
return fmt.Errorf("failed to update account stats: %s", err)
}
err = db.DeleteClaimedAccountCompensations(uuid)
if err != nil {
return fmt.Errorf("failed to delete claimed compensations: %s", err)
}
return db.StoreSystemSaveData(uuid, save)
filename = "system"
db.DeleteClaimedAccountCompensations(uuid)
case defs.SessionSaveData: // Session
if slot < 0 || slot >= defs.SessionSlotCount {
return fmt.Errorf("slot id %d out of range", slot)
}
filename := "session"
filename = "session"
if slot != 0 {
filename += strconv.Itoa(slot)
}
return db.StoreSessionSaveData(uuid, save, slot)
default:
return fmt.Errorf("invalid data type")
}
var buf bytes.Buffer
err = gob.NewEncoder(&buf).Encode(save)
if err != nil {
return fmt.Errorf("failed to serialize save: %s", err)
}
if buf.Len() == 0 {
return fmt.Errorf("tried to write empty save file")
}
err = os.WriteFile(fmt.Sprintf("userdata/%x/%s.pzs", uuid, filename), zstdEncoder.EncodeAll(buf.Bytes(), nil), 0644)
if err != nil {
return fmt.Errorf("failed to write save to disk: %s", err)
}
return nil
}
+19
View File
@@ -53,6 +53,25 @@ func AddAccountSession(username string, token []byte) error {
return nil
}
func AddDiscordAuthByUsername(discordId []byte, username string) error {
_, err := handle.Exec("UPDATE accounts SET discordId = ? WHERE username = ?", discordId, username)
if err != nil {
return err
}
return nil
}
func FetchDiscordIdByUsername(username string) ([]byte, error) {
var discordId []byte
err := handle.QueryRow("SELECT discordId FROM accounts WHERE username = ?", username).Scan(&discordId)
if err != nil {
return nil, err
}
return discordId, nil
}
func UpdateAccountPassword(uuid, key, salt []byte) error {
_, err := handle.Exec("UPDATE accounts SET (hash, salt) VALUES (?, ?) WHERE uuid = ?", key, salt, uuid)
if err != nil {
+4 -16
View File
@@ -23,25 +23,13 @@ import (
"github.com/pagefaultgames/rogueserver/defs"
)
func TryAddDailyRun(seed string) (string, error) {
var actualSeed string
err := handle.QueryRow("INSERT INTO dailyRuns (seed, date) VALUES (?, UTC_DATE()) ON DUPLICATE KEY UPDATE date = date RETURNING seed", seed).Scan(&actualSeed)
func TryAddDailyRun(seed string) error {
_, err := handle.Exec("INSERT INTO dailyRuns (seed, date) VALUES (?, UTC_DATE()) ON DUPLICATE KEY UPDATE date = date", seed)
if err != nil {
return "", err
return err
}
return actualSeed, nil
}
func GetDailyRunSeed() (string, error) {
var seed string
err := handle.QueryRow("SELECT seed FROM dailyRuns WHERE date = UTC_DATE()").Scan(&seed)
if err != nil {
return "", err
}
return seed, nil
return nil
}
func AddOrUpdateAccountDailyRun(uuid []byte, score int, wave int) error {
+1 -130
View File
@@ -19,11 +19,7 @@ package db
import (
"database/sql"
"encoding/hex"
"fmt"
"log"
"os"
"time"
_ "github.com/go-sql-driver/mysql"
)
@@ -38,132 +34,7 @@ func Init(username, password, protocol, address, database string) error {
return fmt.Errorf("failed to open database connection: %s", err)
}
conns := 1024
if protocol != "unix" {
conns = 256
}
handle.SetMaxOpenConns(conns)
handle.SetMaxIdleConns(conns / 4)
handle.SetConnMaxIdleTime(time.Second * 10)
tx, err := handle.Begin()
if err != nil {
panic(err)
}
// accounts
tx.Exec("CREATE TABLE IF NOT EXISTS accounts (uuid BINARY(16) NOT NULL PRIMARY KEY, username VARCHAR(16) UNIQUE NOT NULL, hash BINARY(32) NOT NULL, salt BINARY(16) NOT NULL, registered TIMESTAMP NOT NULL, lastLoggedIn TIMESTAMP DEFAULT NULL, lastActivity TIMESTAMP DEFAULT NULL, banned TINYINT(1) NOT NULL DEFAULT 0, trainerId SMALLINT(5) UNSIGNED DEFAULT 0, secretId SMALLINT(5) UNSIGNED DEFAULT 0)")
// sessions
tx.Exec("CREATE TABLE IF NOT EXISTS sessions (token BINARY(32) NOT NULL PRIMARY KEY, uuid BINARY(16) NOT NULL, active TINYINT(1) NOT NULL DEFAULT 0, expire TIMESTAMP DEFAULT NULL, CONSTRAINT sessions_ibfk_1 FOREIGN KEY (uuid) REFERENCES accounts (uuid) ON DELETE CASCADE ON UPDATE CASCADE)")
tx.Exec("CREATE INDEX IF NOT EXISTS sessionsByUuid ON sessions (uuid)")
// stats
tx.Exec("CREATE TABLE IF NOT EXISTS accountStats (uuid BINARY(16) NOT NULL PRIMARY KEY, playTime INT(11) NOT NULL DEFAULT 0, battles INT(11) NOT NULL DEFAULT 0, classicSessionsPlayed INT(11) NOT NULL DEFAULT 0, sessionsWon INT(11) NOT NULL DEFAULT 0, highestEndlessWave INT(11) NOT NULL DEFAULT 0, highestLevel INT(11) NOT NULL DEFAULT 0, pokemonSeen INT(11) NOT NULL DEFAULT 0, pokemonDefeated INT(11) NOT NULL DEFAULT 0, pokemonCaught INT(11) NOT NULL DEFAULT 0, pokemonHatched INT(11) NOT NULL DEFAULT 0, eggsPulled INT(11) NOT NULL DEFAULT 0, regularVouchers INT(11) NOT NULL DEFAULT 0, plusVouchers INT(11) NOT NULL DEFAULT 0, premiumVouchers INT(11) NOT NULL DEFAULT 0, goldenVouchers INT(11) NOT NULL DEFAULT 0, CONSTRAINT accountStats_ibfk_1 FOREIGN KEY (uuid) REFERENCES accounts (uuid) ON DELETE CASCADE ON UPDATE CASCADE)")
// compensations
tx.Exec("CREATE TABLE IF NOT EXISTS accountCompensations (id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, uuid BINARY(16) NOT NULL, voucherType INT(11) NOT NULL, count INT(11) NOT NULL DEFAULT 1, claimed BIT(1) NOT NULL DEFAULT b'0', CONSTRAINT accountCompensations_ibfk_1 FOREIGN KEY (uuid) REFERENCES accounts (uuid) ON DELETE CASCADE ON UPDATE CASCADE)")
tx.Exec("CREATE INDEX IF NOT EXISTS accountCompensationsByUuid ON accountCompensations (uuid)")
// daily runs
tx.Exec("CREATE TABLE IF NOT EXISTS dailyRuns (date DATE NOT NULL PRIMARY KEY, seed CHAR(24) CHARACTER SET ascii COLLATE ascii_bin NOT NULL)")
tx.Exec("CREATE INDEX IF NOT EXISTS dailyRunsByDateAndSeed ON dailyRuns (date, seed)")
tx.Exec("CREATE TABLE IF NOT EXISTS dailyRunCompletions (uuid BINARY(16) NOT NULL, seed CHAR(24) CHARACTER SET ascii COLLATE ascii_bin NOT NULL, mode INT(11) NOT NULL DEFAULT 0, score INT(11) NOT NULL DEFAULT 0, timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (uuid, seed), CONSTRAINT dailyRunCompletions_ibfk_1 FOREIGN KEY (uuid) REFERENCES accounts (uuid) ON DELETE CASCADE ON UPDATE CASCADE)")
tx.Exec("CREATE INDEX IF NOT EXISTS dailyRunCompletionsByUuidAndSeed ON dailyRunCompletions (uuid, seed)")
tx.Exec("CREATE TABLE IF NOT EXISTS accountDailyRuns (uuid BINARY(16) NOT NULL, date DATE NOT NULL, score INT(11) NOT NULL DEFAULT 0, wave INT(11) NOT NULL DEFAULT 0, timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (uuid, date), CONSTRAINT accountDailyRuns_ibfk_1 FOREIGN KEY (uuid) REFERENCES accounts (uuid) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT accountDailyRuns_ibfk_2 FOREIGN KEY (date) REFERENCES dailyRuns (date) ON DELETE NO ACTION ON UPDATE NO ACTION)")
tx.Exec("CREATE INDEX IF NOT EXISTS accountDailyRunsByDate ON accountDailyRuns (date)")
// save data
tx.Exec("CREATE TABLE IF NOT EXISTS systemSaveData (uuid BINARY(16) PRIMARY KEY, data LONGBLOB, timestamp TIMESTAMP)")
tx.Exec("CREATE TABLE IF NOT EXISTS sessionSaveData (uuid BINARY(16), slot TINYINT, data LONGBLOB, timestamp TIMESTAMP, PRIMARY KEY (uuid, slot))")
err = tx.Commit()
if err != nil {
panic(err)
}
// TODO temp code
_, err = os.Stat("userdata")
if err != nil {
if os.IsNotExist(err) { // not found, do not migrate
return nil
} else {
log.Fatalf("failed to stat userdata directory: %s", err)
return err
}
}
entries, err := os.ReadDir("userdata")
if err != nil {
log.Fatalln(err)
return nil
}
for _, entry := range entries {
if !entry.IsDir() {
continue
}
uuidString := entry.Name()
uuid, err := hex.DecodeString(uuidString)
if err != nil {
log.Printf("failed to decode uuid: %s", err)
continue
}
var count int
err = handle.QueryRow("SELECT COUNT(*) FROM systemSaveData WHERE uuid = ?", uuid).Scan(&count)
if err != nil || count != 0 {
continue
}
// store new system data
systemData, err := LegacyReadSystemSaveData(uuid)
if err != nil {
log.Printf("failed to read system save data for %v: %s", uuidString, err)
continue
}
err = StoreSystemSaveData(uuid, systemData)
if err != nil {
log.Fatalf("failed to store system save data for %v: %s\n", uuidString, err)
continue
}
// delete old system data
err = os.Remove("userdata/" + uuidString + "/system.pzs")
if err != nil {
log.Fatalf("failed to remove legacy system save data for %v: %s", uuidString, err)
}
for i := 0; i < 5; i++ {
sessionData, err := LegacyReadSessionSaveData(uuid, i)
if err != nil {
log.Printf("failed to read session save data %v for %v: %s", i, uuidString, err)
continue
}
// store new session data
err = StoreSessionSaveData(uuid, sessionData, i)
if err != nil {
log.Fatalf("failed to store session save data for %v: %s\n", uuidString, err)
}
// delete old session data
filename := "session"
if i != 0 {
filename += fmt.Sprintf("%d", i)
}
err = os.Remove(fmt.Sprintf("userdata/%s/%s.pzs", uuidString, filename))
if err != nil {
log.Fatalf("failed to remove legacy session save data %v for %v: %s", i, uuidString, err)
}
}
}
handle.SetMaxOpenConns(1000)
return nil
}
-84
View File
@@ -1,84 +0,0 @@
/*
Copyright (C) 2024 Pagefault Games
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package db
import (
"encoding/gob"
"encoding/hex"
"fmt"
"os"
"strconv"
"github.com/klauspost/compress/zstd"
"github.com/pagefaultgames/rogueserver/defs"
)
func LegacyReadSystemSaveData(uuid []byte) (defs.SystemSaveData, error) {
var system defs.SystemSaveData
file, err := os.Open("userdata/" + hex.EncodeToString(uuid) + "/system.pzs")
if err != nil {
return system, fmt.Errorf("failed to open save file for reading: %s", err)
}
defer file.Close()
zstdDecoder, err := zstd.NewReader(file)
if err != nil {
return system, fmt.Errorf("failed to create zstd decoder: %s", err)
}
defer zstdDecoder.Close()
err = gob.NewDecoder(zstdDecoder).Decode(&system)
if err != nil {
return system, fmt.Errorf("failed to deserialize save: %s", err)
}
return system, nil
}
func LegacyReadSessionSaveData(uuid []byte, slotID int) (defs.SessionSaveData, error) {
var session defs.SessionSaveData
fileName := "session"
if slotID != 0 {
fileName += strconv.Itoa(slotID)
}
file, err := os.Open(fmt.Sprintf("userdata/%s/%s.pzs", hex.EncodeToString(uuid), fileName))
if err != nil {
return session, fmt.Errorf("failed to open save file for reading: %s", err)
}
defer file.Close()
zstdDecoder, err := zstd.NewReader(file)
if err != nil {
return session, fmt.Errorf("failed to create zstd decoder: %s", err)
}
defer zstdDecoder.Close()
err = gob.NewDecoder(zstdDecoder).Decode(&session)
if err != nil {
return session, fmt.Errorf("failed to deserialize save: %s", err)
}
return session, nil
}
+1 -110
View File
@@ -17,14 +17,7 @@
package db
import (
"bytes"
"encoding/gob"
"github.com/pagefaultgames/rogueserver/defs"
)
func TryAddSeedCompletion(uuid []byte, seed string, mode int) (bool, error) {
func TryAddDailyRunCompletion(uuid []byte, seed string, mode int) (bool, error) {
var count int
err := handle.QueryRow("SELECT COUNT(*) FROM dailyRunCompletions WHERE uuid = ? AND seed = ?", uuid, seed).Scan(&count)
if err != nil {
@@ -40,105 +33,3 @@ func TryAddSeedCompletion(uuid []byte, seed string, mode int) (bool, error) {
return true, nil
}
func ReadSeedCompleted(uuid []byte, seed string) (bool, error) {
var count int
err := handle.QueryRow("SELECT COUNT(*) FROM dailyRunCompletions WHERE uuid = ? AND seed = ?", uuid, seed).Scan(&count)
if err != nil {
return false, err
}
return count > 0, nil
}
func ReadSystemSaveData(uuid []byte) (defs.SystemSaveData, error) {
var system defs.SystemSaveData
var data []byte
err := handle.QueryRow("SELECT data FROM systemSaveData WHERE uuid = ?", uuid).Scan(&data)
if err != nil {
return system, err
}
err = gob.NewDecoder(bytes.NewReader(data)).Decode(&system)
if err != nil {
return system, err
}
return system, nil
}
func StoreSystemSaveData(uuid []byte, data defs.SystemSaveData) error {
var buf bytes.Buffer
err := gob.NewEncoder(&buf).Encode(data)
if err != nil {
return err
}
_, err = handle.Exec("INSERT INTO systemSaveData (uuid, data, timestamp) VALUES (?, ?, UTC_TIMESTAMP()) ON DUPLICATE KEY UPDATE data = ?, timestamp = UTC_TIMESTAMP()", uuid, buf.Bytes(), buf.Bytes())
if err != nil {
return err
}
return nil
}
func DeleteSystemSaveData(uuid []byte) error {
_, err := handle.Exec("DELETE FROM systemSaveData WHERE uuid = ?", uuid)
if err != nil {
return err
}
return nil
}
func ReadSessionSaveData(uuid []byte, slot int) (defs.SessionSaveData, error) {
var session defs.SessionSaveData
var data []byte
err := handle.QueryRow("SELECT data FROM sessionSaveData WHERE uuid = ? AND slot = ?", uuid, slot).Scan(&data)
if err != nil {
return session, err
}
err = gob.NewDecoder(bytes.NewReader(data)).Decode(&session)
if err != nil {
return session, err
}
return session, nil
}
func GetLatestSessionSaveDataSlot(uuid []byte) (int, error) {
var slot int
err := handle.QueryRow("SELECT slot FROM sessionSaveData WHERE uuid = ? ORDER BY timestamp DESC, slot ASC LIMIT 1", uuid).Scan(&slot)
if err != nil {
return -1, err
}
return slot, nil
}
func StoreSessionSaveData(uuid []byte, data defs.SessionSaveData, slot int) error {
var buf bytes.Buffer
err := gob.NewEncoder(&buf).Encode(data)
if err != nil {
return err
}
_, err = handle.Exec("INSERT INTO sessionSaveData (uuid, slot, data, timestamp) VALUES (?, ?, ?, UTC_TIMESTAMP()) ON DUPLICATE KEY UPDATE data = ?, timestamp = UTC_TIMESTAMP()", uuid, slot, buf.Bytes(), buf.Bytes())
if err != nil {
return err
}
return nil
}
func DeleteSessionSaveData(uuid []byte, slot int) error {
_, err := handle.Exec("DELETE FROM sessionSaveData WHERE uuid = ? AND slot = ?", uuid, slot)
if err != nil {
return err
}
return nil
}
-1
View File
@@ -59,7 +59,6 @@ type StarterEntry struct {
AbilityAttr int `json:"abilityAttr"`
PassiveAttr int `json:"passiveAttr"`
ValueReduction int `json:"valueReduction"`
ClassicWinCount int `json:"classicWinCount"`
}
type StarterMoveData map[int]interface{}
-14
View File
@@ -1,14 +0,0 @@
services:
db:
image: mariadb:11
container_name: pokerogue-db-local
restart: on-failure
environment:
MYSQL_ROOT_PASSWORD: admin
MYSQL_DATABASE: pokeroguedb
MYSQL_USER: pokerogue
MYSQL_PASSWORD: pokerogue
ports:
- "3306:3306"
volumes:
- ./.data/db:/var/lib/mysql
-27
View File
@@ -1,27 +0,0 @@
services:
server:
image: ghcr.io/pagefaultgames/pokerogue:latest
command: --debug --dbaddr db:3306 --dbuser pokerogue --dbpass pokerogue --dbname pokeroguedb
restart: unless-stopped
depends_on:
- db
networks:
- internal
ports:
- "8001:8001"
db:
image: mariadb:11
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: admin
MYSQL_DATABASE: pokeroguedb
MYSQL_USER: pokerogue
MYSQL_PASSWORD: pokerogue
volumes:
- database:/var/lib/mysql
volumes:
database:
networks:
internal:
+17 -2
View File
@@ -6,7 +6,22 @@ require (
github.com/go-sql-driver/mysql v1.7.1
github.com/klauspost/compress v1.17.4
github.com/robfig/cron/v3 v3.0.1
golang.org/x/crypto v0.16.0
golang.org/x/crypto v0.22.0
)
require golang.org/x/sys v0.15.0 // indirect
require (
github.com/golang/protobuf v1.5.3 // indirect
github.com/gorilla/context v1.1.1 // indirect
github.com/gorilla/mux v1.6.2 // indirect
github.com/gorilla/securecookie v1.1.2 // indirect
golang.org/x/oauth2 v0.17.0 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/protobuf v1.32.0 // indirect
)
require (
github.com/gorilla/sessions v1.2.2
github.com/joho/godotenv v1.5.1
github.com/markbates/goth v1.79.0
golang.org/x/sys v0.19.0 // indirect
)
+56
View File
@@ -1,10 +1,66 @@
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.2 h1:Pgr17XVTNXAk3q/r4CpKzC5xBM/qW1uVLV+IhRZpIIk=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA=
github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo=
github.com/gorilla/sessions v1.2.2 h1:lqzMYz6bOfvn2WriPUjNByzeXIlVzURcPmgMczkmTjY=
github.com/gorilla/sessions v1.2.2/go.mod h1:ePLdVu+jbEgHH+KWw8I1z2wqd0BAdAQh/8LRvBeoNcQ=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4=
github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
github.com/markbates/goth v1.79.0 h1:fUYi9R6VubVEK2bpmXvIUp7xRcxA68i8ovfUQx/i5Qc=
github.com/markbates/goth v1.79.0/go.mod h1:RBD+tcFnXul2NnYuODhnIweOcuVPkBohLfEvutPekcU=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY=
golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/oauth2 v0.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ=
golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
+9 -26
View File
@@ -34,16 +34,18 @@ func main() {
debug := flag.Bool("debug", false, "use debug mode")
proto := flag.String("proto", "tcp", "protocol for api to use (tcp, unix)")
addr := flag.String("addr", "0.0.0.0:8001", "network address for api to listen on")
tlscert := flag.String("tlscert", "", "tls certificate path")
tlskey := flag.String("tlskey", "", "tls key path")
addr := flag.String("addr", "0.0.0.0", "network address for api to listen on")
dbuser := flag.String("dbuser", "pokerogue", "database username")
dbpass := flag.String("dbpass", "pokerogue", "database password")
dbpass := flag.String("dbpass", "", "database password")
dbproto := flag.String("dbproto", "tcp", "protocol for database connection")
dbaddr := flag.String("dbaddr", "localhost", "database address")
dbname := flag.String("dbname", "pokeroguedb", "database name")
discordclientid := flag.String("discordclientid", "1225433195617718315", "Discord Oauth2 Client ID")
discordsecretid := flag.String("discordsecretid", "LxtTMCEeRagl7Rve0goZzUnv4mnT5Xzm", "Discord Oauth2 Client ID")
discordcallbackuri := flag.String("discordcallbackuri", "http://localhost:8001/auth/discord/callback", "Discord Oauth2 Client ID")
flag.Parse()
// register gob types
@@ -65,18 +67,14 @@ func main() {
mux := http.NewServeMux()
// init api
api.InitAuth(*discordclientid, *discordsecretid, *discordcallbackuri)
api.Init(mux)
// start web server
handler := prodHandler(mux)
if *debug {
handler = debugHandler(mux)
}
if *tlscert == "" {
err = http.Serve(listener, handler)
err = http.Serve(listener, debugHandler(mux))
} else {
err = http.ServeTLS(listener, handler, *tlscert, *tlskey)
err = http.Serve(listener, mux)
}
if err != nil {
log.Fatalf("failed to create http server or server errored: %s", err)
@@ -100,21 +98,6 @@ func createListener(proto, addr string) (net.Listener, error) {
return listener, nil
}
func prodHandler(router *http.ServeMux) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Headers", "Authorization, Content-Type")
w.Header().Set("Access-Control-Allow-Methods", "OPTIONS, GET, POST")
w.Header().Set("Access-Control-Allow-Origin", "https://pokerogue.net")
if r.Method == "OPTIONS" {
w.WriteHeader(http.StatusOK)
return
}
router.ServeHTTP(w, r)
})
}
func debugHandler(router *http.ServeMux) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Headers", "*")