package sub2api import ( "bytes" "context" "net/http" "strings" ) func (c *Client) ProbeCapabilities(ctx context.Context) (HostCapabilities, error) { groups, err := c.probeEndpoint(ctx, http.MethodGet, "/api/v1/admin/groups", nil) if err != nil { return HostCapabilities{}, err } channels, err := c.probeEndpoint(ctx, http.MethodGet, "/api/v1/admin/channels", nil) if err != nil { return HostCapabilities{}, err } plans, err := c.probeEndpoint(ctx, http.MethodGet, "/api/v1/admin/payment/plans", nil) if err != nil { return HostCapabilities{}, err } accounts, err := c.probeEndpoint(ctx, http.MethodGet, "/api/v1/admin/accounts", nil) if err != nil { return HostCapabilities{}, err } accountTest, err := c.probeEndpoint(ctx, http.MethodGet, "/api/v1/admin/accounts/__probe__/test", nil) if err != nil { return HostCapabilities{}, err } accountModels, err := c.probeEndpoint(ctx, http.MethodGet, "/api/v1/admin/accounts/__probe__/models", nil) if err != nil { return HostCapabilities{}, err } subscriptions, err := c.probeEndpoint(ctx, http.MethodGet, "/api/v1/admin/subscriptions/assign", nil) if err != nil { return HostCapabilities{}, err } return HostCapabilities{ Groups: groups, Channels: channels, Plans: plans, Accounts: accounts, AccountTest: accountTest, AccountModels: accountModels, Subscriptions: subscriptions, }, nil } func (c *Client) probeEndpoint(ctx context.Context, method, path string, requestBody any) (bool, error) { statusCode, _, body, err := c.perform(ctx, method, path, requestBody) if err != nil { return false, err } switch { case statusCode >= http.StatusOK && statusCode < http.StatusMultipleChoices: return true, nil case statusCode == http.StatusUnauthorized || statusCode == http.StatusForbidden: return false, newHTTPError(method, path, statusCode, body) case statusCode == http.StatusNotFound || statusCode == http.StatusMethodNotAllowed: return false, nil case statusCode >= http.StatusBadRequest && statusCode < http.StatusInternalServerError: return true, nil default: return false, newHTTPError(method, path, statusCode, body) } } func looksLikeExistingEndpoint(headers http.Header, body []byte) bool { contentType := strings.ToLower(headers.Get("Content-Type")) trimmedBody := bytes.TrimSpace(body) if strings.Contains(contentType, "application/json") || strings.Contains(contentType, "text/event-stream") { return true } if len(trimmedBody) == 0 { return false } if trimmedBody[0] == '{' || trimmedBody[0] == '[' { return true } return false }