| @@ -9,6 +9,11 @@ import ( | |||
| myio "gitlink.org.cn/cloudream/common/utils/io" | |||
| ) | |||
| type ReadOption struct { | |||
| Offset int64 // 从指定位置开始读取,为-1时代表不设置,从头开始读 | |||
| Length int64 // 读取长度,为-1时代表不设置,读取Offset之后的所有内容 | |||
| } | |||
| type Client struct { | |||
| shell *shell.Shell | |||
| } | |||
| @@ -54,8 +59,33 @@ func (fs *Client) CreateFile(file io.Reader) (string, error) { | |||
| return fs.shell.Add(file) | |||
| } | |||
| func (fs *Client) OpenRead(hash string) (io.ReadCloser, error) { | |||
| return fs.shell.Cat(hash) | |||
| func (fs *Client) OpenRead(hash string, opts ...ReadOption) (io.ReadCloser, error) { | |||
| opt := ReadOption{ | |||
| Offset: 0, | |||
| Length: -1, | |||
| } | |||
| if len(opts) > 0 { | |||
| opt = opts[0] | |||
| } | |||
| req := fs.shell.Request("cat", hash) | |||
| if opt.Offset >= 0 { | |||
| req.Option("offset", opt.Offset) | |||
| } | |||
| if opt.Length >= 0 { | |||
| req.Option("length", opt.Length) | |||
| } | |||
| resp, err := req.Send(context.Background()) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| if resp.Error != nil { | |||
| return nil, resp.Error | |||
| } | |||
| return resp.Output, nil | |||
| } | |||
| func (fs *Client) Pin(hash string) error { | |||
| @@ -0,0 +1,51 @@ | |||
| package imsdk | |||
| import ( | |||
| "gitlink.org.cn/cloudream/common/sdks" | |||
| ) | |||
| type response[T any] struct { | |||
| Code string `json:"code"` | |||
| Message string `json:"message"` | |||
| Data T `json:"data"` | |||
| } | |||
| func (r *response[T]) ToError() *sdks.CodeMessageError { | |||
| return &sdks.CodeMessageError{ | |||
| Code: r.Code, | |||
| Message: r.Message, | |||
| } | |||
| } | |||
| type Client struct { | |||
| baseURL string | |||
| } | |||
| func NewClient(cfg *Config) *Client { | |||
| return &Client{ | |||
| baseURL: cfg.URL, | |||
| } | |||
| } | |||
| type Pool interface { | |||
| Acquire() (*Client, error) | |||
| Release(cli *Client) | |||
| } | |||
| type pool struct { | |||
| cfg *Config | |||
| } | |||
| func NewPool(cfg *Config) Pool { | |||
| return &pool{ | |||
| cfg: cfg, | |||
| } | |||
| } | |||
| func (p *pool) Acquire() (*Client, error) { | |||
| cli := NewClient(p.cfg) | |||
| return cli, nil | |||
| } | |||
| func (p *pool) Release(cli *Client) { | |||
| } | |||
| @@ -0,0 +1,5 @@ | |||
| package imsdk | |||
| type Config struct { | |||
| URL string `json:"url"` | |||
| } | |||
| @@ -0,0 +1,38 @@ | |||
| package imsdk | |||
| import ( | |||
| "io" | |||
| "testing" | |||
| . "github.com/smartystreets/goconvey/convey" | |||
| ) | |||
| func Test_IPFSRead(t *testing.T) { | |||
| Convey("读取IPFS文件", t, func() { | |||
| cli := NewClient(&Config{ | |||
| URL: "http://localhost:7893", | |||
| }) | |||
| file, err := cli.IPFSRead(IPFSRead{ | |||
| FileHash: "QmcYsRZxmYGgSaydEiJwJRMsD8uWzS2x8gCt1iGMtsZKsU", | |||
| Length: 2, | |||
| }) | |||
| So(err, ShouldBeNil) | |||
| defer file.Close() | |||
| data, err := io.ReadAll(file) | |||
| So(err, ShouldBeNil) | |||
| So(len(data), ShouldEqual, 2) | |||
| }) | |||
| } | |||
| func Test_Package(t *testing.T) { | |||
| Convey("获取Package文件列表", t, func() { | |||
| cli := NewClient(&Config{ | |||
| URL: "http://localhost:7893", | |||
| }) | |||
| _, err := cli.PackageGetWithObjectCacheInfos(PackageGetWithObjectCacheInfos{UserID: 0, PackageID: 13}) | |||
| So(err, ShouldBeNil) | |||
| }) | |||
| } | |||
| @@ -0,0 +1,50 @@ | |||
| package imsdk | |||
| import ( | |||
| "fmt" | |||
| "io" | |||
| "net/url" | |||
| "strings" | |||
| myhttp "gitlink.org.cn/cloudream/common/utils/http" | |||
| "gitlink.org.cn/cloudream/common/utils/serder" | |||
| ) | |||
| const IPFSReadPath = "/ipfs/read" | |||
| type IPFSRead struct { | |||
| FileHash string `json:"fileHash"` | |||
| Offset int64 `json:"offset"` | |||
| Length int64 `json:"length,omitempty"` // 接口允许设置Length为0,所以这里只能omitempty | |||
| } | |||
| func (c *Client) IPFSRead(req IPFSRead) (io.ReadCloser, error) { | |||
| url, err := url.JoinPath(c.baseURL, IPFSReadPath) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| resp, err := myhttp.GetForm(url, myhttp.RequestParam{ | |||
| Query: req, | |||
| }) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| contType := resp.Header.Get("Content-Type") | |||
| if strings.Contains(contType, myhttp.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() | |||
| } | |||
| if strings.Contains(contType, myhttp.ContentTypeOctetStream) { | |||
| return resp.Body, nil | |||
| } | |||
| return nil, fmt.Errorf("unknow response content type: %s", contType) | |||
| } | |||
| @@ -0,0 +1,45 @@ | |||
| package imsdk | |||
| import ( | |||
| "net/url" | |||
| "gitlink.org.cn/cloudream/common/consts/errorcode" | |||
| stgsdk "gitlink.org.cn/cloudream/common/sdks/storage" | |||
| myhttp "gitlink.org.cn/cloudream/common/utils/http" | |||
| ) | |||
| const PackageGetWithObjectCacheInfosPath = "/package/getWithObjectCacheInfos" | |||
| type PackageGetWithObjectCacheInfos struct { | |||
| UserID int64 `json:"userID"` | |||
| PackageID int64 `json:"packageID"` | |||
| } | |||
| type PackageGetWithObjectCacheInfosResp struct { | |||
| Package stgsdk.Package `json:"package"` | |||
| ObjectCacheInfos []stgsdk.ObjectCacheInfo `json:"objectCacheInfos"` | |||
| } | |||
| func (c *Client) PackageGetWithObjectCacheInfos(req PackageGetWithObjectCacheInfos) (*PackageGetWithObjectCacheInfosResp, error) { | |||
| url, err := url.JoinPath(c.baseURL, PackageGetWithObjectCacheInfosPath) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| resp, err := myhttp.GetForm(url, myhttp.RequestParam{ | |||
| Query: req, | |||
| }) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| jsonResp, err := myhttp.ParseJSONResponse[response[PackageGetWithObjectCacheInfosResp]](resp) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| if jsonResp.Code == errorcode.OK { | |||
| return &jsonResp.Data, nil | |||
| } | |||
| return nil, jsonResp.ToError() | |||
| } | |||
| @@ -41,15 +41,15 @@ func (c *Client) CacheMovePackage(req CacheMovePackageReq) (*CacheMovePackageRes | |||
| return nil, jsonResp.ToError() | |||
| } | |||
| type GetPackageObjectCacheInfosReq struct { | |||
| type CacheGetPackageObjectCacheInfosReq struct { | |||
| UserID int64 `json:"userID"` | |||
| PackageID int64 `json:"packageID"` | |||
| } | |||
| type GetPackageObjectCacheInfosResp struct { | |||
| type CacheGetPackageObjectCacheInfosResp struct { | |||
| Infos []ObjectCacheInfo `json:"cacheInfos"` | |||
| } | |||
| func (c *Client) GetPackageObjectCacheInfos(req GetPackageObjectCacheInfosReq) (*GetPackageObjectCacheInfosResp, error) { | |||
| func (c *Client) CacheGetPackageObjectCacheInfos(req CacheGetPackageObjectCacheInfosReq) (*CacheGetPackageObjectCacheInfosResp, error) { | |||
| url, err := url.JoinPath(c.baseURL, "/cache/getPackageObjectCacheInfos") | |||
| if err != nil { | |||
| return nil, err | |||
| @@ -62,7 +62,7 @@ func (c *Client) GetPackageObjectCacheInfos(req GetPackageObjectCacheInfosReq) ( | |||
| return nil, err | |||
| } | |||
| jsonResp, err := myhttp.ParseJSONResponse[response[GetPackageObjectCacheInfosResp]](resp) | |||
| jsonResp, err := myhttp.ParseJSONResponse[response[CacheGetPackageObjectCacheInfosResp]](resp) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| @@ -200,7 +200,7 @@ func Test_Cache(t *testing.T) { | |||
| }) | |||
| So(err, ShouldBeNil) | |||
| cacheInfoResp, err := cli.GetPackageObjectCacheInfos(GetPackageObjectCacheInfosReq{ | |||
| cacheInfoResp, err := cli.CacheGetPackageObjectCacheInfos(CacheGetPackageObjectCacheInfosReq{ | |||
| UserID: 0, | |||
| PackageID: upResp.PackageID, | |||
| }) | |||