encx

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: 26 Imported by: 0

Documentation

Overview

Package encx provides a Go client for the Encounter (en.cx) game engine JSON API.

The Encounter platform is an international network of urban quest games. This package implements the full game engine API: authentication, game state polling, code submission, bonus codes, penalty hints, and game discovery.

Index

Constants

View Source
const (
	EventGameNormal          = 0
	EventGameNotFound        = 2
	EventEngineMismatch      = 3
	EventPlayerNotLoggedIn   = 4
	EventGameNotStarted      = 5
	EventGameFinished        = 6
	EventPlayerNoApplication = 7
	EventTeamNoApplication   = 8
	EventPlayerNotAccepted   = 9
	EventPlayerNoTeam        = 10
	EventPlayerInactive      = 11
	EventNoLevels            = 12
	EventTeamLimitExceeded   = 13
	EventLevelDismissed16    = 16
	EventGameEnded           = 17
	EventLevelDismissed18    = 18
	EventLevelAutoAdvance    = 19
	EventAllSectorsSolved    = 20
	EventLevelDismissed21    = 21
	EventLevelTimeout        = 22
)

Game event constants.

View Source
const (
	SequenceLinear        = 0
	SequenceSpecified     = 1
	SequenceRandom        = 2
	SequenceAssault       = 3
	SequenceDynamicRandom = 4
)

Level sequence types.

View Source
const (
	GameTypeSingle   = 0
	GameTypeTeam     = 1
	GameTypePersonal = 2
)

Game type constants.

View Source
const (
	ZoneQuest        = 0
	ZoneBrainstorm   = 1
	ZonePhotohunt    = 2
	ZoneWetWar       = 3
	ZoneCompetition  = 4
	ZonePhotoextreme = 5
	ZonePoints       = 7
	ZoneCompetition2 = 8
	ZoneQuiz         = 9
)

Zone type constants.

View Source
const DefaultEngineMode = EngineAuto

DefaultEngineMode is what a client uses when nothing selects an engine: it asks the API host whether this domain has moved, and stays on the legacy engine when it has not.

View Source
const DefaultResourceMaxBytes = 8 << 20

DefaultResourceMaxBytes caps a fetched resource. Task images are photographs, not archives, and the caller usually has to base64 them into an LLM request.

View Source
const EngineEnvVar = "ENCX_ENGINE"

EngineEnvVar names the environment variable that selects the default engine.

Variables

View Source
var (
	// GameStatusDelivered marks a game as состоявшаяся. Zero means unknown.
	GameStatusDelivered = 0
	// GameStatusCancelled marks a game as несостоявшаяся. Zero means unknown.
	GameStatusCancelled = 0
)

The new engine changes a game's lifecycle through PUT /admin/games/{id}/status with a numeric status_id. The API document does not publish the values and the operation is irreversible ("признание необратимо"), so the two calls that need them refuse rather than guess. Set these to the codes the backend expects to enable them.

View Source
var ErrAdminAccessUnverified = errors.New("encx: signed in, but administration access could not be verified")

ErrAdminAccessUnverified reports that the sign-in itself succeeded and a session is now active, but it could not be confirmed for game administration (the admin check was rejected, or a concurrent sign-in of the same class evicted the fresh session before it could be checked).

Callers that only need a player session may treat a LoginComplete error that matches this via errors.Is as success and keep the session; callers that need administration must not. Either way it means "do not sign in again": the credentials were accepted.

View Source
var ErrAntiSpam = errors.New("encx: anti-spam verification required")

ErrAntiSpam indicates the server redirected to NotHumanRequest.aspx (rate-limit / bot check).

View Source
var ErrSectorStarted = errors.New("encx: sector cannot be deleted because it has been started by participants")

ErrSectorStarted means Encounter refused to delete a sector because participants started it.

Functions

func AntiSpamPageURL added in v0.7.1

func AntiSpamPageURL(domain, scheme, returnPath string) string

AntiSpamPageURL builds the full NotHumanRequest.aspx URL for a domain. returnPath is optional (e.g. "/" or "/home/"); defaults to "/".

func AntiSpamURLFromError added in v0.7.1

func AntiSpamURLFromError(err error) string

AntiSpamURLFromError returns the verification page URL when err is anti-spam, else "".

func AntiSpamUserMessage added in v0.7.1

func AntiSpamUserMessage(err error) string

AntiSpamUserMessage returns a user-facing hint when err is anti-spam, else "".

func EventText

func EventText(code int) string

EventText returns a human-readable description for a game event status code.

func ExtractLoginURLFromNotHumanHTML added in v0.8.0

func ExtractLoginURLFromNotHumanHTML(pageURL string, body []byte) string

ExtractLoginURLFromNotHumanHTML finds Login.aspx href/action on a NotHumanRequest page.

func IsAntiSpam added in v0.7.1

func IsAntiSpam(err error) bool

IsAntiSpam reports whether err is an anti-spam challenge (redirect to NotHumanRequest.aspx).

func IsGameNotFound added in v0.15.0

func IsGameNotFound(err error) bool

IsGameNotFound reports whether err says the domain does not host the game.

func IsPlausibleEncounterLogin added in v0.6.0

func IsPlausibleEncounterLogin(s string) bool

IsPlausibleEncounterLogin reports whether s looks like an Encounter username.

func IsUndecodableAccepted added in v0.11.0

func IsUndecodableAccepted(err error) bool

IsUndecodableAccepted reports whether err is an undecodable body on a 2xx response, i.e. the request definitely reached the engine and only the reply could not be read.

Callers use this to decide that a submitted answer must NOT be resent. It deliberately returns false for non-2xx: mistaking a proxy error page for "delivered" would silently destroy a player's answer.

func LoginErrorText

func LoginErrorText(code int) string

LoginErrorText returns a human-readable description for a login error code.

Types

type ActionResult

type ActionResult struct {
	Answer          *string `json:"Answer"`
	IsCorrectAnswer *bool   `json:"IsCorrectAnswer"`
}

ActionResult indicates whether the last submitted answer was correct.

type AdminActionMonitorEntry added in v0.4.5

type AdminActionMonitorEntry struct {
	Number      string `json:"number"`
	Participant string `json:"participant"`
	Direction   string `json:"direction,omitempty"`
	Answer      string `json:"answer"`
	DateTime    string `json:"datetime"`
	Sectors     string `json:"sectors,omitempty"`
}

AdminActionMonitorEntry represents one row from the game action monitor.

type AdminBonus added in v0.1.6

type AdminBonus struct {
	Name     string   `json:"name"`
	Task     string   `json:"task"`
	Hint     string   `json:"hint"`
	LevelID  int      `json:"level_id"`
	Answers  []string `json:"answers"`
	BonusFor string   `json:"bonus_for"` // ddlBonusFor value

	// Award time
	AwardHours   int  `json:"award_hours"`
	AwardMinutes int  `json:"award_minutes"`
	AwardSeconds int  `json:"award_seconds"`
	Negative     bool `json:"negative"`

	// Absolute time limits
	ValidFrom string `json:"valid_from,omitempty"`
	ValidTo   string `json:"valid_to,omitempty"`

	// Delay before bonus becomes available
	DelayHours   int `json:"delay_hours,omitempty"`
	DelayMinutes int `json:"delay_minutes,omitempty"`
	DelaySeconds int `json:"delay_seconds,omitempty"`

	// Relative time limit (how long bonus is active)
	WorkHours   int `json:"work_hours,omitempty"`
	WorkMinutes int `json:"work_minutes,omitempty"`
	WorkSeconds int `json:"work_seconds,omitempty"`
}

AdminBonus holds the data for creating/editing a bonus in the admin panel.

type AdminCorrection added in v0.1.6

type AdminCorrection struct {
	ID       string `json:"id"`
	DateTime string `json:"datetime"`
	Team     string `json:"team"`
	Level    string `json:"level"`
	Reason   string `json:"reason"`
	Time     string `json:"time"`
	Comment  string `json:"comment"`
}

AdminCorrection represents a bonus/penalty time correction entry.

type AdminCorrectionAdd added in v0.1.6

type AdminCorrectionAdd struct {
	TeamName       string `json:"team_name"`
	LevelName      string `json:"level_name"` // "0" for all levels
	Comment        string `json:"comment"`
	CorrectionType string `json:"correction_type"` // "1" = bonus, "2" = penalty
	Days           string `json:"days"`
	Hours          string `json:"hours"`
	Minutes        string `json:"minutes"`
	Seconds        string `json:"seconds"`
}

AdminCorrectionAdd holds the data for adding a new time correction.

type AdminCreateGameParams added in v0.14.0

