Skip to content Search Apps Documentation Source Content File Folder Download Copy Actions State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

render.gno

6.91 Kb · 211 lines
  1package nightsky
  2
  3import (
  4	"strings"
  5	"time"
  6
  7	"gno.land/p/jeronimoalbi/mdform/v0"
  8	"gno.land/p/moul/md/v0"
  9	"gno.land/p/nt/ufmt/v0"
 10)
 11
 12// RenderNightsky generates the markdown output for the telescope realm.
 13// Call this from your realm's Render(path string) string function.
 14func (r *TelescopeRealm) RenderNightsky(path string) string {
 15	switch path {
 16	case "status":
 17		return r.renderStatus()
 18	case "commands":
 19		return r.renderCommandQueue()
 20	case "captures":
 21		return r.renderCaptureHistory()
 22	case "access":
 23		return r.renderAccessRules()
 24	case "commandData":
 25		return r.renderCommandData()
 26	case "control":
 27		return r.renderControl()
 28	default:
 29		return r.renderMainPage()
 30	}
 31}
 32
 33func (r *TelescopeRealm) renderMainPage() string {
 34	out := "# " + r.Config.Name + " 🔭\n\n"
 35
 36	statusIcon := "🔴"
 37	switch r.Config.Status {
 38	case "online":
 39		statusIcon = "🟢"
 40	case "busy":
 41		statusIcon = "🟡"
 42	case "error":
 43		statusIcon = "🔴"
 44	}
 45
 46	out += statusIcon + " **Status:** " + r.Config.Status + "\n\n"
 47	out += "**Model:** " + r.Config.Model + "\n\n"
 48	out += ufmt.Sprintf("**Position:** %.2f°, %.2f°\n\n", r.Config.Latitude, r.Config.Longitude)
 49
 50	out += "## Quick Stats\n\n"
 51	out += ufmt.Sprintf("📋 Commands in queue: %d\n\n", len(r.CommandQueue))
 52	out += ufmt.Sprintf("📸 Total captures: %d\n\n", r.Captures.Len())
 53	out += ufmt.Sprintf("👥 Authorized users: %d\n\n", r.AccessRules.Size())
 54
 55	out += "## Quick Links\n\n"
 56	out += md.Link("🎮 Control Telescope", r.path(":control")) + " - Submit commands\n\n"
 57	out += md.Link("👥 Access Rules", r.path(":access")) + " - View and manage user access\n\n"
 58	out += md.Link("📋 Command Queue", r.path(":commands")) + "\n\n"
 59	out += md.Link("📸 Capture History", r.path(":captures")) + "\n\n"
 60
 61	if latest, ok := r.Captures.Latest(); ok {
 62		out += "## Latest Capture\n\n"
 63		out += "![Latest capture](" + latest.ImageURL + ")\n\n"
 64		out += ufmt.Sprintf("_RA %.8fh · Dec %.8f° · %ds_\n\n", latest.TargetRA, latest.TargetDec, latest.Exposure)
 65	}
 66
 67	out += "---\n\n"
 68	out += "## CLI Usage\n\n"
 69	out += "```\n"
 70	out += "gnokey maketx call -pkgpath \"gno.land" + r.Config.RealmPath + "\" \\\n"
 71	out += "  -func \"SubmitCommand\" \\\n"
 72	out += "  -args \"capture\" -args \"5.5\" -args \"22.5\" -args \"60\" \\\n"
 73	out += "  -gas-fee 1000000ugnot -gas-wanted 2000000 \\\n"
 74	out += "  -broadcast YOUR_ADDRESS\n"
 75	out += "```\n\n"
 76
 77	out += md.Link("← Back to NightSky Network", "/r/nym-vikbez000/nightsky/v1") + "\n\n"
 78	return out
 79}
 80
 81func (r *TelescopeRealm) renderControl() string {
 82	out := "# 🎮 Control Telescope\n\n"
 83	out += "**Note:** You must have access to submit commands.\n\n"
 84	out += "---\n\n"
 85
 86	form := mdform.
 87		New("exec", "SubmitCommand").
 88		Select("commandType", "capture", "description", "Command type").
 89		Select("commandType", "stop").
 90		Input("targetRA", "placeholder", "0.0", "description", "Right Ascension (0–24h) — leave empty for stop").
 91		Input("targetDec", "placeholder", "0.0", "description", "Declination (−90–90°) — leave empty for stop").
 92		Input("exposure", "placeholder", "60", "description", "Exposure time in seconds (1–300) — leave empty for stop")
 93
 94	out += form.String() + "\n\n"
 95	out += "---\n\n"
 96	out += md.Link("← Back", r.path("")) + "\n\n"
 97	return out
 98}
 99
