enapi

package
v0.18.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 16, 2026 License: Apache-2.0 Imports: 12 Imported by: 0

Documentation

Overview

Package enapi is a low-level HTTP client for the Encounter Go Backend API — the REST engine that replaces the ASP.NET one.

Unlike the legacy engine, every site lives behind a single API host and the site context travels in the X-En-Domain header, so one client can serve any domain. The package deliberately stops at transport and error decoding: the mapping of REST payloads onto the public encx types lives in encx itself.

The specification is a hypothesis, not an oracle

docs/newengine/swagger.json has been materially wrong about the deployed API more than once. GET /teams/{id}/members is documented as an array of models.User, keyed by id; it actually returns membership rows keyed by user_id with three flags models.User does not have. models.AdminUpdateGameRequest documents price_cents as "Fee.Cents" and says nothing about prize_cents, which turns out to take the same units models.Game.prize reports.

A model here is therefore worth only as much as its provenance. Models carrying a "measured against …" note were checked against a live response; the rest were transcribed from the specification and may be wrong in the same way. Before building behaviour on an unmeasured field, read one real response.

Index

Constants

View Source
const (
	AdminSettingsSectionBlocking = "blocking"
	AdminSettingsSectionSectors  = "sectors"
)

Sections accepted by AdminLevelSettingsRequest.Section: the endpoint edits one panel of the level settings at a time, mirroring the ASP editor.

View Source
const (
	EngineMessageSubscribe = "subscribe"
	EngineMessageAnswer    = "answer"
	EngineMessageBonus     = "bonus"
	EngineMessagePenalty   = "penalty"
)

Engine message types accepted by POST /games/{id}/engine and its ASP-compatible aliases. See docs/newengine/engine-websocket.md.

View Source
const (
	PenaltyActUnknown = 0
	PenaltyActApprove = 1
	PenaltyActConfirm = 2
)

Penalty hint actions carried by EngineClientMessage.PenaltyAct.

View Source
const DefaultBaseURL = "https://api.en.cx"

DefaultBaseURL is the production host of the new engine.

View Source
const DomainHeader = "X-En-Domain"

DomainHeader carries the site context (legacy multi-tenant domain).

View Source
const (
	// RejectAnswerBlocked means the level's answer-block rule refused the
	// submission: the attempt was not spent and no verdict was made.
	RejectAnswerBlocked = "answer_blocked"
)

Reject reasons the engine reports in EngineActionSnapshot.RejectReason.

Variables

This section is empty.

Functions

func IsForbidden

func IsForbidden(err error) bool

IsForbidden reports whether err is a 403 from the new engine.

func IsMissingHost

func IsMissingHost(err error) bool

IsMissingHost reports whether err is a MissingHostError.

func IsNotFound

func IsNotFound(err error) bool

IsNotFound reports whether err is a 404 from the new engine.

func IsStatus

func IsStatus(err error, status int) bool

IsStatus reports whether err is an APIError with the given HTTP status.

func IsUnauthorized

func IsUnauthorized(err error) bool

IsUnauthorized reports whether err is a 401 from the new engine.

Types

type APIError

type APIError struct {
	Method      string
	Path        string
	Status      int
	Code        int
	Err         string
	Message     string
	SentenceKey string
	FormatArgs  []string
	Body        string
}

APIError is a failing response from the new engine.

The backend answers with three shapes depending on the handler: a JSON error object, a localizable sentence key for UI strings, or bare text. All of them end up here so callers can branch on Status/Code instead of on the body.

func AsAPIError

func AsAPIError(err error) (*APIError, bool)

AsAPIError extracts an *APIError from an error chain.

func (*APIError) Error

func (e *APIError) Error() string

func (*APIError) Forbidden

func (e *APIError) Forbidden() bool

Forbidden reports whether the session lacks the required site permission.

func (*APIError) NotFound

func (e *APIError) NotFound() bool

NotFound reports whether the addressed object does not exist.

func (*APIError) Unauthorized

func (e *APIError) Unauthorized() bool

Unauthorized reports whether the call failed because the session is missing or expired.

type AdminAnswerBatchItem

type AdminAnswerBatchItem struct {
	AnswerText  string `json:"answer_text"`
	ForMemberID int    `json:"for_member_id"`
	ScoreAward  int    `json:"score_award,omitempty"`
	TimeAward   int    `json:"time_award,omitempty"`
}

AdminAnswerBatchItem is models.AdminAnswerBatchItem.

type AdminAnswerDTO

type AdminAnswerDTO struct {
	AnswerID   int    `json:"answer_id"`
	LevelID    int    `json:"level_id"`
	SectorID   int    `json:"sector_id"`
	AnswerText string `json:"answer_text"`
	ForUserID  int    `json:"for_user_id"`
	ForTeamID  int    `json:"for_team_id"`
	ScoreAward int    `json:"score_award"`
	TimeAward  int    `json:"time_award"`
}

AdminAnswerDTO is models.AdminAnswerDTO.

type AdminAnswerRequest

type AdminAnswerRequest struct {
	AnswerText  string `json:"answer_text"`
	SectorID    int    `json:"sector_id,omitempty"`
	ForMemberID int    `json:"for_member_id"`
	ScoreAward  int    `json:"score_award,omitempty"`
	TimeAward   int    `json:"time_award,omitempty"`
}

AdminAnswerRequest is models.AdminAnswerRequest.

type AdminAnswersBatchRequest

type AdminAnswersBatchRequest struct {
	SectorID int                    `json:"sector_id,omitempty"`
	Answers  []AdminAnswerBatchItem `json:"answers"`
}

AdminAnswersBatchRequest is models.AdminAnswersBatchRequest.

type AdminBonusDTO

type AdminBonusDTO struct {
	BonusID          int      `json:"bonus_id"`
	GameID           int      `json:"game_id"`
	BonusName        string   `json:"bonus_name"`
	Task             string   `json:"task"`
	BonusHelp        string   `json:"bonus_help"`
	Answers          []string `json:"answers"`
	BonusTime        int      `json:"bonus_time"`
	Negative         bool     `json:"negative"`
	AllLevels        bool     `json:"all_levels"`
	LevelIDs         []int    `json:"level_ids"`
	HasAbsoluteLimit bool     `json:"has_absolute_limit"`
	ValidFrom        string   `json:"valid_from"`
	ValidTo          string   `json:"valid_to"`
	HasDelay         bool     `json:"has_delay"`
	DelaySec         int      `json:"delay_sec"`
	HasRelativeLimit bool     `json:"has_relative_limit"`
	LifeTimeSec      int      `json:"life_time_sec"`
	UserID           int      `json:"user_id"`
	Login            string   `json:"login"`
	TeamID           int      `json:"team_id"`
	TeamName         string   `json:"team_name"`
}

AdminBonusDTO is models.AdminBonusDTO.

type AdminBonusRequest

type AdminBonusRequest struct {
	BonusName        string   `json:"bonus_name"`
	Task             string   `json:"task"`
	BonusHelp        string   `json:"bonus_help"`
	Answers          []string `json:"answers"`
	BonusTime        int      `json:"bonus_time"`
	Negative         bool     `json:"negative"`
	ForMemberID      int      `json:"for_member_id"`
	AllLevels        bool     `json:"all_levels"`
	LevelIDs         []int    `json:"level_ids,omitempty"`
	HasAbsoluteLimit bool     `json:"has_absolute_limit"`
	ValidFrom        string   `json:"valid_from,omitempty"`
	ValidTo          string   `json:"valid_to,omitempty"`
	HasDelay         bool     `json:"has_delay"`
	DelaySec         int      `json:"delay_sec,omitempty"`
	HasRelativeLimit bool     `json:"has_relative_limit"`
	LifeTimeSec      int      `json:"life_time_sec,omitempty"`
}

AdminBonusRequest is models.AdminBonusRequest.