type AdminCreateGameParams struct {
	Title       string `json:"title"`
	Description string `json:"description,omitempty"`
	GameType    int    `json:"game_type"` // 0=single, 1=team, 2=personal
	// Dates are written in RFC3339; the legacy engine converts them to the
	// ru-locale spelling its form expects.
	StartDateTime  string `json:"start_datetime"`
	FinishDateTime string `json:"finish_datetime"`

	RequestLastDate string `json:"request_last_date,omitempty"`
	// ZoneID selects the game zone the legacy engine offers (0 Схватка,
	// 1 Мозговой штурм, 2 Фотоэкстрим, 3 Мокрые войны, 4 Кэшинг, 5 Фотоохота,
	// 7 Точки, 8 Конкурс, 9 Викторина). Zero is a zone, not "unset". The new
	// engine takes the zone from the domain instead: demo.en.cx refuses every
	// non-zero value with a validation error.
	ZoneID int `json:"zone_id,omitempty"`
	// Authors lists logins separated by commas or semicolons. Empty means the
	// account creating the game.
	Authors     string `json:"authors,omitempty"`
	IsModerated bool   `json:"is_moderated,omitempty"`
}

AdminCreateGameParams holds the data needed to create a game.

It carries the fields creation alone can set — the game type, the zone and the start — plus the game's identity. Everything else the editor offers (prize, limits, statistics, certificates, author complexity) is writable afterwards through AdminUpdateGameInfo, so it is not duplicated here. Both engines require Title, StartDateTime and FinishDateTime and refuse a start in the past or a finish before the start; Title and StartDateTime are checked before the request is sent, FinishDateTime only by the server.

type AdminGame added in v0.1.7

type AdminGame struct {
	ID     int    `json:"id"`
	Number int    `json:"number"`
	Title  string `json:"title"`
	Status string `json:"status"`
}

AdminGame represents a game in the admin game manager.

type AdminGameInfo added in v0.4.0

type AdminGameInfo struct {
	Title       string `json:"title"`
	Authors     string `json:"authors"`
	Description string `json:"description"`
	Prize       string `json:"prize"`
	// StartDateTime is empty when the game has already begun: the editor
	// disables the field then, and neither engine may move a start that has
	// passed. Dates travel in the spelling their engine speaks — RFC3339 on the
	// new one, "02.01.2006 15:04:05" on the legacy form, which also accepts
	// RFC3339 and converts it.
	StartDateTime   string `json:"start_datetime,omitempty"`
	FinishDateTime  string `json:"finish_datetime,omitempty"`
	RequestLastDate string `json:"request_last_date,omitempty"`
	// IsModerated makes participation requests wait for the organiser's
	// approval; false is the automatic acceptance the editor offers instead.
	IsModerated bool `json:"is_moderated"`

	// Visibility settings
	GameStatAvailability     string `json:"game_stat_availability,omitempty"`
	GameScenarioAvailability string `json:"game_scenario_availability,omitempty"`
	ShowFinishPlace          bool   `json:"show_finish_place"`

	// Limits
	MaxPlayers     string `json:"max_players,omitempty"`
	MaxTeamPlayers string `json:"max_team_players,omitempty"`

	// Fee is the participation fee the editor refuses to save the form without,
	// and FeeCurrency the currency it is charged in; both travel on every
	// update so one that does not mention them leaves them as they were.
	Fee         string `json:"fee,omitempty"`
	FeeCurrency string `json:"fee_currency,omitempty"`

	// Rating/certificates
	ShowFee          string `json:"show_fee,omitempty"`
	CertificateMode  string `json:"certificate_mode,omitempty"`
	FirstPlaces      string `json:"first_places,omitempty"`
	NotFirstPlaces   string `json:"not_first_places,omitempty"`
	AcceptRateMode   string `json:"accept_rate_mode,omitempty"`
	AcceptRateFrom   string `json:"accept_rate_from,omitempty"`
	AuthorComplexity string `json:"author_complexity,omitempty"`
}

AdminGameInfo holds the data from the game editor page (GameEditor.aspx).

type AdminGameMessage added in v0.4.5

type AdminGameMessage struct {
	ID               int    `json:"id,omitempty"`
	Text             string `json:"text"`
	ReplaceNlToBr    bool   `json:"replace_nl_to_br"`
	ShowOnLevelsMode int    `json:"show_on_levels_mode,omitempty"` // 1=all, 2=chosen
	RequiredPoints   string `json:"required_points,omitempty"`
	LevelIDs         []int  `json:"level_ids,omitempty"`
}

AdminGameMessage holds the data for creating/editing a game message in MessageEdit.aspx.

type AdminHint added in v0.1.6

type AdminHint struct {
	Text        string `json:"text"`
	ReplaceNl   bool   `json:"replace_nl"` // chkReplaceNlToBr
	Days        int    `json:"days"`
	Hours       int    `json:"hours"`
	Minutes     int    `json:"minutes"`
	Seconds     int    `json:"seconds"`
	ForMemberID string `json:"for_member_id,omitempty"`

	// Penalty hint fields
	IsPenalty      bool   `json:"is_penalty"`
	PenaltyHours   int    `json:"penalty_hours,omitempty"`
	PenaltyMinutes int    `json:"penalty_minutes,omitempty"`
	PenaltySeconds int    `json:"penalty_seconds,omitempty"`
	PenaltyComment string `json:"penalty_comment,omitempty"`
	RequestConfirm bool   `json:"request_confirm,omitempty"`
}

AdminHint holds the data for creating a hint in the admin panel.

type AdminLevel added in v0.1.6

type AdminLevel struct {
	Number int    `json:"number"`
	Name   string `json:"name"`
	ID     int    `json:"id"`
}

AdminLevel represents a level entry as seen in the admin level manager.

type AdminLevelSettings added in v0.1.6

type AdminLevelSettings struct {
	// Autopass
	AutopassHours   int `json:"autopass_hours"`
	AutopassMinutes int `json:"autopass_minutes"`
	AutopassSeconds int `json:"autopass_seconds"`

	// Autopass penalty (timeout penalty)
	TimeoutPenalty bool `json:"timeout_penalty"`
	PenaltyHours   int  `json:"penalty_hours"`
	PenaltyMinutes int  `json:"penalty_minutes"`
	PenaltySeconds int  `json:"penalty_seconds"`

	// Answer block
	AttemptsNumber        int `json:"attempts_number"`
	AttemptsPeriodHours   int `json:"attempts_period_hours"`
	AttemptsPeriodMinutes int `json:"attempts_period_minutes"`
	AttemptsPeriodSeconds int `json:"attempts_period_seconds"`

	// Apply for: 0=team, 1=player
	ApplyForPlayer int `json:"apply_for_player"`

	// Sectors completion: 0 means complete all sectors.
	RequiredSectorsCount int `json:"required_sectors_count,omitempty"`
}

AdminLevelSettings holds the configuration of a level (autopass, answer block, attempts).

type AdminMessage

type AdminMessage struct {
	OwnerId      int    `json:"OwnerId"`
	OwnerLogin   string `json:"OwnerLogin"`
	MessageId    int    `json:"MessageId"`
	MessageText  string `json:"MessageText"`
	WrappedText  string `json:"WrappedText"`
	ReplaceNl2Br bool   `json:"ReplaceNl2Br"`
}

AdminMessage is a message from game organizers.

type AdminSector added in v0.1.6

type AdminSector struct {
	ID          int      `json:"id,omitempty"`
	Name        string   `json:"name"`
	Answers     []string `json:"answers"`
	ForMemberID string   `json:"for_member_id,omitempty"` // 0 = for all
}

AdminSector holds the data for creating a sector in the admin panel.

type AdminTask added in v0.1.6

type AdminTask struct {
	Text        string `json:"text"`
	ReplaceNl   bool   `json:"replace_nl"` // chkReplaceNlToBr
	ForMemberID string `json:"for_member_id,omitempty"`
}

AdminTask holds the data for creating a task in the admin panel.

type AdminTeam added in v0.1.6

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

AdminTeam represents a team entry as seen in the admin panel.

type AntiSpamError added in v0.7.1

type AntiSpamError struct {
	URL string
}

AntiSpamError carries the page URL the user must open to pass the check.

func (*AntiSpamError) Error added in v0.7.1

func (e *AntiSpamError) Error() string

func (*AntiSpamError) Is added in v0.7.1

func (e *AntiSpamError) Is(target error) bool

type Bonus

type Bonus struct {
	BonusId        int        `json:"BonusId"`
	Name           string     `json:"Name"`
	Number         int        `json:"Number"`
	Task           string     `json:"Task"`
	Help           string     `json:"Help"`
	IsAnswered     bool       `json:"IsAnswered"`
	Answer         FlexString `json:"Answer"`
	Expired        bool       `json:"Expired"`
	SecondsToStart int        `json:"SecondsToStart"`
	SecondsLeft    int        `json:"SecondsLeft"`
	AwardTime      int        `json:"AwardTime"`
	Negative       bool       `json:"Negative"`
	// contains filtered or unexported fields
}

