goban
Version:
[](https://opensource.org/licenses/Apache-2.0) [](https://deepwiki.com/online-go/goban)
650 lines (649 loc) • 24.2 kB
TypeScript
import type { GameListEntry, User, AutomatchPreferences, RemoteStorageReplication, BotConfig } from "./ClientToServer";
import type { JGOFTimeControl } from "../formats/JGOF";
import type { ConditionalMoveResponse } from "../ConditionalMoveTree";
import type { GobanEngineConfig, Score, ReviewMessage } from "../GobanEngine";
import type { AdHocPackedMove } from "../formats/AdHocFormat";
interface Vote {
voter_id: number;
action: string;
updated: string;
}
export interface ServerToClient {
/** Pong response from a ping */
"net/pong": (data: {
/** Client timestamp that was sent */
client: number;
/** Server timestamp when it was received */
server: number;
}) => void;
/** The client should reload */
"HUP": () => void;
/** An error occurred, the message string should be displayed to the user.
* For a list of errcode's used, see
* https://github.com/online-go/online-go.com/blob/devel/src/components/Errcode/Errcode.tsx
*/
"ERROR": (data: string | {
errcode: string;
}) => void;
/** General host information for the termination server you
* are connected to. This is a response to the `hostinfo` client message. */
"hostinfo": (data: {
/** The hostname of the server */
hostname: string;
/** Number of clients connected, if available */
clients: number;
/** Number of seconds the server has been running */
uptime: number;
}) => void;
/** "Inter Tab Communication" message. This is a client utility to enable
* relaying of messages between devices - the event and data are
* application defined, the server blindly relays to all connected devices
* for the sending user. Note this is relayed to all devices regardless
* of client, so your application should be prepared to handle ITC messages
* from other applications, not just your own application. (For instance,
* the web client sending this will arrive on an android and ios instance)
*/
"itc": (data: {
/** User defined event string */
event: string;
/** User defined data */
data: any;
}) => void;
/** A UI Push notification. The event and data are not well defined here,
* they come as a result to subscribing to ui push channels with
* `ui-pushes/subscribe`.
*/
"ui-push": (data: {
/** UI Push event */
event: string;
/** UI Push data */
data: string;
}) => void;
/** Update the user's JWT token */
"user/jwt": (jwt: string) => void;
/** Update user information. For other players, this has the standard User
* fields, when this is the current user, it can have additional fields
* that are found in the ui/config */
"user/update": (user: User & {
[]: any;
}) => void;
/** Updates whether a user is online or not. Subscribe to these updates for
* particular users using the `user/monitor` command. */
"user/state": (data: {
[]: boolean;
}) => void;
/** A notification that should be displayed to the user
* These are not strongly modeled, see
* https://github.com/online-go/online-go.com/blob/devel/src/components/Notifications/Notifications.tsx
* as a reference for what types there are and what data they contain
*/
"notification": (data: {
/** The notification id */
id: string;
/** The notification type */
type: string;
/** There are often more fields here */
[]: any;
}) => void;
/** Message to inform the client of an active game, or a change to an existing game */
"active_game": (data: GameListEntry) => void;
/** Updates the list of bots that are connected and ready to the server */
"active-bots": (data: {
[]: User & {
config: BotConfig;
};
}) => void;
/** An automatch request was canceled */
"automatch/cancel": (data: {
uuid: string;
}) => void;
/** An automatch request is active */
"automatch/entry": (data: AutomatchPreferences) => void;
/** An automatch request was started */
"automatch/start": (data: {
uuid: string;
game_id: number;
}) => void;
/** An automatch offer was added */
"automatch/available/add": (data: {
uuid: string;
preferences: AutomatchPreferences;
player: {
id: number;
username: string;
};
created: number;
}) => void;
/** An automatch offer was removed */
"automatch/available/remove": (uuid: string) => void;
/** User(s) joined a chat channel */
"chat-join": (data: {
/** The channel */
channel: string;
/** List of users that joined */
users: User[];
}) => void;
/** Chat message was received */
"chat-message": (data: {
/** The channel */
channel: string;
/** User id of the sender */
id: number;
/** Username of the sender */
username: string;
/** UI class of the sender */
ui_class: string;
/** Ranking of the sender */
ranking: number;
/** True if the user is a professional */
professional: boolean;
/** Country the user is from */
country?: string;
/** Whether it's a system message or not */
system?: true;
/** The message received */
message: {
/** Message id. This is always set for non system messages. */
i?: string;
/** Message text */
m: string;
/** Timestamp of the message */
t: number;
};
system_message_type?: "flood";
}) => void;
/** User left a chat channel */
"chat-part": (data: {
/** The channel */
channel: string;
/** User that left */
user: User;
}) => void;
/** A chat message should be removed from the display */
"chat-message-removed": (data: {
/** The channel */
channel: string;
/** Message id. Note, despite the name, I don't think this is always a
* uuid in uuid format, just treat it as a string. */
uuid: string;
}) => void;
/** Channel topic was updated */
"chat-topic": (data: {
/** The channel */
channel: string;
/** The new topic */
topic: string;
/** Timestamp (ms) of the topic change */
timestamp: number;
/** User id of the user that changed the topic */
id: number;
/** Username of the user that changed the topic */
username: string;
/** Ranking of the user that changed the topic */
ranking: number;
/** If the user that changed the topic was a professional */
professional: boolean;
/** UI class of the user that changed the topic */
ui_class: string;
/** Country of the user that changed the topic */
country?: string;
}) => void;
/** A user's profile was updated */
"chat-update-user": (data: {
/** The channel */
channel: string;
/** Player id entry that was update. This might change in the case of a
* guest logging in, in this case this will switch from being a
* negative (guest) id, to some positive id. It is not expected that a
* non guest id should change using this system. */
old_player_id: number;
/** New user details */
user: User;
}) => void;
/** Update number of live and correspondence games are currently being
* played */
"gamelist-count": (data: {
/** Number of live games */
live: number;
/** Number of correspondence games */
correspondence: number;
}) => void;
/** Update number of live and correspondence games are currently being
* played in a particular channel */
"gamelist-count-:channel": (data: {
/** Number of live games */
live: number;
/** Number of correspondence games */
correspondence: number;
}) => void;
[]: ServerToClient["gamelist-count-:channel"];
/** Incident report update */
"incident-report": (data: {
id: number;
created: string;
updated: string;
state: "pending" | "claimed" | "resolved";
escalated: boolean;
escalated_at: string;
source: string;
report_type: string;
reporting_user?: User;
reported_user?: User;
reported_game?: number;
reported_review?: number;
reported_conversation?: string;
url: string;
moderator?: User;
cleared_by_user?: boolean;
was_helpful: boolean;
reporter_note: string;
reporter_note_translation: {
source_language: string;
source_text: string;
target_language: string;
target_text: string;
};
moderator_note: string;
system_note: string;
voters: Vote[];
}) => void;
/** A private message was received */
"private-message": (data: {
/** Who sent the message */
from: User;
/** Your user id */
to: User;
/** If true, the private message should be forced to be in focus, this
* is when a moderator needs to talk with a player and ignoring the
* moderator is not suitable thing to do. */
superchat_enabled?: boolean;
/** The message received */
message: {
/** Timestamp of the message */
t: number;
/** Message id. */
i: string;
/** Message text */
m: string;
};
}) => void;
/** Notify the client that a private message "super chat" has started. A
* super chat is an undismissable chat sent by a moderator. It should take
* all focus and not let the client do anything until the conversation is
* resolved (the enable flag is set to false) */
"private-superchat": (data: {
/** The moderator id contacting the player */
moderator_id: number;
/** The moderator username contacting the player */
moderator_username: string;
/** Your id */
player_id: number;
/** Your username */
player_username: string;
/** Whether the superchat is enabled or not. When true, the client
* should make an undismissable chat window, when false the window
* can be dismissed. */
enable: boolean;
}) => void;
/** Notification that the server has completed sending all remote storage
* data and the client should now be up to date. */
"remote_storage/sync_complete": () => void;
/** Updates a key value pair */
"remote_storage/update": (data: {
/** Key for the k/v pair */
key: string;
/** Value of of the k/v pair */
value: any;
/** Replication mode */
replication: RemoteStorageReplication;
/** Timestamp of the update */
modified: string;
}) => void;
/** Notifies the client whether the the client shares an IP with one of the
* players of the game. This is used to disable the score estimator in
* anonymous browsing windows for players of a game when the score
* estimator is disabled for the game. */
"score-estimator-enabled-state": (data: {
/** The game ID */
game_id: number;
/** True if the client shares an IP with one of the players of the game */
shared_ip_with_player: boolean;
}) => void;
"seekgraph/global": (messages: (SeekgraphDeleteMessage | SeekgraphStartedMessage | SeekgraphChallengeMessage)[]) => void;
/** Informs the client the player is scheduled to resign if not cleared */
"game/:id/auto_resign": (data: {
/** The game id */
game_id: number;
/** The player id */
player_id: number;
/** When the auto resign will happen */
expiration: number;
}) => void;
[]: ServerToClient["game/:id/auto_resign"];
/** The auto resign for the given player has been cleared */
"game/:id/clear_auto_resign": (data: {
/** The game id */
game_id: number;
/** The player id */
player_id: number;
}) => void;
[]: ServerToClient["game/:id/clear_auto_resign"];
/** A game chat message */
"game/:id/chat": (data: GameChatMessage) => void;
[]: ServerToClient["game/:id/chat"];
/** Game chat lines should be removed */
"game/:id/chat/remove": (data: {
/** The game id */
game_id: number;
/** The chat ids */
chat_ids: string[];
}) => void;
[]: ServerToClient["game/:id/chat/remove"];
/** Game clock update */
"game/:id/clock": (data: GameClock) => void;
[]: ServerToClient["game/:id/clock"];
/** Update the conditional moves currently active */
"game/:id/conditional_moves": (data: {
/** The game id */
game_id: number;
/** The move number from which the conditional moves are rooted in */
move_number: number;
/** The conditional moves. The top level should be an array that looks
* like `[null, { ... }]` where the second element contains the responses
* to the opponent's move. */
conditional_moves: ConditionalMoveResponse;
}) => void;
[]: ServerToClient["game/:id/conditional_moves"];
/** Error that should be displayed to the user */
"game/:id/error": (data: string) => void;
[]: ServerToClient["game/:id/error"];
/** Update the entire game state */
"game/:id/gamedata": (data: GobanEngineConfig) => void;
[]: ServerToClient["game/:id/gamedata"];
/** Update latency information for a player */
"game/:id/latency": (data: {
/** The game id */
game_id: number;
/** The player id */
player_id: number;
/** The latency in milliseconds */
latency: number;
}) => void;
[]: ServerToClient["game/:id/latency"];
/** A move was made on a game */
[]: (data: {
/** The game id */
game_id: number;
/** Move number the move was made from*/
move_number: number;
/** Move string encoded move */
move: AdHocPackedMove;
}) => void;
/** The phase has changed for the game */
"game/:id/phase": (data: "play" | "stone removal" | "finished") => void;
[]: ServerToClient["game/:id/phase"];
/** Player information has been updated. This is a rengo game thing, every move we rotate out players if applicable. */
[]: (data: {
players: {
/** Active black player id */
black: number;
/** Active white player id */
white: number;
};
rengo_teams: {
/** Active black player ids (in the order of which they'll play) */
black: number[];
/** Active white player ids (in the order of which they'll play) */
white: number[];
};
}) => void;
/** Update the state of the stone removal phase */
"game/:id/removed_stones": (data: {
/** Whether the stones are being flagged or unflagged for
* removal */
removed: boolean;
/** The stones that have changed state. Note, these can be
* empty intersections as well, in which case we are flagging
* them as dame */
stones: string;
/** Current state of all removed stones */
all_removed: string;
} | {
strict_seki_mode: boolean;
}) => void;
[]: ServerToClient["game/:id/removed_stones"];
/** The stone removal phase has been completed, this is the final state and
* indicates a phase change to the given phase (should always be
* "finished") */
"game/:id/removed_stones_accepted": (data: {
player_id: number;
stones: string;
/** True if Japanese strict seki mode was true. This will probably
* always be false and may be removed in the future. */
strict_seki_mode: boolean;
/** Current players and their accepted stone statuses */
players: {
/** Active black player id */
black: User | {
accepted_stones: string;
accepted_strict_seki_mode: boolean;
};
white: User | {
accepted_stones: string;
accepted_strict_seki_mode: boolean;
};
};
/** Game phase (finished */
phase: "finished";
/** Score */
score: Score;
/** Player id of the winner */
winner: number;
/** Outcome of the game */
outcome: string;
/** Timestamp in ms */
end_time: number;
}) => void;
[]: ServerToClient["game/:id/removed_stones_accepted"];
/** The chat log should be reset. */
"game/:id/reset-chats": () => void;
[]: ServerToClient["game/:id/reset-chats"];
/** Undo move has been accepted, the parameter is the new move number */
"game/:id/undo_accepted": (data: number) => void;
[]: ServerToClient["game/:id/undo_accepted"];
/** Undo request has been canceled, the parameter is the move number of the original request */
"game/:id/undo_canceled": (data: number) => void;
[]: ServerToClient["game/:id/undo_canceled"];
/** Undo request has been requested, the parameter is the move number that we want to go back to */
"game/:id/undo_requested": (data: number) => void;
[]: ServerToClient["game/:id/undo_requested"];
/** A score estimation result has been broadcast, this is used for avoiding game stalling */
"game/:id/stalling_score_estimate": (data?: StallingScoreEstimate) => void;
[]: ServerToClient["game/:id/stalling_score_estimate"];
/** Replay of the entire full state of the review */
"review/:id/full_state": (data: ReviewMessage[]) => void;
[]: ServerToClient["review/:id/full_state"];
/** An incremental modification to the review stream */
"review/:id/r": (data: ReviewMessage) => void;
[]: ServerToClient["review/:id/r"];
}
export interface GameChatLine {
chat_id: string;
body: string | AnalysisComment | ReviewComment;
date: number;
move_number: number;
from?: number;
moves?: string;
channel: string;
player_id: number;
username?: string;
}
interface AnalysisComment {
type: "analysis";
name?: string;
branch_move?: number;
from?: number;
moves?: string;
marks?: {
[]: string;
};
pen_marks?: unknown[];
}
interface ReviewComment {
type: "review";
review_id: number;
}
type NoneClock = undefined;
type SimpleClock = number;
interface AbsoluteClock {
thinking_time: number;
}
interface FischerClock {
thinking_time: number;
skip_bonus: boolean;
}
interface ByoYomiClock {
thinking_time: number;
periods: number;
period_time: number;
period_time_left?: number;
}
interface CanadianClock {
thinking_time: number;
moves_left: number;
block_time: number;
}
type ClockTime = NoneClock | SimpleClock | AbsoluteClock | FischerClock | ByoYomiClock | CanadianClock;
export interface GameClock {
game_id: number;
title: string;
expiration: number;
stone_removal_mode?: boolean;
stone_removal_expiration?: number;
black_player_id: number;
white_player_id: number;
current_player: number;
expiration_delta?: number;
pause_delta?: number;
last_move: number;
now?: number;
paused_since?: number;
start_mode?: boolean;
black_time?: ClockTime;
white_time?: ClockTime;
pause?: {
paused?: boolean;
paused_since?: number;
pause_control?: {
[]: boolean;
};
};
}
export interface SeekgraphDeleteMessage {
/** The ID of the challenge */
challenge_id: number;
/** The entry should be deleted if this field exists and is true */
delete: true;
}
export interface SeekgraphStartedMessage {
/** The ID of the challenge */
challenge_id: number;
/** If exists and is true, the game has been started and the entry should be removed from the seek graph */
game_started?: true;
/** The game id */
game_id: number;
/** Player ID of the creator */
creator: number;
/** Black player */
black: User;
/** White player */
white: User;
/** Time control system */
time_control: string;
/** Time control parameters */
time_control_parameters: JGOFTimeControl;
/** Rengo game if true */
rengo?: true;
/** Player ids of the players on the Black team */
rengo_black_team?: number[];
/** Player ids of the players on the White team */
rengo_white_team?: number[];
/** Wether it's a Casual mode rengo game */
rengo_casual_mode?: boolean;
/** Whether the rengo game with automatically start */
rengo_auto_start?: boolean;
}
export interface SeekgraphChallengeMessage {
/** The ID of the challenge */
challenge_id: number;
/** User id of the player who is looking for a game */
user_id: number;
/** Username of the player looking for the game */
username: string;
/** Their ranking **/
ranking: number;
/** If they are a professional player */
professional: boolean;
/** Minimum rank allowed to accept the game */
min_rank: number;
/** Maximum rank allowed to accept the game */
max_rank: number;
/** The game ID */
game_id: number;
/** Game name */
name: string;
/** If the game is ranked */
ranked: boolean;
/** The game handicap */
handicap: number | null;
/** Komi */
komi: number | null;
/** Rules being used */
rules: string;
/** Board width */
width: number;
/** Board height */
height: number;
/** Color the accepting player will be */
challenger_color: "black" | "white" | "automatic";
/** If analysis is disabled */
disable_analysis: boolean;
/** Time control system type */
time_control: string;
/** Time control parameters */
time_control_parameters: JGOFTimeControl;
/** Average time per move */
time_per_move: number;
/** If it's a rengo game */
rengo: boolean;
/** Player ids of people that have been nominated to play */
rengo_nominees: number[];
/** Player ids of the players on the Black team */
rengo_black_team: number[];
/** Player ids of the players on the White team */
rengo_white_team: number[];
/** All player ids involved in the game */
rengo_participants: number[];
/** If the game is a casual rengo game */
rengo_casual_mode: boolean;
/** If the rengo game will automatically start */
rengo_auto_start: boolean;
/** If the game is only joinable by invitation */
invite_only: boolean;
/** A UUID for the invitation */
uuid: string;
}
export interface StallingScoreEstimate {
move_number: number;
predicted_winner: "black" | "white";
game_id: number;
removed: string;
score: number;
win_rate: number;
ownership: any[];
}
export interface GameChatMessage {
channel: "main" | "spectator" | "malkovich" | "shadowban" | "hidden" | "personal";
line: GameChatLine;
}
export {};