Files
alist/server/models/create.go
2021-05-17 16:36:55 +08:00

206 lines
5.1 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 models
import (
"fmt"
"github.com/Xhofe/alist/alidrive"
"github.com/Xhofe/alist/conf"
"github.com/Xhofe/alist/utils"
log "github.com/sirupsen/logrus"
"gorm.io/gorm"
"path/filepath"
"strings"
)
func BuildTreeAll(depth int) {
for i, _ := range conf.Conf.AliDrive.Drives {
if err := BuildTree(&conf.Conf.AliDrive.Drives[i], depth); err != nil {
log.Errorf("盘[%s]构建目录树失败:%s", conf.Conf.AliDrive.Drives[i].Name, err.Error())
} else {
log.Infof("盘[%s]构建目录树成功", conf.Conf.AliDrive.Drives[i].Name)
}
}
}
// build tree
func BuildTree(drive *conf.Drive, depth int) error {
log.Infof("开始构建目录树...")
tx := conf.DB.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
if err := tx.Error; err != nil {
return err
}
rootFile := File{
Dir: "",
FileId: drive.RootFolder,
Name: drive.Name,
Type: "folder",
Password: drive.Password,
}
if err := tx.Create(&rootFile).Error; err != nil {
tx.Rollback()
return err
}
if err := BuildOne(drive.RootFolder, drive.Name+"/", tx, drive.Password, drive, depth); err != nil {
tx.Rollback()
return err
}
return tx.Commit().Error
}
/*
递归构建目录树,插入指定目录下的所有文件
parent 父目录的file_id
path 指定的目录
parentPassword 父目录所携带的密码
drive 要构建的盘
*/
func BuildOne(parent string, path string, tx *gorm.DB, parentPassword string, drive *conf.Drive, depth int) error {
if depth == 0 {
return nil
}
marker := "first"
for marker != "" {
if marker == "first" {
marker = ""
}
files, err := alidrive.GetList(parent, conf.Conf.AliDrive.MaxFilesCount, marker, "", "", drive)
if err != nil {
return err
}
marker = files.NextMarker
for _, file := range files.Items {
name := file.Name
password := parentPassword
if strings.HasSuffix(name, ".hide") {
continue
}
if strings.Contains(name, ".ln-") {
index := strings.Index(name, ".ln-")
name = file.Name[:index]
fileId := file.Name[index+4:]
newFile := File{
Dir: path,
FileExtension: "",
FileId: fileId,
Name: name,
Type: "folder",
UpdatedAt: file.UpdatedAt,
Category: "",
ContentType: "",
Size: 0,
Password: password,
}
log.Debugf("插入file:%+v", newFile)
if err = tx.Create(&newFile).Error; err != nil {
return err
}
if err = BuildOne(fileId, fmt.Sprintf("%s%s/", path, name), tx, password, drive, depth-1); err != nil {
return err
}
continue
}
if strings.Contains(name, ".password-") {
index := strings.Index(name, ".password-")
name = file.Name[:index]
password = file.Name[index+10:]
}
newFile := File{
Dir: path,
FileExtension: file.FileExtension,
FileId: file.FileId,
Name: name,
Type: file.Type,
UpdatedAt: file.UpdatedAt,
Category: file.Category,
ContentType: file.ContentType,
Size: file.Size,
Password: password,
ContentHash: file.ContentHash,
}
log.Debugf("插入file:%+v", newFile)
if err := tx.Create(&newFile).Error; err != nil {
return err
}
if file.Type == "folder" {
if err := BuildOne(file.FileId, fmt.Sprintf("%s%s/", path, name), tx, password, drive, depth-1); err != nil {
return err
}
}
}
}
return nil
}
//重建指定路径与深度的目录树: 先删除该目录与该目录下所有文件的model再重新插入
func BuildTreeWithPath(path string, depth int) error {
dir, name := filepath.Split(path)
driveName := strings.Split(path, "/")[0]
drive := utils.GetDriveByName(driveName)
if drive == nil {
return fmt.Errorf("找不到drive[%s]", driveName)
}
file := &File{
Dir: "",
FileId: drive.RootFolder,
Name: drive.Name,
Type: "folder",
Password: drive.Password,
}
var err error
if dir != "" {
file, err = GetFileByDirAndName(dir, name)
if err != nil {
if file == nil {
return fmt.Errorf("path not found")
}
return err
}
}
tx := conf.DB.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
if err = tx.Error; err != nil {
tx.Rollback()
return err
}
if err = tx.Where("dir = ? AND name = ?", file.Dir, file.Name).Delete(file).Error; err != nil{
tx.Rollback()
return err
}
if err = tx.Where("dir like ?", fmt.Sprintf("%s%%", path)).Delete(&File{}).Error; err != nil{
tx.Rollback()
return err
}
//if dir != "" {
// aliFile, err := alidrive.GetFile(file.FileId, drive)
// if err != nil {
// tx.Rollback()
// return err
// }
// aliName := aliFile.Name
// if strings.HasSuffix(aliName, ".hide") {
// return nil
// }
// if strings.Contains(aliName, ".password-") {
// index := strings.Index(name, ".password-")
// file.Name = aliName[:index]
// file.Password = aliName[index+10:]
// }
//}
if err = tx.Create(&file).Error; err != nil {
return err
}
if err = BuildOne(file.FileId, path+"/", tx, file.Password, drive, depth); err != nil {
tx.Rollback()
return err
}
return tx.Commit().Error
}