mirror of
https://github.com/Buriburizaem0n/nezha_domains.git
synced 2026-09-19 09:40:12 +00:00
91 lines
3.6 KiB
Go
91 lines
3.6 KiB
Go
package client
|
|
|
|
import (
|
|
"context"
|
|
"encoding/base64"
|
|
"errors"
|
|
"net/http"
|
|
)
|
|
|
|
var ErrInvalidSQLiteHoldReceipt = errors.New("client: invalid sqlite hold receipt")
|
|
|
|
type SQLiteHoldState string
|
|
|
|
const (
|
|
SQLiteHoldStateArmed SQLiteHoldState = "armed"
|
|
SQLiteHoldStateSelected SQLiteHoldState = "selected"
|
|
SQLiteHoldStateFinalizing SQLiteHoldState = "finalizing"
|
|
SQLiteHoldStateReleased SQLiteHoldState = "released"
|
|
SQLiteHoldStateAborted SQLiteHoldState = "aborted"
|
|
)
|
|
|
|
type SQLiteHoldReceipt struct {
|
|
ID string `json:"id"`
|
|
State SQLiteHoldState `json:"state,omitempty"`
|
|
}
|
|
|
|
func (client *Client) ArmSQLiteHold(ctx context.Context) (SQLiteHoldReceipt, error) {
|
|
receipt, err := DoREST[struct{}, SQLiteHoldReceipt](ctx, client, RESTRequest[struct{}]{Method: http.MethodPost, Path: "/agentcompat/sqlite-hold/arm", Body: &struct{}{}})
|
|
return validateSQLiteHoldReceipt(receipt, SQLiteHoldStateArmed, err)
|
|
}
|
|
|
|
func (client *Client) WaitForSQLiteHold(ctx context.Context, receipt SQLiteHoldReceipt, target SQLiteHoldState) (SQLiteHoldReceipt, error) {
|
|
if err := validateSQLiteHoldRequest(receipt, target); err != nil {
|
|
return SQLiteHoldReceipt{}, err
|
|
}
|
|
request := SQLiteHoldReceipt{ID: receipt.ID, State: target}
|
|
result, err := DoREST[SQLiteHoldReceipt, SQLiteHoldReceipt](ctx, client, RESTRequest[SQLiteHoldReceipt]{Method: http.MethodPost, Path: "/agentcompat/sqlite-hold/wait", Body: &request})
|
|
return validateSQLiteHoldReceipt(result, target, err)
|
|
}
|
|
|
|
func (client *Client) SnapshotSQLiteHold(ctx context.Context, receipt SQLiteHoldReceipt) (SQLiteHoldReceipt, error) {
|
|
return client.sqliteHoldAction(ctx, receipt, "snapshot", "")
|
|
}
|
|
|
|
func (client *Client) ReleaseSQLiteHold(ctx context.Context, receipt SQLiteHoldReceipt) (SQLiteHoldReceipt, error) {
|
|
return client.sqliteHoldAction(ctx, receipt, "release", SQLiteHoldStateReleased)
|
|
}
|
|
|
|
func (client *Client) AbortSQLiteHold(ctx context.Context, receipt SQLiteHoldReceipt) (SQLiteHoldReceipt, error) {
|
|
return client.sqliteHoldAction(ctx, receipt, "abort", SQLiteHoldStateAborted)
|
|
}
|
|
|
|
func (client *Client) sqliteHoldAction(ctx context.Context, receipt SQLiteHoldReceipt, action string, expected SQLiteHoldState) (SQLiteHoldReceipt, error) {
|
|
if err := validateSQLiteHoldRequest(receipt, ""); err != nil {
|
|
return SQLiteHoldReceipt{}, err
|
|
}
|
|
request := SQLiteHoldReceipt{ID: receipt.ID}
|
|
result, err := DoREST[SQLiteHoldReceipt, SQLiteHoldReceipt](ctx, client, RESTRequest[SQLiteHoldReceipt]{Method: http.MethodPost, Path: "/agentcompat/sqlite-hold/" + action, Body: &request})
|
|
return validateSQLiteHoldReceipt(result, expected, err)
|
|
}
|
|
|
|
func validateSQLiteHoldRequest(receipt SQLiteHoldReceipt, target SQLiteHoldState) error {
|
|
decoded, err := base64.RawURLEncoding.DecodeString(receipt.ID)
|
|
if err != nil || len(receipt.ID) != 43 || len(decoded) != 32 {
|
|
return ErrInvalidSQLiteHoldReceipt
|
|
}
|
|
if target != "" && target != SQLiteHoldStateSelected && target != SQLiteHoldStateFinalizing {
|
|
return ErrInvalidSQLiteHoldReceipt
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func validateSQLiteHoldReceipt(receipt SQLiteHoldReceipt, expected SQLiteHoldState, err error) (SQLiteHoldReceipt, error) {
|
|
if err != nil {
|
|
return SQLiteHoldReceipt{}, err
|
|
}
|
|
if err := validateSQLiteHoldRequest(receipt, ""); err != nil || !validSQLiteHoldState(receipt.State) || expected != "" && receipt.State != expected {
|
|
return SQLiteHoldReceipt{}, ErrInvalidSQLiteHoldReceipt
|
|
}
|
|
return receipt, nil
|
|
}
|
|
|
|
func validSQLiteHoldState(state SQLiteHoldState) bool {
|
|
switch state {
|
|
case SQLiteHoldStateArmed, SQLiteHoldStateSelected, SQLiteHoldStateFinalizing, SQLiteHoldStateReleased, SQLiteHoldStateAborted:
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|