9 Commits

Author SHA1 Message Date
edmand46 2619291b20 v0.6.0: drop Metrics service from the server SDK
CI / build (push) Successful in 50s
2026-08-27 09:53:44 +03:00
edmand46 ef5bbe2df2 v0.5.0: batch-first API, player/leaderboard handles, unified naming, Storage is global project storage, catalog list methods
CI / build (push) Successful in 49s
2026-08-26 18:30:28 +03:00
edmand46 db1223c195 leaderboards: ListEntries/SubmitEntry/UpdateEntry/DeleteEntry against /entries
CI / build (push) Successful in 50s
2026-08-26 13:53:27 +03:00
edmand46 4b5922c92f quests: admin player-quest client (list/reset/force-complete/force-claim), generated models
CI / build (push) Successful in 56s
2026-08-25 16:25:29 +03:00
edmand46 cafc2bfc6a rename Config.APIKey to AdminKey, add search to project storage list
CI / build (push) Successful in 1m2s
2026-08-25 13:59:30 +03:00
edmand46 6e7c818f75 remove UGC surface, add CI, versioning docs
CI / build (push) Successful in 1m14s
2026-08-19 17:49:03 +03:00
edmand46 ae74fb22d3 add player data operations: update, ban/unban, delete, inventory adjust, storage
Players.Update/Ban/Unban/Delete + List search; new InventoryService.Adjust
and StorageService.Get/Upsert/Delete; IdempotencyKey on wallet adjust;
models regenerated via apigen
2026-08-13 08:47:14 +03:00
edmand46 d602a95baf Add ProjectStorageService (list/get/upsert/delete) 2026-08-12 23:58:34 +03:00
rudder 58eb477763 Per-project admin key auth, drop ProjectID; MIT license; go 1.21 2026-08-12 17:37:46 +03:00
71 changed files with 1333 additions and 198 deletions
+26
View File
@@ -0,0 +1,26 @@
name: CI
on:
push:
branches: [master, main]
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.21'
- name: Build
run: go build ./...
- name: Vet
run: go vet ./...
+1
View File
@@ -0,0 +1 @@
.idea/
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2026 Rudder
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+167 -11
View File
@@ -1,8 +1,7 @@
# liveops-go-sdk # rudder-go-sdk
Серверный Go SDK для LiveOps-платформы Rudder. Покрывает server-admin Серверный Go SDK для LiveOps-платформы Rudder. Покрывает server-admin
поверхность `/game/v1` (auth по `X-API-Key`, ключ — `GAME_ADMIN_API_KEY` поверхность `/game/v1` (auth по `X-API-Key`).
на gateway).
## Install ## Install
@@ -14,28 +13,185 @@ go env -w GOPRIVATE=hub.rudder.build/*
go get hub.rudder.build/rudder/rudder-go-sdk@latest go get hub.rudder.build/rudder/rudder-go-sdk@latest
``` ```
Требуется Go 1.25+. Токен не нужен — репозиторий публичный. Требуется Go 1.21+. Токен не нужен — репозиторий публичный.
## Версионирование
Потребители фиксируют версию по git-тегу
(`go get hub.rudder.build/rudder/rudder-go-sdk@vX.Y.Z`). Первый тег `v0.1.0`
будет создан при релизе; до него версионирования нет.
## Доступ
`AdminKey` — это per-project Admin Key: поле «Admin Key» в настройках проекта
в дашборде (app.rudder.build → проект → Settings). Ключ сам определяет
проект, отдельный project ID не нужен. Храните его только на сервере —
никогда не вшивайте в игровые клиенты.
## Usage ## Usage
```go ```go
client, err := rudder.New(rudder.Config{ client, err := rudder.New(rudder.Config{
APIKey: os.Getenv("GAME_ADMIN_API_KEY"), AdminKey: os.Getenv("RUDDER_ADMIN_KEY"),
ProjectID: "your-project-id",
}) })
if err != nil { if err != nil {
// *rudder.APIError с кодом sdk/invalid-options // *rudder.APIError с кодом sdk/invalid-options
} }
players, err := client.Players.List(ctx, rudder.ListPlayersParameters{Limit: 100}) players, err := client.Players.List(ctx, rudder.ListPlayersParameters{Limit: 100})
entries, err := client.Leaderboards.Results(ctx, "weekly") ```
wallet, err := client.Wallet.Adjust(ctx, playerID, rudder.AdjustWalletParameters{
## Handles
`client.Player(id)` и `client.Leaderboard(slug)` создают handle без
HTTP-запроса. Handles — сахар над batch-методами сервисов: каждая операция
отправляет batch из одного элемента с подставленным playerID/slug.
```go
player := client.Player("p1")
wallet, err := player.Wallet().Adjust(ctx, rudder.AdjustPlayerWalletParameters{
IdempotencyKey: "grant-001",
CurrencyCode: "coins", CurrencyCode: "coins",
Amount: 100, Amount: 100,
Reason: "compensation", Reason: "compensation",
}) })
metrics, err := client.Metrics.Get(ctx) history, err := player.Wallet().History(ctx, rudder.WalletHistoryParameters{Limit: 50})
page, err := client.Ugc.List(ctx, rudder.ListUgcParameters{Status: "pending"})
item, err := player.Inventory().Adjust(ctx, rudder.AdjustPlayerInventoryParameters{
Slug: "sword",
Amount: 1,
Reason: "quest reward",
})
inventory, err := player.Inventory().List(ctx, rudder.ListInventoryParameters{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"})
quests, err := player.Quests().List(ctx)
err = player.Quests().Reset(ctx, rudder.PlayerQuestParameters{QuestID: "daily-1"})
// ForceComplete и ForceClaim — аналогично
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, "")
board := client.Leaderboard("weekly")
entries, err := board.List(ctx, rudder.ListLeaderboardEntriesParameters{Limit: 100})
// entries.Entries []models.RankEntry, entries.NextCursor
entry, err := board.Get(ctx, "p1") // *models.RankEntry с rank
around, err := board.GetAround(ctx, "p1", 10) // []models.RankEntry вокруг игрока
err = board.Submit(ctx, []models.BatchLeaderboardEntry{{PlayerID: "p1", Score: 1500}})
err = board.Update(ctx, []models.BatchLeaderboardEntry{{PlayerID: "p1", Score: 1600}})
err = board.Delete(ctx, []string{"p1", "p2"})
```
## 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: []models.BatchAdjustPlayerWalletsItem{
{PlayerID: "p1", CurrencyCode: "coins", Amount: 100, Reason: "compensation"},
{PlayerID: "p2", CurrencyCode: "coins", Amount: 100, Reason: "compensation"},
},
})
items, err := client.Inventory.Adjust(ctx, rudder.AdjustInventoryParameters{
Items: []models.BatchAdjustPlayerInventoryItemsItem{
{PlayerID: "p1", Slug: "sword", Amount: 1, Reason: "quest reward"},
},
})
updated, err := client.Players.Update(ctx, rudder.UpdatePlayersParameters{
Items: []models.BatchUpdatePlayersItem{
{PlayerID: "p1", Nickname: "Neo"},
},
})
banned, err := client.Players.Ban(ctx, rudder.BanPlayersParameters{
Items: []models.BatchBanPlayersItem{
{PlayerID: "p2", Reason: "cheating", BannedUntil: "2030-01-01T00:00:00Z"},
},
})
unbanned, err := client.Players.Unban(ctx, rudder.UnbanPlayersParameters{
Items: []models.BatchPlayerItem{{PlayerID: "p2"}},
})
err = client.Players.Delete(ctx, rudder.DeletePlayersParameters{
Items: []models.BatchPlayerItem{{PlayerID: "p3"}},
})
err = client.Quests.Reset(ctx, rudder.ResetPlayerQuestsParameters{
Items: []models.BatchPlayerQuestsItem{
{PlayerID: "p1", QuestID: "daily-1"},
},
})
// ForceComplete и ForceClaim — аналогично
err = client.Leaderboards.Submit(ctx, "weekly", []models.BatchLeaderboardEntry{
{PlayerID: "p1", Score: 1500},
})
// Update и Delete — аналогично
err = client.Storage.Upsert(ctx, rudder.UpsertStorageParameters{
Items: []models.AdminProjectStorageItem{
{Type: "config", Data: `{"event":"x2"}`},
},
})
err = client.Storage.Delete(ctx, rudder.DeleteStorageParameters{
Types: []string{"config"},
})
```
## Каталоги и read-операции
Курсорная пагинация: передавайте `Limit`/`Cursor`, следующую страницу
запрашивайте по `NextCursor` из ответа.
```go
boards, err := client.Leaderboards.List(ctx, rudder.ListLeaderboardsParameters{Limit: 100})
// boards.Items []models.LeaderboardDefinition, boards.NextCursor
quests, err := client.Quests.List(ctx, rudder.ListQuestsParameters{
Status: &status, // "active" или "archived", optional
Limit: 100,
})
// quests.Items []models.QuestDefinition, quests.NextCursor
history, err := client.Wallet.History(ctx, playerID, rudder.WalletHistoryParameters{
Currency: &currency, // optional
Limit: 50,
})
// history.Entries []models.WalletAudit, history.NextCursor
inventory, err := client.Inventory.List(ctx, playerID, rudder.ListInventoryParameters{
Limit: 50,
})
// inventory.Items []models.InventoryItem, inventory.NextCursor
storage, err := client.Storage.List(ctx, rudder.ListStorageParameters{
Limit: 100,
Search: "config", // optional
})
item, err := client.Storage.Get(ctx, "config")
``` ```
## Ошибки ## Ошибки
@@ -44,7 +200,7 @@ page, err := client.Ugc.List(ctx, rudder.ListUgcParameters{Status: "pending"})
var apiErr *rudder.APIError var apiErr *rudder.APIError
if errors.As(err, &apiErr) { if errors.As(err, &apiErr) {
apiErr.Status // HTTP status apiErr.Status // HTTP status
apiErr.Code // машинный код, константы в models.ErrorCode* apiErr.Code // машинный код из тела ошибки gateway
apiErr.RequestID // корреляция с логами gateway apiErr.RequestID // корреляция с логами gateway
} }
``` ```
+33 -13
View File
@@ -8,8 +8,7 @@ import (
const DefaultBaseURL = "https://api.rudder.build" const DefaultBaseURL = "https://api.rudder.build"
type Config struct { type Config struct {
APIKey string AdminKey string
ProjectID string
BaseURL string BaseURL string
Timeout time.Duration Timeout time.Duration
HTTPClient *http.Client HTTPClient *http.Client
@@ -17,18 +16,18 @@ type Config struct {
type Client struct { type Client struct {
Players *PlayersService Players *PlayersService
Metrics *MetricsService
Leaderboards *LeaderboardsService Leaderboards *LeaderboardsService
Wallet *WalletService Wallet *WalletService
Ugc *UgcService Inventory *InventoryService
Quests *QuestsService
Storage *StorageService
transport *transport
} }
func New(config Config) (*Client, error) { func New(config Config) (*Client, error) {
if config.APIKey == "" { if config.AdminKey == "" {
return nil, &APIError{Code: ErrorCodeInvalidOptions, Message: "APIKey is required"} return nil, &APIError{Code: ErrorCodeInvalidOptions, Message: "AdminKey is required"}
}
if config.ProjectID == "" {
return nil, &APIError{Code: ErrorCodeInvalidOptions, Message: "ProjectID is required"}
} }
if config.BaseURL == "" { if config.BaseURL == "" {
@@ -43,16 +42,37 @@ func New(config Config) (*Client, error) {
transport := &transport{ transport := &transport{
baseURL: config.BaseURL, baseURL: config.BaseURL,
apiKey: config.APIKey, apiKey: config.AdminKey,
projectID: config.ProjectID,
httpClient: config.HTTPClient, httpClient: config.HTTPClient,
} }
return &Client{ return &Client{
Players: &PlayersService{transport: transport}, Players: &PlayersService{transport: transport},
Metrics: &MetricsService{transport: transport},
Leaderboards: &LeaderboardsService{transport: transport}, Leaderboards: &LeaderboardsService{transport: transport},
Wallet: &WalletService{transport: transport}, Wallet: &WalletService{transport: transport},
Ugc: &UgcService{transport: transport}, Inventory: &InventoryService{transport: transport},
Quests: &QuestsService{transport: transport},
Storage: &StorageService{transport: transport},
transport: transport,
}, nil }, nil
} }
func (c *Client) Player(playerID string) *PlayerHandle {
return &PlayerHandle{
playerID: playerID,
transport: c.transport,
players: c.Players,
wallet: c.Wallet,
inventory: c.Inventory,
quests: c.Quests,
}
}
func (c *Client) Leaderboard(slug string) *LeaderboardHandle {
return &LeaderboardHandle{
slug: slug,
transport: c.transport,
leaderboards: c.Leaderboards,
}
}
+1 -1
View File
@@ -1,3 +1,3 @@
module hub.rudder.build/rudder/rudder-go-sdk module hub.rudder.build/rudder/rudder-go-sdk
go 1.25.2 go 1.21
+53
View File
@@ -0,0 +1,53 @@
package rudder
import (
"context"
"net/http"
"net/url"
"strconv"
"hub.rudder.build/rudder/rudder-go-sdk/models"
)
type InventoryService struct {
transport *transport
}
type AdjustInventoryParameters struct {
IdempotencyKey string
Items []models.BatchAdjustPlayerInventoryItemsItem
}
func (s *InventoryService) Adjust(ctx context.Context, parameters AdjustInventoryParameters) ([]models.InventoryItem, error) {
body := models.BatchAdjustPlayerInventoryItemsRequest{
IdempotencyKey: parameters.IdempotencyKey,
Items: parameters.Items,
}
var response models.BatchAdjustPlayerInventoryItemsResponse
if err := s.transport.do(ctx, http.MethodPost, "/players/inventory/adjust", nil, body, &response); err != nil {
return nil, err
}
return response.Items, nil
}
type ListInventoryParameters struct {
Limit int
Cursor *string
}
func (s *InventoryService) List(ctx context.Context, playerID string, parameters ListInventoryParameters) (*models.GetPlayerInventoryResponse, error) {
query := url.Values{}
if parameters.Limit > 0 {
query.Set("limit", strconv.Itoa(parameters.Limit))
}
if parameters.Cursor != nil {
query.Set("cursor", *parameters.Cursor)
}
var response models.GetPlayerInventoryResponse
if err := s.transport.do(ctx, http.MethodGet, "/players/"+url.PathEscape(playerID)+"/inventory", query, nil, &response); err != nil {
return nil, err
}
return &response, nil
}
+70
View File
@@ -0,0 +1,70 @@
package rudder
import (
"context"
"net/http"
"net/url"
"strconv"
"hub.rudder.build/rudder/rudder-go-sdk/models"
)
type LeaderboardHandle struct {
slug string
transport *transport
leaderboards *LeaderboardsService
}
type ListLeaderboardEntriesParameters struct {
Limit int
Cursor *string
}
func (h *LeaderboardHandle) List(ctx context.Context, parameters ListLeaderboardEntriesParameters) (*models.ListLeaderboardEntriesResponse, error) {
query := url.Values{}
if parameters.Limit > 0 {
query.Set("limit", strconv.Itoa(parameters.Limit))
}
if parameters.Cursor != nil {
query.Set("cursor", *parameters.Cursor)
}
var response models.ListLeaderboardEntriesResponse
if err := h.transport.do(ctx, http.MethodGet, "/leaderboards/"+url.PathEscape(h.slug)+"/entries", query, nil, &response); err != nil {
return nil, err
}
return &response, nil
}
func (h *LeaderboardHandle) Get(ctx context.Context, playerID string) (*models.RankEntry, error) {
var response models.RankEntry
if err := h.transport.do(ctx, http.MethodGet, "/leaderboards/"+url.PathEscape(h.slug)+"/entries/"+url.PathEscape(playerID), nil, nil, &response); err != nil {
return nil, err
}
return &response, nil
}
func (h *LeaderboardHandle) GetAround(ctx context.Context, playerID string, limit int) ([]models.RankEntry, error) {
query := url.Values{}
if limit > 0 {
query.Set("limit", strconv.Itoa(limit))
}
var response models.GetLeaderboardEntryAroundResponse
if err := h.transport.do(ctx, http.MethodGet, "/leaderboards/"+url.PathEscape(h.slug)+"/entries/"+url.PathEscape(playerID)+"/around", query, nil, &response); err != nil {
return nil, err
}
return response.Entries, nil
}
func (h *LeaderboardHandle) Submit(ctx context.Context, items []models.BatchLeaderboardEntry) error {
return h.leaderboards.Submit(ctx, h.slug, items)
}
func (h *LeaderboardHandle) Update(ctx context.Context, items []models.BatchLeaderboardEntry) error {
return h.leaderboards.Update(ctx, h.slug, items)
}
func (h *LeaderboardHandle) Delete(ctx context.Context, playerIDs []string) error {
return h.leaderboards.Delete(ctx, h.slug, playerIDs)
}
+39 -4
View File
@@ -4,6 +4,7 @@ import (
"context" "context"
"net/http" "net/http"
"net/url" "net/url"
"strconv"
"hub.rudder.build/rudder/rudder-go-sdk/models" "hub.rudder.build/rudder/rudder-go-sdk/models"
) )
@@ -12,10 +13,44 @@ type LeaderboardsService struct {
transport *transport transport *transport
} }
func (s *LeaderboardsService) Results(ctx context.Context, slug string) ([]models.RankEntry, error) { type ListLeaderboardsParameters struct {
var response models.GetLeaderboardResultsResponse Limit int
if err := s.transport.do(ctx, http.MethodGet, "/leaderboards/"+url.PathEscape(slug)+"/results", nil, nil, &response); err != nil { Cursor *string
}
func (s *LeaderboardsService) List(ctx context.Context, parameters ListLeaderboardsParameters) (*models.ListLeaderboardsResponse, error) {
query := url.Values{}
if parameters.Limit > 0 {
query.Set("limit", strconv.Itoa(parameters.Limit))
}
if parameters.Cursor != nil {
query.Set("cursor", *parameters.Cursor)
}
var response models.ListLeaderboardsResponse
if err := s.transport.do(ctx, http.MethodGet, "/leaderboards", query, nil, &response); err != nil {
return nil, err return nil, err
} }
return response.Entries, nil return &response, nil
}
func (s *LeaderboardsService) Submit(ctx context.Context, slug string, items []models.BatchLeaderboardEntry) error {
body := models.BatchSubmitLeaderboardEntriesRequest{
Items: items,
}
return s.transport.do(ctx, http.MethodPost, "/leaderboards/"+url.PathEscape(slug)+"/entries", nil, body, nil)
}
func (s *LeaderboardsService) Update(ctx context.Context, slug string, items []models.BatchLeaderboardEntry) error {
body := models.BatchUpdateLeaderboardEntriesRequest{
Items: items,
}
return s.transport.do(ctx, http.MethodPatch, "/leaderboards/"+url.PathEscape(slug)+"/entries", nil, body, nil)
}
func (s *LeaderboardsService) Delete(ctx context.Context, slug string, playerIDs []string) error {
body := models.BatchDeleteLeaderboardEntriesRequest{
PlayerIds: playerIDs,
}
return s.transport.do(ctx, http.MethodDelete, "/leaderboards/"+url.PathEscape(slug)+"/entries", nil, body, nil)
} }
-20
View File
@@ -1,20 +0,0 @@
package rudder
import (
"context"
"net/http"
"hub.rudder.build/rudder/rudder-go-sdk/models"
)
type MetricsService struct {
transport *transport
}
func (s *MetricsService) Get(ctx context.Context) (*models.GetProjectMetricsResponse, error) {
var response models.GetProjectMetricsResponse
if err := s.transport.do(ctx, http.MethodGet, "/metrics", nil, nil, &response); err != nil {
return nil, err
}
return &response, nil
}
+7
View File
@@ -0,0 +1,7 @@
// Code generated by apigen. DO NOT EDIT.
package models
type AdminGetProjectStorageResponse struct {
Item ProjectStorageItem `json:"item,omitempty"`
}
+8
View File
@@ -0,0 +1,8 @@
// Code generated by apigen. DO NOT EDIT.
package models
type AdminListQuestsResponse struct {
Items []QuestDefinition `json:"items,omitempty"`
NextCursor string `json:"nextCursor,omitempty"`
}
+4
View File
@@ -5,8 +5,12 @@ package models
import "encoding/json" import "encoding/json"
type AdminPlayer struct { type AdminPlayer struct {
BanReason string `json:"banReason,omitempty"`
BannedAt string `json:"bannedAt,omitempty"`
BannedUntil string `json:"bannedUntil,omitempty"`
CreatedAt string `json:"createdAt,omitempty"` CreatedAt string `json:"createdAt,omitempty"`
Data json.RawMessage `json:"data,omitempty"` Data json.RawMessage `json:"data,omitempty"`
DeletedAt string `json:"deletedAt,omitempty"`
ID string `json:"id,omitempty"` ID string `json:"id,omitempty"`
Language string `json:"language,omitempty"` Language string `json:"language,omitempty"`
LastSeen string `json:"lastSeen,omitempty"` LastSeen string `json:"lastSeen,omitempty"`
+10
View File
@@ -0,0 +1,10 @@
// Code generated by apigen. DO NOT EDIT.
package models
type AdminPlayerQuest struct {
Name string `json:"name,omitempty"`
Objectives []AdminPlayerQuestObjective `json:"objectives,omitempty"`
QuestID string `json:"questId,omitempty"`
Status string `json:"status,omitempty"`
}
+9
View File
@@ -0,0 +1,9 @@
// Code generated by apigen. DO NOT EDIT.
package models
type AdminPlayerQuestObjective struct {
Current int64 `json:"current,omitempty"`
ObjectiveID string `json:"objectiveId,omitempty"`
Target int64 `json:"target,omitempty"`
}
+11
View File
@@ -0,0 +1,11 @@
// Code generated by apigen. DO NOT EDIT.
package models
type AdminProjectStorageItem struct {
Data string `json:"data,omitempty"`
ExpiresAt string `json:"expiresAt,omitempty"`
ReadPermission string `json:"readPermission,omitempty"`
Type string `json:"type,omitempty"`
WritePermission string `json:"writePermission,omitempty"`
}
@@ -0,0 +1,10 @@
// Code generated by apigen. DO NOT EDIT.
package models
type BatchAdjustPlayerInventoryItemsItem struct {
Amount int64 `json:"amount,omitempty"`
PlayerID string `json:"playerId,omitempty"`
Reason string `json:"reason,omitempty"`
Slug string `json:"slug,omitempty"`
}
@@ -0,0 +1,8 @@
// Code generated by apigen. DO NOT EDIT.
package models
type BatchAdjustPlayerInventoryItemsRequest struct {
IdempotencyKey string `json:"idempotencyKey,omitempty"`
Items []BatchAdjustPlayerInventoryItemsItem `json:"items,omitempty"`
}
@@ -0,0 +1,7 @@
// Code generated by apigen. DO NOT EDIT.
package models
type BatchAdjustPlayerInventoryItemsResponse struct {
Items []InventoryItem `json:"items,omitempty"`
}
@@ -2,7 +2,7 @@
package models package models
type AdjustPlayerWalletRequest struct { type BatchAdjustPlayerWalletsItem struct {
Amount int64 `json:"amount,omitempty"` Amount int64 `json:"amount,omitempty"`
CurrencyCode string `json:"currencyCode,omitempty"` CurrencyCode string `json:"currencyCode,omitempty"`
PlayerID string `json:"playerId,omitempty"` PlayerID string `json:"playerId,omitempty"`
@@ -0,0 +1,8 @@
// Code generated by apigen. DO NOT EDIT.
package models
type BatchAdjustPlayerWalletsRequest struct {
IdempotencyKey string `json:"idempotencyKey,omitempty"`
Items []BatchAdjustPlayerWalletsItem `json:"items,omitempty"`
}
@@ -0,0 +1,7 @@
// Code generated by apigen. DO NOT EDIT.
package models
type BatchAdjustPlayerWalletsResponse struct {
Wallets []WalletDetails `json:"wallets,omitempty"`
}
+9
View File
@@ -0,0 +1,9 @@
// Code generated by apigen. DO NOT EDIT.
package models
type BatchBanPlayersItem struct {
BannedUntil string `json:"bannedUntil,omitempty"`
PlayerID string `json:"playerId,omitempty"`
Reason string `json:"reason,omitempty"`
}
+8
View File
@@ -0,0 +1,8 @@
// Code generated by apigen. DO NOT EDIT.
package models
type BatchBanPlayersRequest struct {
IdempotencyKey string `json:"idempotencyKey,omitempty"`
Items []BatchBanPlayersItem `json:"items,omitempty"`
}
@@ -0,0 +1,7 @@
// Code generated by apigen. DO NOT EDIT.
package models
type BatchDeleteLeaderboardEntriesRequest struct {
PlayerIds []string `json:"playerIds,omitempty"`
}
+8
View File
@@ -0,0 +1,8 @@
// Code generated by apigen. DO NOT EDIT.
package models
type BatchDeletePlayersRequest struct {
IdempotencyKey string `json:"idempotencyKey,omitempty"`
Items []BatchPlayerItem `json:"items,omitempty"`
}
+8
View File
@@ -0,0 +1,8 @@
// Code generated by apigen. DO NOT EDIT.
package models
type BatchDeletePlayerStoragesItem struct {
PlayerID string `json:"playerId,omitempty"`
Type string `json:"type,omitempty"`
}
@@ -0,0 +1,8 @@
// Code generated by apigen. DO NOT EDIT.
package models
type BatchDeletePlayerStoragesRequest struct {
IdempotencyKey string `json:"idempotencyKey,omitempty"`
Items []BatchDeletePlayerStoragesItem `json:"items,omitempty"`
}
@@ -0,0 +1,8 @@
// Code generated by apigen. DO NOT EDIT.
package models
type BatchDeleteProjectStorageRequest struct {
IdempotencyKey string `json:"idempotencyKey,omitempty"`
Types []string `json:"types,omitempty"`
}
+8
View File
@@ -0,0 +1,8 @@
// Code generated by apigen. DO NOT EDIT.
package models
type BatchLeaderboardEntry struct {
PlayerID string `json:"playerId,omitempty"`
Score float64 `json:"score,omitempty"`
}
+7
View File
@@ -0,0 +1,7 @@
// Code generated by apigen. DO NOT EDIT.
package models
type BatchPlayerItem struct {
PlayerID string `json:"playerId,omitempty"`
}
+8
View File
@@ -0,0 +1,8 @@
// Code generated by apigen. DO NOT EDIT.
package models
type BatchPlayerQuestsItem struct {
PlayerID string `json:"playerId,omitempty"`
QuestID string `json:"questId,omitempty"`
}
+8
View File
@@ -0,0 +1,8 @@
// Code generated by apigen. DO NOT EDIT.
package models
type BatchPlayerQuestsRequest struct {
IdempotencyKey string `json:"idempotencyKey,omitempty"`
Items []BatchPlayerQuestsItem `json:"items,omitempty"`
}
+7
View File
@@ -0,0 +1,7 @@
// Code generated by apigen. DO NOT EDIT.
package models
type BatchPlayersResponse struct {
Players []AdminPlayer `json:"players,omitempty"`
}
@@ -0,0 +1,7 @@
// Code generated by apigen. DO NOT EDIT.
package models
type BatchSubmitLeaderboardEntriesRequest struct {
Items []BatchLeaderboardEntry `json:"items,omitempty"`
}
+8
View File
@@ -0,0 +1,8 @@
// Code generated by apigen. DO NOT EDIT.
package models
type BatchUnbanPlayersRequest struct {
IdempotencyKey string `json:"idempotencyKey,omitempty"`
Items []BatchPlayerItem `json:"items,omitempty"`
}
@@ -0,0 +1,7 @@
// Code generated by apigen. DO NOT EDIT.
package models
type BatchUpdateLeaderboardEntriesRequest struct {
Items []BatchLeaderboardEntry `json:"items,omitempty"`
}
+11
View File
@@ -0,0 +1,11 @@
// Code generated by apigen. DO NOT EDIT.
package models
import "encoding/json"
type BatchUpdatePlayersItem struct {
Data json.RawMessage `json:"data,omitempty"`
Nickname string `json:"nickname,omitempty"`
PlayerID string `json:"playerId,omitempty"`
}
+8
View File
@@ -0,0 +1,8 @@
// Code generated by apigen. DO NOT EDIT.
package models
type BatchUpdatePlayersRequest struct {
IdempotencyKey string `json:"idempotencyKey,omitempty"`
Items []BatchUpdatePlayersItem `json:"items,omitempty"`
}
+10
View File
@@ -0,0 +1,10 @@
// Code generated by apigen. DO NOT EDIT.
package models
type BatchUpsertPlayerStoragesItem struct {
Data string `json:"data,omitempty"`
ExpiresAt string `json:"expiresAt,omitempty"`
PlayerID string `json:"playerId,omitempty"`
Type string `json:"type,omitempty"`
}
@@ -0,0 +1,8 @@
// Code generated by apigen. DO NOT EDIT.
package models
type BatchUpsertPlayerStoragesRequest struct {
IdempotencyKey string `json:"idempotencyKey,omitempty"`
Items []BatchUpsertPlayerStoragesItem `json:"items,omitempty"`
}
@@ -0,0 +1,7 @@
// Code generated by apigen. DO NOT EDIT.
package models
type BatchUpsertPlayerStoragesResponse struct {
Storages []PlayerStorage `json:"storages,omitempty"`
}
@@ -0,0 +1,8 @@
// Code generated by apigen. DO NOT EDIT.
package models
type BatchUpsertProjectStorageRequest struct {
IdempotencyKey string `json:"idempotencyKey,omitempty"`
Items []AdminProjectStorageItem `json:"items,omitempty"`
}
+11
View File
@@ -0,0 +1,11 @@
// Code generated by apigen. DO NOT EDIT.
package models
type ErrorResponse struct {
Code string `json:"code,omitempty"`
Error string `json:"error,omitempty"`
Index int `json:"index,omitempty"`
PlayerID string `json:"playerId,omitempty"`
RequestID string `json:"requestId,omitempty"`
}
@@ -2,6 +2,6 @@
package models package models
type GetLeaderboardResultsResponse struct { type GetLeaderboardEntryAroundResponse struct {
Entries []RankEntry `json:"entries,omitempty"` Entries []RankEntry `json:"entries,omitempty"`
} }
@@ -2,7 +2,7 @@
package models package models
type ListUgcResponse struct { type GetPlayerInventoryResponse struct {
Items []UgcSubmission `json:"items,omitempty"` Items []InventoryItem `json:"items,omitempty"`
NextCursor string `json:"nextCursor,omitempty"` NextCursor string `json:"nextCursor,omitempty"`
} }
+8
View File
@@ -0,0 +1,8 @@
// Code generated by apigen. DO NOT EDIT.
package models
type GetProjectStorageResponse struct {
Items []ProjectStorageItem `json:"items,omitempty"`
NextCursor string `json:"nextCursor,omitempty"`
}
+8
View File
@@ -0,0 +1,8 @@
// Code generated by apigen. DO NOT EDIT.
package models
type GetWalletHistoryResponse struct {
Entries []WalletAudit `json:"entries,omitempty"`
NextCursor string `json:"nextCursor,omitempty"`
}
+12
View File
@@ -0,0 +1,12 @@
// Code generated by apigen. DO NOT EDIT.
package models
type LeaderboardDefinition struct {
MaxEntries int64 `json:"maxEntries,omitempty"`
Metric string `json:"metric,omitempty"`
Name string `json:"name,omitempty"`
ResetPeriod string `json:"resetPeriod,omitempty"`
Slug string `json:"slug,omitempty"`
SortingOrder string `json:"sortingOrder,omitempty"`
}
+8
View File
@@ -0,0 +1,8 @@
// Code generated by apigen. DO NOT EDIT.
package models
type ListLeaderboardEntriesResponse struct {
Entries []RankEntry `json:"entries,omitempty"`
NextCursor string `json:"nextCursor,omitempty"`
}
+8
View File
@@ -0,0 +1,8 @@
// Code generated by apigen. DO NOT EDIT.
package models
type ListLeaderboardsResponse struct {
Items []LeaderboardDefinition `json:"items,omitempty"`
NextCursor string `json:"nextCursor,omitempty"`
}
+7
View File
@@ -0,0 +1,7 @@
// Code generated by apigen. DO NOT EDIT.
package models
type ListPlayerQuestsResponse struct {
Quests []AdminPlayerQuest `json:"quests,omitempty"`
}
+15
View File
@@ -0,0 +1,15 @@
// Code generated by apigen. DO NOT EDIT.
package models
type ProjectStorageItem struct {
Data string `json:"data,omitempty"`
ExpiresAt string `json:"expiresAt,omitempty"`
ID string `json:"id,omitempty"`
ReadPermission string `json:"readPermission,omitempty"`
Size int64 `json:"size,omitempty"`
Type string `json:"type,omitempty"`
UpdatedAt string `json:"updatedAt,omitempty"`
Version int64 `json:"version,omitempty"`
WritePermission string `json:"writePermission,omitempty"`
}
+12
View File
@@ -0,0 +1,12 @@
// Code generated by apigen. DO NOT EDIT.
package models
type QuestDefinition struct {
ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
NextQuestID string `json:"nextQuestId,omitempty"`
Objectives []QuestObjective `json:"objectives,omitempty"`
Rewards []QuestRewardDefinition `json:"rewards,omitempty"`
Status string `json:"status,omitempty"`
}
+9
View File
@@ -0,0 +1,9 @@
// Code generated by apigen. DO NOT EDIT.
package models
type QuestObjective struct {
ID string `json:"id,omitempty"`
Metric string `json:"metric,omitempty"`
Target int64 `json:"target,omitempty"`
}
+9
View File
@@ -0,0 +1,9 @@
// Code generated by apigen. DO NOT EDIT.
package models
type QuestRewardDefinition struct {
Amount int64 `json:"amount,omitempty"`
Currency string `json:"currency,omitempty"`
ItemID string `json:"itemId,omitempty"`
}
-9
View File
@@ -1,9 +0,0 @@
// Code generated by apigen. DO NOT EDIT.
package models
type ReviewUgcRequest struct {
ID string `json:"id,omitempty"`
ReviewedBy string `json:"reviewedBy,omitempty"`
Status string `json:"status,omitempty"`
}
-8
View File
@@ -1,8 +0,0 @@
// Code generated by apigen. DO NOT EDIT.
package models
type SubmittedBy struct {
UserID string `json:"userId,omitempty"`
Username string `json:"username,omitempty"`
}
-19
View File
@@ -1,19 +0,0 @@
// Code generated by apigen. DO NOT EDIT.
package models
import "encoding/json"
type UgcSubmission struct {
Description string `json:"description,omitempty"`
FileSize int64 `json:"fileSize,omitempty"`
FileURL string `json:"fileUrl,omitempty"`
ID string `json:"id,omitempty"`
Metadata json.RawMessage `json:"metadata,omitempty"`
Name string `json:"name,omitempty"`
ReviewedAt string `json:"reviewedAt,omitempty"`
ReviewedBy string `json:"reviewedBy,omitempty"`
Status string `json:"status,omitempty"`
SubmittedAt string `json:"submittedAt,omitempty"`
SubmittedBy SubmittedBy `json:"submittedBy,omitempty"`
}
-10
View File
@@ -1,10 +0,0 @@
// Code generated by apigen. DO NOT EDIT.
package models
import "encoding/json"
type UpdateUgcMetadataRequest struct {
ID string `json:"id,omitempty"`
Metadata json.RawMessage `json:"metadata,omitempty"`
}
+93
View File
@@ -0,0 +1,93 @@
package rudder
import (
"context"
"encoding/json"
"hub.rudder.build/rudder/rudder-go-sdk/models"
)
type PlayerHandle struct {
playerID string
transport *transport
players *PlayersService
wallet *WalletService
inventory *InventoryService
quests *QuestsService
}
func (h *PlayerHandle) Wallet() *PlayerWalletHandle {
return &PlayerWalletHandle{playerID: h.playerID, wallet: h.wallet}
}
func (h *PlayerHandle) Inventory() *PlayerInventoryHandle {
return &PlayerInventoryHandle{playerID: h.playerID, inventory: h.inventory}
}
func (h *PlayerHandle) Storage() *PlayerStorageHandle {
return &PlayerStorageHandle{playerID: h.playerID, transport: h.transport}
}
func (h *PlayerHandle) Quests() *PlayerQuestsHandle {
return &PlayerQuestsHandle{playerID: h.playerID, transport: h.transport, quests: h.quests}
}
type UpdatePlayerParameters struct {
IdempotencyKey string
Nickname string
Data json.RawMessage
}
func (h *PlayerHandle) Update(ctx context.Context, parameters UpdatePlayerParameters) (*models.AdminPlayer, error) {
players, err := h.players.Update(ctx, UpdatePlayersParameters{
IdempotencyKey: parameters.IdempotencyKey,
Items: []models.BatchUpdatePlayersItem{{
PlayerID: h.playerID,
Nickname: parameters.Nickname,
Data: parameters.Data,
}},
})
if err != nil {
return nil, err
}
return &players[0], nil
}
type BanPlayerParameters struct {
IdempotencyKey string
Reason string
BannedUntil string
}
func (h *PlayerHandle) Ban(ctx context.Context, parameters BanPlayerParameters) (*models.AdminPlayer, error) {
players, err := h.players.Ban(ctx, BanPlayersParameters{
IdempotencyKey: parameters.IdempotencyKey,
Items: []models.BatchBanPlayersItem{{
PlayerID: h.playerID,
Reason: parameters.Reason,
BannedUntil: parameters.BannedUntil,
}},
})
if err != nil {
return nil, err
}
return &players[0], nil
}
func (h *PlayerHandle) Unban(ctx context.Context, idempotencyKey string) (*models.AdminPlayer, error) {
players, err := h.players.Unban(ctx, UnbanPlayersParameters{
IdempotencyKey: idempotencyKey,
Items: []models.BatchPlayerItem{{PlayerID: h.playerID}},
})
if err != nil {
return nil, err
}
return &players[0], nil
}
func (h *PlayerHandle) Delete(ctx context.Context, idempotencyKey string) error {
return h.players.Delete(ctx, DeletePlayersParameters{
IdempotencyKey: idempotencyKey,
Items: []models.BatchPlayerItem{{PlayerID: h.playerID}},
})
}
+39
View File
@@ -0,0 +1,39 @@
package rudder
import (
"context"
"hub.rudder.build/rudder/rudder-go-sdk/models"
)
type PlayerInventoryHandle struct {
playerID string
inventory *InventoryService
}
type AdjustPlayerInventoryParameters struct {
IdempotencyKey string
Slug string
Amount int64
Reason string
}
func (h *PlayerInventoryHandle) Adjust(ctx context.Context, parameters AdjustPlayerInventoryParameters) (*models.InventoryItem, error) {
items, err := h.inventory.Adjust(ctx, AdjustInventoryParameters{
IdempotencyKey: parameters.IdempotencyKey,
Items: []models.BatchAdjustPlayerInventoryItemsItem{{
PlayerID: h.playerID,
Slug: parameters.Slug,
Amount: parameters.Amount,
Reason: parameters.Reason,
}},
})
if err != nil {
return nil, err
}
return &items[0], nil
}
func (h *PlayerInventoryHandle) List(ctx context.Context, parameters ListInventoryParameters) (*models.GetPlayerInventoryResponse, error) {
return h.inventory.List(ctx, h.playerID, parameters)
}
+49
View File
@@ -0,0 +1,49 @@
package rudder
import (
"context"
"net/http"
"net/url"
"hub.rudder.build/rudder/rudder-go-sdk/models"
)
type PlayerQuestsHandle struct {
playerID string
transport *transport
quests *QuestsService
}
func (h *PlayerQuestsHandle) List(ctx context.Context) ([]models.AdminPlayerQuest, error) {
var response models.ListPlayerQuestsResponse
if err := h.transport.do(ctx, http.MethodGet, "/players/"+url.PathEscape(h.playerID)+"/quests", nil, nil, &response); err != nil {
return nil, err
}
return response.Quests, nil
}
type PlayerQuestParameters struct {
IdempotencyKey string
QuestID string
}
func (h *PlayerQuestsHandle) Reset(ctx context.Context, parameters PlayerQuestParameters) error {
return h.quests.Reset(ctx, ResetPlayerQuestsParameters{
IdempotencyKey: parameters.IdempotencyKey,
Items: []models.BatchPlayerQuestsItem{{PlayerID: h.playerID, QuestID: parameters.QuestID}},
})
}
func (h *PlayerQuestsHandle) ForceComplete(ctx context.Context, parameters PlayerQuestParameters) error {
return h.quests.ForceComplete(ctx, ForceCompletePlayerQuestsParameters{
IdempotencyKey: parameters.IdempotencyKey,
Items: []models.BatchPlayerQuestsItem{{PlayerID: h.playerID, QuestID: parameters.QuestID}},
})
}
func (h *PlayerQuestsHandle) ForceClaim(ctx context.Context, parameters PlayerQuestParameters) error {
return h.quests.ForceClaim(ctx, ForceClaimPlayerQuestsParameters{
IdempotencyKey: parameters.IdempotencyKey,
Items: []models.BatchPlayerQuestsItem{{PlayerID: h.playerID, QuestID: parameters.QuestID}},
})
}
+63
View File
@@ -0,0 +1,63 @@
package rudder
import (
"context"
"net/http"
"net/url"
"hub.rudder.build/rudder/rudder-go-sdk/models"
)
type PlayerStorageHandle struct {
playerID string
transport *transport
}
func (h *PlayerStorageHandle) Get(ctx context.Context, storageType string) (*models.PlayerStorage, error) {
var response models.PlayerStorage
if err := h.transport.do(ctx, http.MethodGet, "/players/"+url.PathEscape(h.playerID)+"/storage/"+url.PathEscape(storageType), nil, nil, &response); err != nil {
return nil, err
}
return &response, nil
}
type UpsertPlayerStorageParameters struct {
IdempotencyKey string
Type string
Data string
ExpiresAt string
}
func (h *PlayerStorageHandle) Upsert(ctx context.Context, parameters UpsertPlayerStorageParameters) (*models.PlayerStorage, error) {
body := models.BatchUpsertPlayerStoragesRequest{
IdempotencyKey: parameters.IdempotencyKey,
Items: []models.BatchUpsertPlayerStoragesItem{{
PlayerID: h.playerID,
Type: parameters.Type,
Data: parameters.Data,
ExpiresAt: parameters.ExpiresAt,
}},
}
var response models.BatchUpsertPlayerStoragesResponse
if err := h.transport.do(ctx, http.MethodPut, "/players/storage", nil, body, &response); err != nil {
return nil, err
}
return &response.Storages[0], nil
}
type DeletePlayerStorageParameters struct {
IdempotencyKey string
Type string
}
func (h *PlayerStorageHandle) Delete(ctx context.Context, parameters DeletePlayerStorageParameters) error {
body := models.BatchDeletePlayerStoragesRequest{
IdempotencyKey: parameters.IdempotencyKey,
Items: []models.BatchDeletePlayerStoragesItem{{
PlayerID: h.playerID,
Type: parameters.Type,
}},
}
return h.transport.do(ctx, http.MethodDelete, "/players/storage", nil, body, nil)
}
+39
View File
@@ -0,0 +1,39 @@
package rudder
import (
"context"
"hub.rudder.build/rudder/rudder-go-sdk/models"
)
type PlayerWalletHandle struct {
playerID string
wallet *WalletService
}
type AdjustPlayerWalletParameters struct {
IdempotencyKey string
CurrencyCode string
Amount int64
Reason string
}
func (h *PlayerWalletHandle) Adjust(ctx context.Context, parameters AdjustPlayerWalletParameters) (*models.WalletDetails, error) {
wallets, err := h.wallet.Adjust(ctx, AdjustWalletParameters{
IdempotencyKey: parameters.IdempotencyKey,
Items: []models.BatchAdjustPlayerWalletsItem{{
PlayerID: h.playerID,
CurrencyCode: parameters.CurrencyCode,
Amount: parameters.Amount,
Reason: parameters.Reason,
}},
})
if err != nil {
return nil, err
}
return &wallets[0], nil
}
func (h *PlayerWalletHandle) History(ctx context.Context, parameters WalletHistoryParameters) (*models.GetWalletHistoryResponse, error) {
return h.wallet.History(ctx, h.playerID, parameters)
}
+71
View File
@@ -16,6 +16,7 @@ type PlayersService struct {
type ListPlayersParameters struct { type ListPlayersParameters struct {
Limit int Limit int
Offset int Offset int
Search string
} }
func (s *PlayersService) List(ctx context.Context, parameters ListPlayersParameters) (*models.ListPlayersResponse, error) { func (s *PlayersService) List(ctx context.Context, parameters ListPlayersParameters) (*models.ListPlayersResponse, error) {
@@ -26,6 +27,9 @@ func (s *PlayersService) List(ctx context.Context, parameters ListPlayersParamet
if parameters.Offset > 0 { if parameters.Offset > 0 {
query.Set("offset", strconv.Itoa(parameters.Offset)) query.Set("offset", strconv.Itoa(parameters.Offset))
} }
if parameters.Search != "" {
query.Set("search", parameters.Search)
}
var response models.ListPlayersResponse var response models.ListPlayersResponse
if err := s.transport.do(ctx, http.MethodGet, "/players/list", query, nil, &response); err != nil { if err := s.transport.do(ctx, http.MethodGet, "/players/list", query, nil, &response); err != nil {
@@ -41,3 +45,70 @@ func (s *PlayersService) Get(ctx context.Context, playerID string) (*models.Admi
} }
return &response, nil return &response, nil
} }
type UpdatePlayersParameters struct {
IdempotencyKey string
Items []models.BatchUpdatePlayersItem
}
func (s *PlayersService) Update(ctx context.Context, parameters UpdatePlayersParameters) ([]models.AdminPlayer, error) {
body := models.BatchUpdatePlayersRequest{
IdempotencyKey: parameters.IdempotencyKey,
Items: parameters.Items,
}
var response models.BatchPlayersResponse
if err := s.transport.do(ctx, http.MethodPatch, "/players", nil, body, &response); err != nil {
return nil, err
}
return response.Players, nil
}
type BanPlayersParameters struct {
IdempotencyKey string
Items []models.BatchBanPlayersItem
}
func (s *PlayersService) Ban(ctx context.Context, parameters BanPlayersParameters) ([]models.AdminPlayer, error) {
body := models.BatchBanPlayersRequest{
IdempotencyKey: parameters.IdempotencyKey,
Items: parameters.Items,
}
var response models.BatchPlayersResponse
if err := s.transport.do(ctx, http.MethodPost, "/players/ban", nil, body, &response); err != nil {
return nil, err
}
return response.Players, nil
}
type UnbanPlayersParameters struct {
IdempotencyKey string
Items []models.BatchPlayerItem
}
func (s *PlayersService) Unban(ctx context.Context, parameters UnbanPlayersParameters) ([]models.AdminPlayer, error) {
body := models.BatchUnbanPlayersRequest{
IdempotencyKey: parameters.IdempotencyKey,
Items: parameters.Items,
}
var response models.BatchPlayersResponse
if err := s.transport.do(ctx, http.MethodPost, "/players/unban", nil, body, &response); err != nil {
return nil, err
}
return response.Players, nil
}
type DeletePlayersParameters struct {
IdempotencyKey string
Items []models.BatchPlayerItem
}
func (s *PlayersService) Delete(ctx context.Context, parameters DeletePlayersParameters) error {
body := models.BatchDeletePlayersRequest{
IdempotencyKey: parameters.IdempotencyKey,
Items: parameters.Items,
}
return s.transport.do(ctx, http.MethodDelete, "/players", nil, body, nil)
}
+78
View File
@@ -0,0 +1,78 @@
package rudder
import (
"context"
"net/http"
"net/url"
"strconv"
"hub.rudder.build/rudder/rudder-go-sdk/models"
)
type QuestsService struct {
transport *transport
}
type ListQuestsParameters struct {
Status *string
Limit int
Cursor *string
}
func (s *QuestsService) List(ctx context.Context, parameters ListQuestsParameters) (*models.AdminListQuestsResponse, error) {
query := url.Values{}
if parameters.Status != nil {
query.Set("status", *parameters.Status)
}
if parameters.Limit > 0 {
query.Set("limit", strconv.Itoa(parameters.Limit))
}
if parameters.Cursor != nil {
query.Set("cursor", *parameters.Cursor)
}
var response models.AdminListQuestsResponse
if err := s.transport.do(ctx, http.MethodGet, "/quests", query, nil, &response); err != nil {
return nil, err
}
return &response, nil
}
type ResetPlayerQuestsParameters struct {
IdempotencyKey string
Items []models.BatchPlayerQuestsItem
}
func (s *QuestsService) Reset(ctx context.Context, parameters ResetPlayerQuestsParameters) error {
body := models.BatchPlayerQuestsRequest{
IdempotencyKey: parameters.IdempotencyKey,
Items: parameters.Items,
}
return s.transport.do(ctx, http.MethodPost, "/players/quests/reset", nil, body, nil)
}
type ForceCompletePlayerQuestsParameters struct {
IdempotencyKey string
Items []models.BatchPlayerQuestsItem
}
func (s *QuestsService) ForceComplete(ctx context.Context, parameters ForceCompletePlayerQuestsParameters) error {
body := models.BatchPlayerQuestsRequest{
IdempotencyKey: parameters.IdempotencyKey,
Items: parameters.Items,
}
return s.transport.do(ctx, http.MethodPost, "/players/quests/force-complete", nil, body, nil)
}
type ForceClaimPlayerQuestsParameters struct {
IdempotencyKey string
Items []models.BatchPlayerQuestsItem
}
func (s *QuestsService) ForceClaim(ctx context.Context, parameters ForceClaimPlayerQuestsParameters) error {
body := models.BatchPlayerQuestsRequest{
IdempotencyKey: parameters.IdempotencyKey,
Items: parameters.Items,
}
return s.transport.do(ctx, http.MethodPost, "/players/quests/force-claim", nil, body, nil)
}
+73
View File
@@ -0,0 +1,73 @@
package rudder
import (
"context"
"net/http"
"net/url"
"strconv"
"hub.rudder.build/rudder/rudder-go-sdk/models"
)
type StorageService struct {
transport *transport
}
type ListStorageParameters struct {
Limit int
Cursor string
Search string
}
func (s *StorageService) List(ctx context.Context, parameters ListStorageParameters) (*models.GetProjectStorageResponse, error) {
query := url.Values{}
if parameters.Limit > 0 {
query.Set("limit", strconv.Itoa(parameters.Limit))
}
if parameters.Cursor != "" {
query.Set("cursor", parameters.Cursor)
}
if parameters.Search != "" {
query.Set("search", parameters.Search)
}
var response models.GetProjectStorageResponse
if err := s.transport.do(ctx, http.MethodGet, "/project-storage", query, nil, &response); err != nil {
return nil, err
}
return &response, nil
}
func (s *StorageService) Get(ctx context.Context, itemType string) (*models.ProjectStorageItem, error) {
var response models.AdminGetProjectStorageResponse
if err := s.transport.do(ctx, http.MethodGet, "/project-storage/"+url.PathEscape(itemType), nil, nil, &response); err != nil {
return nil, err
}
return &response.Item, nil
}
type UpsertStorageParameters struct {
IdempotencyKey string
Items []models.AdminProjectStorageItem
}
func (s *StorageService) Upsert(ctx context.Context, parameters UpsertStorageParameters) error {
body := models.BatchUpsertProjectStorageRequest{
IdempotencyKey: parameters.IdempotencyKey,
Items: parameters.Items,
}
return s.transport.do(ctx, http.MethodPut, "/project-storage", nil, body, nil)
}
type DeleteStorageParameters struct {
IdempotencyKey string
Types []string
}
func (s *StorageService) Delete(ctx context.Context, parameters DeleteStorageParameters) error {
body := models.BatchDeleteProjectStorageRequest{
IdempotencyKey: parameters.IdempotencyKey,
Types: parameters.Types,
}
return s.transport.do(ctx, http.MethodDelete, "/project-storage", nil, body, nil)
}
+1 -2
View File
@@ -14,12 +14,11 @@ import (
type transport struct { type transport struct {
baseURL string baseURL string
apiKey string apiKey string
projectID string
httpClient *http.Client httpClient *http.Client
} }
func (t *transport) do(ctx context.Context, method, path string, query url.Values, body any, out any) error { func (t *transport) do(ctx context.Context, method, path string, query url.Values, body any, out any) error {
endpoint := strings.TrimSuffix(t.baseURL, "/") + "/game/v1/projects/" + t.projectID + path endpoint := strings.TrimSuffix(t.baseURL, "/") + "/game/v1" + path
if len(query) > 0 { if len(query) > 0 {
endpoint += "?" + query.Encode() endpoint += "?" + query.Encode()
} }
-72
View File
@@ -1,72 +0,0 @@
package rudder
import (
"context"
"encoding/json"
"net/http"
"net/url"
"strconv"
"hub.rudder.build/rudder/rudder-go-sdk/models"
)
type UgcService struct {
transport *transport
}
type ListUgcParameters struct {
Status string
Limit int
Cursor string
}
func (s *UgcService) List(ctx context.Context, parameters ListUgcParameters) (*models.ListUgcResponse, error) {
query := url.Values{}
if parameters.Status != "" {
query.Set("status", parameters.Status)
}
if parameters.Limit > 0 {
query.Set("limit", strconv.Itoa(parameters.Limit))
}
if parameters.Cursor != "" {
query.Set("cursor", parameters.Cursor)
}
var response models.ListUgcResponse
if err := s.transport.do(ctx, http.MethodGet, "/ugc", query, nil, &response); err != nil {
return nil, err
}
return &response, nil
}
func (s *UgcService) UpdateMetadata(ctx context.Context, id string, metadata json.RawMessage) (*models.UgcSubmission, error) {
body := models.UpdateUgcMetadataRequest{
ID: id,
Metadata: metadata,
}
var response models.UgcSubmission
if err := s.transport.do(ctx, http.MethodPatch, "/ugc/"+url.PathEscape(id)+"/metadata", nil, body, &response); err != nil {
return nil, err
}
return &response, nil
}
type ReviewUgcParameters struct {
Status string
ReviewedBy string
}
func (s *UgcService) Review(ctx context.Context, id string, parameters ReviewUgcParameters) (*models.UgcSubmission, error) {
body := models.ReviewUgcRequest{
ID: id,
Status: parameters.Status,
ReviewedBy: parameters.ReviewedBy,
}
var response models.UgcSubmission
if err := s.transport.do(ctx, http.MethodPost, "/ugc/"+url.PathEscape(id)+"/review", nil, body, &response); err != nil {
return nil, err
}
return &response, nil
}
+34 -11
View File
@@ -4,6 +4,7 @@ import (
"context" "context"
"net/http" "net/http"
"net/url" "net/url"
"strconv"
"hub.rudder.build/rudder/rudder-go-sdk/models" "hub.rudder.build/rudder/rudder-go-sdk/models"
) )
@@ -13,21 +14,43 @@ type WalletService struct {
} }
type AdjustWalletParameters struct { type AdjustWalletParameters struct {
CurrencyCode string IdempotencyKey string
Amount int64 Items []models.BatchAdjustPlayerWalletsItem
Reason string
} }
func (s *WalletService) Adjust(ctx context.Context, playerID string, parameters AdjustWalletParameters) (*models.WalletDetails, error) { func (s *WalletService) Adjust(ctx context.Context, parameters AdjustWalletParameters) ([]models.WalletDetails, error) {
body := models.AdjustPlayerWalletRequest{ body := models.BatchAdjustPlayerWalletsRequest{
PlayerID: playerID, IdempotencyKey: parameters.IdempotencyKey,
CurrencyCode: parameters.CurrencyCode, Items: parameters.Items,
Amount: parameters.Amount,
Reason: parameters.Reason,
} }
var response models.WalletDetails var response models.BatchAdjustPlayerWalletsResponse
if err := s.transport.do(ctx, http.MethodPost, "/players/"+url.PathEscape(playerID)+"/wallet/adjust", nil, body, &response); err != nil { if err := s.transport.do(ctx, http.MethodPost, "/players/wallet/adjust", nil, body, &response); err != nil {
return nil, err
}
return response.Wallets, nil
}
type WalletHistoryParameters struct {
Currency *string
Limit int
Cursor *string
}
func (s *WalletService) History(ctx context.Context, playerID string, parameters WalletHistoryParameters) (*models.GetWalletHistoryResponse, error) {
query := url.Values{}
if parameters.Currency != nil {
query.Set("currency", *parameters.Currency)
}
if parameters.Limit > 0 {
query.Set("limit", strconv.Itoa(parameters.Limit))
}
if parameters.Cursor != nil {
query.Set("cursor", *parameters.Cursor)
}
var response models.GetWalletHistoryResponse
if err := s.transport.do(ctx, http.MethodGet, "/players/"+url.PathEscape(playerID)+"/wallet/history", query, nil, &response); err != nil {
return nil, err return nil, err
} }
return &response, nil return &response, nil