Files
hnh-map/internal/app/admin_export.go
Nikolay Tatarinov 5ffa10f8b7 Update project structure and enhance frontend functionality
- Added a new AGENTS.md file to document the project structure and conventions.
- Updated .gitignore to include node_modules and refined cursor rules.
- Introduced new backend and frontend components for improved map interactions, including context menus and controls.
- Enhanced API composables for better admin and authentication functionalities.
- Refactored existing components for cleaner code and improved user experience.
- Updated README.md to clarify production asset serving and user setup instructions.
2026-02-25 16:32:55 +03:00

135 lines
2.9 KiB
Go

package app
import (
"archive/zip"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"os"
"path/filepath"
"strconv"
"github.com/andyleap/hnh-map/internal/app/store"
"go.etcd.io/bbolt"
)
type mapData struct {
Grids map[string]string
Markers map[string][]Marker
}
func (a *App) export(rw http.ResponseWriter, req *http.Request) {
s := a.getSession(req)
if s == nil || !s.Auths.Has(AUTH_ADMIN) {
http.Error(rw, "Unauthorized", http.StatusUnauthorized)
return
}
rw.Header().Set("Content-Type", "application/zip")
rw.Header().Set("Content-Disposition", "attachment; filename=\"griddata.zip\"")
zw := zip.NewWriter(rw)
defer zw.Close()
err := a.db.Update(func(tx *bbolt.Tx) error {
maps := map[int]mapData{}
gridMap := map[string]int{}
grids := tx.Bucket(store.BucketGrids)
if grids == nil {
return nil
}
tiles := tx.Bucket(store.BucketTiles)
if tiles == nil {
return nil
}
err := grids.ForEach(func(k, v []byte) error {
gd := GridData{}
err := json.Unmarshal(v, &gd)
if err != nil {
return err
}
md, ok := maps[gd.Map]
if !ok {
md = mapData{
Grids: map[string]string{},
Markers: map[string][]Marker{},
}
maps[gd.Map] = md
}
md.Grids[gd.Coord.Name()] = gd.ID
gridMap[gd.ID] = gd.Map
mapb := tiles.Bucket([]byte(strconv.Itoa(gd.Map)))
if mapb == nil {
return nil
}
zoom := mapb.Bucket([]byte("0"))
if zoom == nil {
return nil
}
tdraw := zoom.Get([]byte(gd.Coord.Name()))
if tdraw == nil {
return nil
}
td := TileData{}
err = json.Unmarshal(tdraw, &td)
if err != nil {
return err
}
w, err := zw.Create(fmt.Sprintf("%d/%s.png", gd.Map, gd.ID))
if err != nil {
return err
}
f, err := os.Open(filepath.Join(a.gridStorage, td.File))
if err != nil {
return err
}
_, err = io.Copy(w, f)
f.Close()
return err
})
if err != nil {
return err
}
err = func() error {
markersb := tx.Bucket(store.BucketMarkers)
if markersb == nil {
return nil
}
markersgrid := markersb.Bucket(store.BucketMarkersGrid)
if markersgrid == nil {
return nil
}
return markersgrid.ForEach(func(k, v []byte) error {
marker := Marker{}
err := json.Unmarshal(v, &marker)
if err != nil {
return nil
}
if _, ok := maps[gridMap[marker.GridID]]; ok {
maps[gridMap[marker.GridID]].Markers[marker.GridID] = append(maps[gridMap[marker.GridID]].Markers[marker.GridID], marker)
}
return nil
})
}()
if err != nil {
return err
}
for mapid, mapdata := range maps {
w, err := zw.Create(fmt.Sprintf("%d/grids.json", mapid))
if err != nil {
return err
}
json.NewEncoder(w).Encode(mapdata)
}
return nil
})
if err != nil {
log.Println(err)
}
}