Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alist-org
GitHub Repository: alist-org/alist
Path: blob/main/internal/db/label_file_binding.go
1560 views
1
package db
2
3
import (
4
"fmt"
5
"github.com/alist-org/alist/v3/internal/model"
6
"github.com/pkg/errors"
7
"gorm.io/gorm"
8
"gorm.io/gorm/clause"
9
"time"
10
)
11
12
// GetLabelIds Get all label_ids from database order by file_name
13
func GetLabelIds(userId uint, fileName string) ([]uint, error) {
14
//fmt.Printf(">>> [GetLabelIds] userId: %d, fileName: %s\n", userId, fileName)
15
labelFileBinDingDB := db.Model(&model.LabelFileBinding{})
16
var labelIds []uint
17
if err := labelFileBinDingDB.Where("file_name = ?", fileName).Where("user_id = ?", userId).Pluck("label_id", &labelIds).Error; err != nil {
18
return nil, errors.WithStack(err)
19
}
20
return labelIds, nil
21
}
22
23
func CreateLabelFileBinDing(fileName string, labelId, userId uint) error {
24
var labelFileBinDing model.LabelFileBinding
25
labelFileBinDing.UserId = userId
26
labelFileBinDing.LabelId = labelId
27
labelFileBinDing.FileName = fileName
28
labelFileBinDing.CreateTime = time.Now()
29
err := errors.WithStack(db.Create(&labelFileBinDing).Error)
30
if err != nil {
31
return errors.WithMessage(err, "failed create label in database")
32
}
33
return nil
34
}
35
36
// GetLabelFileBinDingByLabelIdExists Get Label by label_id, used to del label usually
37
func GetLabelFileBinDingByLabelIdExists(labelId, userId uint) bool {
38
var labelFileBinDing model.LabelFileBinding
39
result := db.Where("label_id = ?", labelId).Where("user_id = ?", userId).First(&labelFileBinDing)
40
exists := !errors.Is(result.Error, gorm.ErrRecordNotFound)
41
return exists
42
}
43
44
// DelLabelFileBinDingByFileName used to del usually
45
func DelLabelFileBinDingByFileName(userId uint, fileName string) error {
46
return errors.WithStack(db.Where("file_name = ?", fileName).Where("user_id = ?", userId).Delete(model.LabelFileBinding{}).Error)
47
}
48
49
// DelLabelFileBinDingById used to del usually
50
func DelLabelFileBinDingById(labelId, userId uint, fileName string) error {
51
return errors.WithStack(db.Where("label_id = ?", labelId).Where("file_name = ?", fileName).Where("user_id = ?", userId).Delete(model.LabelFileBinding{}).Error)
52
}
53
54
func GetLabelFileBinDingByLabelId(labelIds []uint, userId uint) (result []model.LabelFileBinding, err error) {
55
if err := db.Where("label_id in (?)", labelIds).Where("user_id = ?", userId).Find(&result).Error; err != nil {
56
return nil, errors.WithStack(err)
57
}
58
return result, nil
59
}
60
61
func GetLabelBindingsByFileNamesPublic(fileNames []string) (map[string][]uint, error) {
62
var binds []model.LabelFileBinding
63
if err := db.Where("file_name IN ?", fileNames).Find(&binds).Error; err != nil {
64
return nil, errors.WithStack(err)
65
}
66
out := make(map[string][]uint, len(fileNames))
67
seen := make(map[string]struct{}, len(binds))
68
for _, b := range binds {
69
key := fmt.Sprintf("%s-%d", b.FileName, b.LabelId)
70
if _, ok := seen[key]; ok {
71
continue
72
}
73
seen[key] = struct{}{}
74
out[b.FileName] = append(out[b.FileName], b.LabelId)
75
}
76
return out, nil
77
}
78
79
func GetLabelsByFileNamesPublic(fileNames []string) (map[string][]model.Label, error) {
80
bindMap, err := GetLabelBindingsByFileNamesPublic(fileNames)
81
if err != nil {
82
return nil, err
83
}
84
85
idSet := make(map[uint]struct{})
86
for _, ids := range bindMap {
87
for _, id := range ids {
88
idSet[id] = struct{}{}
89
}
90
}
91
if len(idSet) == 0 {
92
return make(map[string][]model.Label, 0), nil
93
}
94
allIDs := make([]uint, 0, len(idSet))
95
for id := range idSet {
96
allIDs = append(allIDs, id)
97
}
98
labels, err := GetLabelByIds(allIDs) // 你已有的函数
99
if err != nil {
100
return nil, err
101
}
102
103
labelByID := make(map[uint]model.Label, len(labels))
104
for _, l := range labels {
105
labelByID[l.ID] = l
106
}
107
108
out := make(map[string][]model.Label, len(bindMap))
109
for fname, ids := range bindMap {
110
for _, id := range ids {
111
if lab, ok := labelByID[id]; ok {
112
out[fname] = append(out[fname], lab)
113
}
114
}
115
}
116
return out, nil
117
}
118
119
func ListLabelFileBinDing(userId uint, labelIDs []uint, fileName string, page, pageSize int) ([]model.LabelFileBinding, int64, error) {
120
q := db.Model(&model.LabelFileBinding{}).Where("user_id = ?", userId)
121
122
if len(labelIDs) > 0 {
123
q = q.Where("label_id IN ?", labelIDs)
124
}
125
if fileName != "" {
126
q = q.Where("file_name LIKE ?", "%"+fileName+"%")
127
}
128
129
var total int64
130
if err := q.Count(&total).Error; err != nil {
131
return nil, 0, errors.WithStack(err)
132
}
133
134
var rows []model.LabelFileBinding
135
if err := q.
136
Order("id DESC").
137
Offset((page - 1) * pageSize).
138
Limit(pageSize).
139
Find(&rows).Error; err != nil {
140
return nil, 0, errors.WithStack(err)
141
}
142
return rows, total, nil
143
}
144
145
func RestoreLabelFileBindings(bindings []model.LabelFileBinding, keepIDs bool, override bool) error {
146
if len(bindings) == 0 {
147
return nil
148
}
149
tx := db.Begin()
150
151
if override {
152
type key struct {
153
uid uint
154
name string
155
}
156
toDel := make(map[key]struct{}, len(bindings))
157
for i := range bindings {
158
k := key{uid: bindings[i].UserId, name: bindings[i].FileName}
159
toDel[k] = struct{}{}
160
}
161
for k := range toDel {
162
if err := tx.Where("user_id = ? AND file_name = ?", k.uid, k.name).
163
Delete(&model.LabelFileBinding{}).Error; err != nil {
164
tx.Rollback()
165
return errors.WithStack(err)
166
}
167
}
168
}
169
170
for i := range bindings {
171
b := bindings[i]
172
if !keepIDs {
173
b.ID = 0
174
}
175
if b.CreateTime.IsZero() {
176
b.CreateTime = time.Now()
177
}
178
if override {
179
if err := tx.Create(&b).Error; err != nil {
180
tx.Rollback()
181
return errors.WithStack(err)
182
}
183
} else {
184
if err := tx.Clauses(clause.OnConflict{DoNothing: true}).Create(&b).Error; err != nil {
185
tx.Rollback()
186
return errors.WithStack(err)
187
}
188
}
189
}
190
191
return errors.WithStack(tx.Commit().Error)
192
}
193
194