Files
OpenList/drivers/ipfs_api/driver.go
Kuingsmile fdcc2f136e chore: change module name to OpenListTeam/OpenList (#2)
* Enable blank issue

* chore(README.md): update docs (temporally)

* Update FUNDING.yml

* chore: purge README.md

* chore: change module name to OpenListTeam/OpenList

* fix: fix link errors

* chore: remove v3 in module name

* fix: resolve some conficts

* fix: resolve conficts

* docs: update with latest file

---------

Co-authored-by: ShenLin <773933146@qq.com>
Co-authored-by: Hantong Chen <cxwdyx620@gmail.com>
Co-authored-by: joshua <i@joshua.su>
Co-authored-by: Hantong Chen <70561268+cxw620@users.noreply.github.com>
2025-06-12 22:02:46 +08:00

189 lines
5.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package ipfs
import (
"context"
"fmt"
"net/url"
"path"
shell "github.com/ipfs/go-ipfs-api"
"github.com/OpenListTeam/OpenList/internal/driver"
"github.com/OpenListTeam/OpenList/internal/model"
)
type IPFS struct {
model.Storage
Addition
sh *shell.Shell
gateURL *url.URL
}
func (d *IPFS) Config() driver.Config {
return config
}
func (d *IPFS) GetAddition() driver.Additional {
return &d.Addition
}
func (d *IPFS) Init(ctx context.Context) error {
d.sh = shell.NewShell(d.Endpoint)
gateURL, err := url.Parse(d.Gateway)
if err != nil {
return err
}
d.gateURL = gateURL
return nil
}
func (d *IPFS) Drop(ctx context.Context) error {
return nil
}
func (d *IPFS) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
var ipfsPath string
cid := dir.GetID()
if cid != "" {
ipfsPath = path.Join("/ipfs", cid)
} else {
// 可能出现ipns dns解析失败的情况需要重复获取cid其他情况应该不会出错
ipfsPath = dir.GetPath()
switch d.Mode {
case "ipfs":
ipfsPath = path.Join("/ipfs", ipfsPath)
case "ipns":
ipfsPath = path.Join("/ipns", ipfsPath)
case "mfs":
fileStat, err := d.sh.FilesStat(ctx, ipfsPath)
if err != nil {
return nil, err
}
ipfsPath = path.Join("/ipfs", fileStat.Hash)
default:
return nil, fmt.Errorf("mode error")
}
}
dirs, err := d.sh.List(ipfsPath)
if err != nil {
return nil, err
}
objlist := []model.Obj{}
for _, file := range dirs {
objlist = append(objlist, &model.Object{ID: file.Hash, Name: file.Name, Size: int64(file.Size), IsFolder: file.Type == 1})
}
return objlist, nil
}
func (d *IPFS) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
gateurl := d.gateURL.JoinPath("/ipfs/", file.GetID())
gateurl.RawQuery = "filename=" + url.QueryEscape(file.GetName())
return &model.Link{URL: gateurl.String()}, nil
}
func (d *IPFS) Get(ctx context.Context, rawPath string) (model.Obj, error) {
rawPath = path.Join(d.GetRootPath(), rawPath)
var ipfsPath string
switch d.Mode {
case "ipfs":
ipfsPath = path.Join("/ipfs", rawPath)
case "ipns":
ipfsPath = path.Join("/ipns", rawPath)
case "mfs":
fileStat, err := d.sh.FilesStat(ctx, rawPath)
if err != nil {
return nil, err
}
ipfsPath = path.Join("/ipfs", fileStat.Hash)
default:
return nil, fmt.Errorf("mode error")
}
file, err := d.sh.FilesStat(ctx, ipfsPath)
if err != nil {
return nil, err
}
return &model.Object{ID: file.Hash, Name: path.Base(rawPath), Path: rawPath, Size: int64(file.Size), IsFolder: file.Type == "directory"}, nil
}
func (d *IPFS) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) (model.Obj, error) {
if d.Mode != "mfs" {
return nil, fmt.Errorf("only write in mfs mode")
}
dirPath := parentDir.GetPath()
err := d.sh.FilesMkdir(ctx, path.Join(dirPath, dirName), shell.FilesMkdir.Parents(true))
if err != nil {
return nil, err
}
file, err := d.sh.FilesStat(ctx, path.Join(dirPath, dirName))
if err != nil {
return nil, err
}
return &model.Object{ID: file.Hash, Name: dirName, Path: path.Join(dirPath, dirName), Size: int64(file.Size), IsFolder: true}, nil
}
func (d *IPFS) Move(ctx context.Context, srcObj, dstDir model.Obj) (model.Obj, error) {
if d.Mode != "mfs" {
return nil, fmt.Errorf("only write in mfs mode")
}
dstPath := path.Join(dstDir.GetPath(), path.Base(srcObj.GetPath()))
d.sh.FilesRm(ctx, dstPath, true)
return &model.Object{ID: srcObj.GetID(), Name: srcObj.GetName(), Path: dstPath, Size: int64(srcObj.GetSize()), IsFolder: srcObj.IsDir()},
d.sh.FilesMv(ctx, srcObj.GetPath(), dstDir.GetPath())
}
func (d *IPFS) Rename(ctx context.Context, srcObj model.Obj, newName string) (model.Obj, error) {
if d.Mode != "mfs" {
return nil, fmt.Errorf("only write in mfs mode")
}
dstPath := path.Join(path.Dir(srcObj.GetPath()), newName)
d.sh.FilesRm(ctx, dstPath, true)
return &model.Object{ID: srcObj.GetID(), Name: newName, Path: dstPath, Size: int64(srcObj.GetSize()),
IsFolder: srcObj.IsDir()}, d.sh.FilesMv(ctx, srcObj.GetPath(), dstPath)
}
func (d *IPFS) Copy(ctx context.Context, srcObj, dstDir model.Obj) (model.Obj, error) {
if d.Mode != "mfs" {
return nil, fmt.Errorf("only write in mfs mode")
}
dstPath := path.Join(dstDir.GetPath(), path.Base(srcObj.GetPath()))
d.sh.FilesRm(ctx, dstPath, true)
return &model.Object{ID: srcObj.GetID(), Name: srcObj.GetName(), Path: dstPath, Size: int64(srcObj.GetSize()), IsFolder: srcObj.IsDir()},
d.sh.FilesCp(ctx, path.Join("/ipfs/", srcObj.GetID()), dstPath, shell.FilesCp.Parents(true))
}
func (d *IPFS) Remove(ctx context.Context, obj model.Obj) error {
if d.Mode != "mfs" {
return fmt.Errorf("only write in mfs mode")
}
return d.sh.FilesRm(ctx, obj.GetPath(), true)
}
func (d *IPFS) Put(ctx context.Context, dstDir model.Obj, s model.FileStreamer, up driver.UpdateProgress) (model.Obj, error) {
if d.Mode != "mfs" {
return nil, fmt.Errorf("only write in mfs mode")
}
outHash, err := d.sh.Add(driver.NewLimitedUploadStream(ctx, &driver.ReaderUpdatingProgress{
Reader: s,
UpdateProgress: up,
}))
if err != nil {
return nil, err
}
dstPath := path.Join(dstDir.GetPath(), s.GetName())
if s.GetExist() != nil {
d.sh.FilesRm(ctx, dstPath, true)
}
err = d.sh.FilesCp(ctx, path.Join("/ipfs/", outHash), dstPath, shell.FilesCp.Parents(true))
gateurl := d.gateURL.JoinPath("/ipfs/", outHash)
gateurl.RawQuery = "filename=" + url.QueryEscape(s.GetName())
return &model.Object{ID: outHash, Name: s.GetName(), Path: dstPath, Size: int64(s.GetSize()), IsFolder: s.IsDir()}, err
}
//func (d *Template) Other(ctx context.Context, args model.OtherArgs) (interface{}, error) {
// return nil, errs.NotSupport
//}
var _ driver.Driver = (*IPFS)(nil)