Bonus represents a bonus task within a level.

func (Bonus) MarshalJSON added in v0.11.0

func (b Bonus) MarshalJSON() ([]byte, error)

MarshalJSON encodes a bonus while preserving an Answer JSON decoded from the API.

func (Bonus) RawAnswerJSON added in v0.11.0

func (b Bonus) RawAnswerJSON() json.RawMessage

RawAnswerJSON returns a copy of Answer in its original JSON form.

func (*Bonus) UnmarshalJSON added in v0.11.0

func (b *Bonus) UnmarshalJSON(data []byte) error

UnmarshalJSON decodes a bonus while retaining its original Answer JSON.

type Client

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

Client is an HTTP client for the Encounter (en.cx) game engine API.

func New

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

New creates a new Encounter API client for the given domain. By default it uses HTTPS, a 15-second timeout, and the standard User-Agent.

func (*Client) APIBaseURL added in v0.12.0

func (c *Client) APIBaseURL() string

APIBaseURL returns the host used for new-engine requests, empty when the domain is outside the Encounter zones and no host was given explicitly.

func (*Client) APIToken added in v0.12.0

func (c *Client) APIToken() string

APIToken returns the new engine's bearer token, empty on the legacy engine.

func (*Client) AcceptTeamInvitation

func (c *Client) AcceptTeamInvitation(ctx context.Context, teamId int) error

AcceptTeamInvitation accepts a team invitation by team ID.

func (*Client) AdminAddCorrection added in v0.1.6

func (c *Client) AdminAddCorrection(ctx context.Context, gameId int, corr AdminCorrectionAdd) error

func (*Client) AdminAddSectorAnswers added in v0.10.0

func (c *Client) AdminAddSectorAnswers(ctx context.Context, gameId, levelNum, sectorId int, answers []string) error

func (*Client) AdminAwardPoints added in v0.4.5

func (c *Client) AdminAwardPoints(ctx context.Context, gameId int) error

func (*Client) AdminCalculateIK added in v0.4.5

func (c *Client) AdminCalculateIK(ctx context.Context, gameId int) error

func (*Client) AdminClearLevelSectors added in v0.8.0

func (c *Client) AdminClearLevelSectors(ctx context.Context, gameID, levelNum int) error

func (*Client) AdminCloneLevels added in v0.4.5

func (c *Client) AdminCloneLevels(ctx context.Context, gameId, count, likeLevel int) error

func (*Client) AdminCopyGame added in v0.1.6

func (c *Client) AdminCopyGame(ctx context.Context, srcGameId, dstGameId int, progress func(string)) error

AdminCopyGame copies all levels, settings, bonuses, sectors, hints, tasks, and comments from one game to another. The target game must exist (can be empty).

func (*Client) AdminCreateBonus added in v0.1.6

func (c *Client) AdminCreateBonus(ctx context.Context, gameId, levelNum int, b AdminBonus) error

func (*Client) AdminCreateGame added in v0.14.0

func (c *Client) AdminCreateGame(ctx context.Context, params AdminCreateGameParams) (int, error)

func (*Client) AdminCreateHint added in v0.1.6

func (c *Client) AdminCreateHint(ctx context.Context, gameId, levelNum int, h AdminHint) error

func (*Client) AdminCreateLevels added in v0.1.6

func (c *Client) AdminCreateLevels(ctx context.Context, gameId, count int) error

func (*Client) AdminCreateMessage added in v0.4.5

func (c *Client) AdminCreateMessage(ctx context.Context, gameId, levelID int, m AdminGameMessage) error

func (*Client) AdminCreateSector added in v0.1.6

func (c *Client) AdminCreateSector(ctx context.Context, gameId, levelNum int, s AdminSector) error

func (*Client) AdminCreateTask added in v0.1.6

func (c *Client) AdminCreateTask(ctx context.Context, gameId, levelNum int, t AdminTask) error

func (*Client) AdminDelay added in v0.8.0

func (c *Client) AdminDelay() time.Duration

AdminDelay returns the configured pause between admin panel POST requests.

func (*Client) AdminDeleteBonus added in v0.1.6

func (c *Client) AdminDeleteBonus(ctx context.Context, gameId, levelNum, bonusId int) error

func (*Client) AdminDeleteCorrection added in v0.1.6

func (c *Client) AdminDeleteCorrection(ctx context.Context, gameId int, correctionId string) error

func (*Client) AdminDeleteGame added in v0.16.0

func (c *Client) AdminDeleteGame(ctx context.Context, gameId int) error

AdminDeleteGame deletes the game and everything in it. There is no undo, and no engine asks for a confirmation: the caller owns that decision.

func (*Client) AdminDeleteHint added in v0.1.6

func (c *Client) AdminDeleteHint(ctx context.Context, gameId, levelNum, hintId int) error

func (*Client) AdminDeleteLevel added in v0.1.6

func (c *Client) AdminDeleteLevel(ctx context.Context, gameId, levelNum int) error

func (*Client) AdminDeleteMessage added in v0.4.5

func (c *Client) AdminDeleteMessage(ctx context.Context, gameId, levelNum, messageId int) error

func (*Client) AdminDeleteSector added in v0.1.6

func (c *Client) AdminDeleteSector(ctx context.Context, gameId, levelNum, sectorId int) error

func (*Client) AdminDeleteTask added in v0.4.5

func (c *Client) AdminDeleteTask(ctx context.Context, gameId, levelNum, taskId int) error

func (*Client) AdminDeliverGame added in v0.4.5

func (c *Client) AdminDeliverGame(ctx context.Context, gameId int) error

func (*Client) AdminEndRatings added in v0.4.5

func (c *Client) AdminEndRatings(ctx context.Context, gameId int) error

func (*Client) AdminGETDelay added in v0.10.0

func (c *Client) AdminGETDelay() time.Duration

AdminGETDelay returns the pause between admin panel GET requests.

func (*Client) AdminGetActionMonitor added in v0.4.5

func (c *Client) AdminGetActionMonitor(ctx context.Context, gameId int) ([]AdminActionMonitorEntry, error)

func (*Client) AdminGetBonus added in v0.1.6

func (c *Client) AdminGetBonus(ctx context.Context, gameId, levelNum, bonusId int) (*AdminBonus, error)

func (*Client) AdminGetBonusIds added in v0.1.6

func (c *Client) AdminGetBonusIds(ctx context.Context, gameId, levelNum int) ([]int, error)

func (*Client) AdminGetComment added in v0.1.6

func (c *Client) AdminGetComment(ctx context.Context, gameId, levelNum int) (name, comment string, err error)

func (*Client) AdminGetCorrections added in v0.1.6

func (c *Client) AdminGetCorrections(ctx context.Context, gameId int) ([]AdminCorrection, error)

func (*Client) AdminGetGameInfo added in v0.4.0

func (c *Client) AdminGetGameInfo(ctx context.Context, gameId int) (*AdminGameInfo, error)

func (*Client) AdminGetGames added in v0.1.7

func (c *Client) AdminGetGames(ctx context.Context) ([]AdminGame, error)

func (*Client) AdminGetHint added in v0.1.6

func (c *Client) AdminGetHint(ctx context.Context, gameId, levelNum, hintId int) (*AdminHint, error)

func (*Client) AdminGetHintIds added in v0.1.6

func (c *Client) AdminGetHintIds(ctx context.Context, gameId, levelNum int) ([]int, error)

func (*Client) AdminGetLevelSettings added in v0.1.6

func (c *Client) AdminGetLevelSettings(ctx context.Context, gameId, levelNum int) (*AdminLevelSettings, error)

func (*Client) AdminGetLevels added in v0.1.6

func (c *Client) AdminGetLevels(ctx context.Context, gameId int) ([]AdminLevel, error)

func (*Client) AdminGetMessage added in v0.4.5

func (c *Client) AdminGetMessage(ctx context.Context, gameId, levelNum, messageId int) (*AdminGameMessage, error)

func (*Client) AdminGetMessageIds added in v0.4.5

func (c *Client) AdminGetMessageIds(ctx context.Context, gameId, levelNum int) ([]int, error)

func (*Client) AdminGetSectorAnswers added in v0.1.6

func (c *Client) AdminGetSectorAnswers(ctx context.Context, gameId, levelNum int) ([]AdminSector, error)

func (*Client) AdminGetSectorRefs added in v0.11.1

func (c *Client) AdminGetSectorRefs(ctx context.Context, gameId, levelNum int) ([]AdminSector, error)

func (*Client) AdminGetTask added in v0.1.6

func (c *Client) AdminGetTask(ctx context.Context, gameId, levelNum, taskId int) (*AdminTask, error)

func (*Client) AdminGetTaskIds added in v0.1.6

