server/admin/sync/exercice_hints.go

93 lines
2.9 KiB
Go

package sync
import (
"bufio"
"crypto"
"encoding/hex"
"fmt"
"io"
"os"
"path"
"strings"
"srs.epita.fr/fic-server/libfic"
_ "golang.org/x/crypto/blake2b"
)
// SyncExerciceHints reads the content of hints/ directories and import it as EHint for the given challenge.
func SyncExerciceHints(i Importer, exercice fic.Exercice) (errs []string) {
params, err := parseExerciceParams(i, exercice.Path)
if err != nil {
errs = append(errs, fmt.Sprintf("%q: challenge.txt: %s", path.Base(exercice.Path), err))
}
if _, err := exercice.WipeHints(); err != nil {
errs = append(errs, err.Error())
} else if ! i.exists(path.Join(exercice.Path, "hints")) {
return
} else if hints, err := i.listDir(path.Join(exercice.Path, "hints")); err != nil {
errs = append(errs, err.Error())
} else {
for n, hfile := range hints {
// Find corresponding parameters
var hint_title = fmt.Sprintf("Astuce #%d", n + 1)
var hint_cost = exercice.Gain / 4
for _, hp := range params.Hints {
if hp.Filename == hfile {
if hp.Cost > 0 {
hint_cost = hp.Cost
}
if hp.Title != "" {
hint_title = hp.Title
}
break
}
}
// Extract hint content
var hint_cnt string
if fi, err := i.stat(path.Join(exercice.Path, "hints", hfile)); err != nil {
errs = append(errs, fmt.Sprintf("%q: unable to add hint %q: %s", path.Base(exercice.Path), hfile, err))
} else if ! fi.IsDir() && fi.Size() > 512 {
// Handle big files as downloadable content
if res, err := i.importFile(path.Join(exercice.Path, "hints", hfile), func(filePath string, origin string) (interface{}, error) {
// Calculate hash
hash512 := crypto.BLAKE2b_512.New()
if fd, err := os.Open(filePath); err != nil {
return nil, err
} else {
defer fd.Close()
reader := bufio.NewReader(fd)
if _, err := io.Copy(hash512, reader); err != nil {
return nil, err
}
}
result512 := hash512.Sum(nil)
return "$FILES" + hex.EncodeToString(result512) + strings.TrimPrefix(filePath, fic.FilesDir), nil
}); err != nil {
errs = append(errs, fmt.Sprintf("%q: unable to import hint file %q: %s", path.Base(exercice.Path), hfile, err))
continue
} else if s, ok := res.(string); !ok {
errs = append(errs, fmt.Sprintf("%q: unable to import hint file %q: invalid string returned as filename", path.Base(exercice.Path), hfile))
continue
} else {
hint_cnt = s
}
} else if hint_cnt, err = getFileContent(i, path.Join(exercice.Path, "hints", hfile)); err != nil {
errs = append(errs, fmt.Sprintf("%q: unable to read hint file %q: %s", path.Base(exercice.Path), hfile, err))
continue
}
// Import hint
if _, err := exercice.AddHint(hint_title, hint_cnt, hint_cost); err != nil {
errs = append(errs, fmt.Sprintf("%q: unable to add hint %q: %s", path.Base(exercice.Path), hfile, err))
}
}
}
return
}