qdmp

package module
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 3, 2026 License: MIT Imports: 15 Imported by: 0

Documentation

Overview

Package qdmp is the Go Server SDK for 千岛小程序开放平台 OpenAPI.

Construct a client with NewClient, exchange an app-level access token via Client.Auth.GetAppAccessToken (cached and single-flight refreshed automatically), and call the business operation groups (User, Island, Spu, Tag, Mark, WishSpu, GenAI) on it, passing the caller's credential explicitly on every call as a Context. See the exported types on Client, AuthService, QdmpApiError, and TokenStore for the full contract; the *_test.go files in this directory exercise it end-to-end against mock HTTP servers.

Index

Constants

This section is empty.

Variables

View Source
var ErrAccessTokenRequired = errors.New("qdmp: access token is required")

ErrAccessTokenRequired is a sentinel error returned when a business method that requires a user/app-level access token (x-qdmp-token-required=true in shared/openapi.yaml) is called without one. Callers should use errors.Is to detect this case. The SDK fails locally, before any HTTP request is sent, whenever this error is returned.

View Source
var ErrInvalidAccessToken = errors.New("qdmp: access token contains a character that cannot be safely sent as an HTTP header value")

ErrInvalidAccessToken is a sentinel error returned when a caller-supplied access token contains a byte that cannot be safely sent as an HTTP header value (any byte <= 0x1F, or 0x7F/DEL — including a bare tab, 0x09, which Go's net/http would otherwise transmit as-is instead of rejecting it). The SDK fails locally, before any HTTP request is sent, whenever this error is returned.

Functions

This section is empty.

Types

type AppAccessTokenResult added in v0.2.0

type AppAccessTokenResult struct {
	AccessToken string `json:"accessToken"`
	// ExpiresAt is the absolute Unix-seconds expiry timestamp as a string,
	// matching the wire shape (see UserAccessTokenResult.ExpiresAt).
	ExpiresAt    string `json:"expiresAt"`
	RefreshToken string `json:"refreshToken"`
	OpenID       string `json:"openId"`
}

AppAccessTokenResult is the CLIENT_CREDENTIALS ("应用凭证") exchange result.

Real traffic capture confirms this grant type returns the very same data shape as the user-level one — {accessToken, expiresAt, refreshToken, openId} — with a genuinely non-empty refreshToken and an empty openId (an app-level token belongs to no user). All four fields are handed back verbatim so the caller can see the real expiry and decide for itself whether to use the refreshToken; the SDK's own renewal strategy for this credential is unchanged (re-exchange via CLIENT_CREDENTIALS ahead of expiry, never via refreshToken).

Validation is deliberately strict only on accessToken/expiresAt: openId is empty by design here, and refreshToken is passed through as received without being required.

func (AppAccessTokenResult) GoString added in v0.2.0

func (r AppAccessTokenResult) GoString() string

GoString implements fmt.GoStringer — see UserAccessTokenResult.GoString for why.

func (AppAccessTokenResult) LogValue added in v0.2.0

func (r AppAccessTokenResult) LogValue() slog.Value

LogValue implements slog.LogValuer — see UserAccessTokenResult.LogValue for why.

func (AppAccessTokenResult) String added in v0.2.0

func (r AppAccessTokenResult) String() string

String implements fmt.Stringer — see UserAccessTokenResult.String for why.

type AuthService

type AuthService struct {
	// contains filtered or unexported fields
}

AuthService implements the qdmp OAuth2-flavored auth endpoints.

GetAppAccessToken manages the app-level (CLIENT_CREDENTIALS) token: cached in TokenStore, refreshed automatically ahead of expiry, with concurrent callers collapsed into a single outbound HTTP exchange (single-flight) to avoid a thundering herd against the real qdmp gateway.

GetUserAccessToken and RefreshToken are one-shot exchanges the SDK never caches — user-level tokens are the calling application's responsibility to persist, since a single server process serves many end users and the SDK has no way to know which user a given call belongs to.

func (*AuthService) GetAppAccessToken added in v0.2.0

func (a *AuthService) GetAppAccessToken(ctx context.Context) (*AppAccessTokenResult, error)

GetAppAccessToken returns a valid app-level ("应用凭证") credential, using the cached value if it is not within tokenRefreshBufferSeconds of expiry, otherwise exchanging for a new one (collapsing concurrent callers via single-flight).

func (*AuthService) GetUserAccessToken added in v0.2.0

func (a *AuthService) GetUserAccessToken(ctx context.Context, code string) (*UserAccessTokenResult, error)

GetUserAccessToken performs a one-shot AUTHORIZATION_CODE exchange. Never cached — see the AuthService doc comment.

func (*AuthService) RefreshToken

func (a *AuthService) RefreshToken(ctx context.Context, refreshToken string) (*RefreshTokenResult, error)

RefreshToken performs a one-shot refreshToken exchange. Never cached — see the AuthService doc comment. HTTP 200 does not imply success here: an expired refreshToken comes back as HTTP 200 + code=10008, which doRequest already turns into a *QdmpApiError.

type Client

type Client struct {

	// Auth manages the app-level (CLIENT_CREDENTIALS) token lifecycle
	// (cached + single-flight refresh) plus the one-shot,
	// never-cached getUserAccessToken/refreshToken exchanges.
	Auth *AuthService

	User    *UserGroup
	Island  *IslandGroup
	Spu     *SpuGroup
	Tag     *TagGroup
	Mark    *MarkGroup
	WishSpu *WishSpuGroup
	GenAI   *GenAIGroup
	// contains filtered or unexported fields
}

Client is the root qdmp SDK client. It exposes Auth (app-level token exchange, using appId/appSecret — no user access token needed) plus every business group (User/Island/Spu/...).

Business group methods take the caller's credential as an explicit Context argument on every call — the SDK holds no user credential of its own and never renews one. This mirrors the Node and Java SDKs, where the credential is likewise passed per call (`qdmp.user.me({accessToken})` / `qdmp.user().me(ctx)`), so the three ends behave identically.

func NewClient

func NewClient(opts ClientOptions) (*Client, error)

NewClient constructs a qdmp SDK client from the given options.

type ClientOptions

type ClientOptions struct {
	// AppID is the qdmp application ID. Required.
	AppID string
	// AppSecret is the qdmp application secret, used only for the
	// CLIENT_CREDENTIALS/AUTHORIZATION_CODE token exchange. Required. Never
	// logged or attached to any error value produced by this SDK.
	AppSecret string
	// BaseURL overrides the qdmp OpenAPI host. Defaults to the production
	// host. Tests point this at an httptest.Server.
	BaseURL string
	// QdmpVersion overrides the x-echo-qdmp-version header value sent on
	// "standard" authScheme requests. Defaults to "1.0".
	QdmpVersion string
	// HTTPClient overrides the *http.Client used for outbound requests.
	// Defaults to a new client with a defaultHTTPTimeout (30s) request
	// timeout, so a hung qdmp endpoint can never block a caller forever. Its
	// CheckRedirect is always overridden by NewClient (on a shallow copy,
	// never mutating the caller's original client) to refuse redirects --
	// see the comment in NewClient for why this can't be left configurable.
	HTTPClient *http.Client
	// TokenStore overrides the app-level access token cache. Defaults to an
	// in-process memory store. See TokenStore for why a pluggable store
	// exists (multi-instance deployments).
	TokenStore TokenStore
}

ClientOptions configures NewClient.

type Context added in v0.3.0

type Context struct {
	// AccessToken is the user-level (or, where explicitly opted into,
	// app-level) access token to authenticate this call with.
	AccessToken string
}

Context carries the caller's credential for one business call. It is the Go counterpart of the Node SDK's `{accessToken}` context object and the Java SDK's QdmpContext, and is passed explicitly to every business group method:

me, err := client.User.Me(ctx, qdmp.Context{AccessToken: credential.AccessToken})

The SDK stores no user credential and never renews one. When a call fails because the token expired or was revoked, the *QdmpApiError is returned unchanged; obtaining a new token (see AuthService.RefreshToken) and passing it on the next call is the caller's job.

It is a plain struct with no constructor on purpose: like Node, the token is validated when a call actually uses it (see requireAccessToken), not at construction time, so building a Context can never fail.

type GenAIDetailResult

type GenAIDetailResult struct {
	ID       string         `json:"id"`
	Status   string         `json:"status"`
	Response map[string]any `json:"response"`
}

GenAIDetailResult is the response of genai.detail.

type GenAIGenerateResult

type GenAIGenerateResult struct {
	ID string `json:"id"`
}

GenAIGenerateResult is the response of genai.generate.

type GenAIGroup

type GenAIGroup struct {
	// contains filtered or unexported fields
}

GenAIGroup implements the "genai" operation group. Unlike every other group, genai uses its own distinct authScheme ("genai" in shared/generated/route-meta.json): it sends x-openapi-access-token / x-openapi-app-id instead of access-token / x-echo-qdmp-version, and never sends the latter pair (confirmed by the absence of x-echo-qdmp-version in this group's codeExample, per shared/openapi.yaml).

func (*GenAIGroup) Detail

Detail polls the status/result of an async AI generation task by ID.

generated.GenaiDetailParams also carries this scheme's own header fields (XOpenapiAccessToken, XOpenapiAppId); like SpuGroup.Search, this method never reads them back off params — the real values come from the derived per-call Context's access token and the client's own configured AppID.

func (*GenAIGroup) Generate

Generate submits an async AI generation task.

type IslandDetailResult

type IslandDetailResult struct {
	Island IslandInfo `json:"island"`
}

IslandDetailResult is the response of island.detail.

type IslandGroup

type IslandGroup struct {
	// contains filtered or unexported fields
}

IslandGroup implements the "island" operation group.

func (*IslandGroup) Detail

Detail fetches an island's basic info by ID. Confirmed by real testing to also work with an app-level (CLIENT_CREDENTIALS) token; the SDK still requires the caller to explicitly pass some token (there is no silent app-token fallback).

type IslandInfo

type IslandInfo struct {
	ID     string `json:"id"`
	Name   string `json:"name"`
	Image  string `json:"image"`
	Joined bool   `json:"joined"`
}

IslandInfo is the island/v1/detail data.island shape, also reused as tag/v1/detail's data.tag.island (a Tag's optionally-associated island).

type MarkAddResult

type MarkAddResult struct {
	ID string `json:"id"`
}

MarkAddResult is the response of mark.add.

type MarkDetailResult

type MarkDetailResult struct {
	ID        string            `json:"id"`
	Spu       *SpuSummary       `json:"spu"`
	MarkAt    string            `json:"markAt"`
	Count     string            `json:"count"`
	Rating    *Rating           `json:"rating"`
	CreatedAt string            `json:"createdAt"`
	TypeID    string            `json:"typeId"`
	TypeName  string            `json:"typeName"`
	Marks     []MarkHistoryItem `json:"marks"`
	HasMore   bool              `json:"hasMore"`
}

MarkDetailResult is the response of mark.detail.

type MarkGroup

type MarkGroup struct {
	// contains filtered or unexported fields
}

MarkGroup implements the "marks" operation group.

func (*MarkGroup) Add

Add adds a mark (optionally with a rating) for a given SPU.

func (*MarkGroup) Detail

func (g *MarkGroup) Detail(ctx context.Context, qdmpCtx Context, params generated.MarkDetailParams) (*MarkDetailResult, error)

Detail fetches a single mark's details, including its history.

func (*MarkGroup) List

func (g *MarkGroup) List(ctx context.Context, qdmpCtx Context, params generated.MarkListParams) (*MarkListResult, error)

List fetches the current user's marks, paginated.

func (*MarkGroup) Search

func (g *MarkGroup) Search(ctx context.Context, qdmpCtx Context, params generated.MarkSearchParams) (*MarkSearchResult, error)

Search searches the current user's marks by category.

type MarkHistoryItem

type MarkHistoryItem struct {
	ID        string `json:"id"`
	MarkAt    string `json:"markAt"`
	CreatedAt string `json:"createdAt"`
}

MarkHistoryItem is one element of mark.detail's data.marks[] history list.

type MarkItem

type MarkItem struct {
	ID        string      `json:"id"`
	Spu       *SpuSummary `json:"spu"`
	MarkAt    string      `json:"markAt"`
	Count     string      `json:"count"`
	Rating    *Rating     `json:"rating"`
	CreatedAt string      `json:"createdAt"`
	TypeID    string      `json:"typeId"`
}

MarkItem is one element of mark.list / mark.search's data.items[].

type MarkListResult

type MarkListResult struct {
	Items      []MarkItem `json:"items"`
	TotalCount string     `json:"totalCount"`
}

MarkListResult is the response of mark.list.

type MarkSearchResult

type MarkSearchResult struct {
	Items      []MarkItem `json:"items"`
	TotalCount string     `json:"totalCount"`
}

MarkSearchResult is the response of mark.search.

type QdmpApiError

type QdmpApiError struct {
	// Code is the normalized business error code (e.g. "10005", "13").
	Code string
	// Message is the human-readable message reported by the server.
	Message string
	// RequestID is the request tracing ID, when present (only the "normal"
	// business envelope {code,message,requestId,data} carries one; the
	// gateway-style envelope {code,message,details} does not).
	RequestID string
	// HTTPStatus is the transport-level HTTP status code of the response
	// that carried this business error.
	HTTPStatus int
}

QdmpApiError represents a business-level failure reported by the qdmp OpenAPI, as opposed to a transport-level failure (network error, etc).

This repository has confirmed by real traffic capture that HTTP status is not authoritative: a refreshToken that has expired is HTTP 200 with code=10008, while an invalid access-token is a genuine HTTP 401 with code=10005. Callers must inspect Code, not just check for a non-nil error.

Code is intentionally a string (not a closed enum/int): the qdmp API is known to use non-numeric-looking business codes in one envelope shape and small gRPC-style integer codes in the other, and undocumented codes have already been observed in practice (10005, 20000, 13, 2, ...).

func (*QdmpApiError) Error

func (e *QdmpApiError) Error() string

Error implements the error interface. It intentionally only ever interpolates fields already stored on QdmpApiError (Code/Message/ RequestID/HTTPStatus) — accessToken and appSecret are never stored on this type, so they can never leak through this method.

type Rating

type Rating struct {
	Value int `json:"value"`
}

Rating is the { value: 1-5 } rating object attached to a mark.

type RefreshTokenResult

type RefreshTokenResult struct {
	AccessToken string `json:"accessToken"`
	ExpiresAt   string `json:"expiresAt"`
}

RefreshTokenResult is the one-shot refreshToken exchange result. Also never cached by the SDK.

func (RefreshTokenResult) GoString added in v0.1.1

func (r RefreshTokenResult) GoString() string

GoString implements fmt.GoStringer — see UserAccessTokenResult.GoString for why.

func (RefreshTokenResult) LogValue added in v0.1.1

func (r RefreshTokenResult) LogValue() slog.Value

LogValue implements slog.LogValuer — see UserAccessTokenResult.LogValue for why.

func (RefreshTokenResult) String added in v0.1.1

func (r RefreshTokenResult) String() string

String implements fmt.Stringer — see UserAccessTokenResult.String for why.

type SpuDetailResult

type SpuDetailResult struct {
	Spu SpuInfo `json:"spu"`
}

SpuDetailResult is the response of spu.detail.

type SpuGroup

type SpuGroup struct {
	// contains filtered or unexported fields
}

SpuGroup implements the "spu" operation group.

func (*SpuGroup) Detail

func (g *SpuGroup) Detail(ctx context.Context, qdmpCtx Context, params generated.SpuDetailParams) (*SpuDetailResult, error)

Detail fetches a single SPU's details by ID.

func (*SpuGroup) Search

func (g *SpuGroup) Search(ctx context.Context, qdmpCtx Context, params generated.SpuSearchParams) (*SpuSearchResult, error)

Search searches SPUs by keyword/category/IP-tag filters. Confirmed by real testing to also work with an app-level (CLIENT_CREDENTIALS) token.

generated.SpuSearchParams bundles the query fields together with the "standard" authScheme's header fields (AccessToken, XEchoQdmpVersion) because that is what oapi-codegen produced from the shared openapi.yaml spec (header params and query params both land on the operation's Params struct). This method deliberately never reads params.AccessToken or params.XEchoQdmpVersion — the real access-token comes from the derived per-call Context, and the real x-echo-qdmp-version comes from the client's own configured QdmpVersion — so a caller cannot spoof either header by setting those two fields.