func (c *Client) AdminGetTaskIds(ctx context.Context, gameId, levelNum int) ([]int, error)

func (*Client) AdminGetTeams added in v0.1.6

func (c *Client) AdminGetTeams(ctx context.Context, gameId, levelNum int) ([]AdminTeam, error)

func (*Client) AdminInsertLevel added in v0.4.5

func (c *Client) AdminInsertLevel(ctx context.Context, gameId, src, dst int) error

func (*Client) AdminNotDeliverGame added in v0.4.5

func (c *Client) AdminNotDeliverGame(ctx context.Context, gameId int) error

func (*Client) AdminRenameLevels added in v0.1.6

func (c *Client) AdminRenameLevels(ctx context.Context, gameId int, names map[int]string) error

func (*Client) AdminSwapLevels added in v0.4.5

func (c *Client) AdminSwapLevels(ctx context.Context, gameId, level1, level2 int) error

func (*Client) AdminUpdateAnswerBlock added in v0.1.6

func (c *Client) AdminUpdateAnswerBlock(ctx context.Context, gameId, levelNum int, s AdminLevelSettings) error

func (*Client) AdminUpdateAutopass added in v0.1.6

func (c *Client) AdminUpdateAutopass(ctx context.Context, gameId, levelNum int, s AdminLevelSettings) error

func (*Client) AdminUpdateBonus added in v0.4.5

func (c *Client) AdminUpdateBonus(ctx context.Context, gameId, levelNum, bonusId int, b AdminBonus) error

func (*Client) AdminUpdateComment added in v0.1.6

func (c *Client) AdminUpdateComment(ctx context.Context, gameId, levelNum int, name, comment string) error

func (*Client) AdminUpdateGameInfo added in v0.4.0

func (c *Client) AdminUpdateGameInfo(ctx context.Context, gameId int, info AdminGameInfo) error

func (*Client) AdminUpdateHint added in v0.4.5

func (c *Client) AdminUpdateHint(ctx context.Context, gameId, levelNum, hintId int, h AdminHint) error

func (*Client) AdminUpdateMessage added in v0.4.5

func (c *Client) AdminUpdateMessage(ctx context.Context, gameId, levelNum, messageId int, m AdminGameMessage) error

func (*Client) AdminUpdateSector added in v0.4.5

func (c *Client) AdminUpdateSector(ctx context.Context, gameId, levelNum, sectorId int, s AdminSector) error

func (*Client) AdminUpdateSectorCompletion added in v0.10.0

func (c *Client) AdminUpdateSectorCompletion(ctx context.Context, gameId, levelNum, requiredCount int) error

func (*Client) AdminUpdateTask added in v0.4.5

func (c *Client) AdminUpdateTask(ctx context.Context, gameId, levelNum, taskId int, t AdminTask) error

func (*Client) AdminWipeGame added in v0.1.6

func (c *Client) AdminWipeGame(ctx context.Context, gameId int, progress func(string)) error

AdminWipeGame completely resets a game: removes all bonuses, hints, sectors, and levels.

func (*Client) ClearHAR added in v0.8.0

func (c *Client) ClearHAR()

ClearHAR removes all captured HAR entries.

func (*Client) ClearHARFirst added in v0.11.0

func (c *Client) ClearHARFirst(n int)

ClearHARFirst removes the n oldest captured HAR entries.

func (*Client) Engine added in v0.12.0

func (c *Client) Engine() EngineMode

Engine returns the backend actually in use, resolving EngineAuto by probing the API host once.

func (*Client) EngineMode added in v0.12.0

func (c *Client) EngineMode() EngineMode

EngineMode returns the configured mode, which may still be EngineAuto.

func (*Client) EnterGame

func (c *Client) EnterGame(ctx context.Context, gameId int) (string, error)

EnterGame registers the player in a game (application / fee confirmation).

func (*Client) ExportCookies

func (c *Client) ExportCookies() ([]byte, error)

ExportCookies serializes the client's session.

With no new-engine state to carry it emits the historical cookie array, so sessions stay readable by older builds; otherwise it emits a session object.

func (*Client) ExportHARJSON added in v0.8.0

func (c *Client) ExportHARJSON() (string, error)

ExportHARJSON returns captured traffic as a HAR 1.2 JSON document.

func (*Client) ExportHARSnapshot added in v0.11.0

func (c *Client) ExportHARSnapshot() (string, int, error)

ExportHARSnapshot atomically returns the HAR document and the number of entries it contains; pass the count to ClearHARFirst after the document is persisted to drop exactly the exported entries.

func (*Client) FetchResource added in v0.12.0

func (c *Client) FetchResource(ctx context.Context, rawURL string, opts ...ResourceOptions) (*Resource, error)

FetchResource downloads a file referenced by game content, reusing the authenticated session — many Encounter attachments are not public.

rawURL may be absolute or site-relative, and may point at any public host: authors host task images wherever they like. Addresses on the local network are still refused, because a URL taken from game content is untrusted input and the device running this may sit inside a private network.

func (*Client) GetAdminGameScenario added in v0.16.0

func (c *Client) GetAdminGameScenario(ctx context.Context, gameID int) (*scenario.Document, error)

GetAdminGameScenario reads an author's scenario with administrative details omitted by the public export, notably the sign of bonus time.

func (*Client) GetDomainGames

func (c *Client) GetDomainGames(ctx context.Context) ([]DomainGame, error)

GetDomainGames fetches the domain's list of available games.

func (*Client) GetGameDetails

func (c *Client) GetGameDetails(ctx context.Context, gameId int) (string, error)

GetGameDetails fetches the game details document.

The legacy engine returns the HTML page; the new engine has no HTML export and returns the structured details document as JSON instead.

func (*Client) GetGameList

func (c *Client) GetGameList(ctx context.Context, page ...int) (*GameListResponse, error)

GetGameList fetches the domain's coming and active games. An optional page number can be passed for pagination (1-based).

func (*Client) GetGameModel

func (c *Client) GetGameModel(ctx context.Context, gameId int, formValues ...url.Values) (*GameModel, error)

GetGameModel retrieves the current game state. Passing form values is retained for backward compatibility and performs a POST action request; prefer SendCode, SendBonusCode, or GetPenaltyHint.

func (*Client) GetGameModelLevel added in v0.8.2

func (c *Client) GetGameModelLevel(ctx context.Context, gameId, levelNumber int) (*GameModel, error)

GetGameModelLevel retrieves the state for a specific level number. This is used by storm sequence games where the engine accepts a level parameter.

func (*Client) GetGameScenario added in v0.12.0

func (c *Client) GetGameScenario(ctx context.Context, gameId int) (*scenario.Document, error)

GetGameScenario reads the author's scenario export of a game.

The two engines publish it differently — the legacy one renders GameScenario.aspx as HTML, the new one answers with a structured document — so this method returns the parsed model rather than a page. Callers that need the legacy HTML itself keep using GetGameScenarioHTML.

func (*Client) GetGameScenarioHTML added in v0.10.0

func (c *Client) GetGameScenarioHTML(ctx context.Context, gameId int) (string, error)

GetGameScenarioHTML reads the GameScenario.aspx export page.

It exists only on the legacy engine; the new backend publishes no HTML scenario, so prefer GetGameScenario, which works on both.

func (*Client) GetGameStatistics added in v0.1.6

func (c *Client) GetGameStatistics(ctx context.Context, gameId int) (*GameStatisticsResponse, error)

GetGameStatistics fetches full game statistics: per-level results, player/team rankings and level metadata.

func (*Client) GetMyTeamDetails added in v0.9.0

func (c *Client) GetMyTeamDetails(ctx context.Context) (string, error)

GetMyTeamDetails fetches the signed-in user's own team page.

func (*Client) GetPenaltyHint

func (c *Client) GetPenaltyHint(ctx context.Context, gameId, penaltyId int) (*GameModel, error)

GetPenaltyHint requests a penalty hint by its ID.

func (*Client) GetProfile added in v0.1.8

func (c *Client) GetProfile(ctx context.Context) (*Profile, error)

GetProfile fetches the signed-in user's profile.

func (*Client) GetTeamDetails

func (c *Client) GetTeamDetails(ctx context.Context, teamId int) (string, error)

GetTeamDetails fetches the team page.

The legacy engine returns HTML; the new engine returns the team document as JSON, since it publishes no HTML page.

func (*Client) GetTeamInvitations added in v0.9.0

func (c *Client) GetTeamInvitations(ctx context.Context) ([]TeamInvitation, error)

GetTeamInvitations fetches team invitations addressed to the current user.

func (*Client) GetTeamManagementInfo added in v0.9.0

func (c *Client) GetTeamManagementInfo(ctx context.Context, teamID int) (*TeamManagementInfo, error)

GetTeamManagementInfo reports what the current session may do with a team.

