mirror of
https://github.com/fumiama/paper-manager.git
synced 2026-06-07 17:00:23 +08:00
192 lines
4.3 KiB
Go
192 lines
4.3 KiB
Go
package global
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
_ "image/jpeg"
|
|
_ "image/png"
|
|
|
|
_ "golang.org/x/image/webp"
|
|
|
|
sql "github.com/FloatTech/sqlite"
|
|
|
|
"github.com/fumiama/paper-manager/backend/utils"
|
|
)
|
|
|
|
const (
|
|
FileTableList = "lst"
|
|
FileTableFile = "file"
|
|
FileTableTempFile = "tmpfile"
|
|
FileTableQuestion = "question"
|
|
FileTableTempQuestion = "tmpqstn"
|
|
)
|
|
|
|
var (
|
|
ErrMajorSplitsTooShort = errors.New("major splits too short")
|
|
ErrEmptyClass = errors.New("empty class")
|
|
ErrHasntAnalyzed = errors.New("hasn't analyzed")
|
|
ErrNoGetFileStatusPermission = errors.New("no get file status permission")
|
|
)
|
|
|
|
func init() {
|
|
err := FileDB.db.Open(time.Hour)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
err = FileDB.db.Create(FileTableList, &List{})
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
err = FileDB.db.Create(FileTableFile, &File{},
|
|
"FOREIGN KEY(ListID) REFERENCES "+FileTableList+"(ID)",
|
|
)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
err = FileDB.db.Create(FileTableTempFile, &File{})
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
err = FileDB.db.Create(FileTableQuestion, &Question{},
|
|
"FOREIGN KEY(ListID) REFERENCES "+FileTableList+"(ID)",
|
|
)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
err = FileDB.db.Create(FileTableTempQuestion, &Question{})
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
err = FileDB.db.Close()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
err = os.Chmod(FileDB.db.DBPath, 0600)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
err = FileDB.db.Open(time.Hour)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
// File stores to paper/Class/2022-2023学年/第一学期/期末/A/xxx.docx
|
|
type File struct {
|
|
ID int64 // ID is the first 8 bytes of the original file's md5
|
|
ListID int // ListID is the foreign key to List(ID)
|
|
Year StudyYear
|
|
Type PaperType
|
|
Date uint32 // Date is the yyyymmdd of 考试日期
|
|
Time time.Duration // Time is 考试时长
|
|
Class string // Class is 考试科目
|
|
Rate string // Rate is 成绩构成比例
|
|
Questions []byte // Questions is for []QuestionJSON
|
|
}
|
|
|
|
// StudyYear 学年
|
|
type StudyYear uint16
|
|
|
|
// String ex. 2022-2023学年
|
|
func (sy StudyYear) String() string {
|
|
next := sy + 1
|
|
return strconv.Itoa(int(sy)) + "-" + strconv.Itoa(int(next)) + "学年"
|
|
}
|
|
|
|
// DelFile by listid
|
|
func (f *FileDatabase) DelFile(lstid, uid int, istemp bool) error {
|
|
user, err := UserDB.GetUserByID(uid)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !user.IsSuper() && !istemp {
|
|
return ErrInvalidRole
|
|
}
|
|
ftable := ""
|
|
if istemp {
|
|
ftable = FileTableTempFile
|
|
} else {
|
|
ftable = FileTableFile
|
|
}
|
|
f.mu.RLock()
|
|
lst, err := sql.Find[List](&f.db, FileTableList, "WHERE ID="+strconv.Itoa(lstid))
|
|
f.mu.RUnlock()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if istemp && lst.Uploader != uid {
|
|
return ErrInvalidRole
|
|
}
|
|
if lst.Path == "" || strings.Contains(lst.Path, "..") {
|
|
return os.ErrNotExist
|
|
}
|
|
err = f.db.Del(FileTableList, "WHERE ID="+strconv.Itoa(lstid))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if lst.HasntAnalyzed {
|
|
return os.RemoveAll(lst.Path)
|
|
}
|
|
i := strings.LastIndex(lst.Path, "/")
|
|
if i <= 0 {
|
|
return os.ErrNotExist
|
|
}
|
|
parentfolder := lst.Path[:i]
|
|
if utils.IsNotExist(parentfolder) {
|
|
return os.ErrNotExist
|
|
}
|
|
f.mu.RLock()
|
|
file, err := sql.Find[File](&f.db, ftable, "WHERE ListID="+strconv.Itoa(lstid))
|
|
f.mu.RUnlock()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = f.db.Del(ftable, "WHERE ListID="+strconv.Itoa(lstid))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
ques := make([]QuestionJSON, 0, 64)
|
|
err = json.Unmarshal(file.Questions, &ques)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for _, q := range ques {
|
|
q.Delete(f, istemp)
|
|
}
|
|
return os.RemoveAll(parentfolder)
|
|
}
|
|
|
|
// GetFile get analyzed file's structure from List(ID)
|
|
func (f *FileDatabase) GetFile(lstid, uid int) (file *File, sz int64, istemp bool, err error) {
|
|
f.mu.RLock()
|
|
defer f.mu.RUnlock()
|
|
lst, err := sql.Find[List](&f.db, FileTableList, "WHERE ID="+strconv.Itoa(lstid))
|
|
if err != nil {
|
|
return
|
|
}
|
|
if lst.HasntAnalyzed {
|
|
err = ErrHasntAnalyzed
|
|
return
|
|
}
|
|
if lst.IsTemp && lst.Uploader != uid {
|
|
err = ErrNoGetFileStatusPermission
|
|
return
|
|
}
|
|
ftable := ""
|
|
if lst.IsTemp {
|
|
ftable = FileTableTempFile
|
|
} else {
|
|
ftable = FileTableFile
|
|
}
|
|
filestruct, err := sql.Find[File](&f.db, ftable, "WHERE ListID="+strconv.Itoa(lstid))
|
|
if err != nil {
|
|
return
|
|
}
|
|
return &filestruct, lst.Size, lst.IsTemp, nil
|
|
}
|