mirror of
https://github.com/fumiama/paper-manager.git
synced 2026-06-04 23:40:24 +08:00
implement file.AddFile
This commit is contained in:
@@ -1,9 +1,17 @@
|
||||
package global
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/fumiama/go-docx"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -11,6 +19,10 @@ const (
|
||||
FileTableQuestion = "question"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrMajorSplitsTooShort = errors.New("major splits too short")
|
||||
)
|
||||
|
||||
// PaperType [4 开 一页纸 闭] [4 上下] [4 中末] [4 AB]
|
||||
type PaperType uint16
|
||||
|
||||
@@ -161,6 +173,144 @@ type File struct {
|
||||
Questions []byte // Questions is for json struct QuestionJSON
|
||||
}
|
||||
|
||||
// AddFile from FileFolder+tempath and copy it to File.Path.
|
||||
// The para res must belong to a valid user
|
||||
func (f *FileDatabase) AddFile(tempath string, reg *Regex) (*File, error) {
|
||||
user, err := UserDB.GetUserByID(reg.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !user.IsFileManager() {
|
||||
return nil, ErrInvalidRole
|
||||
}
|
||||
if strings.Contains(tempath, "..") {
|
||||
return nil, os.ErrNotExist
|
||||
}
|
||||
tempath = FileFolder + tempath
|
||||
docf, err := os.Open(tempath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer docf.Close()
|
||||
h := md5.New()
|
||||
_, err = io.Copy(h, docf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var buf [md5.Size]byte
|
||||
id := binary.LittleEndian.Uint64(h.Sum(buf[:0]))
|
||||
_, err = docf.Seek(0, io.SeekStart)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stat, err := docf.Stat()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sz := stat.Size()
|
||||
doc, err := docx.Parse(docf, sz)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
majorre, err := regexp.Compile(reg.Major)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
docs := doc.SplitByParagraph(docx.SplitDocxByPlainTextRegex(majorre))
|
||||
if len(docs) < 2 {
|
||||
return nil, ErrMajorSplitsTooShort
|
||||
}
|
||||
file := &File{
|
||||
ID: id,
|
||||
UID: *user.ID,
|
||||
UpTime: time.Now().Unix(),
|
||||
Size: sz,
|
||||
}
|
||||
titlere, err := regexp.Compile(reg.Title)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
classre, err := regexp.Compile(reg.Class)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
opclre, err := regexp.Compile(reg.OpenCl)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
datere, err := regexp.Compile(reg.Date)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
timere, err := regexp.Compile(reg.Time)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ratere, err := regexp.Compile(reg.Rate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, it := range docs[0].Document.Body.Items {
|
||||
if p, ok := it.(*docx.Paragraph); ok {
|
||||
text := p.String()
|
||||
title := titlere.FindStringSubmatch(text)
|
||||
if len(title) >= 5 {
|
||||
years, semesters, mfs, abs := title[1], title[2], title[3], title[4]
|
||||
y, err := strconv.Atoi(years)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
file.Year = StudyYear(y)
|
||||
if len(semesters) > 0 {
|
||||
file.Type = file.Type.SetFirstSecond(semesters[0])
|
||||
}
|
||||
file.Type = file.Type.SetMiddleFinal(mfs)
|
||||
if len(abs) > 0 {
|
||||
file.Type = file.Type.SetAB(abs[0])
|
||||
}
|
||||
}
|
||||
class := classre.FindStringSubmatch(text)
|
||||
if len(class) >= 2 {
|
||||
file.Class = class[1]
|
||||
}
|
||||
opcl := opclre.FindStringSubmatch(text)
|
||||
if len(opcl) >= 2 {
|
||||
file.Type = file.Type.SetOpenClose(opcl[1])
|
||||
}
|
||||
date := datere.FindStringSubmatch(text)
|
||||
if len(date) >= 4 {
|
||||
y, m, d := date[1], date[2], date[3]
|
||||
if y != "" && m != "" && d != "" {
|
||||
yyyy, err := strconv.ParseUint(y, 10, 64)
|
||||
if err == nil && yyyy > 1600 {
|
||||
mm, err := strconv.ParseUint(m, 10, 64)
|
||||
if err == nil && mm >= 1 && mm <= 12 {
|
||||
dd, err := strconv.ParseUint(d, 10, 64)
|
||||
if err == nil && dd >= 1 && dd <= 31 {
|
||||
file.Date = uint32(yyyy*10000 + mm*100 + dd)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
times := timere.FindStringSubmatch(text)
|
||||
if len(times) >= 2 {
|
||||
min, err := strconv.Atoi(times[1])
|
||||
if err == nil && min > 0 {
|
||||
file.Time = time.Minute * time.Duration(min)
|
||||
}
|
||||
}
|
||||
rate := ratere.FindStringSubmatch(text)
|
||||
if len(rate) >= 2 {
|
||||
file.Rate = rate[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
docs = docs[1:]
|
||||
|
||||
return file, nil
|
||||
}
|
||||
|
||||
// QuestionJSON is the struct representation of File.Questions
|
||||
type QuestionJSON struct {
|
||||
Name string `json:"name"` // Name is name or Question ID
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
// Regex stores user's config of splitting docx file
|
||||
type Regex struct {
|
||||
ID int // ID is User(ID)
|
||||
Title string // Title default `.*(\d{4})\s*-.*学年.*(\d).*([中末]).*([AB])\s*卷`
|
||||
Title string // Title default `.*(\d{4})\s*-.*学年.*(\d?).*([中末]?).*([AB]?)\s*卷`
|
||||
Class string // Class default `考试科目:\s*(\S+)\s*`
|
||||
OpenCl string // OpenCl default `考试形式:\s*(\S+)\s*`
|
||||
Date string // Date default `考试日期:\s*(\d+)\s*年\s*(\d+)\s*月\s*(\d+)\s*日`
|
||||
@@ -20,7 +20,7 @@ type Regex struct {
|
||||
}
|
||||
|
||||
func newRegex() (reg Regex) {
|
||||
reg.Title = `.*(\d{4})\s*-.*学年.*(\d).*([中末]).*([AB])\s*卷`
|
||||
reg.Title = `.*(\d{4})\s*-.*学年.*(\d?).*([中末]?).*([AB]?)\s*卷`
|
||||
reg.Class = `考试科目:\s*(\S+)\s*`
|
||||
reg.OpenCl = `考试形式:\s*(\S+)\s*`
|
||||
reg.Date = `考试日期:\s*(\d+)\s*年\s*(\d+)\s*月\s*(\d+)\s*日`
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/fumiama/paper-manager/backend/utils"
|
||||
@@ -23,6 +24,7 @@ var (
|
||||
ErrEmptyName = errors.New("empty name")
|
||||
ErrInvalidUsersCount = errors.New("invalid users count")
|
||||
ErrInvalidUserID = errors.New("invalid user ID")
|
||||
ErrInvalidAvatar = errors.New("invalid avatar")
|
||||
ErrEmptyUserID = errors.New("empty user ID")
|
||||
ErrEmptyContact = errors.New("empty contact")
|
||||
ErrUsernameExists = errors.New("username exists")
|
||||
@@ -147,6 +149,9 @@ func (u *UserDatabase) UpdateUserInfo(id int, opname, nick, avtr, desc string) e
|
||||
user.Nick = nick
|
||||
}
|
||||
if avtr != "" {
|
||||
if strings.Contains(avtr, "..") {
|
||||
return ErrInvalidAvatar
|
||||
}
|
||||
user.Avtr = avtr
|
||||
}
|
||||
if desc != "" {
|
||||
|
||||
@@ -179,7 +179,7 @@ func setUserInfo(id int, nick, desc, avtr *string) error {
|
||||
}
|
||||
if a == "" {
|
||||
*avtr = user.Avtr
|
||||
} else if utils.IsNotExist(global.DataFolder + a) {
|
||||
} else if strings.Contains(a, "..") || utils.IsNotExist(global.DataFolder+a) {
|
||||
return os.ErrNotExist
|
||||
}
|
||||
if a == user.Avtr {
|
||||
|
||||
1
go.mod
1
go.mod
@@ -7,6 +7,7 @@ require (
|
||||
github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b
|
||||
github.com/RomiChan/syncx v0.0.0-20221202055724-5f842c53020e
|
||||
github.com/fumiama/go-base16384 v1.6.4
|
||||
github.com/fumiama/go-docx v0.0.0-20230310052825-daf7190ea69b
|
||||
github.com/fumiama/imgsz v0.0.2
|
||||
github.com/sirupsen/logrus v1.9.0
|
||||
)
|
||||
|
||||
2
go.sum
2
go.sum
@@ -11,6 +11,8 @@ github.com/fumiama/bigfft v0.0.0-20211011143303-6e0bfa3c836b h1:Zt3pFQditAdWTHCO
|
||||
github.com/fumiama/bigfft v0.0.0-20211011143303-6e0bfa3c836b/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/fumiama/go-base16384 v1.6.4 h1:rYDRwD/th2cG4U7QLokpzmST1cCxZGXtHmolOUePt5o=
|
||||
github.com/fumiama/go-base16384 v1.6.4/go.mod h1:OEn+947GV5gsbTAnyuUW/SrfxJYUdYupSIQXOuGOcXM=
|
||||
github.com/fumiama/go-docx v0.0.0-20230310052825-daf7190ea69b h1:1KYtEitNxRbh+O8mgGlji4nQKzf7SQHYxiuqDAwRCc8=
|
||||
github.com/fumiama/go-docx v0.0.0-20230310052825-daf7190ea69b/go.mod h1:ssRF0IaB1hCcKIObp3FkZOsjTcAHpgii70JelNb4H8M=
|
||||
github.com/fumiama/imgsz v0.0.2 h1:fAkC0FnIscdKOXwAxlyw3EUba5NzxZdSxGaq3Uyfxak=
|
||||
github.com/fumiama/imgsz v0.0.2/go.mod h1:dR71mI3I2O5u6+PCpd47M9TZptzP+39tRBcbdIkoqM4=
|
||||
github.com/fumiama/sqlite3 v1.20.0-with-win386 h1:ZR1AXGBEtkfq9GAXehOVcwn+aaCG8itrkgEsz4ggx5k=
|
||||
|
||||
Reference in New Issue
Block a user