code.pablomurad.com

bbs-hammer

SSH BBS with forums, chat, door games, retro terminals and a weather service, written in Go

feat: show radio and sky activity in presence
author
Pablo Murad
date
commit
6be1158246a486873bb996c2f1bff653d5df4e21
parent
186c1b3029381a7b2703cabb8c1167b0b714d124
changes
10 files +94 −6
@@ -569,9 +569,18 @@ Summary: "who is connected to the BBS right now", 			Free:    true,
 			Run: func(context.Context, *dispatch.Call) (*dispatch.Result, error) {
 				online := s.presence.List()
+				for i := range online {
+					if online[i].Anonymous {
+						online[i].Doing = "" // what a guest does stays theirs
+					}
+				}
 				lines := make([]string, 0, len(online))
 				for _, o := range online {
-					lines = append(lines, fmt.Sprintf("%-16s  %-4s  %s", o.Nick, o.Where, ago(time.Since(o.Since))))
+					line := fmt.Sprintf("%-16s  %-4s  %s", o.Nick, o.Where, ago(time.Since(o.Since)))
+					if o.Doing != "" && !o.Anonymous {
+						line += "  " + o.Doing
+					}
+					lines = append(lines, line)
 				}
 				if online == nil {
 					online = []community.Online{}
@@ -411,4 +411,7 @@ "BBS_RADIO_SHARED":          "Recommended on the wall", 	"BBS_RADIO_PICKED":          "%s is now on Hammer FM",
 	"AWARD_TUNED_IN":            "Tuned in",
 	"AWARD_DJ":                  "DJ",
+	"BBS_WHERE_ALMANAC":         "under the sky",
+	"BBS_WHERE_RADIO":           "at the radio",
+	"BBS_LINECAST_DOING":        "watching the %s",
 }
@@ -289,6 +289,10 @@ where:      community.WhereAlmanac, 		counter:    awards.Almanac,
 	}
 	play.start = func(node int, deadline time.Time) (door.Session, error) {
+		if st.pres != nil {
+			defer st.pres.SetDoing(st.tf("BBS_LINECAST_DOING", st.t("BBS_LINECAST_"+strings.ToUpper(app))))
+		}
+
 		return door.Start(door.Spec{
 			Name:    "linecast",
 			Program: lc.program,
@@ -48,6 +48,11 @@ 	if !waitWhere(srv, "ana", community.WhereAlmanac) {
 		t.Errorf("presence does not show ana in the almanac: %+v", srv.presence.List())
 	}
+	for _, o := range srv.presence.List() {
+		if o.Nick == "ana" && o.Doing != "olhando: lua" && o.Doing != "watching the moon" {
+			t.Errorf("doing = %q, want her watching the moon", o.Doing)
+		}
+	}
 
 	mark := ana.mark()
 	ana.send("q")
@@ -39,6 +39,7 @@ // liveOnline is one person on the live page. type liveOnline struct {
 	Nick  string    `json:"nick"`
 	Where string    `json:"where"`
+	Doing string    `json:"doing,omitempty"`
 	Since time.Time `json:"since"`
 }
 
@@ -56,7 +57,7 @@ snap.Guests++ 
 			continue
 		}
-		snap.Online = append(snap.Online, liveOnline{Nick: o.Nick, Where: o.Where, Since: o.Since.UTC().Truncate(time.Second)})
+		snap.Online = append(snap.Online, liveOnline{Nick: o.Nick, Where: o.Where, Doing: o.Doing, Since: o.Since.UTC().Truncate(time.Second)})
 	}
 
 	return snap
@@ -229,7 +230,7 @@ function show(snap) {   list.replaceChildren();
   for (const o of snap.online) {
     const li = document.createElement('li');
-    for (const [cls, text] of [['nick', o.nick], ['where', o.where], ['since', ago(o.since)]]) {
+    for (const [cls, text] of [['nick', o.nick], ['where', o.doing || o.where], ['since', ago(o.since)]]) {
       const span = document.createElement('span');
       span.className = cls; span.textContent = text; li.append(span);
     }
@@ -69,6 +69,10 @@ case community.WhereChat: 		return "chat"
 	case community.WhereGame:
 		return "game"
+	case community.WhereAlmanac:
+		return "sky"
+	case community.WhereRadio:
+		return "radio"
 	}
 
 	return "menu"
@@ -100,7 +104,11 @@ } 			nodes := s.presence.Nodes()
 			lines := make([]string, 0, len(nodes))
 			for _, n := range nodes {
-				lines = append(lines, fmt.Sprintf("%3d  %-16s  %-6s  %-16s  %-5s  idle %s", n.Node, n.Nick, n.Via, n.IP, n.Where, ago(n.Idle)))
+				line := fmt.Sprintf("%3d  %-16s  %-6s  %-16s  %-5s  idle %s", n.Node, n.Nick, n.Via, n.IP, n.Where, ago(n.Idle))
+				if n.Doing != "" {
+					line += "  " + n.Doing
+				}
+				lines = append(lines, line)
 			}
 
 			return &dispatch.Result{Data: nodes, Lines: lines}, nil
@@ -182,8 +182,15 @@ case community.WhereChat: 			where = st.t("BBS_WHERE_CHAT")
 		case community.WhereGame:
 			where = st.t("BBS_WHERE_GAME")
+		case community.WhereAlmanac:
+			where = st.t("BBS_WHERE_ALMANAC")
+		case community.WhereRadio:
+			where = st.t("BBS_WHERE_RADIO")
 		}
 		extra := ""
