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

admin.gno

4.27 Kb · 140 lines
  1package radio
  2
  3import (
  4	"chain"
  5	"strings"
  6
  7	"gno.land/p/nym-alexiscolin000/gnoradio/role/v0"
  8	"gno.land/p/nym-alexiscolin000/gnoradio/text/v0"
  9	"gno.land/r/nym-alexiscolin000/gnoradio/data"
 10)
 11
 12// The radio admin (curator and moderator) is a p/role held by this realm,
 13// passed in two steps. Each change is mirrored to radio/config "admin", so
 14// the next release keeps it, and the mirror is the authority: a change the
 15// previous release made after this one's init counts.
 16
 17// adminAddr is the admin ("" once renounced).
 18func adminAddr() address {
 19	h, ok := data.Get(cConfig, "admin")
 20	return role.Mirror(admin, h, ok)
 21}
 22
 23// syncAdmin adopts the mirror when the previous release changed it after
 24// this one's init (during the release's delay).
 25func syncAdmin() {
 26	h, ok := data.Get(cConfig, "admin")
 27	admin = role.Adopt(admin, "admin", h, ok)
 28}
 29
 30func onlyAdmin(cur realm) {
 31	syncAdmin()
 32	if admin == nil || !admin.Is(0, cur) {
 33		panic("radio: admin only")
 34	}
 35	noPayment()
 36}
 37
 38// Admin is the radio admin ("" once renounced).
 39func Admin() address { return adminAddr() }
 40
 41// PendingAdmin is the address the admin role is offered to ("" if none).
 42func PendingAdmin() address { return admin.Pending() }
 43
 44// Ready tells the data realm that this release is on chain (see
 45// data.Propose). Anyone may call it.
 46func Ready(cur realm) {
 47	noPayment()
 48	data.Ready(cross(cur))
 49}
 50
 51// OfferAdmin offers the admin role to an address (offering it to the admin
 52// cancels the offer); AcceptAdmin takes it. Each change is mirrored to the
 53// data realm, so the next release keeps the admin.
 54func OfferAdmin(cur realm, to address) {
 55	onlyAdmin(cur)
 56	admin.Offer(0, cur, to)
 57}
 58
 59func AcceptAdmin(cur realm) {
 60	noPayment()
 61	syncAdmin()
 62	if admin == nil {
 63		panic("radio: nothing offered to you")
 64	}
 65	admin.Accept(0, cur)
 66	data.Set(cross(cur), cConfig, "admin", admin.Holder().String())
 67}
 68
 69// RenounceAdmin gives the admin role up for good, for this release and the
 70// next ones.
 71func RenounceAdmin(cur realm) {
 72	onlyAdmin(cur)
 73	admin.Renounce(0, cur)
 74	data.Set(cross(cur), cConfig, "admin", "")
 75}
 76
 77// DropSlot silences a track in one station's rotation (moderation of last
 78// resort). It stays silent through Refresh until RestoreSlot. Radio admin only.
 79func DropSlot(cur realm, stationID, trackID int) {
 80	onlyAdmin(cur)
 81	t := rd()
 82	st := t.station(stationID)
 83	i, ok := st.slot(trackID)
 84	if st.id == MainStation {
 85		ok = trackID >= 1 && trackID <= t.synced() // Main simulcasts: the drop flag alone silences it there
 86	}
 87	if !ok {
 88		panic("radio: track not in this station's rotation")
 89	}
 90	ts := now()
 91	if !t.has(cDropped, dropKey(st.id, trackID)) {
 92		t.set(cDropped, dropKey(st.id, trackID), "1")
 93		t.setFlowAt(fDrops, 4, t.flowAt(fDrops, 4)+1)
 94	}
 95	if st.id != MainStation {
 96		st.setDuration(i, 0, ts)
 97	}
 98	release(cur, st.dropSlots(trackID, ts))
 99	save(cur, t)
100	chain.Emit("SlotDropped", "station", text.Itoa(st.id), "track", text.Itoa(trackID))
101}
102
103// RestoreSlot undoes DropSlot: the track plays again on that station if the
104// catalog still allows it. Radio admin only.
105func RestoreSlot(cur realm, stationID, trackID int) {
106	onlyAdmin(cur)
107	mustStation(stationID)
108	t := rd()
109	if !t.del(cDropped, dropKey(stationID, trackID)) {
110		panic("radio: this slot was not dropped")
111	}
112	t.setFlowAt(fDrops, 4, t.flowAt(fDrops, 4)-1)
113	refresh(cur, t, trackID)
114	save(cur, t)
115	chain.Emit("SlotRestored", "station", text.Itoa(stationID), "track", text.Itoa(trackID))
116}
117
118// Unqueue removes a track's programmed slots from a station; one on air ends
119// now. Radio admin (curator) only.
120func Unqueue(cur realm, stationID, trackID int) {
121	onlyAdmin(cur)
122	t := rd()
123	st := t.station(stationID)
124	release(cur, st.dropSlots(trackID, now()))
125	save(cur, t)
126	chain.Emit("Unqueued", "station", text.Itoa(st.id), "track", text.Itoa(trackID))
127}
128
129// Render points gnoweb visitors to the GnoRadio site; a retired release says
130// which realm took over.
131func Render(_ string) string {
132	home := strings.TrimPrefix(strings.TrimSuffix(self, "radio/v1"), "gno.land") + "home/v1"
133	d := strings.TrimPrefix(dataPath, "gno.land")
134	out := "# GnoRadio · radio\n\nThis contract holds GnoRadio's radio rules; its data lives in [" + d + "](" + d +
135		"). The site lives at [" + home + "](" + home + ").\n"
136	if w := data.Writer("radio"); w != self {
137		out += "\nThis release is retired: the radio is now `" + w + "`.\n"
138	}
139	return out
140}