The has_* switches carry no omitempty: they are the form's checkboxes, and an omitted false would leave a limit the caller cleared still in place.

type AdminBulkLevelsRequest

type AdminBulkLevelsRequest struct {
	LevelIDs []int `json:"level_ids"`
}

AdminBulkLevelsRequest is models.AdminBulkLevelsRequest.

type AdminCopyLevelsRequest

type AdminCopyLevelsRequest struct {
	FromLevelID int `json:"from_level_id"`
	Count       int `json:"count"`
}

AdminCopyLevelsRequest is models.AdminCopyLevelsRequest.

type AdminCreateGameAuthor added in v0.14.0

type AdminCreateGameAuthor struct {
	Login  string `json:"login,omitempty"`
	UserID int    `json:"user_id,omitempty"`
}

AdminCreateGameAuthor is models.AdminCreateGameAuthor — an author is named either by login or by id.

type AdminCreateGameRequest added in v0.14.0

type AdminCreateGameRequest struct {
	Title          string `json:"title"`
	Descr          string `json:"descr,omitempty"`
	GameTypeID     int    `json:"game_type_id"`
	StartDateTime  string `json:"start_date_time"`
	FinishDateTime string `json:"finish_date_time"`

	RequestLastDate        string                  `json:"request_last_date,omitempty"`
	AcceptRateFromDateTime string                  `json:"accept_rate_from_date_time,omitempty"`
	ZoneID                 int                     `json:"zone_id,omitempty"`
	Authors                []AdminCreateGameAuthor `json:"authors,omitempty"`
	IsModerated            bool                    `json:"is_moderated,omitempty"`
	MaxPlayers             int                     `json:"max_players,omitempty"`
	MaxTeamMembers         int                     `json:"max_team_members,omitempty"`
	PrizeCents             int                     `json:"prize_cents,omitempty"`
	CertificateAccessMode  int                     `json:"certificate_access_mode,omitempty"`
	CertificatePlaces      int                     `json:"certificate_places,omitempty"`
	StatAvailabilityTypeID int                     `json:"stat_availability_type_id,omitempty"`
	ScenarioAvailability   int                     `json:"scenario_availability,omitempty"`
	ShowFee                int                     `json:"show_fee,omitempty"`
	// CompetitionID is the calendar category; -1 is "Typical".
	CompetitionID int `json:"competition_id,omitempty"`
	// AFC is the author complexity in the route's own 0..1 spelling.
	AFC float64 `json:"afc,omitempty"`
}

AdminCreateGameRequest is models.AdminCreateGameRequest, the body of POST /admin/games.

type AdminCreateLevelRequest

type AdminCreateLevelRequest struct {
	LevelName   string `json:"level_name,omitempty"`
	Comment     string `json:"comment,omitempty"`
	AfterLevel  int    `json:"after_level,omitempty"`
	BeforeLevel int    `json:"before_level,omitempty"`
}

AdminCreateLevelRequest is models.AdminCreateLevelRequest.

type AdminExchangeLevelsRequest

type AdminExchangeLevelsRequest struct {
	Level1ID int `json:"level1_id"`
	Level2ID int `json:"level2_id"`
}

AdminExchangeLevelsRequest is models.AdminExchangeLevelsRequest.

type AdminGameEditorResponse

type AdminGameEditorResponse struct {
	Game     *Game        `json:"game"`
	Authors  []GameAuthor `json:"authors"`
	Referees []GameAuthor `json:"referees"`
}

AdminGameEditorResponse is models.AdminGameEditorResponse.

type AdminGameLevelsResponse

type AdminGameLevelsResponse struct {
	GameID                  int              `json:"game_id"`
	GameNum                 int              `json:"game_num"`
	GameTypeID              int              `json:"game_type_id"`
	ZoneID                  int              `json:"zone_id"`
	StatusID                int              `json:"status_id"`
	Title                   string           `json:"title"`
	Started                 bool             `json:"started"`
	LevelsSequenceID        int              `json:"levels_sequence_id"`
	CanManipulateLevels     bool             `json:"can_manipulate_levels"`
	CanChangeLevelsSequence bool             `json:"can_change_levels_sequence"`
	ShowPassingSequence     bool             `json:"show_passing_sequence"`
	Levels                  []AdminLevelItem `json:"levels"`
}

AdminGameLevelsResponse is models.AdminGameLevelsResponse — the level manager.

Measured against demo.en.cx: can_manipulate_levels is true even for a started game — can_change_levels_sequence is the one that goes false there.

type AdminGameLifecycle

type AdminGameLifecycle struct {
	GameID                int    `json:"game_id"`
	GameNum               int    `json:"game_num"`
	Title                 string `json:"title"`
	StatusID              int    `json:"status_id"`
	Started               bool   `json:"started"`
	Finished              bool   `json:"finished"`
	RateClosed            bool   `json:"rate_closed"`
	PointsCalculated      bool   `json:"points_calculated"`
	QualityRateCalculated bool   `json:"quality_rate_calculated"`
	CanDeliver            bool   `json:"can_deliver"`
	CanCancel             bool   `json:"can_cancel"`
	CanCalculatePoints    bool   `json:"can_calculate_points"`
	CanCancelPoints       bool   `json:"can_cancel_points"`
	CanCloseRate          bool   `json:"can_close_rate"`
	CanOpenRate           bool   `json:"can_open_rate"`
	CanCalculateQI        bool   `json:"can_calculate_qi"`
	CanCancelQI           bool   `json:"can_cancel_qi"`
	CanCorrectResults     bool   `json:"can_correct_results"`
}

AdminGameLifecycle is models.AdminGameLifecycleResponse — which management actions the current session may perform on a game.

type AdminGameListItem

type AdminGameListItem struct {
	GameID         int    `json:"game_id"`
	GameNum        int    `json:"game_num"`
	Title          string `json:"title"`
	ZoneID         int    `json:"zone_id"`
	GameTypeID     int    `json:"game_type_id"`
	StatusID       int    `json:"status_id"`
	StartDateTime  string `json:"start_date_time"`
	FinishDateTime string `json:"finish_date_time"`
	FeeType        string `json:"fee_type"`
	OwnerID        int    `json:"owner_id"`
	OwnerLogin     string `json:"owner_login"`
	RefereeEnd     bool   `json:"referee_end"`
}

AdminGameListItem is one row of the admin game manager.

type AdminGameStatusRequest

type AdminGameStatusRequest struct {
	StatusID           int  `json:"status_id"`
	Force              bool `json:"force,omitempty"`
	ReturnFeeToPlayers bool `json:"return_fee_to_players,omitempty"`
}

AdminGameStatusRequest is models.AdminGameStatusRequest.

type AdminGamesListResponse

type AdminGamesListResponse struct {
	Items      []AdminGameListItem `json:"items"`
	TotalCount int                 `json:"total_count"`
	TotalPages int                 `json:"total_pages"`
	Page       int                 `json:"page"`
	OnlyOwn    bool                `json:"only_own"`
}

AdminGamesListResponse is the answer of GET /admin/games.

It is not models.GamesResponse: the admin listing has its own row shape, keyed by game_id rather than id, as a live call to api.en.cx confirms.

type AdminHelpDTO

type AdminHelpDTO struct {
	HelpID                int    `json:"help_id"`
	LevelID               int    `json:"level_id"`
	HelpNumber            int    `json:"help_number"`
	HelpText              string `json:"help_text"`
	Timeout               int    `json:"timeout"`
	IsPenalty             bool   `json:"is_penalty"`
	PenaltyTime           int    `json:"penalty_time"`
	PenaltyScore          int    `json:"penalty_score"`
	PenaltyComment        string `json:"penalty_comment"`
	RequestPenaltyConfirm bool   `json:"request_penalty_confirm"`
	ForUserID             int    `json:"for_user_id"`
	ForUserLogin          string `json:"for_user_login"`
	ForTeamID             int    `json:"for_team_id"`
	ForTeamName           string `json:"for_team_name"`
}