+		if o.Doing != "" {
+			extra = "  " + st.th.Value + o.Doing + st.th.Reset
+		}
 		if o.Anonymous {
 			extra = "  " + st.th.Dim + "(" + st.t("BBS_ANON_TAG") + ")" + st.th.Reset
 		}
@@ -0,0 +1,45 @@+package bbs
+
+import (
+	"encoding/json"
+	"strings"
+	"testing"
+
+	"github.com/runawaydevil/hammer/internal/community"
+)
+
+// Who is on, the node monitor and /:live show the radio and the sky, and
+// what people are listening to; a guest's never reaches the public page.
+func TestPresenceShowsRadioAndSky(t *testing.T) {
+	srv := testServer(t, &Config{Live: &LiveConfig{Enabled: true}})
+	ana := srv.presence.Join("fp:SHA256:ana", "ana", false)
+	ana.SetWhere(community.WhereRadio)
+	ana.SetDoing("listening to Jazz FM")
+	cia := srv.presence.Join("fp:SHA256:cia", "cia", false)
+	cia.SetWhere(community.WhereAlmanac)
+	cia.SetDoing("watching the moon")
+	guest := srv.presence.Join("anon:1", "guest-1", true)
+	guest.SetWhere(community.WhereRadio)
+	guest.SetDoing("listening to Secret Station")
+
+	bia := login(t, listen(t, srv), "bia", newSigner(t))
+	bia.send("w")
+	bia.send("o\r")
+	bia.waitFor("listening to Jazz FM")
+	bia.waitFor("watching the moon")
+	bia.waitFor("at the radio")
+	bia.waitFor("under the sky")
+
+	raw, _ := json.Marshal(srv.liveSnapshot())
+	if !strings.Contains(string(raw), "listening to Jazz FM") || !strings.Contains(string(raw), "watching the moon") {
+		t.Fatalf("/:live lacks what people are doing: %s", raw)
+	}
+	if strings.Contains(string(raw), "Secret Station") {
+		t.Fatalf("/:live shows a guest's station: %s", raw)
+	}
+
+	st := &session{}
+	if st.whereShort(community.WhereRadio) != "radio" || st.whereShort(community.WhereAlmanac) != "sky" {
+		t.Fatalf("node monitor: radio %q, almanac %q", st.whereShort(community.WhereRadio), st.whereShort(community.WhereAlmanac))
+	}
+}
@@ -405,5 +405,8 @@ "BBS_RADIO_RECOMMENDS": "♪ recommends %s (%s), find it in [o] on the air",   "BBS_RADIO_SHARED": "Recommended on the wall",
   "BBS_RADIO_PICKED": "%s is now on Hammer FM",
   "AWARD_TUNED_IN": "Tuned in",
-  "AWARD_DJ": "DJ"
+  "AWARD_DJ": "DJ",
+  "BBS_WHERE_ALMANAC": "under the sky",
+  "BBS_WHERE_RADIO": "at the radio",
+  "BBS_LINECAST_DOING": "watching the %s"
 }
@@ -405,5 +405,8 @@ "BBS_RADIO_RECOMMENDS": "♪ recomenda %s (%s), está no [o] no ar",   "BBS_RADIO_SHARED": "Recomendada no mural",
   "BBS_RADIO_PICKED": "%s agora está na Hammer FM",
   "AWARD_TUNED_IN": "Sintonizado",
-  "AWARD_DJ": "DJ"
+  "AWARD_DJ": "DJ",
+  "BBS_WHERE_ALMANAC": "sob o céu",
+  "BBS_WHERE_RADIO": "no rádio",
+  "BBS_LINECAST_DOING": "olhando: %s"
 }