type SpuInfo

type SpuInfo struct {
	ID                string           `json:"id"`
	Name              string           `json:"name"`
	Image             string           `json:"image"`
	WhiteBgPng        string           `json:"whiteBgPng"`
	TypeID            string           `json:"typeId"`
	TypeName          string           `json:"typeName"`
	WishCount         string           `json:"wishCount"`
	MarkCount         string           `json:"markCount"`
	WishCount3day     string           `json:"wishCount3day"`
	MarkCount3day     string           `json:"markCount3day"`
	EntryProfileItems []map[string]any `json:"entryProfileItems"`
}

SpuInfo is the spu/v1/detail data.spu shape.

type SpuSearchItem

type SpuSearchItem struct {
	ID        string `json:"id"`
	Name      string `json:"name"`
	Image     string `json:"image"`
	TypeID    string `json:"typeId"`
	TypeName  string `json:"typeName"`
	WishCount string `json:"wishCount"`
	MarkCount string `json:"markCount"`
}

SpuSearchItem is one element of spu.search's data.items[].

type SpuSearchResult

type SpuSearchResult struct {
	Items      []SpuSearchItem `json:"items"`
	TotalCount string          `json:"totalCount"`
}

SpuSearchResult is the response of spu.search.

type SpuSummary

type SpuSummary struct {
	ID    string `json:"id"`
	Name  string `json:"name"`
	Image string `json:"image"`
}