AdminHelpDTO is models.AdminHelpDTO.

type AdminHelpRequest

type AdminHelpRequest struct {
	HelpText              string `json:"help_text"`
	Timeout               int    `json:"timeout"`
	ForMemberID           int    `json:"for_member_id"`
	IsPenalty             bool   `json:"is_penalty"`
	PenaltyTime           int    `json:"penalty_time"`
	PenaltyScore          int    `json:"penalty_score"`
	PenaltyComment        string `json:"penalty_comment"`
	RequestPenaltyConfirm bool   `json:"request_penalty_confirm"`
}

AdminHelpRequest is models.AdminHelpRequest. Timeout and PenaltyTime are seconds. penalty_comment and request_penalty_confirm carry no omitempty so a caller can clear them.

type AdminLevelAutoPassRequest

type AdminLevelAutoPassRequest struct {
	TimeoutHours   int  `json:"timeout_hours"`
	TimeoutMinutes int  `json:"timeout_minutes"`
	TimeoutSeconds int  `json:"timeout_seconds"`
	PenaltyEnabled bool `json:"penalty_enabled"`
	PenaltyHours   int  `json:"penalty_hours"`
	PenaltyMinutes int  `json:"penalty_minutes"`
	PenaltySeconds int  `json:"penalty_seconds"`
	AwardIsPenalty bool `json:"award_is_penalty"`
	PointsAward    int  `json:"points_award,omitempty"`
}

AdminLevelAutoPassRequest is models.AdminLevelAutoPassRequest.

type AdminLevelEditorResponse

type AdminLevelEditorResponse struct {
	GameID               int                 `json:"game_id"`
	GameNum              int                 `json:"game_num"`
	GameTypeID           int                 `json:"game_type_id"`
	ZoneID               int                 `json:"zone_id"`
	Title                string              `json:"title"`
	Version              string              `json:"version"`
	Level                *AdminLevelItem     `json:"level"`
	Levels               []AdminLevelItem    `json:"levels"`
	Tasks                []AdminTaskDTO      `json:"tasks"`
	Helps                []AdminHelpDTO      `json:"helps"`
	PenaltyHelps         []AdminHelpDTO      `json:"penalty_helps"`
	Bonuses              []AdminBonusDTO     `json:"bonuses"`
	Sectors              []AdminSectorDTO    `json:"sectors"`
	Answers              []AdminAnswerDTO    `json:"answers"`
	Messages             []AdminMessageDTO   `json:"messages"`
	Members              []AdminMemberOption `json:"members"`
	TimeoutSec           int                 `json:"timeout_sec"`
	TimeoutTimeAwardSec  int                 `json:"timeout_time_award_sec"`
	TimeoutPointsAward   int                 `json:"timeout_points_award"`
	AttemptsNumber       int                 `json:"attempts_number"`
	AttemptsPeriodSec    int                 `json:"attempts_period_sec"`
	BlockTypeID          int                 `json:"block_type_id"`
	PassingConditionID   int                 `json:"passing_condition_id"`
	RequiredSectorsCount int                 `json:"required_sectors_count"`
	SupportsAutoPass     bool                `json:"supports_auto_pass"`
	SupportsBonuses      bool                `json:"supports_bonuses"`
	SupportsSectors      bool                `json:"supports_answers"`
	SupportsHelps        bool                `json:"supports_helps"`
	SupportsPenaltyHelps bool                `json:"supports_penalty_helps"`
	SupportsMessages     bool                `json:"supports_messages"`
	SupportsTasks        bool                `json:"supports_tasks"`
}

AdminLevelEditorResponse is models.AdminLevelEditorResponse: the whole level in one document, where the legacy engine needed a page per collection.

Measured against demo.en.cx: timeout_time_award_sec is signed — negative for a penalty, positive for a bonus — and required_sectors_count keeps its previous value unless passing_condition_id is 1.

type AdminLevelItem

type AdminLevelItem struct {
	LevelID     int    `json:"level_id"`
	LevelNumber int    `json:"level_number"`
	LevelName   string `json:"level_name"`
	Comment     string `json:"comment"`
	Dismissed   bool   `json:"dismissed"`
	OwnerID     int    `json:"owner_id"`
}

AdminLevelItem is models.AdminLevelItem.

type AdminLevelMetaRequest

type AdminLevelMetaRequest struct {
	LevelName    string `json:"level_name"`
	Comment      string `json:"comment"`
	AnswerTypeID int    `json:"answer_type_id,omitempty"`
}

AdminLevelMetaRequest is models.AdminLevelMetaRequest.

type AdminLevelSettingsRequest

type AdminLevelSettingsRequest struct {
	Section               string `json:"section"`
	AttemptsNumber        int    `json:"attempts_number"`
	AttemptsCount         int    `json:"attempts_count"`
	AttemptsPeriodHours   int    `json:"attempts_period_hours"`
	AttemptsPeriodMinutes int    `json:"attempts_period_minutes"`
	AttemptsPeriodSeconds int    `json:"attempts_period_seconds"`
	BlockTypeID           int    `json:"block_type_id"`
	PassingConditionID    int    `json:"passing_condition_id"`
	RequiredSectorsCount  int    `json:"required_sectors_count"`
	Unrestricted          bool   `json:"unrestricted,omitempty"`
	RestrictionEnabled    bool   `json:"restriction_enabled,omitempty"`
}

AdminLevelSettingsRequest is models.AdminLevelSettingsRequest.

The numeric fields carry no omitempty on purpose: zero is a meaningful value here — passing_condition_id 0 means "close every sector" and required_sectors_count 0 means "all of them" — so omitting them would leave the server unable to tell "all sectors" from "field not sent".

type AdminMemberOption

type AdminMemberOption struct {
	ID    int    `json:"id"`
	Label string `json:"label"`
}

AdminMemberOption is models.AdminMemberOption — the ForMember dropdown.

type AdminMessageDTO

type AdminMessageDTO struct {
	MessageID      int    `json:"message_id"`
	MessageText    string `json:"message_text"`
	ReplaceNlToBr  bool   `json:"replace_nl_to_br"`
	AllLevels      bool   `json:"all_levels"`
	LevelIDs       []int  `json:"level_ids"`
	RequiredPoints int    `json:"required_points"`
}

AdminMessageDTO is models.AdminMessageDTO.

type AdminMessageRequest

type AdminMessageRequest struct {
	MessageText    string `json:"message_text"`
	ReplaceNlToBr  bool   `json:"replace_nl_to_br"`
	AllLevels      bool   `json:"all_levels"`
	LevelIDs       []int  `json:"level_ids,omitempty"`
	RequiredPoints int    `json:"required_points,omitempty"`
}

AdminMessageRequest is models.AdminMessageRequest.

type AdminPutLevelRequest

type AdminPutLevelRequest struct {
	LevelID      int `json:"level_id"`
	AfterLevelID int `json:"after_level_id"`
}

AdminPutLevelRequest is models.AdminPutLevelRequest.

type AdminSectorDTO

type AdminSectorDTO struct {
	SectorID                int    `json:"sector_id"`
	LevelID                 int    `json:"level_id"`
	SectorName              string `json:"sector_name"`
	TaskID                  int    `json:"task_id"`
	AnswerTypeID            int    `json:"answer_type_id"`
	ValidAnswerScoreAward   int    `json:"valid_answer_score_award"`
	WrongAnswerScorePenalty int    `json:"wrong_answer_score_penalty"`
}

AdminSectorDTO is models.AdminSectorDTO.

type AdminSectorRequest

type AdminSectorRequest struct {
	SectorName              string `json:"sector_name"`
	TaskID                  int    `json:"task_id,omitempty"`
	ValidAnswerScoreAward   int    `json:"valid_answer_score_award,omitempty"`
	WrongAnswerScorePenalty int    `json:"wrong_answer_score_penalty,omitempty"`
}

