v0.13.0 web and terminal client enhance, replay api, linux server deploy, doc and dependency update
test / test (push) Canceled after 0s

This commit is contained in:
lixen committed 2026-09-28 22:35:52 -04:00
1 parent 52ac0fe31a
commit f1ac4cbbe7
71 files changed
+7677 -537

No files matched your search

+40 -3
View File
@@ -6,6 +6,7 @@ import (
"fmt"
"io"
"net/http"
"net/url"
"strings"
"time"
@@ -140,7 +141,11 @@ func (c *Client) doRequest(method, path string, body any, result any) error {
return fmt.Errorf("request failed with status %d", resp.StatusCode)
}
// Parse success response
// Parse success response; a *string receives a non-JSON body as-is
if text, ok := result.(*string); ok {
*text = string(respBody)
return nil
}
if result != nil && len(respBody) > 0 {
if err := json.Unmarshal(respBody, result); err != nil {
// For debug, show raw response if parsing fails
@@ -198,6 +203,22 @@ func (c *Client) UndoMoves(gameID string, count int) (*GameResponse, error) {
return &resp, err
}
// Resign ends the game in the opponent's favor; color may be "" when the
// caller plays exactly one human side.
func (c *Client) Resign(gameID, color string) (*GameResponse, error) {
var resp GameResponse
err := c.doRequest("POST", "/api/games/"+gameID+"/resign", &ResignRequest{Color: color}, &resp)
return &resp, err
}
// Draw offers, accepts, or declines a draw; the response's DrawOutcome says
// what happened.
func (c *Client) Draw(gameID, action, color string) (*GameResponse, error) {
var resp GameResponse
err := c.doRequest("POST", "/api/games/"+gameID+"/draw", &DrawRequest{Action: action, Color: color}, &resp)
return &resp, err
}
func (c *Client) GetBoard(gameID string) (*BoardResponse, error) {
var resp BoardResponse
err := c.doRequest("GET", "/api/games/"+gameID+"/board", nil, &resp)
@@ -210,9 +231,25 @@ func (c *Client) GetGameHistory(gameID string) (*GameHistoryResponse, error) {
return &resp, err
}
func (c *Client) GetMyGames(limit, offset int) (*GameListResponse, error) {
// GetGamePGN returns the stored game in PGN; ply < 0 exports every move.
func (c *Client) GetGamePGN(gameID string, ply int) (string, error) {
path := "/api/games/" + gameID + "/pgn"
if ply >= 0 {
path += fmt.Sprintf("?ply=%d", ply)
}
var text string
err := c.doRequest("GET", path, nil, &text)
return text, err
}
// GetMyGames lists the caller's games, newest first; cursor is "" for the
// first page, then the previous page's NextCursor.
func (c *Client) GetMyGames(limit int, cursor string) (*GameListResponse, error) {
var resp GameListResponse
path := fmt.Sprintf("/api/users/me/games?limit=%d&offset=%d", limit, offset)
path := fmt.Sprintf("/api/users/me/games?limit=%d", limit)
if cursor != "" {
path += "&cursor=" + url.QueryEscape(cursor)
}
err := c.doRequest("GET", path, nil, &resp)
return &resp, err
}
+24 -7
View File
@@ -36,13 +36,25 @@ type LoginRequest struct {
// Response types
type GameResponse struct {
GameID string `json:"gameId"`
FEN string `json:"fen"`
Turn string `json:"turn"`
State string `json:"state"`
Moves []string `json:"moves"`
Players PlayersResponse `json:"players"`
LastMove *MoveInfo `json:"lastMove,omitempty"`
GameID string `json:"gameId"`
FEN string `json:"fen"`
Turn string `json:"turn"`
State string `json:"state"`
Termination string `json:"termination,omitempty"`
DrawOffer string `json:"drawOffer,omitempty"`
DrawOutcome string `json:"drawOutcome,omitempty"`
Moves []string `json:"moves"`
Players PlayersResponse `json:"players"`
LastMove *MoveInfo `json:"lastMove,omitempty"`
}
type ResignRequest struct {
Color string `json:"color,omitempty"`
}
type DrawRequest struct {
Action string `json:"action"`
Color string `json:"color,omitempty"`
}
type PlayersResponse struct {
@@ -104,6 +116,8 @@ type GameHistoryResponse struct {
GameID string `json:"gameId"`
InitialFEN string `json:"initialFen"`
Result string `json:"result,omitempty"`
PGNResult string `json:"pgnResult"`
Termination string `json:"termination,omitempty"`
StartTimeUTC time.Time `json:"startTimeUtc"`
EndTimeUTC *time.Time `json:"endTimeUtc,omitempty"`
Players PlayersResponse `json:"players"`
@@ -113,6 +127,7 @@ type GameHistoryResponse struct {
type HistoryMove struct {
MoveNumber int `json:"moveNumber"`
MoveUCI string `json:"moveUci"`
SAN string `json:"san,omitempty"`
FENAfterMove string `json:"fenAfterMove"`
PlayerColor string `json:"playerColor"`
MoveTimeUTC time.Time `json:"moveTimeUtc"`
@@ -123,6 +138,7 @@ type GameSummary struct {
InitialFEN string `json:"initialFen"`
FinalFEN string `json:"finalFen"`
Result string `json:"result,omitempty"`
PGNResult string `json:"pgnResult"`
StartTimeUTC time.Time `json:"startTimeUtc"`
EndTimeUTC *time.Time `json:"endTimeUtc,omitempty"`
MoveCount int `json:"moveCount"`
@@ -134,4 +150,5 @@ type GameListResponse struct {
Limit int `json:"limit"`
Offset int `json:"offset"`
NextOffset *int `json:"nextOffset,omitempty"`
NextCursor string `json:"nextCursor,omitempty"`
}