271 lines
6.8 KiB
Markdown
271 lines
6.8 KiB
Markdown
# Remnawave GO SDK
|
|
|
|
A Go SDK client for interacting with the **[Remnawave API](https://remna.st)**.
|
|
|
|
## Version Compatibility
|
|
|
|
| API Version | SDK Version | Install |
|
|
|-------------|-------------|---------|
|
|
| 2.8.0 | v2.8.0 | `go get github.com/shiranuiyami/remnawave-api-go/v2@v2.8.0` |
|
|
| 2.7.4 | v2.7.4 | `go get github.com/shiranuiyami/remnawave-api-go/v2@v2.7.4` |
|
|
|
|
Generated with [**ogen**](https://github.com/ogen-go/ogen) v1.19.0:
|
|
* Zero-reflection JSON decoder for high throughput
|
|
* Compile-time validation against OpenAPI 3.0 spec
|
|
* First-class `context.Context` support
|
|
* Built-in OpenTelemetry instrumentation
|
|
* Per-request options via `RequestOption`
|
|
* Request/response editors (middleware)
|
|
* Organized sub-clients for clean API access
|
|
* Simplified method signatures (no verbose Params structs)
|
|
|
|
## Installation
|
|
|
|
```bash
|
|
go get github.com/shiranuiyami/remnawave-api-go/v2@v2.8.0
|
|
```
|
|
|
|
## Quick Start
|
|
|
|
```go
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
remapi "github.com/shiranuiyami/remnawave-api-go/v2/api"
|
|
)
|
|
|
|
func main() {
|
|
ctx := context.Background()
|
|
|
|
// Create base client
|
|
baseClient, _ := remapi.NewClient(
|
|
"https://your-panel.example.com",
|
|
remapi.StaticToken{Token: "YOUR_JWT_TOKEN"},
|
|
)
|
|
|
|
// Wrap with organized sub-clients
|
|
client := remapi.NewClientExt(baseClient)
|
|
|
|
// Get user by UUID - simple string argument
|
|
user, _ := client.Users().GetUserByUuid(ctx, "user-uuid-here")
|
|
fmt.Printf("User: %s\n", user.(*remapi.UserResponse).Response.Username)
|
|
|
|
// Get node by UUID
|
|
node, _ := client.Nodes().GetOneNode(ctx, "node-uuid-here")
|
|
fmt.Printf("Node: %s\n", node.(*remapi.NodeResponse).Response.Name)
|
|
|
|
// Create user
|
|
newUser, _ := client.Users().CreateUser(ctx, &remapi.CreateUserRequest{
|
|
Username: "john_doe",
|
|
})
|
|
fmt.Printf("Created: %s\n", newUser.(*remapi.UserResponse).Response.Username)
|
|
}
|
|
```
|
|
|
|
## Available Controllers
|
|
|
|
| Controller | Description |
|
|
|------------|-------------|
|
|
| `client.ApiTokens()` | API token management |
|
|
| `client.Auth()` | Authentication |
|
|
| `client.BandwidthStatsNodes()` | Node bandwidth statistics |
|
|
| `client.BandwidthStatsUsers()` | User bandwidth statistics |
|
|
| `client.ConfigProfile()` | Config profiles |
|
|
| `client.ExternalSquad()` | External squads |
|
|
| `client.Hosts()` | Host management |
|
|
| `client.HostsBulkActions()` | Bulk host operations |
|
|
| `client.HwidUserDevices()` | HWID devices |
|
|
| `client.InfraBilling()` | Infrastructure billing |
|
|
| `client.InternalSquad()` | Internal squads |
|
|
| `client.Keygen()` | Key generation |
|
|
| `client.Nodes()` | Node management |
|
|
| `client.NodesUsageHistory()` | Node usage history |
|
|
| `client.Passkey()` | Passkey authentication |
|
|
| `client.RemnawaveSettings()` | Panel settings |
|
|
| `client.Snippets()` | Code snippets |
|
|
| `client.Subscription()` | Subscription management |
|
|
| `client.SubscriptionPageConfig()` | Subscription page config |
|
|
| `client.SubscriptionSettings()` | Subscription settings |
|
|
| `client.SubscriptionTemplate()` | Subscription templates |
|
|
| `client.Subscriptions()` | Multiple subscriptions |
|
|
| `client.System()` | System info |
|
|
| `client.UserSubscriptionRequestHistory()` | Request history |
|
|
| `client.Users()` | User management |
|
|
| `client.UsersBulkActions()` | Bulk user operations |
|
|
|
|
## Error Handling
|
|
|
|
Unified error types for consistent error handling:
|
|
|
|
```go
|
|
resp, err := client.Users().GetUserByUuid(ctx, "invalid-uuid")
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
switch e := resp.(type) {
|
|
case *remapi.UserResponse:
|
|
fmt.Printf("User: %s\n", e.Response.Username)
|
|
case *remapi.BadRequestError:
|
|
for _, validationErr := range e.Errors {
|
|
fmt.Printf("Field: %v, Error: %s\n", validationErr.Path, validationErr.Message)
|
|
}
|
|
case *remapi.NotFoundError:
|
|
fmt.Println("User not found")
|
|
case *remapi.InternalServerError:
|
|
fmt.Printf("Server error: %s\n", e.Message.Value)
|
|
}
|
|
```
|
|
|
|
### Error Types
|
|
|
|
| Type | Status | Description |
|
|
|------|--------|-------------|
|
|
| `BadRequestError` | 400 | Validation errors with `[]ValidationError` |
|
|
| `UnauthorizedError` | 401 | Authentication required |
|
|
| `ForbiddenError` | 403 | Access denied |
|
|
| `NotFoundError` | 404 | Resource not found |
|
|
| `InternalServerError` | 500 | Server error |
|
|
|
|
### ValidationError Structure
|
|
|
|
```go
|
|
type ValidationError struct {
|
|
Validation string // e.g., "uuid"
|
|
Code string // e.g., "invalid_string"
|
|
Message string // e.g., "Invalid uuid"
|
|
Path []string // e.g., ["uuid"]
|
|
}
|
|
```
|
|
|
|
## Common Operations
|
|
|
|
### Users
|
|
|
|
```go
|
|
// Get by UUID (simplified - just pass the string)
|
|
user, _ := client.Users().GetUserByUuid(ctx, "uuid-here")
|
|
|
|
// Get by username
|
|
user, _ := client.Users().GetUserByUsername(ctx, "john")
|
|
|
|
// Get by short UUID
|
|
user, _ := client.Users().GetUserByShortUuid(ctx, "short-uuid")
|
|
|
|
// Create
|
|
user, _ := client.Users().CreateUser(ctx, &remapi.CreateUserRequest{
|
|
Username: "new_user",
|
|
})
|
|
|
|
// Update
|
|
user, _ := client.Users().UpdateUser(ctx, &remapi.UpdateUserRequest{
|
|
Uuid: "uuid-here",
|
|
})
|
|
|
|
// Delete
|
|
client.Users().DeleteUser(ctx, "uuid-here")
|
|
|
|
// Enable/Disable
|
|
client.Users().EnableUser(ctx, "uuid-here")
|
|
client.Users().DisableUser(ctx, "uuid-here")
|
|
|
|
// Reset traffic
|
|
client.Users().ResetUserTraffic(ctx, "uuid-here")
|
|
```
|
|
|
|
### Nodes
|
|
|
|
```go
|
|
// List all
|
|
nodes, _ := client.Nodes().GetAllNodes(ctx)
|
|
|
|
// Get one (simplified)
|
|
node, _ := client.Nodes().GetOneNode(ctx, "uuid-here")
|
|
|
|
// Create
|
|
node, _ := client.Nodes().CreateNode(ctx, &remapi.CreateNodeRequest{
|
|
Name: "Node-1",
|
|
})
|
|
|
|
// Delete
|
|
client.Nodes().DeleteNode(ctx, "uuid-here")
|
|
|
|
// Enable/Disable
|
|
client.Nodes().EnableNode(ctx, "uuid-here")
|
|
client.Nodes().DisableNode(ctx, "uuid-here")
|
|
|
|
// Restart
|
|
client.Nodes().RestartNode(ctx, "uuid-here")
|
|
|
|
// Reset traffic
|
|
client.Nodes().ResetNodeTraffic(ctx, "uuid-here")
|
|
```
|
|
|
|
### Hosts
|
|
|
|
```go
|
|
// List all
|
|
hosts, _ := client.Hosts().GetAllHosts(ctx)
|
|
|
|
// Get one
|
|
host, _ := client.Hosts().GetOneHost(ctx, "uuid-here")
|
|
|
|
// Create
|
|
host, _ := client.Hosts().CreateHost(ctx, &remapi.CreateHostRequest{...})
|
|
|
|
// Delete
|
|
client.Hosts().DeleteHost(ctx, "uuid-here")
|
|
```
|
|
|
|
### Authentication
|
|
|
|
```go
|
|
// Login
|
|
resp, _ := client.Auth().Login(ctx, &remapi.LoginRequest{
|
|
Username: "admin",
|
|
Password: "password",
|
|
})
|
|
token := resp.(*remapi.TokenResponse).Response.AccessToken
|
|
|
|
// Get status
|
|
status, _ := client.Auth().GetStatus(ctx)
|
|
```
|
|
|
|
## Request Options
|
|
|
|
All methods support per-request `RequestOption` for customization:
|
|
|
|
```go
|
|
// Pass options as the last variadic argument
|
|
user, err := client.Users().GetUserByUuid(ctx, "uuid-here", opts...)
|
|
```
|
|
|
|
## Access to Base Client
|
|
|
|
If you need direct access to the underlying ogen client:
|
|
|
|
```go
|
|
baseClient := client.Client()
|
|
```
|
|
|
|
## Requirements
|
|
|
|
| Requirement | Version |
|
|
|-------------|---------|
|
|
| Go | 1.21+ |
|
|
| Remnawave API | 2.8.+ |
|
|
|
|
## License
|
|
|
|
[MIT](LICENSE)
|
|
|
|
## Acknowledgments
|
|
|
|
* [Jolymmiles](https://github.com/Jolymmiles)
|
|
|
|
## Donation
|
|
|
|
- **LTC:** `ltc1qac3x0rfh6py309apjlztzrmr2rdv0jmu9dytex`
|