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) } }