func (*Client) GetTimeoutToGame

func (c *Client) GetTimeoutToGame(ctx context.Context, gameId int) (*int, error)

GetTimeoutToGame reports the seconds remaining until the game starts, or nil when the engine does not publish a countdown.

func (*Client) HAREntryCount added in v0.8.0

func (c *Client) HAREntryCount() int

HAREntryCount returns the number of captured HAR entries.

func (*Client) ImportCookies

func (c *Client) ImportCookies(data []byte) error

ImportCookies restores a session produced by ExportCookies. Both the legacy cookie array and the session object are accepted.

func (*Client) InviteTeamMember added in v0.9.0

func (c *Client) InviteTeamMember(ctx context.Context, teamID int, login string) error

InviteTeamMember invites a user login into the specified team.

func (*Client) LeaveTeam added in v0.9.0

func (c *Client) LeaveTeam(ctx context.Context, teamID int) error

LeaveTeam removes the current user from the team.

func (*Client) Login

func (c *Client) Login(ctx context.Context, login, password string, opts ...LoginOptions) (*LoginResponse, error)

Login authenticates the user on the Encounter domain. On success (Error == 0) the session is stored in the client and used for subsequent requests: cookies on the legacy engine, a JWT on the new one.

Optional LoginOptions can be passed to specify network or CAPTCHA digits.

func (*Client) LoginComplete added in v0.8.0

func (c *Client) LoginComplete(ctx context.Context, login, password string, opts ...LoginOptions) error

LoginComplete establishes a session that also works for game administration. On the legacy engine it signs in through Login.aspx and falls back to the JSON endpoint; on the new engine one JWT covers both.

func (*Client) LoginForAntiSpamRecovery added in v0.8.0

func (c *Client) LoginForAntiSpamRecovery(ctx context.Context, loginPageURL, login, password string, opts ...LoginOptions) (*LoginResponse, error)

LoginForAntiSpamRecovery signs in during anti-spam recovery: Login.aspx form first, then JSON /login/signin. loginPageURL should be the Login.aspx link from NotHumanRequest (see ResolveAntiSpamLoginURL).

func (*Client) LoginViaLoginPage added in v0.8.0

func (c *Client) LoginViaLoginPage(ctx context.Context, loginPageURL, login, password string, opts ...LoginOptions) error

LoginViaLoginPage signs in through the HTML Login.aspx form (used during anti-spam recovery).

func (*Client) RejectTeamInvitation added in v0.9.0

func (c *Client) RejectTeamInvitation(ctx context.Context, teamID int) error

RejectTeamInvitation rejects a team invitation by team ID.

func (*Client) RemoveTeamInvitation added in v0.9.0

func (c *Client) RemoveTeamInvitation(ctx context.Context, teamID, userID int) error

RemoveTeamInvitation withdraws an invitation the captain sent.

func (*Client) RenameTeam added in v0.9.0

func (c *Client) RenameTeam(ctx context.Context, teamID int, name string) error

RenameTeam changes the team name.

func (*Client) RequestTeamMembership added in v0.9.0

func (c *Client) RequestTeamMembership(ctx context.Context, teamName string) error

RequestTeamMembership sends a request to join the named team.

func (*Client) ResolveAntiSpamLoginURL added in v0.8.0

func (c *Client) ResolveAntiSpamLoginURL(ctx context.Context, challengeURL string) (string, error)

ResolveAntiSpamLoginURL loads NotHumanRequest.aspx and returns the login page URL from it. Falls back to challengeURL when the page cannot be read or has no login link.

func (*Client) SendBonusCode

func (c *Client) SendBonusCode(ctx context.Context, gameId, levelId, levelNumber int, code string) (*GameModel, error)

SendBonusCode submits a bonus answer. Both engines keep this action separate from level answers so it still works while level answers are blocked.

func (*Client) SendCode

func (c *Client) SendCode(ctx context.Context, gameId, levelId, levelNumber int, code string) (*GameModel, error)

SendCode submits a level answer (level, sectors, and bonuses when the level has no active answer block rule).

func (*Client) SetAPIToken added in v0.12.0

func (c *Client) SetAPIToken(token string)

SetAPIToken installs a previously obtained new-engine bearer token.

func (*Client) SetAdminDelay added in v0.8.0

func (c *Client) SetAdminDelay(d time.Duration)

SetAdminDelay overrides the pause between admin panel POST requests at runtime.

func (*Client) SetEngine added in v0.12.0

func (c *Client) SetEngine(mode EngineMode)

SetEngine switches the backend at runtime and discards a cached auto probe.

func (*Client) SetHARRecordingEnabled added in v0.8.0

func (c *Client) SetHARRecordingEnabled(enabled bool)

SetHARRecordingEnabled toggles HAR capture for subsequent HTTP requests.

func (*Client) SetTeamForum added in v0.9.0

func (c *Client) SetTeamForum(ctx context.Context, teamID int, forum string) error

SetTeamForum sets the team forum link.

func (*Client) SetTeamSite added in v0.9.0

func (c *Client) SetTeamSite(ctx context.Context, teamID int, site string) error

SetTeamSite sets the team web site.

func (*Client) VerifyAdminSession added in v0.8.0

func (c *Client) VerifyAdminSession(ctx context.Context) error

VerifyAdminSession reports whether the current session can reach the game administration API.

type CodeAction

type CodeAction struct {
	ActionId      int       `json:"ActionId"`
	LevelId       int       `json:"LevelId"`
	LevelNumber   int       `json:"LevelNumber"`
	UserId        int       `json:"UserId"`
	Kind          int       `json:"Kind"` // 1=level, 2=bonus
	Login         string    `json:"Login"`
	Answer        string    `json:"Answer"`
	AnswForm      *string   `json:"AnswForm"`
	EnterDateTime *DateTime `json:"EnterDateTime"`
	LocDateTime   string    `json:"LocDateTime"`
	IsCorrect     bool      `json:"IsCorrect"`
	Award         *Duration `json:"Award"`
	LocAward      *string   `json:"LocAward"`
	Penalty       int       `json:"Penalty"`
	Negative      bool      `json:"Negative"`
	// contains filtered or unexported fields
}

CodeAction represents a code entry in the action log.

func (CodeAction) MarshalJSON added in v0.11.0

func (a CodeAction) MarshalJSON() ([]byte, error)

MarshalJSON encodes a code action while preserving a decoded local time JSON.

func (*CodeAction) UnmarshalJSON added in v0.11.0

func (a *CodeAction) UnmarshalJSON(data []byte) error

UnmarshalJSON decodes a code action while retaining its original local time JSON.

type DateTime

type DateTime struct {
	Value     float64 `json:"Value"`
	Timestamp int64   `json:"Timestamp"`
}

DateTime represents a date-time value as returned by the EN API.

type DomainGame

type DomainGame struct {
	Title  string `json:"title"`
	GameId int    `json:"gameId"`
}

DomainGame represents a game listed on a domain's main page (from HTML scraping).

type Duration

type Duration struct {
	Ticks             int64   `json:"Ticks,omitempty"`
	Days              int     `json:"Days"`
	Hours             int     `json:"Hours"`
	Milliseconds      int     `json:"Milliseconds,omitempty"`
	Minutes           int     `json:"Minutes"`
	Seconds           int     `json:"Seconds"`
	TotalDays         float64 `json:"TotalDays,omitempty"`
	TotalHours        float64 `json:"TotalHours,omitempty"`
	TotalMilliseconds float64 `json:"TotalMilliseconds,omitempty"`
	TotalMinutes      float64 `json:"TotalMinutes,omitempty"`
	TotalSeconds      float64 `json:"TotalSeconds"`
}

Duration represents a time duration as returned by the EN API.

type EngineAction

type EngineAction struct {
	LevelNumber   int                  `json:"LevelNumber"`
	LevelAction   *ActionResult        `json:"LevelAction"`
	BonusAction   *ActionResult        `json:"BonusAction"`
	PenaltyAction *PenaltyActionResult `json:"PenaltyAction"`
	GameId        int                  `json:"GameId"`
	LevelId       int                  `json:"LevelId"`
	// RejectReason explains why an answer was not judged, e.g. "answer_blocked"
	// when the level's answer-block rule refused it. Only the new engine
	// reports it; the legacy one leaves it empty.
	RejectReason string `json:"RejectReason,omitempty"`
}

EngineAction holds the result of the last game action.

type EngineMode added in v0.12.0

type EngineMode string

EngineMode selects which Encounter backend the client talks to.

const (
	// EngineLegacy is the ASP.NET engine: JSON endpoints plus HTML admin forms.
	EngineLegacy EngineMode = "legacy"
	// EngineNew is the Encounter Go Backend REST API (see docs/newengine).
	EngineNew EngineMode = "new"
	// EngineAuto probes the new engine once and falls back to legacy.
	EngineAuto EngineMode = "auto"
)

