PathrockNetwork Gno Explorer
HomeBlocksTransactionsTokensRealmsPackagesValidatorsAnalytics

PathrockNetwork Gno Explorer — an independent explorer for Gno.land Mainnet (gnoland-1), operated by PathrockNetwork. Not an official Gno.land service.

gnowebarchive RPC

gno.land/p/nym-vikbez000/nightsky/v1

Package
Open in gnoweb ↗

Overview

Kind
Pure package
Name
v1
Namespace
nym-vikbez000 / nightsky
Files
5 (gnomod.toml)
Exported functions
n/a — not supported for pure packages by the node (vm/qfuncs)
Module
gno.land/p/nym-vikbez000/nightsky/v1
gno
0.9

Files (5)

  • gnomod.tomltoml
  • feed.gnogno
  • nightsky.gnogno
  • render.gnogno
  • nightsky_test.gnogno
nightsky.gnogno
1// Package nightsky holds the shared types and single-telescope logic for the2// GnoNightSky telescope network.3//4// Note on panics: although this lives under p/, it is application-specific5// logic for the NightSky realms rather than a general-purpose reusable6// library. It deliberately panics on invalid input / failed preconditions7// (the assert-like style described in effective-gno) so the wrapping realms8// don't have to re-check every error. Callers that want softer handling9// should validate before calling.10package nightsky1112import (13	"time"1415	"gno.land/p/nt/avl/v0"16)1718// TelescopeConfig contains the settings and configuration for a telescope19type TelescopeConfig struct {20	Name       string    // Name of the telescope21	Model      string    // Telescope model (e.g., "Seestar S50")22	Latitude   float64   // Geographic location23	Longitude  float64   // Geographic location24	Owner      string    // Owner's gno address25	RealmPath  string    // Path to the telescope's realm (e.g., "/r/username/telescope")26	Status     string    // Current status: "online", "offline", "busy", "error"27	LastUpdate time.Time // Last status update28}2930// AccessRule defines who can access a telescope31type AccessRule struct {32	AllowedAddress string    // Gno address allowed to access33	GrantedBy      string    // Who granted access34	GrantedAt      time.Time // When access was granted35	ExpiresAt      time.Time // When access expires (zero time = never)36}3738// TelescopeCommand represents a command sent to a telescope39type TelescopeCommand struct {40	CommandType string    // "capture" or "stop"41	TargetRA    float64   // Right Ascension (for pointing/tracking)42	TargetDec   float64   // Declination (for pointing/tracking)43	Exposure    int       // Exposure time in seconds (for capture)44	RequestedBy string    // Who requested the command45	RequestedAt time.Time // When the command was requested46}4748// CaptureResult represents the result of an image capture49type CaptureResult struct {50	ImageURL    string    // URL to the captured image (e.g., Imgur)51	TargetRA    float64   // Right Ascension of target52	TargetDec   float64   // Declination of target53	Exposure    int       // Exposure time in seconds54	CapturedBy  string    // Who captured the image55	CapturedAt  time.Time // When the image was captured56	TelescopeID string    // Which telescope captured it57}5859// NewTelescopeConfig creates a new telescope configuration60func NewTelescopeConfig(name, model string, lat, lon float64, owner, realmPath string) TelescopeConfig {61	return TelescopeConfig{62		Name:       name,63		Model:      model,64		Latitude:   lat,65		Longitude:  lon,66		Owner:      owner,67		RealmPath:  realmPath,68		Status:     "offline",69		LastUpdate: time.Now(),70	}71}7273// UpdateStatus updates the telescope status74func (t *TelescopeConfig) UpdateStatus(status string) {75	t.Status = status76	t.LastUpdate = time.Now()77}7879// IsAccessAllowed checks if an address has a current (non-expired) access rule.80// rules is an avl.Tree keyed by allowed address holding AccessRule values.81func IsAccessAllowed(address string, rules *avl.Tree) bool {82	if !rules.Has(address) {83		return false84	}85	rule := rules.Get(address).(AccessRule)86	return rule.ExpiresAt.IsZero() || time.Now().Before(rule.ExpiresAt)87}8889// ValidateCommand validates a telescope command90func ValidateCommand(cmd TelescopeCommand, config TelescopeConfig) {91	switch cmd.CommandType {92	case "capture", "stop":93	default:94		panic("invalid command type: must be capture or stop")95	}9697	if cmd.CommandType == "capture" {98		if cmd.TargetRA < 0 || cmd.TargetRA >= 24 {99			panic("invalid RA: must be between 0 and 24 hours")100		}101		if cmd.TargetDec < -90 || cmd.TargetDec > 90 {102			panic("invalid Dec: must be between -90 and 90 degrees")103		}104		if cmd.Exposure < 1 || cmd.Exposure > 300 {105			panic("invalid exposure time: must be between 1 and 300 seconds")106		}107	}108}109110// maxCaptureHistory is the number of captures a single telescope keeps locally.111const maxCaptureHistory = 100112113// TelescopeRealm manages a single telescope's state and operations114type TelescopeRealm struct {115	Config       *TelescopeConfig116	AccessRules  *avl.Tree // key: allowed address -> AccessRule117	CommandQueue []TelescopeCommand118	Captures     *CaptureFeed119	OwnerAddress string120}121122// NewTelescopeRealm creates a new telescope realm instance123func NewTelescopeRealm(config *TelescopeConfig) *TelescopeRealm {124	return &TelescopeRealm{125		Config:       config,126		AccessRules:  avl.NewTree(),127		CommandQueue: []TelescopeCommand{},128		Captures:     NewCaptureFeed(maxCaptureHistory),129		OwnerAddress: config.Owner,130	}131}132133// GrantAccess allows the owner to grant access to another user. Re-granting to134// an existing address overwrites the previous rule.135func (r *TelescopeRealm) GrantAccess(caller, address string, durationDays int) {136	r.checkOwner(caller)137138	if address == "" {139		panic("address cannot be empty")140	}141142	expiresAt := time.Time{} // Never expires by default143	if durationDays > 0 {144		expiresAt = time.Now().Add(time.Duration(durationDays) * 24 * time.Hour)145	}146147	rule := AccessRule{148		AllowedAddress: address,149		GrantedBy:      r.OwnerAddress,150		GrantedAt:      time.Now(),151		ExpiresAt:      expiresAt,152	}153154	r.AccessRules.Set(address, rule)155}156157// RevokeAccess removes access for a specific address158func (r *TelescopeRealm) RevokeAccess(caller, address string) {159	r.checkOwner(caller)160	r.AccessRules.Remove(address)161}162163// SubmitCommand allows authorized users to submit telescope commands164func (r *TelescopeRealm) SubmitCommand(caller, commandType string, targetRA, targetDec float64, exposure int) {165	// Check if caller has access (owner always has access)166	if caller != r.OwnerAddress {167		if !IsAccessAllowed(caller, r.AccessRules) {168			panic("access denied: you don't have permission to use this telescope")169		}170	}171172	// Create command173	cmd := TelescopeCommand{174		CommandType: commandType,175		TargetRA:    targetRA,176		TargetDec:   targetDec,177		Exposure:    exposure,178		RequestedBy: caller,179		RequestedAt: time.Now(),180	}181182	// Validate command183	ValidateCommand(cmd, *r.Config)184185	// Add to queue186	r.CommandQueue = append(r.CommandQueue, cmd)187188	// Update telescope status to busy189	r.Config.UpdateStatus("busy")190}191192// GetNextCommand returns the next command in the queue (for telescope controller)193func (r *TelescopeRealm) GetNextCommand(caller string) TelescopeCommand {194	r.checkOwner(caller)195196	if len(r.CommandQueue) == 0 {197		panic("no commands in queue")198	}199200	cmd := r.CommandQueue[0]201	r.CommandQueue = r.CommandQueue[1:]202203	return cmd204}205206// UpdateStatus allows the owner to update telescope status207func (r *TelescopeRealm) UpdateStatus(caller string, status string) {208	r.checkOwner(caller)209	r.Config.UpdateStatus(status)210}211212// RecordCapture allows the owner to record a capture result213func (r *TelescopeRealm) RecordCapture(caller, imageURL string, targetRA, targetDec float64, exposure int, capturedBy string) {214	r.checkOwner(caller)215216	if imageURL == "" {217		panic("image URL cannot be empty")218	}219220	capture := CaptureResult{221		ImageURL:    imageURL,222		TargetRA:    targetRA,223		TargetDec:   targetDec,224		Exposure:    exposure,225		CapturedBy:  capturedBy,226		CapturedAt:  time.Now(),227		TelescopeID: r.Config.Name,228	}229230	r.Captures.Add(capture)231232	// Update status back to online233	r.Config.UpdateStatus("online")234}235236// ClearCommandQueue clears all pending commands (emergency stop)237func (r *TelescopeRealm) ClearCommandQueue(caller string) {238	r.checkOwner(caller)239	r.CommandQueue = []TelescopeCommand{}240	r.Config.UpdateStatus("online")241}242243// GetCommandCount returns the number of pending commands244func (r *TelescopeRealm) GetCommandCount() int {245	return len(r.CommandQueue)246}247248// GetCaptureCount returns the number of stored captures249func (r *TelescopeRealm) GetCaptureCount() int {250	return r.Captures.Len()251}252253// GetAccessRuleCount returns the number of access rules254func (r *TelescopeRealm) GetAccessRuleCount() int {255	return r.AccessRules.Size()256}257258// checkOwner verifies the caller is the owner259func (r *TelescopeRealm) checkOwner(caller string) {260	if caller != r.OwnerAddress {261		panic("access restricted: owner only")262	}263}264

Functions

not supported for pure packages by the node (vm/qfuncs)

Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.