AdminSectorRequest is models.AdminSectorRequest.

type AdminTaskDTO

type AdminTaskDTO struct {
	TaskID        int     `json:"task_id"`
	LevelID       int     `json:"level_id"`
	TaskText      string  `json:"task_text"`
	ReplaceNlToBr bool    `json:"replace_nl_to_br"`
	ForUserID     int     `json:"for_user_id"`
	ForUserLogin  string  `json:"for_user_login"`
	ForTeamID     int     `json:"for_team_id"`
	ForTeamName   string  `json:"for_team_name"`
	Latitude      float64 `json:"latitude"`
	Longitude     float64 `json:"longitude"`
}

AdminTaskDTO is models.AdminTaskDTO.

type AdminTaskRequest

type AdminTaskRequest struct {
	TaskText      string  `json:"task_text"`
	ReplaceNlToBr bool    `json:"replace_nl_to_br"`
	ForMemberID   int     `json:"for_member_id"`
	Latitude      float64 `json:"latitude,omitempty"`
	Longitude     float64 `json:"longitude,omitempty"`
}

AdminTaskRequest is models.AdminTaskRequest.

type BonusScenario

type BonusScenario struct {
	BonusID       int      `json:"bonus_id"`
	BonusName     string   `json:"bonus_name"`
	Task          string   `json:"task"`
	BonusHelp     string   `json:"bonus_help"`
	Answers       []string `json:"answers"`
	BonusTime     int      `json:"bonus_time"`
	BonusTimeText string   `json:"bonus_time_text"`
	HasBonusTime  bool     `json:"has_bonus_time"`
	Delay         int      `json:"delay"`
	HasDelay      bool     `json:"has_delay"`
	LifeTime      int      `json:"life_time"`
	ValidFrom     string   `json:"valid_from"`
	ValidTo       string   `json:"valid_to"`
	Title         string   `json:"title"`
}

BonusScenario is models.BonusScenario.

type City

type City struct {
	ID   int    `json:"id"`
	Name string `json:"name"`
}

City is models.City.

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client performs authenticated JSON calls against the new engine.

The zero value is not usable — construct it with New.

func New

func New(httpClient *http.Client, baseURL, domain string, opts ...Option) *Client

New creates a client for the given API host and site domain.

httpClient is supplied by the caller so that the cookie jar, HAR recording and debug logging configured on encx.Client apply to the new engine too.

An empty baseURL is kept as-is rather than defaulted: the caller could not name a host, and quietly substituting one would send this domain's requests — including its sign-in — to a backend that never claimed to serve it. Requests then fail with an actionable error instead.

func (*Client) BaseURL

func (c *Client) BaseURL() string

BaseURL returns the API host without a trailing slash.

func (*Client) Delete

func (c *Client) Delete(ctx context.Context, path string, query url.Values, out any) error

Delete performs a DELETE request, decoding the response into out when given.

func (*Client) Do

func (c *Client) Do(ctx context.Context, req Request) error

Do performs the request, decoding a JSON body into req.Out on success.

func (*Client) Domain

func (c *Client) Domain() string

Domain returns the site domain sent in X-En-Domain.

func (*Client) GetBytes

func (c *Client) GetBytes(ctx context.Context, path string, query url.Values) ([]byte, http.Header, error)

GetBytes performs a GET request and returns the raw response body. It is used for endpoints that answer with media or HTML rather than JSON.

func (*Client) GetJSON

func (c *Client) GetJSON(ctx context.Context, path string, query url.Values, out any) error

GetJSON performs a GET request and decodes the response into out.

func (*Client) Lang

func (c *Client) Lang() string

Lang returns the configured language code.

func (*Client) PatchJSON

func (c *Client) PatchJSON(ctx context.Context, path string, body, out any) error

PatchJSON performs a PATCH request with a JSON body.

func (*Client) PostJSON

func (c *Client) PostJSON(ctx context.Context, path string, body, out any) error

PostJSON performs a POST request with a JSON body.

func (*Client) PutJSON

func (c *Client) PutJSON(ctx context.Context, path string, body, out any) error

PutJSON performs a PUT request with a JSON body.

func (*Client) SetToken

func (c *Client) SetToken(token string)

SetToken stores the bearer token used by subsequent requests.

func (*Client) Token

func (c *Client) Token() string

Token returns the current bearer token, empty when not signed in.

func (*Client) URL

func (c *Client) URL(path string, query url.Values) string

URL builds an absolute request URL for an API path and optional query.

type CorrectionLevelOption

type CorrectionLevelOption struct {
	LevelID  int    `json:"level_id"`
	LevelNum int    `json:"level_num"`
	Name     string `json:"name"`
}

CorrectionLevelOption is models.CorrectionLevelOption.

type CorrectionPlayerOption

type CorrectionPlayerOption struct {
	ID           int    `json:"id"`
	GamePlayerID int    `json:"game_player_id"`
	Label        string `json:"label"`
}

CorrectionPlayerOption is models.CorrectionPlayerOption.

type Country

type Country struct {
	ID   int    `json:"id"`
	Name string `json:"name"`
}

Country is models.Country.

type EngineActionSnapshot

type EngineActionSnapshot struct {
	GameID             int    `json:"game_id"`
	LevelID            int    `json:"level_id"`
	LevelNumber        int    `json:"level_number"`
	LevelAnswer        string `json:"level_answer"`
	LevelOK            *bool  `json:"level_ok"`
	BonusAnswer        string `json:"bonus_answer"`
	BonusOK            *bool  `json:"bonus_ok"`
	RejectReason       string `json:"reject_reason"`
	RequestLevelID     int    `json:"request_level_id"`
	RequestLevelNumber int    `json:"request_level_number"`
}

EngineActionSnapshot reports the outcome of the last submitted action.

LevelOK and BonusOK are pointers because the engine omits them when it never judged the answer — a submission refused by the answer-block rule comes back with reject_reason set and no verdict at all. Decoding that absence into a plain false would report the player's answer as wrong.

type EngineBonus

type EngineBonus struct {
	BonusID        int                   `json:"bonus_id"`
	Number         int                   `json:"number"`
	Name           string                `json:"name"`
	Task           string                `json:"task"`
	Help           string                `json:"help"`
	IsAnswered     bool                  `json:"is_answered"`
	AnswerText     string                `json:"answer_text"`
	AnswerLogin    string                `json:"answer_login"`
	AnswerUserID   int                   `json:"answer_user_id"`
	AnswerUnix     int64                 `json:"answer_unix"`
	Answers        []EnginePreviewAnswer `json:"answers"`
	Expired        bool                  `json:"expired"`
	SecondsToStart int                   `json:"seconds_to_start"`
	SecondsLeft    int                   `json:"seconds_left"`
	AwardTime      int                   `json:"award_time"`
	Negative       bool                  `json:"negative"`
	Delay          int                   `json:"delay"`
	LifeTime       int                   `json:"life_time"`
	AvailableFrom  string                `json:"available_from"`
	AvailableTo    string                `json:"available_to"`
	StartsAtUnix   int64                 `json:"starts_at_unix"`
	ExpiresAtUnix  int64                 `json:"expires_at_unix"`
	ForPlayerID    int                   `json:"for_player_id"`
	ForPlayerLoc   string                `json:"for_player_loc"`
}

EngineBonus is a bonus task of the current level.

type EngineClientMessage

type EngineClientMessage struct {
	Type        string `json:"type,omitempty"`
	Answer      string `json:"answer,omitempty"`
	LevelID     int    `json:"level_id,omitempty"`
	LevelNumber int    `json:"level_number,omitempty"`
	PenaltyID   int    `json:"penalty_id,omitempty"`
	PenaltyAct  int    `json:"penalty_act,omitempty"`
	ReqID       string `json:"req_id,omitempty"`
	Compact     bool   `json:"compact,omitempty"`
}

EngineClientMessage is a player action sent to the engine.