func ParseEngineMode added in v0.12.0

func ParseEngineMode(value string) (EngineMode, bool)

ParseEngineMode maps a user-supplied value onto an EngineMode. Unknown and empty values report false and resolve to DefaultEngineMode, so a typo cannot silently pin a caller to one engine.

type FlexString added in v0.7.1

type FlexString string

FlexString decodes JSON string, number, bool, null, or object into a display string. The Encounter game engine sometimes returns sector/bonus answers as objects after a code is accepted.

func (FlexString) MarshalJSON added in v0.7.1

func (s FlexString) MarshalJSON() ([]byte, error)

func (FlexString) String added in v0.7.1

func (s FlexString) String() string

func (*FlexString) UnmarshalJSON added in v0.7.1

func (s *FlexString) UnmarshalJSON(data []byte) error

type GameInfo

type GameInfo struct {
	GameID                  int       `json:"GameID"`
	GameNum                 int       `json:"GameNum"`
	SiteID                  int       `json:"SiteID,omitempty"`
	LangID                  int       `json:"LangID,omitempty"`
	CompetitionID           int       `json:"CompetitionID,omitempty"`
	OwnerID                 int       `json:"OwnerID,omitempty"`
	LevelNumber             int       `json:"LevelNumber,omitempty"`
	CreateDateTime          *DateTime `json:"CreateDateTime"`
	StartDateTime           *DateTime `json:"StartDateTime"`
	FinishDateTime          *DateTime `json:"FinishDateTime"`
	Title                   string    `json:"Title"`
	Descr                   string    `json:"Descr"`
	DescrWrapped            string    `json:"DescrWrapped,omitempty"`
	GameTypeID              int       `json:"GameTypeID"` // 0=single, 1=team, 2=personal
	ZoneId                  int       `json:"ZoneId"`     // 0=quest, 1=brainstorm, 2=photohunt, etc.
	LevelsSequence          int       `json:"LevelsSequence,omitempty"`
	ScenarioAvailability    int       `json:"ScenarioAvailability,omitempty"`
	MaxPlayers              int       `json:"MaxPlayers"`
	MaxTeamMembers          int       `json:"MaxTeamMembers"`
	ShowInCalendar          bool      `json:"ShowInCalendar"`
	FeeType                 int       `json:"FeeType"`
	FeeCurrencyId           int       `json:"FeeCurrencyId"`
	FeeName                 string    `json:"FeeName"`
	ShowFee                 int       `json:"ShowFee"`
	Fee                     *Money    `json:"Fee"`
	Prize                   *Money    `json:"Prize"`
	PrizeType               int       `json:"PrizeType,omitempty"`
	PrizeTypeSymbol         string    `json:"PrizeTypeSymbol,omitempty"`
	TSRemain                *Duration `json:"TSRemain"`
	Started                 bool      `json:"Started"`
	Finished                bool      `json:"Finished"`
	InProgress              bool      `json:"InProgress"`
	IsSectorsSupported      bool      `json:"IsSectorsSupported,omitempty"`
	IsOnlineStatAvailable   bool      `json:"IsOnlineStatAvailable,omitempty"`
	IsComplexitySupported   bool      `json:"IsComplexitySupported,omitempty"`
	IsModerated             bool      `json:"IsModerated,omitempty"`
	ComplexityFactor        int       `json:"ComplexityFactor,omitempty"`
	ComplexityMembersFactor int       `json:"ComplexityMembersFactor,omitempty"`
	QualityRate             int       `json:"QualityRate,omitempty"`
	QualityRateFormatted    string    `json:"QualityRateFormatted,omitempty"`
	TopicId                 int       `json:"TopicId,omitempty"`
	AcceptRateFromDateTime  *DateTime `json:"AcceptRateFromDateTime,omitempty"`
	RequestLastDate         *DateTime `json:"RequestLastDate,omitempty"`
	HideLevelsNames         bool      `json:"HideLevelsNames,omitempty"`
	AlwaysAvailable         bool      `json:"AlwaysAvailable,omitempty"`
	PublicAccess            bool      `json:"PublicAccess,omitempty"`
	DisplayMonitoring       int       `json:"DisplayMonitoring,omitempty"`

	Owner                    any  `json:"Owner,omitempty"`
	Type                     int  `json:"Type,omitempty"`
	CertificatePlaces        int  `json:"CertificatePlaces,omitempty"`
	CertificateAccessMode    int  `json:"CertificateAccessMode,omitempty"`
	ShowFinishPlace          bool `json:"ShowFinishPlace,omitempty"`
	StatusId                 int  `json:"StatusId,omitempty"`
	Status                   int  `json:"Status,omitempty"`
	IsAvailableAfterFinished bool `json:"IsAvailableAfterFinished,omitempty"`
	StatAvailabilityTypeID   int  `json:"StatAvailabilityTypeID,omitempty"`
	StatAvailabilityType     int  `json:"StatAvailabilityType,omitempty"`
	RateClosed               bool `json:"RateClosed,omitempty"`
	LevelsSequenceId         int  `json:"LevelsSequenceId,omitempty"`
	QualityRateCalculated    bool `json:"QualityRateCalculated,omitempty"`
	Zone                     int  `json:"Zone,omitempty"`
	AllowMakeStakes          bool `json:"AllowMakeStakes,omitempty"`
	HidePlayersList          bool `json:"HidePlayersList,omitempty"`
	ReplaceNlToBr            bool `json:"ReplaceNlToBr,omitempty"`
	HideGameDescr            bool `json:"HideGameDescr,omitempty"`
	DisplayAnnouncement      int  `json:"DisplayAnnouncement,omitempty"`
	ForUserID                int  `json:"ForUserID,omitempty"`
	// AFC arrives as a fractional number on some domains (e.g. 0.1 on tech.en.cx).
	AFC                   float64 `json:"AFC,omitempty"`
	IsQualityRateVisible  bool    `json:"IsQualityRateVisible,omitempty"`
	AuthorIndexCalculated bool    `json:"AuthorIndexCalculated,omitempty"`
	State                 int     `json:"State,omitempty"`
	IsModified            bool    `json:"IsModified,omitempty"`
	IsNewObject           bool    `json:"IsNewObject,omitempty"`
	ReadOnly              bool    `json:"ReadOnly,omitempty"`
	SyncRoot              any     `json:"SyncRoot,omitempty"`
	// contains filtered or unexported fields
}

GameInfo holds full game metadata returned by the /home/?json=1 endpoint.

func (GameInfo) MarshalJSON added in v0.11.0

func (g GameInfo) MarshalJSON() ([]byte, error)

MarshalJSON encodes game metadata while preserving its decoded FeeName JSON.

func (*GameInfo) UnmarshalJSON added in v0.11.0

func (g *GameInfo) UnmarshalJSON(data []byte) error

UnmarshalJSON decodes game metadata while retaining nullable and explicit JSON fields.

type GameListResponse

type GameListResponse struct {
	ComingGames          []GameInfo `json:"ComingGames"`
	ActiveGames          []GameInfo `json:"ActiveGames"`
	Error                int        `json:"Error,omitempty"`
	Message              string     `json:"Message,omitempty"`
	IpUnblockUrl         *string    `json:"IpUnblockUrl,omitempty"`
	BruteForceUnblockUrl *string    `json:"BruteForceUnblockUrl,omitempty"`
	ConfirmEmailUrl      *string    `json:"ConfirmEmailUrl,omitempty"`
	CaptchaUrl           *string    `json:"CaptchaUrl,omitempty"`
	AdminWhoCanActivate  []string   `json:"AdminWhoCanActivate,omitempty"`
	// contains filtered or unexported fields
}

GameListResponse is the JSON response from GET /home/?json=1.

func (GameListResponse) MarshalJSON added in v0.11.0

func (r GameListResponse) MarshalJSON() ([]byte, error)

MarshalJSON encodes a game list while retaining explicit keys decoded from the API.

func (*GameListResponse) UnmarshalJSON added in v0.11.0

func (r *GameListResponse) UnmarshalJSON(data []byte) error

UnmarshalJSON decodes a game list while retaining explicit observed keys.

type GameModel

type GameModel struct {
	Event             any            `json:"Event"`
	GameId            int            `json:"GameId"`
	GameNumber        int            `json:"GameNumber"`
	GameTitle         string         `json:"GameTitle"`
	GameTypeId        int            `json:"GameTypeId"`
	GameZoneId        int            `json:"GameZoneId"`
	LevelSequence     int            `json:"LevelSequence"`
	UserId            int            `json:"UserId"`
	TeamId            int            `json:"TeamId"`
	Login             string         `json:"Login"`
	TeamName          string         `json:"TeamName"`
	IsCaptain         bool           `json:"IsCaptain"`
	GameDateTimeStart string         `json:"GameDateTimeStart"`
	Levels            []LevelSummary `json:"Levels"`
	Level             *Level         `json:"Level"`
	EngineAction      *EngineAction  `json:"EngineAction"`
}

