tripwire/player.go

146 lines
3.4 KiB
Go

package main
// todo: make a consistent "player" type and have these functions return it
// todo: dont manually patch column name into various internal funcs (would make the extra funcs unnecessary)
import (
"database/sql"
"errors"
"io/fs"
"os"
)
func _playerExistsBy(query string, value any) (bool, error) {
sqlStatement := `
SELECT username FROM users WHERE ` + query + ` = ?;
`
var x string
err := DB.QueryRow(sqlStatement, value).Scan(&x)
if err != nil {
if err == sql.ErrNoRows {
return false, nil
}
return false, err
}
return true, nil
}
func playerExistsByUUID(uuid string) (bool, error) {
return _playerExistsBy("uuid", uuid)
}
func playerExistsByUsername(username string) (bool, error) {
return _playerExistsBy("username", username)
}
func _getPlayerBy(query string, value any) (PlayerData, error) {
// todo: make this function less repetitive if possible
sqlStatement := `
SELECT id, username, password, uuid, client_token, auth_token, web_token, created_at FROM users WHERE ` + query + ` = ?;
`
var player PlayerData
err := DB.QueryRow(sqlStatement, value).Scan(
&player.Id,
&player.Username,
&player.Password,
&player.UUID,
&player.ClientToken,
&player.AuthToken,
&player.WebToken,
&player.CreatedAt,
)
if err != nil {
if err == sql.ErrNoRows {
return player, nil
}
return player, err
}
return player, nil
}
func getPlayerByUUID(uuid string) (PlayerData, error) {
return _getPlayerBy("uuid", uuid)
}
func getPlayerByUsername(username string) (PlayerData, error) {
return _getPlayerBy("username", username)
}
func getPlayerByAuthToken(auth string) (PlayerData, error) {
return _getPlayerBy("auth_token", auth)
}
// todo: dedupe skin and cape functions if possible
func getPlayerTexture(textureId string, uuid string) ([]byte, error) {
if !(textureId == "skin" || textureId == "cape") {
return []byte{}, &InvalidDataError{}
}
tex, err := os.ReadFile(textureId + "s/" + uuid + ".png")
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
return []byte{}, &NotFoundError{}
}
return []byte{}, err
}
return tex, nil
}
func setPlayerTexture(textureId string, uuid string, tex []byte) error {
if !(textureId == "skin" || textureId == "cape") {
return &InvalidDataError{}
}
if len(tex) > config.MaxTextureSize {
return &TooLargeError{}
}
exists, err := playerExistsByUUID(uuid)
if err != nil {
return err
}
if !exists {
return &NotFoundError{}
}
err = os.WriteFile(textureId+"s/"+uuid+".png", tex, 0644)
if err != nil {
return err
}
return nil
}
func playerHasTexture(textureId string, uuid string) (bool, error) {
if !(textureId == "skin" || textureId == "cape") {
return false, &InvalidDataError{}
}
_, err := os.Stat(textureId + "s/" + uuid + ".png")
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
return false, nil
}
return false, err
}
return true, nil
}
func _checkPlayerPassBy(query string, value any, password string) (bool, error) {
sqlStatement := `
SELECT password FROM users WHERE ` + query + ` = ?;
`
row := DB.QueryRow(sqlStatement, value)
var pass string
err := row.Scan(&pass)
if err != nil {
return false, err
}
if pass != password {
return false, nil
}
return true, nil
}
func checkPlayerPassByUUID(uuid string, password string) (bool, error) {
return _checkPlayerPassBy("uuid", uuid, password)
}
func checkPlayerPassByUsername(username string, password string) (bool, error) {
return _checkPlayerPassBy("username", username, password)
}