type EngineCurrentLevel

type EngineCurrentLevel struct {
	LevelID              int                   `json:"level_id"`
	Number               int                   `json:"number"`
	Name                 string                `json:"name"`
	Timeout              int                   `json:"timeout"`
	TimeoutAward         int                   `json:"timeout_award"`
	TimeoutSecondsRemain int                   `json:"timeout_seconds_remain"`
	TimeoutExpiresUnix   int64                 `json:"timeout_expires_unix"`
	IsPassed             bool                  `json:"is_passed"`
	Dismissed            bool                  `json:"dismissed"`
	LevelStartUnix       int64                 `json:"level_start_unix"`
	LevelPassedUnix      int64                 `json:"level_passed_unix"`
	StartsAtUnix         int64                 `json:"starts_at_unix"`
	SecondsToStart       int                   `json:"seconds_to_start"`
	HasAnswerBlockRule   bool                  `json:"has_answer_block_rule"`
	BlockDuration        int                   `json:"block_duration"`
	BlockTargetID        int                   `json:"block_target_id"`
	AttemptsNumber       int                   `json:"attempts_number"`
	AttemptsPeriod       int                   `json:"attempts_period"`
	RequiredSectorsCount int                   `json:"required_sectors_count"`
	PassedSectorsCount   int                   `json:"passed_sectors_count"`
	PassedBonusesCount   int                   `json:"passed_bonuses_count"`
	SectorsLeftToClose   int                   `json:"sectors_left_to_close"`
	Tasks                []EngineTask          `json:"tasks"`
	Messages             []EngineLevelMessage  `json:"messages"`
	Sectors              []EngineSector        `json:"sectors"`
	Helps                []EngineHelp          `json:"helps"`
	PenaltyHelps         []EngineHelp          `json:"penalty_helps"`
	Bonuses              []EngineBonus         `json:"bonuses"`
	MixedActions         []EngineMixedAction   `json:"mixed_actions"`
	Answers              []EnginePreviewAnswer `json:"answers"`
}

EngineCurrentLevel is the level the player is standing on.

type EngineHelp

type EngineHelp struct {
	HelpID         int    `json:"help_id"`
	HelpNumber     int    `json:"help_number"`
	HelpText       string `json:"help_text"`
	IsPenalty      bool   `json:"is_penalty"`
	PenaltyTime    int    `json:"penalty_time"`
	PenaltyComment string `json:"penalty_comment"`
	RequestConfirm bool   `json:"request_confirm"`
	RemainSeconds  int    `json:"remain_seconds"`
	State          int    `json:"state"`
	Award          int    `json:"award"`
	Delay          int    `json:"delay"`
	OpensAtUnix    int64  `json:"opens_at_unix"`
	ForPlayerID    int    `json:"for_player_id"`
	ForPlayerLoc   string `json:"for_player_loc"`
}

EngineHelp is a hint, regular or penalty.

type EngineLevelBand

type EngineLevelBand struct {
	LevelID     int    `json:"level_id"`
	LevelNumber int    `json:"level_number"`
	LevelName   string `json:"level_name"`
	Dismissed   bool   `json:"dismissed"`
	IsPassed    bool   `json:"is_passed"`
}

EngineLevelBand is a level entry in the level strip.

type EngineLevelMessage

type EngineLevelMessage struct {
	MessageID   int    `json:"message_id"`
	OwnerID     int    `json:"owner_id"`
	OwnerLogin  string `json:"owner_login"`
	WrappedText string `json:"wrapped_text"`
}

EngineLevelMessage is a message from the organizers.

type EngineMixedAction

type EngineMixedAction struct {
	LevelID     int    `json:"level_id"`
	LevelNumber int    `json:"level_number"`
	UserID      int    `json:"user_id"`
	Login       string `json:"login"`
	Answer      string `json:"answer"`
	Kind        int    `json:"kind"`
	IsCorrect   bool   `json:"is_correct"`
	Negative    bool   `json:"negative"`
	EnterUnix   int64  `json:"enter_unix"`
}

EngineMixedAction is an entry of the level answer log.

type EnginePreviewAnswer

type EnginePreviewAnswer struct {
	Text         string `json:"text"`
	ForPlayerID  int    `json:"for_player_id"`
	ForPlayerLoc string `json:"for_player_loc"`
}

EnginePreviewAnswer is an author-visible answer shown in preview mode.

type EngineSector

type EngineSector struct {
	SectorID     int                   `json:"sector_id"`
	Order        int                   `json:"order"`
	Name         string                `json:"name"`
	IsPassed     bool                  `json:"is_passed"`
	AnswerText   string                `json:"answer_text"`
	AnswerLogin  string                `json:"answer_login"`
	AnswerUserID int                   `json:"answer_user_id"`
	AnswerUnix   int64                 `json:"answer_unix"`
	Answers      []EnginePreviewAnswer `json:"answers"`
}

EngineSector is a sector of the current level.

type EngineState

type EngineState struct {
	Event             int                   `json:"event"`
	GameID            int                   `json:"game_id"`
	GameNumber        int                   `json:"game_number"`
	GameTitle         string                `json:"game_title"`
	GameTypeID        int                   `json:"game_type_id"`
	GameZoneID        int                   `json:"game_zone_id"`
	GameDateTimeStart string                `json:"game_date_time_start"`
	LevelSequence     int                   `json:"level_sequence"`
	CountLevels       int                   `json:"count_levels"`
	UserID            int                   `json:"user_id"`
	TeamID            int                   `json:"team_id"`
	Login             string                `json:"login"`
	TeamName          string                `json:"team_name"`
	IsCaptain         bool                  `json:"is_captain"`
	IsChatVisible     bool                  `json:"is_chat_visible"`
	IsGuestMode       bool                  `json:"is_guest_mode"`
	AllowedToAnswer   bool                  `json:"allowed_to_answer"`
	UserAnswerHit     bool                  `json:"user_answer_hit"`
	ServerUnix        int64                 `json:"server_unix"`
	Level             *EngineCurrentLevel   `json:"level"`
	Levels            []EngineLevelBand     `json:"levels"`
	EngineAction      *EngineActionSnapshot `json:"engine_action"`
}

EngineState is the full engine state (models.EngineState).

type EngineTask

type EngineTask struct {
	TaskID            int    `json:"task_id"`
	TaskTextFormatted string `json:"task_text_formatted"`
	ForPlayerID       int    `json:"for_player_id"`
	ForPlayerLoc      string `json:"for_player_loc"`
}

EngineTask is the level assignment text.

type Game

