feat(ipfs): better ipfs support (#8225)
Some checks failed
auto_lang / auto generate lang.json (1.21, ubuntu-latest) (push) Has been cancelled
beta release / Beta Release Changelog (1.21, ubuntu-latest) (push) Has been cancelled
build / Build (ubuntu-latest, android-arm64) (push) Has been cancelled
build / Build (ubuntu-latest, darwin-amd64) (push) Has been cancelled
build / Build (ubuntu-latest, darwin-arm64) (push) Has been cancelled
build / Build (ubuntu-latest, linux-amd64-musl) (push) Has been cancelled
build / Build (ubuntu-latest, linux-arm64-musl) (push) Has been cancelled
build / Build (ubuntu-latest, windows-amd64) (push) Has been cancelled
build / Build (ubuntu-latest, windows-arm64) (push) Has been cancelled
release_docker / Build Binaries for Docker Release (push) Has been cancelled
beta release / Beta Release (md5, !(*musl*|*windows-arm64*|*android*|*freebsd*)) (push) Has been cancelled
beta release / Beta Release (md5-android, android-*) (push) Has been cancelled
beta release / Beta Release (md5-freebsd, freebsd-*) (push) Has been cancelled
beta release / Beta Release (md5-linux-musl, linux-!(arm*)-musl*) (push) Has been cancelled
beta release / Beta Release (md5-linux-musl-arm, linux-arm*-musl*) (push) Has been cancelled
beta release / Beta Release Desktop (push) Has been cancelled
release_docker / Release Docker image (INSTALL_FFMPEG=true INSTALL_ARIA2=true , aio, suffix=-aio,onlatest=true) (push) Has been cancelled
beta release / Beta Release (md5-windows-arm64, windows-arm64) (push) Has been cancelled
release_docker / Release Docker image (, latest, ) (push) Has been cancelled
release_docker / Release Docker image (INSTALL_ARIA2=true, aria2, suffix=-aria2,onlatest=true) (push) Has been cancelled
release_docker / Release Docker image (INSTALL_FFMPEG=true, ffmpeg, suffix=-ffmpeg,onlatest=true) (push) Has been cancelled
Close inactive / close-inactive (push) Has been cancelled

* feat:  better ipfs support

fixed mfs crud, added ipns support

* Update driver.go

clean up
This commit is contained in:
jerry 2025-03-27 23:25:23 +08:00 committed by GitHub
parent 7b62dcb88c
commit 0cde4e73d6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 48 additions and 31 deletions

View File

@ -4,13 +4,13 @@ import (
"context"
"fmt"
"net/url"
stdpath "path"
"path/filepath"
"strings"
shell "github.com/ipfs/go-ipfs-api"
"github.com/alist-org/alist/v3/internal/driver"
"github.com/alist-org/alist/v3/internal/model"
shell "github.com/ipfs/go-ipfs-api"
)
type IPFS struct {
@ -44,27 +44,32 @@ func (d *IPFS) Drop(ctx context.Context) error {
func (d *IPFS) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
path := dir.GetPath()
if path[len(path):] != "/" {
path += "/"
switch d.Mode {
case "ipfs":
path, _ = url.JoinPath("/ipfs", path)
case "ipns":
path, _ = url.JoinPath("/ipns", path)
case "mfs":
fileStat, err := d.sh.FilesStat(ctx, path)
if err != nil {
return nil, err
}
path, _ = url.JoinPath("/ipfs", fileStat.Hash)
default:
return nil, fmt.Errorf("mode error")
}
path_cid, err := d.sh.FilesStat(ctx, path)
if err != nil {
return nil, err
}
dirs, err := d.sh.List(path_cid.Hash)
dirs, err := d.sh.List(path)
if err != nil {
return nil, err
}
objlist := []model.Obj{}
for _, file := range dirs {
gateurl := *d.gateURL
gateurl.Path = "ipfs/" + file.Hash
gateurl := *d.gateURL.JoinPath("/ipfs/" + file.Hash)
gateurl.RawQuery = "filename=" + url.PathEscape(file.Name)
objlist = append(objlist, &model.ObjectURL{
Object: model.Object{ID: file.Hash, Name: file.Name, Size: int64(file.Size), IsFolder: file.Type == 1},
Object: model.Object{ID: "/ipfs/" + file.Hash, Name: file.Name, Size: int64(file.Size), IsFolder: file.Type == 1},
Url: model.Url{Url: gateurl.String()},
})
}
@ -73,11 +78,15 @@ func (d *IPFS) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]
}
func (d *IPFS) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
link := d.Gateway + "/ipfs/" + file.GetID() + "/?filename=" + url.PathEscape(file.GetName())
return &model.Link{URL: link}, nil
gateurl := d.gateURL.JoinPath(file.GetID())
gateurl.RawQuery = "filename=" + url.PathEscape(file.GetName())
return &model.Link{URL: gateurl.String()}, nil
}
func (d *IPFS) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error {
if d.Mode != "mfs" {
return fmt.Errorf("only write in mfs mode")
}
path := parentDir.GetPath()
if path[len(path):] != "/" {
path += "/"
@ -86,42 +95,48 @@ func (d *IPFS) MakeDir(ctx context.Context, parentDir model.Obj, dirName string)
}
func (d *IPFS) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
if d.Mode != "mfs" {
return fmt.Errorf("only write in mfs mode")
}
return d.sh.FilesMv(ctx, srcObj.GetPath(), dstDir.GetPath())
}
func (d *IPFS) Rename(ctx context.Context, srcObj model.Obj, newName string) error {
if d.Mode != "mfs" {
return fmt.Errorf("only write in mfs mode")
}
newFileName := filepath.Dir(srcObj.GetPath()) + "/" + newName
return d.sh.FilesMv(ctx, srcObj.GetPath(), strings.ReplaceAll(newFileName, "\\", "/"))
}
func (d *IPFS) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
// TODO copy obj, optional
fmt.Println(srcObj.GetPath())
fmt.Println(dstDir.GetPath())
if d.Mode != "mfs" {
return fmt.Errorf("only write in mfs mode")
}
newFileName := dstDir.GetPath() + "/" + filepath.Base(srcObj.GetPath())
fmt.Println(newFileName)
return d.sh.FilesCp(ctx, srcObj.GetPath(), strings.ReplaceAll(newFileName, "\\", "/"))
}
func (d *IPFS) Remove(ctx context.Context, obj model.Obj) error {
// TODO remove obj, optional
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) error {
// TODO upload file, optional
_, err := d.sh.Add(driver.NewLimitedUploadStream(ctx, &driver.ReaderUpdatingProgress{
if d.Mode != "mfs" {
return fmt.Errorf("only write in mfs mode")
}
outHash, err := d.sh.Add(driver.NewLimitedUploadStream(ctx, &driver.ReaderUpdatingProgress{
Reader: s,
UpdateProgress: up,
}), ToFiles(stdpath.Join(dstDir.GetPath(), s.GetName())))
return err
}
func ToFiles(dstDir string) shell.AddOpts {
return func(rb *shell.RequestBuilder) error {
rb.Option("to-files", dstDir)
return nil
}))
if err != nil {
return err
}
err = d.sh.FilesCp(ctx, "/ipfs/"+outHash, dstDir.GetPath()+"/"+strings.ReplaceAll(s.GetName(), "\\", "/"))
return err
}
//func (d *Template) Other(ctx context.Context, args model.OtherArgs) (interface{}, error) {

View File

@ -8,14 +8,16 @@ import (
type Addition struct {
// Usually one of two
driver.RootPath
Mode string `json:"mode" options:"ipfs,ipns,mfs" type:"select" required:"true"`
Endpoint string `json:"endpoint" default:"http://127.0.0.1:5001"`
Gateway string `json:"gateway" default:"https://ipfs.io"`
Gateway string `json:"gateway" default:"http://127.0.0.1:8080"`
}
var config = driver.Config{
Name: "IPFS API",
DefaultRoot: "/",
LocalSort: true,
OnlyProxy: false,
}
func init() {