100func (r *TelescopeRealm) renderCommandQueue() string {
101	out := "# Command Queue\n\n"
102
103	if len(r.CommandQueue) == 0 {
104		out += "No pending commands.\n\n"
105	} else {
106		out += ufmt.Sprintf("%d command(s) pending:\n\n", len(r.CommandQueue))
107		for i, cmd := range r.CommandQueue {
108			out += ufmt.Sprintf("### Command #%d\n\n", i+1)
109			out += "**Type:** " + cmd.CommandType + "\n\n"
110			if cmd.CommandType == "capture" {
111				out += ufmt.Sprintf("**Target:** RA %.8fh, Dec %.8f°\n\n", cmd.TargetRA, cmd.TargetDec)
112				out += ufmt.Sprintf("**Exposure:** %d seconds\n\n", cmd.Exposure)
113			}
114			out += "**Requested by:** " + cmd.RequestedBy + "\n\n"
115			out += "---\n\n"
116		}
117	}
118
119	out += md.Link("← Back", r.path("")) + "\n\n"
120	return out
121}
122
123func (r *TelescopeRealm) renderCaptureHistory() string {
124	out := "# Capture History\n\n"
125
126	if r.Captures.Len() == 0 {
127		out += "No captures yet.\n\n"
128	} else {
129		out += ufmt.Sprintf("Showing %d most recent captures:\n\n", r.Captures.Len())
130		i := 0
131		r.Captures.IterateNewest(func(capture CaptureResult) bool {
132			i++
133			out += ufmt.Sprintf("### Capture #%d\n\n", i)
134			out += ufmt.Sprintf("**Target:** RA %.8fh, Dec %.8f°\n\n", capture.TargetRA, capture.TargetDec)
135			out += ufmt.Sprintf("**Exposure:** %d seconds\n\n", capture.Exposure)
136			out += "**Captured by:** " + capture.CapturedBy + "\n\n"
137			out += "**Image:** " + md.Link("View", capture.ImageURL) + "\n\n"
138			out += "---\n\n"
139			return false
140		})
141	}
142
143	out += md.Link("← Back", r.path("")) + "\n\n"
144	return out
145}
146
147func (r *TelescopeRealm) renderAccessRules() string {
148	out := "# 👥 Access Rules\n\n"
149
150	if r.AccessRules.Size() == 0 {
151		out += "No access rules configured. Only the owner can use the telescope.\n\n"
152	} else {
153		out += ufmt.Sprintf("%d user(s) have access:\n\n", r.AccessRules.Size())
154		r.AccessRules.Iterate("", "", func(_ string, value any) bool {
155			rule := value.(AccessRule)
156			out += "**User:** " + rule.AllowedAddress
157			if rule.ExpiresAt.IsZero() {
158				out += " (Expires: Never)\n\n"
159			} else {
160				out += " (Expires: " + rule.ExpiresAt.Format(time.RFC1123) + ")\n\n"
161			}
162			out += "---\n\n"
163			return false
164		})
165	}
166
167	out += "## Grant Access\n\n"
168	out += mdform.
169		New("exec", "GrantAccess").
170		Input("address", "placeholder", "g1...", "description", "Gno address to grant access to").
171		Input("durationDays", "placeholder", "0", "description", "Duration in days (0 = never expires)").
172		String() + "\n\n"
173
174	out += "## Revoke Access\n\n"
175	out += mdform.
176		New("exec", "RevokeAccess").
177		Input("address", "placeholder", "g1...", "description", "Gno address to revoke").
178		String() + "\n\n"
179
180	out += "---\n\n"
181	out += md.Link("← Back", r.path("")) + "\n\n"
182	return out
183}
184
185// renderStatus returns a machine-readable status block for the telescope controller.
186func (r *TelescopeRealm) renderStatus() string {
187	out := ufmt.Sprintf("commands=%d\n", len(r.CommandQueue))
188	out += "status=" + r.Config.Status
189	return "```\n" + out + "\n```"
190}
191
192// renderCommandData returns the first queued command in a machine-readable block.
193func (r *TelescopeRealm) renderCommandData() string {
194	if len(r.CommandQueue) == 0 {
195		return "```\nno_commands\n```"
196	}
197	cmd := r.CommandQueue[0]
198	data := "type=" + cmd.CommandType + "\n"
199	data += ufmt.Sprintf("ra=%.8f\n", cmd.TargetRA)
200	data += ufmt.Sprintf("dec=%.8f\n", cmd.TargetDec)
201	data += ufmt.Sprintf("exposure=%d\n", cmd.Exposure)
202	data += "requester=" + cmd.RequestedBy
203	return "```\n" + data + "\n```"
204}
205
206// path builds an absolute URL path for this realm with an optional suffix,
207// using the pkgPath stored on the config at construction time. This avoids a
208// runtime realm lookup entirely (no chain/runtime/unsafe needed).
209func (r *TelescopeRealm) path(addon string) string {
210	return strings.TrimPrefix(r.Config.RealmPath, "gno.land") + addon
211}