type Game struct {
	ID                       int             `json:"id"`
	GameNum                  int             `json:"game_num"`
	SiteID                   int             `json:"site_id"`
	LangID                   int             `json:"lang_id"`
	OwnerID                  int             `json:"owner_id"`
	CompetitionID            int             `json:"competition_id"`
	LevelNumber              int             `json:"level_number"`
	Title                    string          `json:"title"`
	Descr                    string          `json:"descr"`
	GameTypeID               int             `json:"game_type_id"`
	ZoneID                   int             `json:"zone_id"`
	StatusID                 int             `json:"status_id"`
	LevelsSequenceID         int             `json:"levels_sequence_id"`
	ScenarioAvailability     int             `json:"scenario_availability"`
	MaxPlayers               int             `json:"max_players"`
	MaxTeamMembers           int             `json:"max_team_members"`
	TopicID                  int             `json:"topic_id"`
	CreateDateTime           string          `json:"create_date_time"`
	StartDateTime            string          `json:"start_date_time"`
	FinishDateTime           string          `json:"finish_date_time"`
	RequestLastDate          string          `json:"request_last_date"`
	AcceptRateFromDateTime   string          `json:"accept_rate_from_date_time"`
	Fee                      int             `json:"fee"`
	Prize                    int             `json:"prize"`
	Price                    int             `json:"price"`
	FeeName                  string          `json:"fee_name"`
	FeeTypeID                int             `json:"fee_type_id"`
	FeeCurrencyID            int             `json:"fee_currency_id"`
	PrizeType                int             `json:"prize_type"`
	ShowFee                  int             `json:"show_fee"`
	Started                  bool            `json:"started"`
	Finished                 bool            `json:"finished"`
	IsModerated              bool            `json:"is_moderated"`
	IsAvailableAfterFinished bool            `json:"is_available_after_finished"`
	StatAvailabilityTypeID   int             `json:"stat_availability_type_id"`
	QualityRate              json.Number     `json:"quality_rate"`
	QualityRateCalculated    bool            `json:"quality_rate_calculated"`
	AuthorIndexCalculated    bool            `json:"author_index_calculated"`
	AFC                      float64         `json:"afc"`
	ShowInCalendar           bool            `json:"show_in_calendar"`
	ShowFinishPlace          bool            `json:"show_finish_place"`
	HideLevelsNames          bool            `json:"hide_levels_names"`
	HidePlayersList          bool            `json:"hide_players_list"`
	HideGameDescr            bool            `json:"hide_game_descr"`
	ReplaceNlToBr            bool            `json:"replace_nl_to_br"`
	PublicAccess             bool            `json:"public_access"`
	RateClosed               bool            `json:"rate_closed"`
	AllowMakeStakes          bool            `json:"allow_make_stakes"`
	DisplayMonitoring        int             `json:"display_monitoring"`
	DisplayAnnouncement      int             `json:"display_announcement"`
	CertificatePlaces        int             `json:"certificate_places"`
	CertificateAccessMode    int             `json:"certificate_access_mode"`
	ForUserID                int             `json:"for_user_id"`
	PrimaryDomain            string          `json:"primary_domain"`
	Authors                  []GameAuthor    `json:"authors"`
	Team                     *Team           `json:"team"`
	Zone                     *Zone           `json:"zone"`
	Raw                      json.RawMessage `json:"-"`
}

Game is models.Game — the catalog entry the new engine returns for every game listing. Fields the client does not map are omitted deliberately.

type GameAuthor

type GameAuthor struct {
	UserID      int     `json:"user_id"`
	Login       string  `json:"login"`
	Name        string  `json:"name"`
	AvatarURL   string  `json:"avatar_url"`
	GenderID    int     `json:"gender_id"`
	CommonIndex float64 `json:"common_index"`
}

GameAuthor is models.GameAuthor.

type GameCorrection

type GameCorrection struct {
	CorrectID       int    `json:"correct_id"`
	GameID          int    `json:"game_id"`
	CorrectDateTime string `json:"correct_date_time"`
	CorrectText     string `json:"correct_text"`
	Comment         string `json:"comment"`
	CorrectionType  int    `json:"correction_type"`
	CorrectionValue int    `json:"correction_value"`
	ValueText       string `json:"value_text"`
	LevelID         int    `json:"level_id"`
	LevelNum        int    `json:"level_num"`
	UserID          int    `json:"user_id"`
	Login           string `json:"login"`
	TeamID          int    `json:"team_id"`
	TeamName        string `json:"team_name"`
	GamePlayerID    int    `json:"game_player_id"`
	ByAdminID       int    `json:"by_admin_id"`
	ByAdminLogin    string `json:"by_admin_login"`
	CanEdit         bool   `json:"can_edit"`
}

GameCorrection is models.GameCorrection.

type GameCorrectionWriteRequest

type GameCorrectionWriteRequest struct {
	PlayerID     int    `json:"player_id"`
	GamePlayerID int    `json:"game_player_id,omitempty"`
	LevelID      int    `json:"level_id"`
	IsBonus      bool   `json:"is_bonus"`
	Seconds      int    `json:"seconds"`
	Score        int    `json:"score,omitempty"`
	Comment      string `json:"comment"`
}

GameCorrectionWriteRequest is models.GameCorrectionWriteRequest.

type GameCorrectionsResponse

type GameCorrectionsResponse struct {
	GameID    int                      `json:"game_id"`
	GameNum   int                      `json:"game_num"`
	GameTitle string                   `json:"game_title"`
	CanAdd    bool                     `json:"can_add"`
	IsAdmin   bool                     `json:"is_admin"`
	Items     []GameCorrection         `json:"items"`
	Levels    []CorrectionLevelOption  `json:"levels"`
	Players   []CorrectionPlayerOption `json:"players"`
}

GameCorrectionsResponse is models.GameCorrectionsResponse.

type GameDetails

type GameDetails struct {
	Game          *Game            `json:"game"`
	Authors       []GameAuthor     `json:"authors"`
	CanManageGame bool             `json:"can_manage_game"`
	FeeName       string           `json:"fee_name"`
	StatisticLink string           `json:"statistic_link"`
	GuestbookLink string           `json:"guestbook_link"`
	Winners       []GameWinner     `json:"winners"`
	TotalWinners  int              `json:"total_winners"`
	PlayerStats   *json.RawMessage `json:"player_stats"`
}

GameDetails is models.GameDetails.

type GameFeeBox

type GameFeeBox struct {
	Game           *Game  `json:"game"`
	Status         string `json:"status"`
	CanEnter       bool   `json:"can_enter"`
	CanMakeFee     bool   `json:"can_make_fee"`
	CanDismiss     bool   `json:"can_dismiss"`
	FeeAccepted    bool   `json:"fee_accepted"`
	FeeText        string `json:"fee_text"`
	HasRequest     bool   `json:"has_request"`
	SecondsToStart int    `json:"seconds_to_start"`
	ShowTimer      bool   `json:"show_timer"`
	ShowEnterBox   bool   `json:"show_enter_box"`
	TeamName       string `json:"team_name"`
	EnterGameLink  string `json:"enter_game_link"`
}

GameFeeBox is models.GameFeeBoxModel — the join block of a game page. It carries the countdown the legacy engine only exposed as StartCounter in HTML.

type GameJoinResponse

type GameJoinResponse struct {
	Success                 bool   `json:"success"`
	Message                 string `json:"message"`
	FeeAccepted             bool   `json:"fee_accepted"`
	FeeAcceptedText         string `json:"fee_accepted_text"`
	ShowPointsGameAttention bool   `json:"show_points_game_attention"`
	PointsGameAttentionText string `json:"points_game_attention_text"`
}

GameJoinResponse is models.GameJoinResponse — the answer to make-fee.

type GameMonitoringResponse

type GameMonitoringResponse struct {
	GameID     int                `json:"game_id"`
	GameNum    int                `json:"game_num"`
	GameTitle  string             `json:"game_title"`
	CanView    bool               `json:"can_view"`
	Mode       string             `json:"mode"`
	Page       int                `json:"page"`
	TotalPages int                `json:"total_pages"`
	TotalRows  int                `json:"total_rows"`
	Actions    []MonitoringAction `json:"actions"`
	Levels     []MonitoringLevel  `json:"levels"`
	Players    []MonitoringPlayer `json:"players"`
}

GameMonitoringResponse is models.GameMonitoringResponse.

type GameScenario

type GameScenario struct {
	Game          *LocalizedGame     `json:"game"`
	IsClassicGame bool               `json:"is_classic_game"`
	Levels        []LevelScenario    `json:"levels"`
	LevelNumbers  []ScenarioLevelRef `json:"level_numbers"`
	Bonuses       []BonusScenario    `json:"whole_game_bonuses"`
	Error         *GameScenarioError `json:"error"`
}

GameScenario is models.GameScenario — the structured scenario export that replaces the legacy GameScenario.aspx page.

type GameScenarioError

type GameScenarioError struct {
	Type    string `json:"type"`
	Key     string `json:"key"`
	Message string `json:"message"`
}

GameScenarioError is models.GameScenarioError — why the export is unavailable.

type GameStatisticsResponse