GameModel is the full game state returned by the game engine.

type GameNotFoundError added in v0.15.0

type GameNotFoundError struct {
	GameID int
	Domain string
}

GameNotFoundError means the ASP.NET engine does not host this game: the play URL answered with a redirect to the site's home page, which is how the engine reports a game id the domain does not know (a typo, or a game that lives on another domain). This is a permanent condition — retrying or re-logging in cannot make the game appear.

func (*GameNotFoundError) Error added in v0.15.0

func (e *GameNotFoundError) Error() string

type GameStatisticsResponse added in v0.1.6

type GameStatisticsResponse struct {
	Game                *GameInfo          `json:"Game"`
	Level               *LevelStatInfo     `json:"Level"`
	StatItems           [][]StatItem       `json:"StatItems"`
	Levels              []LevelStatInfo    `json:"Levels"`
	IsLevelNamesVisible bool               `json:"IsLevelNamesVisible"`
	LevelPlayers        []LevelPlayerCount `json:"LevelPlayers"`
	User                *UserProfile       `json:"User"`
	PagerVisible        bool               `json:"PagerVisible"`
	ShowAdminWarning    bool               `json:"ShowAdminWarning"`
}

GameStatisticsResponse is the JSON response from GET /gamestatistics/full/{gameId}?json=1.

type HARRecorder added in v0.8.0

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

HARRecorder captures HTTP traffic in HAR 1.2 format for debugging and mock servers.

func NewHARRecorder added in v0.8.0

func NewHARRecorder() *HARRecorder

func (*HARRecorder) Clear added in v0.8.0

func (r *HARRecorder) Clear()

func (*HARRecorder) ClearFirst added in v0.11.0

func (r *HARRecorder) ClearFirst(n int)

ClearFirst removes up to n oldest entries, preserving entries appended after the matching ExportSnapshot call.

func (*HARRecorder) Enabled added in v0.8.0

func (r *HARRecorder) Enabled() bool

func (*HARRecorder) EntryCount added in v0.8.0

func (r *HARRecorder) EntryCount() int

func (*HARRecorder) ExportJSON added in v0.8.0

func (r *HARRecorder) ExportJSON() (string, error)

func (*HARRecorder) ExportSnapshot added in v0.11.0

func (r *HARRecorder) ExportSnapshot() (string, int, error)

ExportSnapshot atomically returns the HAR document together with the number of entries it contains, so the caller can later remove exactly the exported entries with ClearFirst while keeping entries captured in the meantime.

func (*HARRecorder) SetEnabled added in v0.8.0

func (r *HARRecorder) SetEnabled(enabled bool)

type Help

type Help struct {
	HelpId           int     `json:"HelpId"`
	Number           int     `json:"Number"`
	HelpText         *string `json:"HelpText"`
	IsPenalty        bool    `json:"IsPenalty"`
	Penalty          int     `json:"Penalty"`
	PenaltyComment   *string `json:"PenaltyComment"`
	RequestConfirm   bool    `json:"RequestConfirm"`
	PenaltyHelpState int     `json:"PenaltyHelpState"` // 0=locked, 1=requested/opened, 2=confirmed
	RemainSeconds    int     `json:"RemainSeconds"`
	PenaltyMessage   *string `json:"PenaltyMessage"`
}

Help represents a hint (regular or penalty). Both Helps and PenaltyHelps arrays in the API use the same structure.

type Level

type Level struct {
	LevelId              int            `json:"LevelId"`
	Number               int            `json:"Number"`
	Name                 string         `json:"Name"`
	Timeout              int            `json:"Timeout"`
	TimeoutSecondsRemain int            `json:"TimeoutSecondsRemain"`
	TimeoutAward         int            `json:"TimeoutAward"`
	IsPassed             bool           `json:"IsPassed"`
	Dismissed            bool           `json:"Dismissed"`
	StartTime            *DateTime      `json:"StartTime"`
	HasAnswerBlockRule   bool           `json:"HasAnswerBlockRule"`
	BlockDuration        int            `json:"BlockDuration"`
	BlockTargetId        int            `json:"BlockTargetId"`
	AttemtsNumber        int            `json:"AttemtsNumber"`
	AttemtsPeriod        int            `json:"AttemtsPeriod"`
	RequiredSectorsCount int            `json:"RequiredSectorsCount"`
	PassedSectorsCount   int            `json:"PassedSectorsCount"`
	PassedBonusesCount   int            `json:"PassedBonusesCount"`
	SectorsLeftToClose   int            `json:"SectorsLeftToClose"`
	Tasks                []LevelTask    `json:"Tasks"`
	Task                 *LevelTask     `json:"Task,omitempty"`
	Messages             []AdminMessage `json:"Messages"`
	Sectors              []Sector       `json:"Sectors"`
	Helps                []Help         `json:"Helps"`
	Bonuses              []Bonus        `json:"Bonuses"`
	PenaltyHelps         []Help         `json:"PenaltyHelps"`
	MixedActions         []CodeAction   `json:"MixedActions"`
}

Level represents a game level with its current state.

func (*Level) CanSubmitLevelAnswer added in v0.8.2

func (l *Level) CanSubmitLevelAnswer() bool

CanSubmitLevelAnswer reports whether the documented level state allows submitting LevelAction.Answer. BonusAction.Answer is not blocked by this rule.

type LevelPlayerCount added in v0.1.6

type LevelPlayerCount struct {
	LevelNum int `json:"LevelNum"`
	Count    int `json:"Count"`
}

LevelPlayerCount holds the number of players who reached a given level.

type LevelStatInfo added in v0.1.6

type LevelStatInfo struct {
	LevelId       int    `json:"LevelId"`
	LevelNumber   int    `json:"LevelNumber"`
	LevelName     string `json:"LevelName"`
	Dismissed     bool   `json:"Dismissed"`
	PassedPlayers int    `json:"PassedPlayers"`
}

LevelStatInfo holds level metadata used in game statistics.

type LevelSummary added in v0.1.6

type LevelSummary struct {
	LevelId     int           `json:"LevelId"`
	LevelNumber int           `json:"LevelNumber"`
	LevelName   string        `json:"LevelName"`
	Dismissed   bool          `json:"Dismissed"`
	IsPassed    bool          `json:"IsPassed"`
	Task        *LevelTask    `json:"Task"`
	LevelAction *ActionResult `json:"LevelAction"`
}

LevelSummary is a brief level entry as returned in the GameModel.Levels array.

type LevelTask

type LevelTask struct {
	TaskText          string `json:"TaskText"`
	TaskTextFormatted string `json:"TaskTextFormatted"`
	ReplaceNlToBr     bool   `json:"ReplaceNlToBr"`
}

LevelTask holds the task/assignment text for a level.

type LoginOptions

type LoginOptions struct {
	Network      int    // 1=Encounter (default), 2=QuestUa
	MagicNumbers string // CAPTCHA digits when Error==1
}

LoginOptions holds optional parameters for the Login request.

type LoginResponse

type LoginResponse struct {
	Error                int      `json:"Error"`
	Message              string   `json:"Message"`
	IpUnblockUrl         *string  `json:"IpUnblockUrl"`
	BruteForceUnblockUrl *string  `json:"BruteForceUnblockUrl"`
	ConfirmEmailUrl      *string  `json:"ConfirmEmailUrl"`
	CaptchaUrl           *string  `json:"CaptchaUrl"`
	AdminWhoCanActivate  []string `json:"AdminWhoCanActivate"`
}

LoginResponse is the response from the /login/signin endpoint.

type Money

type Money struct {
	Cents                       int    `json:"Cents"`
	Value                       int    `json:"Value"`
	Formated                    string `json:"Formated"`
	FormatedFull                string `json:"FormatedFull,omitempty"`
	DefaultCultureFormated      string `json:"DefaultCultureFormated,omitempty"`
	DefaultCultureShortFormated string `json:"DefaultCultureShortFormated,omitempty"`
}

Money represents a monetary value (fee or prize) as returned by the EN API.

type Option

type Option func(*Client)

Option configures the Client.

func WithAPIBaseURL added in v0.12.0

func WithAPIBaseURL(baseURL string) Option

WithAPIBaseURL overrides the host of the new engine (default: api.<zone>).

Naming the host is also the caller vouching for it: a host given here is trusted even when the site it returns does not list its domains, which a derived host is not.

func WithAPIRequestInterval added in v0.16.0

func WithAPIRequestInterval(interval time.Duration) Option

WithAPIRequestInterval configures REST request pacing. Nonpositive values keep the default. Clients sharing a host use the slowest configured pace.

