package dbfs import ( "context" "path" "strings" "github.com/cloudreve/Cloudreve/v4/pkg/auth/requestinfo" "github.com/cloudreve/Cloudreve/v4/pkg/filemanager/eventhub" "github.com/cloudreve/Cloudreve/v4/pkg/filemanager/fs" "github.com/cloudreve/Cloudreve/v4/pkg/hashid" "github.com/samber/lo" ) func (f *DBFS) emitFileCreated(ctx context.Context, file *File) { subscribers := f.getEligibleSubscriber(ctx, file, true) for _, subscriber := range subscribers { subscriber.Publish(eventhub.Event{ Type: eventhub.EventTypeCreate, FileID: hashid.EncodeFileID(f.hasher, file.Model.ID), From: subscriber.relativePath(file), }) } } func (f *DBFS) emitFileModified(ctx context.Context, file *File) { subscribers := f.getEligibleSubscriber(ctx, file, true) for _, subscriber := range subscribers { subscriber.Publish(eventhub.Event{ Type: eventhub.EventTypeModify, FileID: hashid.EncodeFileID(f.hasher, file.Model.ID), From: subscriber.relativePath(file), }) } } func (f *DBFS) emitFileRenamed(ctx context.Context, file *File, newName string) { subscribers := f.getEligibleSubscriber(ctx, file, true) for _, subscriber := range subscribers { from := subscriber.relativePath(file) to := strings.TrimSuffix(from, file.Name()) + newName subscriber.Publish(eventhub.Event{ Type: eventhub.EventTypeRename, FileID: hashid.EncodeFileID(f.hasher, file.Model.ID), From: subscriber.relativePath(file), To: to, }) } } func (f *DBFS) emitFileDeleted(ctx context.Context, files ...*File) { for _, file := range files { subscribers := f.getEligibleSubscriber(ctx, file, true) for _, subscriber := range subscribers { subscriber.Publish(eventhub.Event{ Type: eventhub.EventTypeDelete, FileID: hashid.EncodeFileID(f.hasher, file.Model.ID), From: subscriber.relativePath(file), }) } } } func (f *DBFS) emitFileMoved(ctx context.Context, src, dst *File) { srcSubMap := lo.SliceToMap(f.getEligibleSubscriber(ctx, src, true), func(subscriber foundSubscriber) (string, *foundSubscriber) { return subscriber.ID(), &subscriber }) dstSubMap := lo.SliceToMap(f.getEligibleSubscriber(ctx, dst, false), func(subscriber foundSubscriber) (string, *foundSubscriber) { return subscriber.ID(), &subscriber }) for _, subscriber := range srcSubMap { subId := subscriber.ID() if dstSub, ok := dstSubMap[subId]; ok { // Src and Dst subscribed by the same subscriber subscriber.Publish(eventhub.Event{ Type: eventhub.EventTypeRename, FileID: hashid.EncodeFileID(f.hasher, src.Model.ID), From: subscriber.relativePath(src), To: path.Join(dstSub.relativePath(dst), src.Name()), }) delete(dstSubMap, subId) } else { // Only Src is subscribed by the subscriber subscriber.Publish(eventhub.Event{ Type: eventhub.EventTypeDelete, FileID: hashid.EncodeFileID(f.hasher, src.Model.ID), From: subscriber.relativePath(src), }) } } for _, subscriber := range dstSubMap { // Only Dst is subscribed by the subscriber subscriber.Publish(eventhub.Event{ Type: eventhub.EventTypeCreate, FileID: hashid.EncodeFileID(f.hasher, src.Model.ID), From: path.Join(subscriber.relativePath(dst), src.Name()), }) } } func (f *DBFS) getEligibleSubscriber(ctx context.Context, file *File, checkParentPerm bool) []foundSubscriber { roots := file.Ancestors() if !checkParentPerm { // Include file itself roots = file.AncestorsChain() } requestInfo := requestinfo.RequestInfoFromContext(ctx) eligibleSubscribers := make([]foundSubscriber, 0) for _, root := range roots { subscribers := f.eventHub.GetSubscribers(ctx, root.Model.ID) subscribers = lo.Filter(subscribers, func(subscriber eventhub.Subscriber, index int) bool { // Exlucde self from subscribers if requestInfo != nil && subscriber.ID() == requestInfo.ClientID { return false } return true }) eligibleSubscribers = append(eligibleSubscribers, lo.Map(subscribers, func(subscriber eventhub.Subscriber, index int) foundSubscriber { return foundSubscriber{ Subscriber: subscriber, root: root, } })...) } return eligibleSubscribers } type foundSubscriber struct { eventhub.Subscriber root *File } func (s *foundSubscriber) relativePath(file *File) string { res := strings.TrimPrefix(file.Uri(true).Path(), s.root.Uri(true).Path()) if res == "" { res = fs.Separator } if res[0] != fs.Separator[0] { res = fs.Separator + res } return res }