type GameStatisticsResponse struct {
	GameID               int                        `json:"game_id"`
	GameNum              int                        `json:"game_num"`
	GameTitle            string                     `json:"game_title"`
	GameTypeID           int                        `json:"game_type_id"`
	ZoneID               int                        `json:"zone_id"`
	LevelsSequenceID     int                        `json:"levels_sequence_id"`
	TotalLevels          int                        `json:"total_levels"`
	Levels               []StatLevelMeta            `json:"levels"`
	LevelStats           map[string][]LevelStatItem `json:"level_stats"`
	LevelCorrections     []LevelCorrectionSum       `json:"level_corrections"`
	HideLevelsNames      bool                       `json:"hide_levels_names"`
	CanViewStats         bool                       `json:"can_view_stats"`
	IsGameAuthor         bool                       `json:"is_game_author"`
	AdminWarning         string                     `json:"admin_warning"`
	NeedsConfirm         bool                       `json:"needs_confirm"`
	ConfirmMessage       string                     `json:"confirm_message"`
	CurrentPage          int                        `json:"current_page"`
	TotalPages           int                        `json:"total_pages"`
	RowsPerPage          int                        `json:"rows_per_page"`
	SortField            string                     `json:"sort_field"`
	StatAvailabilityType int                        `json:"stat_availability_type"`
	HasCorrections       bool                       `json:"has_corrections"`
	IsWetWars            bool                       `json:"is_wet_wars"`
}

GameStatisticsResponse is models.GameStatisticsResponse.

type GameWinner

type GameWinner struct {
	Place     int     `json:"place"`
	UserID    int     `json:"user_id"`
	Login     string  `json:"login"`
	TeamID    int     `json:"team_id"`
	TeamName  string  `json:"team_name"`
	Points    float64 `json:"points"`
	BestTime  string  `json:"best_time"`
	FinalTime string  `json:"final_time"`
}

GameWinner is models.Winner.

type GamesResponse

type GamesResponse struct {
	Items      []Game `json:"items"`
	TotalCount int    `json:"total_count"`
}

GamesResponse is models.GamesResponse — a paged game listing.

type HomeGamesResponse

type HomeGamesResponse struct {
	ComingGames []Game `json:"coming_games"`
	ActiveGames []Game `json:"active_games"`
}

HomeGamesResponse is models.HomeGamesResponse, trimmed to the catalog blocks.

type InvitationResponseRequest

type InvitationResponseRequest struct {
	Accept bool `json:"accept"`
}

InvitationResponseRequest is models.InvitationResponseRequest.

type LevelAnswerScenario

type LevelAnswerScenario struct {
	AnswerID   int    `json:"answer_id"`
	AnswerText string `json:"answer_text"`
	AnswerFor  string `json:"answer_for"`
}

LevelAnswerScenario is models.LevelAnswerScenario.

type LevelCorrectionSum

type LevelCorrectionSum struct {
	LevelID         int `json:"level_id"`
	TeamID          int `json:"team_id"`
	UserID          int `json:"user_id"`
	CorrectionValue int `json:"correction_value"`
}

LevelCorrectionSum is models.LevelCorrectionSum.

type LevelHelpScenario

type LevelHelpScenario struct {
	HelpID                int    `json:"help_id"`
	Title                 string `json:"title"`
	HelpText              string `json:"help_text"`
	Timeout               int    `json:"timeout"`
	IsPenalty             bool   `json:"is_penalty"`
	PenaltyTime           int    `json:"penalty_time"`
	PenaltyTimeText       string `json:"penalty_time_text"`
	PenaltyComment        string `json:"penalty_comment"`
	RequestPenaltyConfirm bool   `json:"request_penalty_confirm"`
}

LevelHelpScenario is models.LevelHelpScenario.

type LevelScenario

type LevelScenario struct {
	LevelID               int                   `json:"level_id"`
	LevelNumber           int                   `json:"level_number"`
	LevelName             string                `json:"level_name"`
	Title                 string                `json:"title"`
	Comment               string                `json:"comment"`
	AutopassText          string                `json:"autopass_text"`
	SectorsCompletionRule string                `json:"sectors_completion_rule"`
	Tasks                 []LevelTaskScenario   `json:"tasks"`
	Sectors               []LevelSectorScenario `json:"sectors"`
	Answers               []LevelAnswerScenario `json:"answers"`
	Helps                 []LevelHelpScenario   `json:"helps"`
	PenaltyHelps          []LevelHelpScenario   `json:"penalty_helps"`
	Bonuses               []BonusScenario       `json:"bonuses"`
}

LevelScenario is models.LevelScenario.

type LevelSectorScenario

type LevelSectorScenario struct {
	SectorID    int                   `json:"sector_id"`
	SectorName  string                `json:"sector_name"`
	DisplayName string                `json:"display_name"`
	Answers     []LevelAnswerScenario `json:"answers"`
}

LevelSectorScenario is models.LevelSectorScenario.

type LevelStatItem

type LevelStatItem struct {
	ActionID      int    `json:"action_id"`
	LevelID       int    `json:"level_id"`
	LevelNum      int    `json:"level_num"`
	LevelOrder    int    `json:"level_order"`
	Position      int    `json:"position"`
	UserID        int    `json:"user_id"`
	UserLogin     string `json:"user_login"`
	UserName      string `json:"user_name"`
	TeamID        int    `json:"team_id"`
	TeamName      string `json:"team_name"`
	GamePlayerID  int    `json:"game_player_id"`
	CityID        int    `json:"city_id"`
	CityName      string `json:"city_name"`
	SpentSeconds  int    `json:"spent_seconds"`
	Scores        int    `json:"scores"`
	EnterDateTime string `json:"enter_date_time"`
	// PassTypeID: 0 answered, 1 dismissed by an admin, 2 timeout autopass.
	PassTypeID int `json:"pass_type_id"`
}

LevelStatItem is models.LevelStatItem — one player's pass of one level.

type LevelTaskScenario

type LevelTaskScenario struct {
	TaskID   int    `json:"task_id"`
	TaskText string `json:"task_text"`
	TaskFor  string `json:"task_for"`
}

LevelTaskScenario is models.LevelTaskScenario.

type LocalizedGame

type LocalizedGame struct {
	ID      int    `json:"id"`
	GameNum int    `json:"game_num"`
	Title   string `json:"title"`
}

LocalizedGame is models.LocalizedGame, trimmed to what identifies the game.

type MissingHostError

type MissingHostError struct {
	Domain string
}

MissingHostError reports that no API host is known for a domain, so the request was not sent. It carries the remedy because the caller cannot guess it: the host is only derivable for Encounter's own zones.

func (*MissingHostError) Error

func (e *MissingHostError) Error() string

type MonitoringAction

type MonitoringAction struct {
	ActionID       int    `json:"action_id"`
	LevelID        int    `json:"level_id"`
	LevelNumber    int    `json:"level_number"`
	UserID         int    `json:"user_id"`
	UserLogin      string `json:"user_login"`
	TeamID         int    `json:"team_id"`
	TeamName       string `json:"team_name"`
	Answer         string `json:"answer"`
	AnswerDateTime string `json:"answer_date_time"`
	IsCorrect      bool   `json:"is_correct"`
	IsLevelPass    bool   `json:"is_level_pass"`
	SectorID       int    `json:"sector_id"`
	SectorsInfo    string `json:"sectors_info"`
	ScoresText     string `json:"scores_text"`
}

MonitoringAction is models.MonitoringAction — one answer in the monitor.

type MonitoringLevel

type MonitoringLevel struct {
	LevelID     int    `json:"level_id"`
	LevelNumber int    `json:"level_number"`
	Name        string `json:"name"`
}

MonitoringLevel is models.MonitoringLevelOption.

type MonitoringPlayer

type MonitoringPlayer struct {
	UserID   int    `json:"user_id"`
	Login    string `json:"login"`
	TeamID   int    `json:"team_id"`
	TeamName string `json:"team_name"`
}

