v0.16.0 import PGN, delete games, two-layout web client
This commit is contained in:
1 parent
e1fa5242e3
commit
664cf9654e
34 files changed
+2007
-150
No files matched your search
@@ -98,8 +98,8 @@ func (r *Registry) registerGameCommands() {
|
||||
r.Register(&Command{
|
||||
Name: "games",
|
||||
ShortName: "g",
|
||||
Description: "List your stored games, newest first (login required)",
|
||||
Usage: "games [more]",
|
||||
Description: "List, or delete, your stored games (login required)",
|
||||
Usage: "games [more] | games delete <#|gameId>",
|
||||
Handler: gamesHandler,
|
||||
Paged: true,
|
||||
})
|
||||
@@ -113,6 +113,14 @@ func (r *Registry) registerGameCommands() {
|
||||
Paged: true,
|
||||
})
|
||||
|
||||
r.Register(&Command{
|
||||
Name: "import",
|
||||
ShortName: "",
|
||||
Description: "Store a PGN file as one of your games (login required)",
|
||||
Usage: "import <path>",
|
||||
Handler: importHandler,
|
||||
})
|
||||
|
||||
r.Register(&Command{
|
||||
Name: "poll",
|
||||
ShortName: "p",
|
||||
@@ -686,6 +694,9 @@ func gamesHandler(s *session.Session, args []string) error {
|
||||
if s.AuthToken == "" {
|
||||
return fmt.Errorf("login required")
|
||||
}
|
||||
if len(args) > 0 && args[0] == "delete" {
|
||||
return gamesDeleteHandler(s, args[1:])
|
||||
}
|
||||
cursor := ""
|
||||
if len(args) > 0 && args[0] == "more" {
|
||||
if s.GamesCursor == "" {
|
||||
@@ -718,6 +729,62 @@ func gamesHandler(s *session.Session, args []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// gamesDeleteHandler removes a game from the user's list by its number in
|
||||
// the last listing or its ID. A game another player also claims is only
|
||||
// released; one the user alone holds is deleted with its moves.
|
||||
func gamesDeleteHandler(s *session.Session, args []string) error {
|
||||
if len(args) < 1 {
|
||||
return fmt.Errorf("usage: games delete <#|gameId>")
|
||||
}
|
||||
gameID := args[0]
|
||||
if index, err := strconv.Atoi(gameID); err == nil {
|
||||
if index < 1 || index > len(s.GamesPage) {
|
||||
return fmt.Errorf("index %d is outside the last listing (1-%d)", index, len(s.GamesPage))
|
||||
}
|
||||
gameID = s.GamesPage[index-1].GameID
|
||||
}
|
||||
resp, err := s.Client.RemoveMyGame(gameID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if resp.Removed == "claim" {
|
||||
display.Println(display.Yellow, "Released your side of %s; the other player keeps the game", gameID)
|
||||
} else {
|
||||
display.Println(display.Green, "Deleted game %s", gameID)
|
||||
}
|
||||
if s.Replay != nil && s.Replay.History.GameID == gameID {
|
||||
s.Replay = nil
|
||||
}
|
||||
if s.CurrentGame == gameID && resp.Removed == "game" {
|
||||
s.CurrentGame = ""
|
||||
s.CurrentGameState = nil
|
||||
s.LastMoveCount = 0
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// importHandler stores a PGN file (one game) under the user's account and
|
||||
// makes it the replay.
|
||||
func importHandler(s *session.Session, args []string) error {
|
||||
if s.AuthToken == "" {
|
||||
return fmt.Errorf("login required")
|
||||
}
|
||||
if len(args) < 1 {
|
||||
return fmt.Errorf("usage: import <path>")
|
||||
}
|
||||
text, err := readImportFile(args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resp, err := s.Client.ImportGame(text)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
display.Println(display.Green, "Imported game %s (%d plies, %s)", resp.GameID, resp.MoveCount, resp.PGNResult)
|
||||
display.Println(display.Cyan, "Replay it: replay %s", resp.GameID)
|
||||
return nil
|
||||
}
|
||||
|
||||
func playerLabel(p api.PlayerInfo) string {
|
||||
switch {
|
||||
case p.Type == 2:
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
//go:build !js && !wasm
|
||||
|
||||
package command
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
const maxImportFile = 64 << 10
|
||||
|
||||
// readImportFile reads a PGN file for import.
|
||||
func readImportFile(path string) (string, error) {
|
||||
info, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if info.Size() > maxImportFile {
|
||||
return "", fmt.Errorf("%s is larger than %d bytes", path, maxImportFile)
|
||||
}
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(data), nil
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
//go:build js && wasm
|
||||
|
||||
package command
|
||||
|
||||
import "fmt"
|
||||
|
||||
// readImportFile has no file system in the browser; the web board imports
|
||||
// a pasted PGN instead.
|
||||
func readImportFile(path string) (string, error) {
|
||||
return "", fmt.Errorf("files cannot be read in the browser; paste the PGN into the web board's Import instead")
|
||||
}
|
||||
@@ -152,6 +152,7 @@ func (r *Registry) helpHandler(s *session.Session, args []string) error {
|
||||
{"draw", "", ""},
|
||||
{"games", "g", ""},
|
||||
{"pgn", "", ""},
|
||||
{"import", "", ""},
|
||||
}
|
||||
|
||||
replayCommands := []cmdInfo{
|
||||
|
||||
Reference in new issue
Block a user