Initial commit
This commit is contained in:
Generated
+10
@@ -0,0 +1,10 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Ignored default folder with query files
|
||||
/queries/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
Generated
+11
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GoImports">
|
||||
<option name="excludedPackages">
|
||||
<array>
|
||||
<option value="github.com/pkg/errors" />
|
||||
<option value="golang.org/x/net/context" />
|
||||
</array>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
Generated
+9
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="WEB_MODULE" version="4">
|
||||
<component name="Go" enabled="true" />
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
Generated
+4
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="KubernetesApiProvider">{}</component>
|
||||
</project>
|
||||
Generated
+8
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/liveops-go-sdk.iml" filepath="$PROJECT_DIR$/.idea/liveops-go-sdk.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
Generated
+6
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,55 @@
|
||||
# liveops-go-sdk
|
||||
|
||||
Серверный Go SDK для LiveOps-платформы Rudder. Покрывает server-admin
|
||||
поверхность `/game/v1` (auth по `X-API-Key`, ключ — `GAME_ADMIN_API_KEY`
|
||||
на gateway).
|
||||
|
||||
## 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@latest
|
||||
```
|
||||
|
||||
Требуется Go 1.25+. Токен не нужен — репозиторий публичный.
|
||||
|
||||
## Usage
|
||||
|
||||
```go
|
||||
client, err := rudder.New(rudder.Config{
|
||||
APIKey: os.Getenv("GAME_ADMIN_API_KEY"),
|
||||
ProjectID: "your-project-id",
|
||||
})
|
||||
if err != nil {
|
||||
// *rudder.APIError с кодом sdk/invalid-options
|
||||
}
|
||||
|
||||
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{
|
||||
CurrencyCode: "coins",
|
||||
Amount: 100,
|
||||
Reason: "compensation",
|
||||
})
|
||||
metrics, err := client.Metrics.Get(ctx)
|
||||
page, err := client.Ugc.List(ctx, rudder.ListUgcParameters{Status: "pending"})
|
||||
```
|
||||
|
||||
## Ошибки
|
||||
|
||||
```go
|
||||
var apiErr *rudder.APIError
|
||||
if errors.As(err, &apiErr) {
|
||||
apiErr.Status // HTTP status
|
||||
apiErr.Code // машинный код, константы в models.ErrorCode*
|
||||
apiErr.RequestID // корреляция с логами gateway
|
||||
}
|
||||
```
|
||||
|
||||
## Генерация
|
||||
|
||||
`models/` генерируется apigen'ом из `liveops-gateway/openapi.yaml`
|
||||
(`make generate-openapi` в liveops-gateway). Руками не править.
|
||||
@@ -0,0 +1,58 @@
|
||||
package rudder
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
const DefaultBaseURL = "https://api.rudder.build"
|
||||
|
||||
type Config struct {
|
||||
APIKey string
|
||||
ProjectID string
|
||||
BaseURL string
|
||||
Timeout time.Duration
|
||||
HTTPClient *http.Client
|
||||
}
|
||||
|
||||
type Client struct {
|
||||
Players *PlayersService
|
||||
Metrics *MetricsService
|
||||
Leaderboards *LeaderboardsService
|
||||
Wallet *WalletService
|
||||
Ugc *UgcService
|
||||
}
|
||||
|
||||
func New(config Config) (*Client, error) {
|
||||
if config.APIKey == "" {
|
||||
return nil, &APIError{Code: ErrorCodeInvalidOptions, Message: "APIKey is required"}
|
||||
}
|
||||
if config.ProjectID == "" {
|
||||
return nil, &APIError{Code: ErrorCodeInvalidOptions, Message: "ProjectID is required"}
|
||||
}
|
||||
|
||||
if config.BaseURL == "" {
|
||||
config.BaseURL = DefaultBaseURL
|
||||
}
|
||||
if config.Timeout == 0 {
|
||||
config.Timeout = 30 * time.Second
|
||||
}
|
||||
if config.HTTPClient == nil {
|
||||
config.HTTPClient = &http.Client{Timeout: config.Timeout}
|
||||
}
|
||||
|
||||
transport := &transport{
|
||||
baseURL: config.BaseURL,
|
||||
apiKey: config.APIKey,
|
||||
projectID: config.ProjectID,
|
||||
httpClient: config.HTTPClient,
|
||||
}
|
||||
|
||||
return &Client{
|
||||
Players: &PlayersService{transport: transport},
|
||||
Metrics: &MetricsService{transport: transport},
|
||||
Leaderboards: &LeaderboardsService{transport: transport},
|
||||
Wallet: &WalletService{transport: transport},
|
||||
Ugc: &UgcService{transport: transport},
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package rudder
|
||||
|
||||
import "fmt"
|
||||
|
||||
const ErrorCodeInvalidOptions = "sdk/invalid-options"
|
||||
|
||||
type APIError struct {
|
||||
Status int
|
||||
Code string
|
||||
Message string
|
||||
RequestID string
|
||||
}
|
||||
|
||||
func (e *APIError) Error() string {
|
||||
if e.RequestID != "" {
|
||||
return fmt.Sprintf("rudder: status %d, code %q: %s (request %s)", e.Status, e.Code, e.Message, e.RequestID)
|
||||
}
|
||||
return fmt.Sprintf("rudder: status %d, code %q: %s", e.Status, e.Code, e.Message)
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package rudder
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"hub.rudder.build/rudder/rudder-go-sdk/models"
|
||||
)
|
||||
|
||||
type LeaderboardsService struct {
|
||||
transport *transport
|
||||
}
|
||||
|
||||
func (s *LeaderboardsService) Results(ctx context.Context, slug string) ([]models.RankEntry, error) {
|
||||
var response models.GetLeaderboardResultsResponse
|
||||
if err := s.transport.do(ctx, http.MethodGet, "/leaderboards/"+url.PathEscape(slug)+"/results", nil, nil, &response); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return response.Entries, nil
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
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
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// Code generated by apigen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
type AdjustPlayerWalletRequest struct {
|
||||
Amount int64 `json:"amount,omitempty"`
|
||||
CurrencyCode string `json:"currencyCode,omitempty"`
|
||||
PlayerID string `json:"playerId,omitempty"`
|
||||
Reason string `json:"reason,omitempty"`
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// Code generated by apigen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
type AdminPlayer struct {
|
||||
CreatedAt string `json:"createdAt,omitempty"`
|
||||
Data json.RawMessage `json:"data,omitempty"`
|
||||
ID string `json:"id,omitempty"`
|
||||
Language string `json:"language,omitempty"`
|
||||
LastSeen string `json:"lastSeen,omitempty"`
|
||||
Nickname string `json:"nickname,omitempty"`
|
||||
PayerFlag bool `json:"payerFlag,omitempty"`
|
||||
ProjectID string `json:"projectId,omitempty"`
|
||||
Region string `json:"region,omitempty"`
|
||||
StableID string `json:"stableId,omitempty"`
|
||||
UpdatedAt string `json:"updatedAt,omitempty"`
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// Code generated by apigen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
type AdminPlayerDetails struct {
|
||||
Inventory []InventoryItem `json:"inventory,omitempty"`
|
||||
Player AdminPlayer `json:"player,omitempty"`
|
||||
Storages []PlayerStorage `json:"storages,omitempty"`
|
||||
WalletTransactions []WalletAudit `json:"walletTransactions,omitempty"`
|
||||
Wallets []WalletDetails `json:"wallets,omitempty"`
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
// Code generated by apigen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
const (
|
||||
ErrorCodeEarlyCompletion = "early_completion"
|
||||
ErrorCodeForbidden = "forbidden"
|
||||
ErrorCodeLevelNotReached = "level_not_reached"
|
||||
ErrorCodeNodeNotActive = "node_not_active"
|
||||
ErrorCodeObjectivesIncomplete = "objectives_incomplete"
|
||||
ErrorCodeRunExpired = "run_expired"
|
||||
ErrorCodeRunNotActive = "run_not_active"
|
||||
ErrorCodeScenarioNotActive = "scenario_not_active"
|
||||
ErrorCodeUnknownRun = "unknown_run"
|
||||
)
|
||||
@@ -0,0 +1,7 @@
|
||||
// Code generated by apigen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
type GetLeaderboardResultsResponse struct {
|
||||
Entries []RankEntry `json:"entries,omitempty"`
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// Code generated by apigen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
type GetProjectMetricsResponse struct {
|
||||
Dau int `json:"dau,omitempty"`
|
||||
DauChange float64 `json:"dauChange,omitempty"`
|
||||
Mau int `json:"mau,omitempty"`
|
||||
MauChange float64 `json:"mauChange,omitempty"`
|
||||
Retention []RetentionPoint `json:"retention,omitempty"`
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// Code generated by apigen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
type InventoryItem struct {
|
||||
Amount int64 `json:"amount,omitempty"`
|
||||
ID string `json:"id,omitempty"`
|
||||
Slug string `json:"slug,omitempty"`
|
||||
UpdatedAt string `json:"updatedAt,omitempty"`
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// Code generated by apigen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
type ListPlayersResponse struct {
|
||||
Limit int `json:"limit,omitempty"`
|
||||
Offset int `json:"offset,omitempty"`
|
||||
Players []AdminPlayer `json:"players,omitempty"`
|
||||
Total int `json:"total,omitempty"`
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// Code generated by apigen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
type ListUgcResponse struct {
|
||||
Items []UgcSubmission `json:"items,omitempty"`
|
||||
NextCursor string `json:"nextCursor,omitempty"`
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// Code generated by apigen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
type PlayerStorage struct {
|
||||
Data string `json:"data,omitempty"`
|
||||
ExpiresAt string `json:"expiresAt,omitempty"`
|
||||
ID string `json:"id,omitempty"`
|
||||
PlayerID string `json:"playerId,omitempty"`
|
||||
Type string `json:"type,omitempty"`
|
||||
UpdatedAt string `json:"updatedAt,omitempty"`
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// Code generated by apigen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
type RankEntry struct {
|
||||
PlayerID string `json:"playerId,omitempty"`
|
||||
PlayerName string `json:"playerName,omitempty"`
|
||||
Rank int64 `json:"rank,omitempty"`
|
||||
Score float64 `json:"score,omitempty"`
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// Code generated by apigen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
type RetentionPoint struct {
|
||||
Day int `json:"day,omitempty"`
|
||||
Value float64 `json:"value,omitempty"`
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// 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"`
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// Code generated by apigen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
type SubmittedBy struct {
|
||||
UserID string `json:"userId,omitempty"`
|
||||
Username string `json:"username,omitempty"`
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// 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"`
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// 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"`
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// Code generated by apigen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
type WalletAudit struct {
|
||||
Amount int64 `json:"amount,omitempty"`
|
||||
BalanceAfter int64 `json:"balanceAfter,omitempty"`
|
||||
BalanceBefore int64 `json:"balanceBefore,omitempty"`
|
||||
CreatedAt string `json:"createdAt,omitempty"`
|
||||
CurrencyCode string `json:"currencyCode,omitempty"`
|
||||
ID string `json:"id,omitempty"`
|
||||
Metadata json.RawMessage `json:"metadata,omitempty"`
|
||||
PlayerID string `json:"playerId,omitempty"`
|
||||
Reason string `json:"reason,omitempty"`
|
||||
Source string `json:"source,omitempty"`
|
||||
WalletID string `json:"walletId,omitempty"`
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// Code generated by apigen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
type WalletDetails struct {
|
||||
Balance int64 `json:"balance,omitempty"`
|
||||
CurrencyCode string `json:"currencyCode,omitempty"`
|
||||
ID string `json:"id,omitempty"`
|
||||
PlayerID string `json:"playerId,omitempty"`
|
||||
UpdatedAt string `json:"updatedAt,omitempty"`
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
package rudder
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
|
||||
"hub.rudder.build/rudder/rudder-go-sdk/models"
|
||||
)
|
||||
|
||||
type PlayersService struct {
|
||||
transport *transport
|
||||
}
|
||||
|
||||
type ListPlayersParameters struct {
|
||||
Limit int
|
||||
Offset int
|
||||
}
|
||||
|
||||
func (s *PlayersService) List(ctx context.Context, parameters ListPlayersParameters) (*models.ListPlayersResponse, error) {
|
||||
query := url.Values{}
|
||||
if parameters.Limit > 0 {
|
||||
query.Set("limit", strconv.Itoa(parameters.Limit))
|
||||
}
|
||||
if parameters.Offset > 0 {
|
||||
query.Set("offset", strconv.Itoa(parameters.Offset))
|
||||
}
|
||||
|
||||
var response models.ListPlayersResponse
|
||||
if err := s.transport.do(ctx, http.MethodGet, "/players/list", query, nil, &response); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &response, nil
|
||||
}
|
||||
|
||||
func (s *PlayersService) Get(ctx context.Context, playerID string) (*models.AdminPlayerDetails, error) {
|
||||
var response models.AdminPlayerDetails
|
||||
if err := s.transport.do(ctx, http.MethodGet, "/players/"+url.PathEscape(playerID), nil, nil, &response); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &response, nil
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package rudder
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type transport struct {
|
||||
baseURL string
|
||||
apiKey string
|
||||
projectID string
|
||||
httpClient *http.Client
|
||||
}
|
||||
|
||||
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
|
||||
if len(query) > 0 {
|
||||
endpoint += "?" + query.Encode()
|
||||
}
|
||||
|
||||
var reader io.Reader
|
||||
if body != nil {
|
||||
data, err := json.Marshal(body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("rudder: encode request body: %w", err)
|
||||
}
|
||||
reader = bytes.NewReader(data)
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, method, endpoint, reader)
|
||||
if err != nil {
|
||||
return fmt.Errorf("rudder: build request: %w", err)
|
||||
}
|
||||
req.Header.Set("X-API-Key", t.apiKey)
|
||||
if body != nil {
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
}
|
||||
|
||||
resp, err := t.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return fmt.Errorf("rudder: %s %s: %w", method, path, err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
data, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("rudder: read response body: %w", err)
|
||||
}
|
||||
|
||||
if resp.StatusCode >= 400 {
|
||||
apiErr := &APIError{Status: resp.StatusCode}
|
||||
var payload struct {
|
||||
Error string `json:"error"`
|
||||
Code string `json:"code"`
|
||||
RequestID string `json:"requestId"`
|
||||
}
|
||||
if json.Unmarshal(data, &payload) == nil {
|
||||
apiErr.Code = payload.Code
|
||||
apiErr.Message = payload.Error
|
||||
apiErr.RequestID = payload.RequestID
|
||||
}
|
||||
if apiErr.Message == "" {
|
||||
apiErr.Message = http.StatusText(resp.StatusCode)
|
||||
}
|
||||
return apiErr
|
||||
}
|
||||
|
||||
if out == nil || len(data) == 0 {
|
||||
return nil
|
||||
}
|
||||
if err := json.Unmarshal(data, out); err != nil {
|
||||
return fmt.Errorf("rudder: decode response: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
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
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package rudder
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"hub.rudder.build/rudder/rudder-go-sdk/models"
|
||||
)
|
||||
|
||||
type WalletService struct {
|
||||
transport *transport
|
||||
}
|
||||
|
||||
type AdjustWalletParameters struct {
|
||||
CurrencyCode string
|
||||
Amount int64
|
||||
Reason string
|
||||
}
|
||||
|
||||
func (s *WalletService) Adjust(ctx context.Context, playerID string, parameters AdjustWalletParameters) (*models.WalletDetails, error) {
|
||||
body := models.AdjustPlayerWalletRequest{
|
||||
PlayerID: playerID,
|
||||
CurrencyCode: parameters.CurrencyCode,
|
||||
Amount: parameters.Amount,
|
||||
Reason: parameters.Reason,
|
||||
}
|
||||
|
||||
var response models.WalletDetails
|
||||
if err := s.transport.do(ctx, http.MethodPost, "/players/"+url.PathEscape(playerID)+"/wallet/adjust", nil, body, &response); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &response, nil
|
||||
}
|
||||
Reference in New Issue
Block a user