func WithAdminDelay added in v0.8.0

func WithAdminDelay(d time.Duration) Option

WithAdminDelay sets the pause between admin panel POST requests. Pass 0 to disable admin throttling (e.g. httptest).

func WithAntiSpamHandler added in v0.8.0

func WithAntiSpamHandler(handler func(url string) error) Option

WithAntiSpamHandler sets a callback used when Encounter anti-spam challenge is detected. The callback should block until user passes verification (or return an error to abort).

func WithDebugLogger added in v0.2.1

func WithDebugLogger(logf func(string, ...any)) Option

WithDebugLogger enables verbose request/response logging.

func WithEngine added in v0.12.0

func WithEngine(mode EngineMode) Option

WithEngine selects the backend explicitly, overriding ENCX_ENGINE.

func WithHARRecording added in v0.8.0

func WithHARRecording(enabled bool) Option

WithHARRecording enables HAR 1.2 capture for all HTTP requests made by the client.

func WithHTTP

func WithHTTP() Option

WithHTTP forces plain HTTP instead of HTTPS.

func WithInsecureTLS

func WithInsecureTLS() Option

WithInsecureTLS disables TLS certificate verification.

func WithLang

func WithLang(lang string) Option

WithLang sets the language parameter for API requests.

func WithTimeout

func WithTimeout(d time.Duration) Option

WithTimeout sets the HTTP client timeout.

func WithUserAgent

func WithUserAgent(ua string) Option

WithUserAgent sets a custom User-Agent header.

type PenaltyActionResult added in v0.1.6

type PenaltyActionResult struct {
	PenaltyId  int `json:"PenaltyId"`
	ActionType int `json:"ActionType"` // 0=none, 1=request
}

PenaltyActionResult holds the result of a penalty hint action.

type Profile added in v0.1.8

type Profile struct {
	ID       int    `json:"id"`
	Login    string `json:"login"`
	Name     string `json:"name"`
	Rank     string `json:"rank"`
	Team     string `json:"team"`
	TeamID   int    `json:"team_id,omitempty"`
	Domain   string `json:"domain"`
	Points   string `json:"points"`
	Location string `json:"location,omitempty"`
}

Profile represents user profile data parsed from the profile page.

type Resource added in v0.12.0

type Resource struct {
	URL         string `json:"url"`
	ContentType string `json:"content_type"`
	Data        []byte `json:"-"`
}

Resource is a file fetched from the Encounter site with the player's session.

type ResourceOptions added in v0.12.0

type ResourceOptions struct {
	// MaxBytes rejects anything larger. Zero means DefaultResourceMaxBytes.
	MaxBytes int64
	// RestrictToDomain limits fetches to the client's own domain. Off by
	// default: game authors routinely host task images on image services, and a
	// viewer that refused them would be useless.
	RestrictToDomain bool
}

ResourceOptions bounds a resource fetch.

type Sector

type Sector struct {
	SectorId   int        `json:"SectorId"`
	Order      int        `json:"Order"`
	Name       string     `json:"Name"`
	IsAnswered bool       `json:"IsAnswered"`
	Answer     FlexString `json:"Answer"`
	// contains filtered or unexported fields
}

Sector represents a sector within a level.

func (Sector) MarshalJSON added in v0.11.0

func (s Sector) MarshalJSON() ([]byte, error)

MarshalJSON encodes a sector while preserving an Answer JSON decoded from the API.

func (Sector) RawAnswerJSON added in v0.11.0

func (s Sector) RawAnswerJSON() json.RawMessage

RawAnswerJSON returns a copy of Answer in its original JSON form.

func (*Sector) UnmarshalJSON added in v0.11.0

func (s *Sector) UnmarshalJSON(data []byte) error

UnmarshalJSON decodes a sector while retaining its original Answer JSON.

type StatItem added in v0.1.6

type StatItem struct {
	ActionTime     *DateTime `json:"ActionTime"`
	UserId         int       `json:"UserId"`
	LevelId        int       `json:"LevelId"`
	TeamId         int       `json:"TeamId"`
	UserName       string    `json:"UserName"`
	TeamName       string    `json:"TeamName"`
	LevelNum       int       `json:"LevelNum"`
	SpentSeconds   int       `json:"SpentSeconds"`
	LevelOrder     int       `json:"LevelOrder"`
	SpentLevelTime *Duration `json:"SpentLevelTime"`
	PassType       int       `json:"PassType"`
	Corrections    *Duration `json:"Corrections"`
	Scores         int       `json:"Scores"`
}

StatItem represents a single team/player entry in the game statistics.

type TeamActionError added in v0.9.0

type TeamActionError struct {
	Operation string
	Message   string
}

TeamActionError reports an Encounter team-management action that returned HTTP OK but did not change the page state as requested.

func (*TeamActionError) Error added in v0.9.0

func (e *TeamActionError) Error() string

type TeamInfo

type TeamInfo struct {
	TeamId int    `json:"teamId"`
	Name   string `json:"name"`
}

TeamInfo represents basic team information parsed from HTML.

func ParseTeamLinks(body string) []TeamInfo

ParseTeamLinks extracts team IDs and names from an HTML page.

type TeamInvitation added in v0.9.0

type TeamInvitation struct {
	TeamID int    `json:"team_id"`
	Name   string `json:"name"`
	Action string `json:"action,omitempty"`
}

TeamInvitation represents an invitation to join a team.

func ParseTeamInvitations added in v0.9.0

func ParseTeamInvitations(body string) []TeamInvitation

ParseTeamInvitations extracts invitations addressed to the current user.

type TeamManagementInfo added in v0.9.0

type TeamManagementInfo struct {
	TeamID             int                     `json:"team_id"`
	TeamName           string                  `json:"team_name,omitempty"`
	PendingInvitations []TeamPendingInvitation `json:"pending_invitations,omitempty"`
	Actions            map[string]string       `json:"actions,omitempty"`
}

TeamManagementInfo contains team management actions parsed from TeamDetails.aspx.

func ParseTeamManagementInfo added in v0.9.0

func ParseTeamManagementInfo(body string, teamID int) *TeamManagementInfo

ParseTeamManagementInfo extracts known team management actions and invitations from a team page.

type TeamPendingInvitation added in v0.9.0

type TeamPendingInvitation struct {
	UserID int    `json:"user_id"`
	Login  string `json:"login"`
}

TeamPendingInvitation represents a user invited to the current team.

type UndecodableResponseError added in v0.11.0

type UndecodableResponseError struct {
	StatusCode int
	Context    string
	Err        error
}

UndecodableResponseError means the server answered but the body could not be parsed into the expected model.

StatusCode is what makes this error actionable. A 2xx means the request reached the engine and only the reply was unreadable — for an answer submission that means the answer was recorded, so resending it would duplicate it. A non-2xx means an intermediary (proxy, gateway) answered instead, so the request may never have reached the engine and must stay retryable.

func (*UndecodableResponseError) Error added in v0.11.0

func (e *UndecodableResponseError) Error() string

func (*UndecodableResponseError) Unwrap added in v0.11.0

func (e *UndecodableResponseError) Unwrap() error

type UserProfile added in v0.1.6

type UserProfile struct {
	ID             int       `json:"ID"`
	Login          string    `json:"Login"`
	FirstName      string    `json:"FirstName"`
	PatronymicName string    `json:"PatronymicName"`
	LastName       string    `json:"LastName"`
	Email          string    `json:"Email"`
	EmailChecked   bool      `json:"EmailChecked"`
	GenderID       int       `json:"GenderID"` // 1=male, 2=female
	BirthDate      *DateTime `json:"BirthDate"`
	CityId         int       `json:"CityId"`
	CountryId      int       `json:"CountryId"`
	ProvinceId     int       `json:"ProvinceId"`
	TeamID         int       `json:"TeamID"`
	ParentID       int       `json:"ParentID"`
	SiteId         int       `json:"SiteId"`
	IsActive       bool      `json:"IsActive"`
	RegDateTime    *DateTime `json:"RegDateTime"`
	Points         float64   `json:"Points"`
	BonusPoints    float64   `json:"BonusPoints"`
	RankID         int       `json:"RankID"`
	StatusId       int       `json:"StatusId"`
	Network        int       `json:"Network"`
	LastVisitTime  *DateTime `json:"LastVisitTime"`
	VkId           *string   `json:"VkId"`
	FbId           *string   `json:"FbId"`
	TgId           *string   `json:"TgId"`
	GooId          *string   `json:"GooId"`
	IsSuperAdmin   bool      `json:"IsSuperAdmin"`
	BlockByIP      bool      `json:"BlockByIP"`
}

UserProfile represents the authenticated user's profile as returned in game statistics.

Directories

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

Jump to

Keyboard shortcuts

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