package cdsapi import ( "context" "fmt" "io" "mime" "net/http" "net/url" "strings" "time" v4 "github.com/aws/aws-sdk-go-v2/aws/signer/v4" "github.com/aws/aws-sdk-go-v2/credentials" "gitlink.org.cn/cloudream/common/consts/errorcode" "gitlink.org.cn/cloudream/common/pkgs/iterator" "gitlink.org.cn/cloudream/common/sdks" cdssdk "gitlink.org.cn/cloudream/common/sdks/storage" "gitlink.org.cn/cloudream/common/utils/http2" "gitlink.org.cn/cloudream/common/utils/serder" ) type PackageService struct { *Client } func (c *Client) Package() *PackageService { return &PackageService{c} } const PackageGetPath = "/package/get" type PackageGetReq struct { UserID cdssdk.UserID `form:"userID" url:"userID" binding:"required"` PackageID cdssdk.PackageID `form:"packageID" url:"packageID" binding:"required"` } func (r *PackageGetReq) MakeParam() *sdks.RequestParam { return sdks.MakeQueryParam(http.MethodGet, PackageGetPath, r) } type PackageGetResp struct { cdssdk.Package } func (r *PackageGetResp) ParseResponse(resp *http.Response) error { return sdks.ParseCodeDataJSONResponse(resp, r) } func (c *PackageService) Get(req PackageGetReq) (*PackageGetResp, error) { return JSONAPI(c.cfg, http.DefaultClient, &req, &PackageGetResp{}) } const PackageGetByFullNamePath = "/package/getByFullName" type PackageGetByFullName struct { UserID cdssdk.UserID `form:"userID" url:"userID" binding:"required"` BucketName string `form:"bucketName" url:"bucketName" binding:"required"` PackageName string `form:"packageName" url:"packageName" binding:"required"` } func (r *PackageGetByFullName) MakeParam() *sdks.RequestParam { return sdks.MakeQueryParam(http.MethodGet, PackageGetByFullNamePath, r) } type PackageGetByFullNameResp struct { Package cdssdk.Package `json:"package"` } func (r *PackageGetByFullNameResp) ParseResponse(resp *http.Response) error { return sdks.ParseCodeDataJSONResponse(resp, r) } func (c *PackageService) GetByName(req PackageGetByFullName) (*PackageGetByFullNameResp, error) { return JSONAPI(c.cfg, http.DefaultClient, &req, &PackageGetByFullNameResp{}) } const PackageCreatePath = "/package/create" type PackageCreate struct { UserID cdssdk.UserID `json:"userID"` BucketID cdssdk.BucketID `json:"bucketID"` Name string `json:"name"` } func (r *PackageCreate) MakeParam() *sdks.RequestParam { return sdks.MakeJSONParam(http.MethodPost, PackageCreatePath, r) } type PackageCreateResp struct { Package cdssdk.Package `json:"package"` } func (r *PackageCreateResp) ParseResponse(resp *http.Response) error { return sdks.ParseCodeDataJSONResponse(resp, r) } func (s *PackageService) Create(req PackageCreate) (*PackageCreateResp, error) { return JSONAPI(s.cfg, http.DefaultClient, &req, &PackageCreateResp{}) } const PackageCreateLoadPath = "/package/createLoad" type PackageCreateLoad struct { PackageCreateLoadInfo Files UploadObjectIterator `json:"-"` } type PackageCreateLoadInfo struct { UserID cdssdk.UserID `json:"userID" binding:"required"` BucketID cdssdk.BucketID `json:"bucketID" binding:"required"` Name string `json:"name" binding:"required"` LoadTo []cdssdk.StorageID `json:"loadTo"` LoadToPath []string `json:"loadToPath"` } type PackageCreateLoadResp struct { Package cdssdk.Package `json:"package"` Objects []cdssdk.Object `json:"objects"` } func (c *PackageService) CreateLoad(req PackageCreateLoad) (*PackageCreateLoadResp, error) { url, err := url.JoinPath(c.cfg.URL, PackageCreateLoadPath) if err != nil { return nil, err } infoJSON, err := serder.ObjectToJSON(req) if err != nil { return nil, fmt.Errorf("upload info to json: %w", err) } resp, err := PostMultiPart(c.cfg, url, map[string]string{"info": string(infoJSON)}, iterator.Map(req.Files, func(src *UploadingObject) (*http2.IterMultiPartFile, error) { return &http2.IterMultiPartFile{ FieldName: "files", FileName: src.Path, File: src.File, }, nil })) if err != nil { return nil, err } codeResp, err := ParseJSONResponse[response[PackageCreateLoadResp]](resp) if err != nil { return nil, err } if codeResp.Code == errorcode.OK { return &codeResp.Data, nil } return nil, codeResp.ToError() } const PackageDownloadPath = "/v1/package/download" type PackageDownload struct { UserID cdssdk.UserID `url:"userID" form:"userID" binding:"required"` PackageID cdssdk.PackageID `url:"packageID" form:"packageID" binding:"required"` } func (r *PackageDownload) MakeParam() *sdks.RequestParam { return sdks.MakeJSONParam(http.MethodGet, PackageDownloadPath, r) } type DownloadingPackage struct { Name string File io.ReadCloser } func (c *PackageService) Download(req PackageDownload) (*DownloadingPackage, error) { httpReq, err := req.MakeParam().MakeRequest(c.cfg.URL) if err != nil { return nil, err } if c.cfg.AccessKey != "" && c.cfg.SecretKey != "" { prod := credentials.NewStaticCredentialsProvider(c.cfg.AccessKey, c.cfg.SecretKey, "") cred, err := prod.Retrieve(context.TODO()) if err != nil { return nil, err } signer := v4.NewSigner() err = signer.SignHTTP(context.Background(), cred, httpReq, "", AuthService, AuthRegion, time.Now()) if err != nil { return nil, err } } resp, err := http.DefaultClient.Do(httpReq) if err != nil { return nil, err } contType := resp.Header.Get("Content-Type") if strings.Contains(contType, http2.ContentTypeJSON) { var codeResp response[any] if err := serder.JSONToObjectStream(resp.Body, &codeResp); err != nil { return nil, fmt.Errorf("parsing response: %w", err) } return nil, codeResp.ToError() } _, params, err := mime.ParseMediaType(resp.Header.Get("Content-Disposition")) if err != nil { return nil, fmt.Errorf("parsing content disposition: %w", err) } return &DownloadingPackage{ Name: params["filename"], File: resp.Body, }, nil } const PackageDeletePath = "/package/delete" type PackageDelete struct { UserID cdssdk.UserID `json:"userID" binding:"required"` PackageID cdssdk.PackageID `json:"packageID" binding:"required"` } func (r *PackageDelete) MakeParam() *sdks.RequestParam { return sdks.MakeJSONParam(http.MethodPost, PackageDeletePath, r) } type PackageDeleteResp struct{} func (r *PackageDeleteResp) ParseResponse(resp *http.Response) error { return sdks.ParseCodeDataJSONResponse(resp, r) } func (c *PackageService) Delete(req PackageDelete) error { return JSONAPINoData(c.cfg, http.DefaultClient, &req) } const PackageClonePath = "/package/clone" type PackageClone struct { UserID cdssdk.UserID `json:"userID" binding:"required"` PackageID cdssdk.PackageID `json:"packageID" binding:"required"` BucketID cdssdk.BucketID `json:"bucketID" binding:"required"` Name string `json:"name" binding:"required"` } func (r *PackageClone) MakeParam() *sdks.RequestParam { return sdks.MakeJSONParam(http.MethodPost, PackageClonePath, r) } type PackageCloneResp struct { Package cdssdk.Package `json:"package"` } func (r *PackageCloneResp) ParseResponse(resp *http.Response) error { return sdks.ParseCodeDataJSONResponse(resp, r) } func (c *PackageService) Clone(req PackageClone) (*PackageCloneResp, error) { return JSONAPI(c.cfg, http.DefaultClient, &req, &PackageCloneResp{}) } const PackageListBucketPackagesPath = "/package/listBucketPackages" type PackageListBucketPackages struct { UserID cdssdk.UserID `form:"userID" url:"userID" binding:"required"` BucketID cdssdk.BucketID `form:"bucketID" url:"bucketID" binding:"required"` } func (r *PackageListBucketPackages) MakeParam() *sdks.RequestParam { return sdks.MakeQueryParam(http.MethodGet, PackageListBucketPackagesPath, r) } type PackageListBucketPackagesResp struct { Packages []cdssdk.Package `json:"packages"` } func (r *PackageListBucketPackagesResp) ParseResponse(resp *http.Response) error { return sdks.ParseCodeDataJSONResponse(resp, r) } func (c *PackageService) ListBucketPackages(req PackageListBucketPackages) (*PackageListBucketPackagesResp, error) { return JSONAPI(c.cfg, http.DefaultClient, &req, &PackageListBucketPackagesResp{}) } const PackageGetCachedStoragesPath = "/package/getCachedStorages" type PackageGetCachedStoragesReq struct { PackageID cdssdk.PackageID `form:"packageID" url:"packageID" binding:"required"` UserID cdssdk.UserID `form:"userID" url:"userID" binding:"required"` } func (r *PackageGetCachedStoragesReq) MakeParam() *sdks.RequestParam { return sdks.MakeQueryParam(http.MethodGet, PackageGetCachedStoragesPath, r) } type PackageGetCachedStoragesResp struct { cdssdk.PackageCachingInfo } func (r *PackageGetCachedStoragesResp) ParseResponse(resp *http.Response) error { return sdks.ParseCodeDataJSONResponse(resp, r) } func (c *PackageService) GetCachedStorages(req PackageGetCachedStoragesReq) (*PackageGetCachedStoragesResp, error) { return JSONAPI(c.cfg, http.DefaultClient, &req, &PackageGetCachedStoragesResp{}) } const PackageCalcHashPath = "/v1/package/calcHash" type PackageCalcHash struct { UserID cdssdk.UserID `json:"userID" binding:"required"` PackageID cdssdk.PackageID `json:"packageID" binding:"required"` } func (r *PackageCalcHash) MakeParam() *sdks.RequestParam { return sdks.MakeJSONParam(http.MethodPost, PackageCalcHashPath, r) } type PackageCalcHashResp struct { cdssdk.PackageHash } func (r *PackageCalcHashResp) ParseResponse(resp *http.Response) error { return sdks.ParseCodeDataJSONResponse(resp, r) } func (c *PackageService) CalcHash(req PackageCalcHash) (*PackageCalcHashResp, error) { return JSONAPI(c.cfg, http.DefaultClient, &req, &PackageCalcHashResp{}) }