This repository has been archived on 2026-09-17. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
rudder-go-sdk/README.md
T
2026-09-17 12:27:51 +03:00

214 lines
8.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# rudder-go-sdk
Серверный Go SDK для LiveOps-платформы Rudder. Покрывает server-admin
поверхность `/game/v1` (auth по `X-API-Key`).
## Install
Модуль раздаётся напрямую с self-hosted Gitea, минуя proxy.golang.org,
поэтому Go должен пропускать его мимо checksum database:
```bash
go env -w GOPRIVATE=hub.rudder.build/*
go get hub.rudder.build/rudder/rudder-go-sdk/v2@latest
```
Требуется Go 1.21+. Токен не нужен — репозиторий публичный.
## Версионирование
Потребители фиксируют версию по git-тегу
(`go get hub.rudder.build/rudder/rudder-go-sdk/v2@vX.Y.Z`). Текущая мажорная
версия — `v2`, поэтому путь модуля содержит суффикс `/v2`, а импорты идут
через `hub.rudder.build/rudder/rudder-go-sdk/v2`.
## Доступ
`AdminKey` — это Admin Key окружения: у проекта их два, для `staging` и для
`prod` (app.rudder.build → проект → Settings → Environments). Ключ сам
определяет и проект, и окружение, поэтому ни project ID, ни параметр
окружения передавать не нужно; игроки и контент разных окружений полностью
изолированы. Храните ключ только на сервере — никогда не вшивайте в игровые
клиенты.
## Usage
```go
client, err := rudder.New(rudder.Config{
AdminKey: os.Getenv("RUDDER_ADMIN_KEY"),
})
if err != nil {
// *rudder.APIError с кодом sdk/invalid-options
}
players, err := client.Players.List(ctx, rudder.ListPlayersParameters{Limit: 100})
```
Публичные типы живут в пакете `rudder`. Пакет `models` — сгенерированный
wire-формат, в прикладном коде его импортировать не нужно.
## Handles
`client.Player(id)` создаёт handle без HTTP-запроса. Handle — сахар над
batch-методами сервисов: каждая операция отправляет batch из одного элемента
с подставленным playerID.
```go
player := client.Player("p1")
wallet, err := player.Wallet().Adjust(ctx, rudder.AdjustPlayerWalletParameters{
IdempotencyKey: "grant-001",
CurrencyCode: "coins",
Amount: 100,
Reason: "compensation",
})
history, err := player.Wallet().History(ctx, rudder.WalletHistoryParameters{Limit: 50})
storage, err := player.Storage().Get(ctx, "settings")
updated, err := player.Storage().Upsert(ctx, rudder.UpsertPlayerStorageParameters{
Type: "settings",
Data: `{"lang":"ru"}`,
})
err = player.Storage().Delete(ctx, rudder.DeletePlayerStorageParameters{Type: "settings"})
updatedPlayer, err := player.Update(ctx, rudder.UpdatePlayerParameters{Nickname: "Neo"})
banned, err := player.Ban(ctx, rudder.BanPlayerParameters{
Reason: "cheating",
BannedUntil: "2030-01-01T00:00:00Z",
})
unbanned, err := player.Unban(ctx, "")
err = player.Delete(ctx, "")
```
## Batch-first API
Все мутирующие операции верхнего уровня — batch-only: тело
`{idempotencyKey?, items:[...]}` (`playerId` внутри элементов), до 100
элементов, all-or-nothing в одной транзакции, один idempotency key на батч.
```go
wallets, err := client.Wallet.Adjust(ctx, rudder.AdjustWalletParameters{
IdempotencyKey: "grant-001",
Items: []rudder.WalletAdjustment{
{PlayerID: "p1", CurrencyCode: "coins", Amount: 100, Reason: "compensation"},
{PlayerID: "p2", CurrencyCode: "coins", Amount: 100, Reason: "compensation"},
},
})
updated, err := client.Players.Update(ctx, rudder.UpdatePlayersParameters{
Items: []rudder.PlayerUpdate{
{PlayerID: "p1", Nickname: "Neo"},
},
})
banned, err := client.Players.Ban(ctx, rudder.BanPlayersParameters{
Items: []rudder.PlayerBan{
{PlayerID: "p2", Reason: "cheating", BannedUntil: "2030-01-01T00:00:00Z"},
},
})
unbanned, err := client.Players.Unban(ctx, rudder.UnbanPlayersParameters{
PlayerIDs: []string{"p2"},
})
err = client.Players.Delete(ctx, rudder.DeletePlayersParameters{
PlayerIDs: []string{"p3"},
})
err = client.Storage.Upsert(ctx, rudder.UpsertStorageParameters{
Items: []rudder.ProjectStorageInput{
{Type: "config", Data: `{"event":"x2"}`},
},
})
err = client.Storage.Delete(ctx, rudder.DeleteStorageParameters{
Types: []string{"config"},
})
rows, err := client.Resources.Create(ctx, "entries", []rudder.ResourceBatchItem{
{PlayerID: "p1", Data: map[string]any{"board": "weekly", "score": 1500}},
})
// Update и Delete — аналогично, строка задаётся полем ID
```
## Модули
Игровые фичи (инвентарь, квесты, лидерборды, магазины, battle pass, remote
config) — это установленные модули. Их данные доступны через
`client.Resources`, а функции с триггером `admin` вызываются через
`client.Modules.Call` (`POST /game/v1/modules/{module}/{fn}`):
```go
out, err := client.Modules.Call(ctx, rudder.CallParameters{
Module: "leaderboards",
Fn: "resetNow",
Args: map[string]any{"row": map[string]any{"id": boardID}},
})
// out.Result, out.Error, out.Log, out.Console; DryRun: true всегда откатывает транзакцию
```
Бизнес-ошибка модуля приходит как `*rudder.APIError` со статусом 422 и
`Code`, который задаёт сам модуль (произвольная строка, констант для неё нет).
## Верификация авторизации
`Players.VerifyAuth` — одиночный (не batch) вызов `POST /players/auth/verify`:
проверяет access token игрока и возвращает `playerId`, `projectId`,
`environment` (`staging`/`prod`) и `status` (`active`/`banned`/`deleted`).
```go
verification, err := client.Players.VerifyAuth(ctx, accessToken)
// verification.PlayerID, verification.ProjectID, verification.Environment, verification.Status
```
`VerifyWebhookSignature` — пакетный хелпер для приёма webhook'ов с подписью
`X-Signature` (hex HMAC-SHA256 от сырого тела, ключ — webhook secret проекта):
```go
if !rudder.VerifyWebhookSignature(secret, body, r.Header.Get("X-Signature")) {
// подпись не сошлась — отклонить запрос
}
```
## Каталоги и read-операции
Курсорная пагинация: передавайте `Limit`/`Cursor`, следующую страницу
запрашивайте по `NextCursor` из ответа.
```go
history, err := client.Wallet.History(ctx, playerID, rudder.WalletHistoryParameters{
Currency: &currency, // optional
Limit: 50,
})
// history.Entries []rudder.WalletTransaction, history.NextCursor
storage, err := client.Storage.List(ctx, rudder.ListStorageParameters{
Limit: 100,
Search: "config", // optional
})
item, err := client.Storage.Get(ctx, "config")
rows, err := client.Resources.List(ctx, "boards")
// rows.Items, rows.Total
```
## Ошибки
```go
var apiErr *rudder.APIError
if errors.As(err, &apiErr) {
apiErr.Status // HTTP status
apiErr.Code // машинный код из тела ошибки
apiErr.RequestID // корреляция с логами сервера
}
```
Сгенерированные коды сервера — `forbidden` и `row_referenced`. Бизнес-ошибки
модулей (422) несут собственный код модуля.
## Генерация
`models/` генерируется apigen'ом из `liveops-backend/openapi/openapi.yaml`
(`make generate-openapi` в liveops-backend). Руками не править.
Публичные имена — aliases в корне пакета `rudder` (`types.go`).