SpuSummary is the small SPU summary shape ({id, name, image}) embedded in mark/wishspu list-style responses' data.items[].spu field.

type TagDetailResult

type TagDetailResult struct {
	Tag TagInfo `json:"tag"`
}

TagDetailResult is the response of tag.detail.

type TagGroup

type TagGroup struct {
	// contains filtered or unexported fields
}

TagGroup implements the "tag" operation group.

func (*TagGroup) Detail

func (g *TagGroup) Detail(ctx context.Context, qdmpCtx Context, params generated.TagDetailParams) (*TagDetailResult, error)

Detail fetches a single Tag's details by ID.

func (*TagGroup) Search

func (g *TagGroup) Search(ctx context.Context, qdmpCtx Context, params generated.TagSearchParams) (*TagSearchResult, error)

Search searches Tags by keyword/category filters.

type TagInfo

type TagInfo struct {
	ID       string      `json:"id"`
	Name     string      `json:"name"`
	Image    string      `json:"image"`
	TypeID   string      `json:"typeId"`
	TypeName string      `json:"typeName"`
	Island   *IslandInfo `json:"island"`
}

TagInfo is the tag/v1/detail data.tag shape, also reused by tag/v1/search's data.items[].

type TagSearchResult

type TagSearchResult struct {
	Items      []TagInfo `json:"items"`
	TotalCount string    `json:"totalCount"`
}

TagSearchResult is the response of tag.search.

type TokenEntry

type TokenEntry struct {
	AccessToken  string
	ExpiresAt    int64
	RefreshToken string
	OpenID       string
}

TokenEntry is a cached app-level ("应用凭证") credential: the whole thing, not just the access token. ExpiresAt mirrors the wire format confirmed by real traffic capture — an absolute Unix seconds timestamp, not a relative "seconds remaining" duration and not milliseconds — parsed from the string the server sends.

RefreshToken and OpenID are cached alongside so that a call served from this cache returns exactly the same fields as the call that performed the exchange (see AppAccessTokenResult). The CLIENT_CREDENTIALS grant really does return a non-empty refreshToken and an empty openId; neither is required, and neither changes how the SDK renews this credential (it re-exchanges ahead of expiry, it never uses this refreshToken).

type TokenStore

type TokenStore interface {
	Get() (TokenEntry, bool)
	Set(entry TokenEntry)
	Clear()
}

TokenStore is the pluggable persistence interface for the SDK's app-level (CLIENT_CREDENTIALS) token cache. The default implementation is an in-process memory store; multi-instance deployments can supply their own (e.g. backed by Redis) so that all instances share one cached token instead of each independently exchanging one and colliding/rate-limiting each other against the real qdmp gateway.

User-level tokens (from AUTHORIZATION_CODE) are never stored here — the SDK never caches them, per the token lifecycle model in the design.

func NewMemoryTokenStore

func NewMemoryTokenStore() TokenStore

NewMemoryTokenStore returns a TokenStore backed by process memory. This is the default used by NewClient when ClientOptions.TokenStore is nil.

type UserAccessTokenResult added in v0.2.0

type UserAccessTokenResult struct {
	AccessToken  string `json:"accessToken"`
	RefreshToken string `json:"refreshToken"`
	// ExpiresAt is the absolute Unix-seconds expiry timestamp, confirmed by
	// capture to be a *string* on the wire (e.g. "1785508950") even though
	// it is logically an int64. It is intentionally kept as a Go string
	// end-to-end so this round-trips byte-for-byte with no risk of a
	// numeric-conversion implementation silently corrupting it.
	ExpiresAt string `json:"expiresAt"`
	OpenID    string `json:"openId"`
}

UserAccessTokenResult is the one-shot AUTHORIZATION_CODE exchange result. The SDK never caches this — the caller's own store/DB persists it, scoped to whichever end-user the code belonged to.

func (UserAccessTokenResult) GoString added in v0.2.0

func (r UserAccessTokenResult) GoString() string

GoString implements fmt.GoStringer. The %#v verb does NOT consult fmt.Stringer — it falls back to Go-syntax struct reflection, which would print every exported field (including the raw AccessToken/RefreshToken) even with String() defined above. GoStringer is the only way to also redact under %#v.