MonitoringPlayer is models.MonitoringPlayerOption.

type Option

type Option func(*Client)

Option configures the Client.

func WithLang

func WithLang(lang string) Option

WithLang sets the language passed to endpoints that localize their answer.

func WithRequestInterval added in v0.16.0

func WithRequestInterval(interval time.Duration) Option

WithRequestInterval changes API pacing. Nonpositive values keep the default.

func WithToken

func WithToken(token string) Option

WithToken presets the bearer token, e.g. after restoring a saved session.

func WithUserAgent

func WithUserAgent(ua string) Option

WithUserAgent sets the User-Agent header sent with every request.

type Province

type Province struct {
	ID   int    `json:"id"`
	Name string `json:"name"`
}

Province is models.Province.

type Request

type Request struct {
	Method string
	Path   string
	Query  url.Values
	// Body is marshalled as JSON when non-nil.
	Body any
	// Out receives the decoded JSON response when non-nil.
	Out any
	// Header carries extra headers (rarely needed).
	Header http.Header
}

Request describes a single API call.

type ScenarioLevelRef

type ScenarioLevelRef struct {
	Number int    `json:"number"`
	Name   string `json:"name"`
	Anchor string `json:"anchor"`
}

ScenarioLevelRef is models.LevelNumber.

type Session

type Session struct {
	UserID int    `json:"user_id"`
	ID     int    `json:"id"`
	Login  string `json:"login"`
	User   *User  `json:"user"`
}

Session is the answer of GET /auth/session. The backend documents it only as a free-form object, so both a flat user and a nested one are accepted.

func (*Session) CurrentUserID

func (s *Session) CurrentUserID() int

CurrentUserID returns the signed-in user's ID regardless of the shape used.

type Site

type Site struct {
	ID            int          `json:"id"`
	Name          string       `json:"name"`
	PrimaryDomain string       `json:"primary_domain"`
	Domains       []SiteDomain `json:"domains"`
	NetworkID     int          `json:"network_id"`
	City          *City        `json:"city"`
	Province      *Province    `json:"province"`
	Country       *Country     `json:"country"`
	// IsSiteActiveByRule separates the sites this backend actually serves from
	// the ones it merely lists: the registry mirrors legacy sites that are still
	// on the ASP.NET engine, and only the migrated ones carry this flag.
	IsSiteActiveByRule bool `json:"is_site_active_by_rule"`
}

Site is models.Site, trimmed to what identifies a site and its domains.

type SiteDomain

type SiteDomain struct {
	ID        int    `json:"id"`
	SiteID    int    `json:"site_id"`
	Domain    string `json:"domain"`
	IsPrimary bool   `json:"is_primary"`
}

SiteDomain is models.SiteDomain — one of the domains a site answers on.

type StatLevelMeta

type StatLevelMeta struct {
	LevelID     int    `json:"level_id"`
	LevelNumber int    `json:"level_number"`
	LevelName   string `json:"level_name"`
	Dismissed   bool   `json:"dismissed"`
}

StatLevelMeta is models.StatLevelMeta.

type Team

type Team struct {
	ID           int     `json:"id"`
	Name         string  `json:"name"`
	CaptainID    int     `json:"captain_id"`
	CreateDate   string  `json:"create_date"`
	FlagURL      string  `json:"flag_url"`
	HymnURL      string  `json:"hymn_url"`
	HasHymn      bool    `json:"has_hymn"`
	ForumLink    string  `json:"forum_link"`
	WebSite      string  `json:"web_site"`
	Points       float64 `json:"points"`
	FlagFileName string  `json:"flag_file_name"`
	HymnFileName string  `json:"hymn_file_name"`
}

Team is models.Team.

type TeamInviteRequest

type TeamInviteRequest struct {
	Login string `json:"login"`
}

TeamInviteRequest is the body of POST /teams/{id}/invitations, which the API document describes only in prose ("пригласить в команду по логину").

type TeamListItem

type TeamListItem struct {
	ID           int     `json:"id"`
	Name         string  `json:"name"`
	CaptainID    int     `json:"captain_id"`
	CaptainLogin string  `json:"captain_login"`
	CreateDate   string  `json:"create_date"`
	Points       float64 `json:"points"`
	MembersCount int     `json:"members_count"`
	SiteID       int     `json:"site_id"`
}

TeamListItem is models.TeamListItem.

type TeamMember

type TeamMember struct {
	UserID            int    `json:"user_id"`
	ID                int    `json:"id"`
	TeamID            int    `json:"team_id"`
	Login             string `json:"login"`
	ApprovedByCaptain bool   `json:"approved_by_captain"`
	ApprovedByUser    bool   `json:"approved_by_user"`
	IsActive          bool   `json:"is_active"`
}

TeamMember is one row of GET /teams/{id}/members.

Measured against demo.en.cx: the row carries user_id, team_id, login and the three membership flags, and no id at all.

It is a live record read, which is what makes it a usable oracle for "did the membership change": unlike /auth/session it cannot be served from claims the caller is still holding from before the change.

The shape is taken from the deployed API, which answers with user_id/team_id/login/approved_by_*/is_active. The specification describes this route as an array of models.User, whose key is id and which has none of the membership flags — that does not match what the server sends, so id is accepted as well rather than instead. MemberID reads whichever arrived.

func (TeamMember) MemberID

func (m TeamMember) MemberID() int

MemberID returns the user this row describes under either spelling.

type TeamPreview

type TeamPreview struct {
	ID        int    `json:"id"`
	Name      string `json:"name"`
	CaptainID int    `json:"captain_id"`
}

TeamPreview is models.TeamPreview — a team named in an invitation or request.

type TeamUpdateRequest

type TeamUpdateRequest struct {
	Name      string `json:"name"`
	WebSite   string `json:"web_site"`
	ForumLink string `json:"forum_link"`
}

TeamUpdateRequest is models.TeamUpdateRequest. PUT /teams/{id} replaces all three fields, so callers must send the current values of the ones they keep.

type TeamsListResponse

type TeamsListResponse struct {
	Items      []TeamListItem `json:"items"`
	TotalCount int            `json:"total_count"`
	TotalPages int            `json:"total_pages"`
	Page       int            `json:"page"`
	PageSize   int            `json:"page_size"`
	SortField  string         `json:"sort_field"`
	Mode       string         `json:"mode"`
}

TeamsListResponse is models.TeamsListResponse — a paged team search.

type User

type User struct {
	ID              int     `json:"id"`
	Login           string  `json:"login"`
	FirstName       string  `json:"first_name"`
	LastName        string  `json:"last_name"`
	PatronymicName  string  `json:"patronymic_name"`
	Email           string  `json:"email"`
	EmailChecked    bool    `json:"email_checked"`
	GenderID        int     `json:"gender_id"`
	BirthDate       string  `json:"birth_date"`
	CityID          int     `json:"city_id"`
	CountryID       int     `json:"country_id"`
	ProvinceID      int     `json:"province_id"`
	TeamID          int     `json:"team_id"`
	Team            *Team   `json:"team"`
	Site            *Site   `json:"site"`
	Points          float64 `json:"points"`
	RankID          int     `json:"rank_id"`
	RankSentenceKey string  `json:"rank_sentence_key"`
	StatusID        int     `json:"status_id"`
	RegDateTime     string  `json:"reg_date_time"`
	LastVisit       string  `json:"last_visit"`
	IsSuperAdmin    bool    `json:"is_super_admin"`
	IsBlacklisted   bool    `json:"is_blacklisted"`
	AvatarURL       string  `json:"avatar_url"`
	VkID            string  `json:"vk_id"`
	FbID            string  `json:"fb_id"`
	GooID           string  `json:"goo_id"`
}

User is models.User, trimmed to the fields the profile needs.

type Zone

type Zone struct {
	ID   int    `json:"id"`
	Name string `json:"name"`
}

Zone is models.Zone.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL