Add export, improve config saving
This commit is contained in:
parent
f50f4f1919
commit
8a571dbee8
5 changed files with 94 additions and 15 deletions
8
TODO.md
8
TODO.md
|
@ -1,13 +1,11 @@
|
||||||
# TODO
|
# TODO
|
||||||
List of things to add to this project
|
List of things to add to this project
|
||||||
|
|
||||||
## Crucial
|
* Use reflection in config loading
|
||||||
* Add export feature
|
* Check export function for improvements
|
||||||
* Add missing frontend pages
|
* Add missing frontend pages
|
||||||
* More slog.Debug?
|
* More slog.Debug?
|
||||||
|
* Make the CLI multi-functional - export to path, edit file etc.
|
||||||
## Long-medium term considerations
|
|
||||||
* Make the CLI better
|
|
||||||
* Think about timezones
|
* Think about timezones
|
||||||
* Consider more secure auth methods
|
* Consider more secure auth methods
|
||||||
* *Go* dependency-less? <-- this is a terrible idea
|
* *Go* dependency-less? <-- this is a terrible idea
|
24
config.go
24
config.go
|
@ -6,6 +6,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
@ -13,18 +14,25 @@ import (
|
||||||
var ConfigFile = "config/config.txt"
|
var ConfigFile = "config/config.txt"
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Username string
|
Username string `config:"username"`
|
||||||
Password string
|
Password string `config:"password"`
|
||||||
Port int
|
Port int `config:"port"`
|
||||||
|
|
||||||
TelegramToken string
|
TelegramToken string `config:"tg_token"`
|
||||||
TelegramChat string
|
TelegramChat string `config:"tg_chat"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) Save() error {
|
func (c *Config) Save() error {
|
||||||
output := fmt.Sprintf("port=%d\nusername=%s\npassword=%s", c.Port, c.Username, c.Password)
|
output := ""
|
||||||
if c.TelegramToken != "" && c.TelegramChat != "" {
|
|
||||||
output += fmt.Sprintf("\ntg_token=%s\ntg_chat=%s", c.TelegramToken, c.TelegramChat)
|
v := reflect.ValueOf(*c)
|
||||||
|
typeOfS := v.Type()
|
||||||
|
for i := 0; i < v.NumField(); i++ {
|
||||||
|
key := typeOfS.Field(i).Tag.Get("config")
|
||||||
|
value := v.Field(i).Interface()
|
||||||
|
if value != "" {
|
||||||
|
output += fmt.Sprintf("%s=%v\n", key, value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
f, err := os.OpenFile(ConfigFile, os.O_CREATE|os.O_WRONLY, 0644)
|
f, err := os.OpenFile(ConfigFile, os.O_CREATE|os.O_WRONLY, 0644)
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
port=7101
|
|
||||||
username=admin
|
username=admin
|
||||||
password=admin
|
password=admin
|
||||||
|
port=7101
|
||||||
|
|
71
export.go
Normal file
71
export.go
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"archive/zip"
|
||||||
|
"io"
|
||||||
|
"log/slog"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ExportPath = "data/export.zip"
|
||||||
|
|
||||||
|
func Export(filename string) error {
|
||||||
|
file, err := os.Create(filename)
|
||||||
|
if err != nil {
|
||||||
|
slog.Error("error creating export archive", "error", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
w := zip.NewWriter(file)
|
||||||
|
defer w.Close()
|
||||||
|
|
||||||
|
walker := func(path string, info os.FileInfo, err error) error {
|
||||||
|
if path == filename { // Do not add export .zip itself
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
slog.Debug("export crawling", "path", path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if info.IsDir() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
file, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
f, err := w.Create(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = io.Copy(f, file)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
err = filepath.Walk("data/", walker)
|
||||||
|
if err != nil {
|
||||||
|
slog.Error("error walking files", "error", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetExport returns a .zip archive with contents of the data folder
|
||||||
|
func GetExport(w http.ResponseWriter, r *http.Request) {
|
||||||
|
err := Export(ExportPath)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, "could not export", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
http.ServeFile(w, r, "data/export.zip")
|
||||||
|
}
|
2
serve.go
2
serve.go
|
@ -41,6 +41,8 @@ func Serve() {
|
||||||
apiRouter.Get("/today", GetToday)
|
apiRouter.Get("/today", GetToday)
|
||||||
apiRouter.Post("/today", PostToday)
|
apiRouter.Post("/today", PostToday)
|
||||||
|
|
||||||
|
apiRouter.Get("/export", GetExport)
|
||||||
|
|
||||||
r.Mount("/api", apiRouter)
|
r.Mount("/api", apiRouter)
|
||||||
|
|
||||||
// Static files
|
// Static files
|
||||||
|
|
Loading…
Reference in a new issue