func (UserAccessTokenResult) LogValue added in v0.2.0

func (r UserAccessTokenResult) LogValue() slog.Value

LogValue implements slog.LogValuer. Structured loggers built on log/slog (e.g. slog.JSONHandler, slog.TextHandler) do NOT consult fmt.Stringer — slog.JSONHandler JSON-marshals values directly, which would still emit the raw AccessToken/RefreshToken fields even with String()/GoString() already redacting the fmt-based paths above. LogValuer is slog's own redaction hook; it has no effect on json.Marshal (persistence stays exactly as before).

func (UserAccessTokenResult) String added in v0.2.0

func (r UserAccessTokenResult) String() string

String implements fmt.Stringer so that accidental debug-printing (e.g. fmt.Println(result), fmt.Printf("%v"/"%+v", result), or most structured loggers that fall back to %v/%+v) never leaks the raw AccessToken/ RefreshToken values. This is a value-receiver method, so it is also picked up for *UserAccessTokenResult (a pointer's method set includes all value-receiver methods of the pointed-to type).

This must never affect json.Marshal(result): encoding/json only consults the json.Marshaler interface (MarshalJSON), not fmt.Stringer, so callers that persist the real values via JSON — the entire point of GetUserAccessToken/RefreshToken existing — are unaffected. Direct field access (result.AccessToken) is likewise untouched.

type UserGroup

type UserGroup struct {
	// contains filtered or unexported fields
}

UserGroup implements the "user" operation group.

func (*UserGroup) Me

func (g *UserGroup) Me(ctx context.Context, qdmpCtx Context) (*UserMeResult, error)

Me fetches the current user identified by the per-call Context's access token (user.me has x-qdmp-token-required=true — no query parameters, the server identifies the caller purely from the access-token header).

type UserMeResult

type UserMeResult struct {
	ID           string           `json:"id"`
	Nickname     string           `json:"nickname"`
	Avatar       string           `json:"avatar"`
	IdentityTags []map[string]any `json:"identityTags"`
	InterestTags []map[string]any `json:"interestTags"`
}

UserMeResult is the response of user.me (data.identityTags/interestTags have no documented internal shape, per shared/openapi.yaml — modeled as open maps, unverified).

type WishAddResult

type WishAddResult struct {
	SuccessCount string `json:"successCount"`
}

WishAddResult is the response of wishspu.add.

type WishCancelResult

type WishCancelResult struct {
	SuccessCount string `json:"successCount"`
}

WishCancelResult is the response of wishspu.cancel.

type WishItem

type WishItem struct {
	ID        string      `json:"id"`
	Spu       *SpuSummary `json:"spu"`
	TypeID    string      `json:"typeId"`
	MarkAt    string      `json:"markAt"`
	CreatedAt string      `json:"createdAt"`
}

WishItem is one element of wishspu.list's data.items[].

type WishListResult

type WishListResult struct {
	Items      []WishItem `json:"items"`
	TotalCount string     `json:"totalCount"`
}

WishListResult is the response of wishspu.list.

type WishSpuGroup

type WishSpuGroup struct {
	// contains filtered or unexported fields
}

WishSpuGroup implements the "wishspu" operation group.

func (*WishSpuGroup) Add

Add batch-adds "wish" entries.

func (*WishSpuGroup) Cancel

Cancel batch-cancels "wish" entries.

func (*WishSpuGroup) List

func (g *WishSpuGroup) List(ctx context.Context, qdmpCtx Context, params generated.WishListParams) (*WishListResult, error)

List fetches the current user's "wish" list, paginated.

Directories

Path Synopsis
Package generated provides primitives to interact with the openapi HTTP API.
Package generated provides primitives to interact with the openapi HTTP API.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL