-
Notifications
You must be signed in to change notification settings - Fork 0
/
model.go
185 lines (164 loc) · 5.13 KB
/
model.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
package util
import (
"encoding/json"
"fmt"
"github.com/samber/lo"
"hash/crc32"
"os"
"path/filepath"
"strconv"
"strings"
"time"
)
const (
GB = 1 << 30
MB = 1024 * 1024
Day = 24 * 60 * 60
RFC3339 = "2006-01-02 15:04:05Z07:00"
MIMEOctetStream = "application/octet-stream"
NormalFilePerm = 0666
NormalDirPerm = 0750
RepoName = "Wuliu File Manager"
RepoURL = "https://github.com/ahui2016/wuliu"
ProjectInfoPath = "project.json"
FileCheckedPath = "file_checked.json"
DatabasePath = "project.db"
)
const (
FILES = "files"
METADATA = "metadata"
INPUT = "input"
BUFFER = "buffer"
WEBPAGES = "webpages"
TEMPLATES = "webpages/templates"
RECYCLEBIN = "recyclebin"
)
var Folders = []string{
FILES,
METADATA,
INPUT,
BUFFER,
WEBPAGES,
TEMPLATES,
RECYCLEBIN,
}
var (
Epoch = time.Unix(0, 0).Format(RFC3339)
Separator = string(filepath.Separator)
)
type (
Base64String = string
HexString = string
)
type ProjectInfo struct {
RepoName string // 用于判断资料夹是否 Wuliu 专案
ProjectName string // 备份时要求专案名称相同
IsBackup bool // 是否副本(副本禁止添加、删除等)
Projects []string // 第一个是主专案,然后是备份专案
LastBackupAt []string // 上次备份时间
CheckInterval int // 检查完整性, 单位: day
CheckSizeLimit int // 检查完整性, 单位: MB
ExportSizeLimit int64 // 導出檔案體積上限,單位: MB
ThumbSize [2]int // 縮略圖尺寸
}
func NewProjectInfo(name string) (info ProjectInfo) {
info.RepoName = RepoName
info.ProjectName = name
info.Projects = []string{"."} // 注意必须确保第一个是 "."
info.LastBackupAt = []string{Epoch}
info.CheckInterval = 30
info.CheckSizeLimit = 1024
info.ExportSizeLimit = 300
info.ThumbSize = [2]int{150, 150}
return
}
type ProjectStatus struct {
*ProjectInfo
Root string // 专案根目录
TotalSize int64 // 全部檔案體積合計
FilesCount int // 檔案數量合計
DamagedCount int // 受損檔案數量合計
}
// EditFiles 用于批量修改档案属性。
type EditFiles struct {
IDs []string `json:"ids"` // 通过 ID 指定档案
Filenames []string `json:"filenames"` // 通过档案名称指定档案
Like int `json:"like"` // 點贊
Label string `json:"label"` // 标签,便於搜尋
Notes string `json:"notes"` // 備註,便於搜尋
Keywords []string `json:"keywords"` // 關鍵詞, 便於搜尋
Collections []string `json:"collections"` // 集合(分组),一个档案可属于多个集合
Albums []string `json:"albums"` // 相册(专辑),主要用于图片和音乐
}
func NewEditFiles(ids, filenames []string) *EditFiles {
ef := new(EditFiles)
ef.IDs = ids
ef.Filenames = filenames
ef.Keywords = []string{}
ef.Collections = []string{}
ef.Albums = []string{}
return ef
}
func (ef *EditFiles) Check() (err error) {
if len(ef.IDs) > 0 && len(ef.Filenames) > 0 {
err = fmt.Errorf("只能指定 ID 或檔案名稱,不可兩者同時指定。")
}
return
}
type FileChecked struct {
ID string // 档案名称的 CRC32
Checked string // RFC3339 上次校驗檔案完整性的時間
Damaged bool // 上次校驗結果 (檔案是否損壞)
}
type File struct {
ID string `json:"id"` // 档案名称的 CRC32
Filename string `json:"filename"` // 档案名称
Checksum string `json:"checksum"` // BLAKE2b
Size int64 `json:"size"` // length in bytes for regular files
Type string `json:"type"` // 檔案類型, 例: text/js, office/docx
Like int `json:"like"` // 點贊
Label string `json:"label"` // 标签,便於搜尋
Notes string `json:"notes"` // 備註,便於搜尋
Keywords []string `json:"keywords"` // 關鍵詞, 便於搜尋
Collections []string `json:"collections"` // 集合(分组),一个档案可属于多个集合
Albums []string `json:"albums"` // 相册(专辑),主要用于图片和音乐
CTime string `json:"ctime"` // RFC3339 檔案入庫時間
UTime string `json:"utime"` // RFC3339 檔案更新時間
}
type FileAndMeta struct {
*File
Metadata []byte
}
func NewFile(name string) *File {
now := Now()
f := new(File)
f.ID = NameToID(name)
f.Filename = name
f.CTime = now
f.UTime = now
return f
}
func ReadFile(filePath string) (f File) {
data := lo.Must(os.ReadFile(filePath))
lo.Must0(json.Unmarshal(data, &f))
return
}
func NamesToIds(names []string) (ids []string) {
for _, name := range names {
ids = append(ids, NameToID(name))
}
return
}
// NameToID 目前采用 CRC32Str36
func NameToID(name string) string {
return CRC32Str36(name)
}
// CRC32Str36 把一个字符串转化为 crc32, 再转化为 36 进制。
func CRC32Str36(s string) string {
sum := crc32.ChecksumIEEE([]byte(s))
str36 := strconv.FormatUint(uint64(sum), 36)
return strings.ToUpper(str36)
}
func Now() string {
return time.Now().Format(RFC3339)
}