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.

boardlegal.gno

4.92 Kb · 171 lines
  1package kourt
  2import "strconv"
  3func boardActCode(verb string, rowID uint64, categoryCode string) string {
  4	code := verb + "#" + strconv.FormatUint(rowID, 10)
  5	if categoryCode != "" {
  6		code += ":" + categoryCode
  7	}
  8	return code
  9}
 10const (
 11	boardCodeSpam      = "spam"
 12	boardCodeOffTopic  = "off-topic"
 13	boardCodeAbuse     = "abuse"
 14	boardCodeImpersonation = "impersonation"
 15	boardCodeIllegal   = "illegal-referred"
 16)
 17func mustBoardCode(code string) {
 18	switch code {
 19	case boardCodeSpam, boardCodeOffTopic, boardCodeAbuse,
 20		boardCodeImpersonation, boardCodeIllegal:
 21		return
 22	}
 23	panic("kourtv2: a board moderation code is one of: spam, off-topic, abuse, " +
 24		"impersonation, illegal-referred")
 25}
 26func BoardCodes() string {
 27	return boardCodeSpam + "," + boardCodeOffTopic + "," + boardCodeAbuse + "," +
 28		boardCodeImpersonation + "," + boardCodeIllegal
 29}
 30func GlobalHideRow(cur realm, courtSlug string, claimID, rowID uint64, categoryCode string) {
 31	if !cur.IsCurrent() {
 32		panic(errStaleRealm)
 33	}
 34	who := cur.Previous().Address()
 35	if !isGlobalMod(who) {
 36		panic("kourtv2: only a global DAO member may globally hide a comment")
 37	}
 38	checkReason(categoryCode)
 39	c := mustCourt(courtSlug)
 40	cs := mustClaim(c, claimID)
 41	r := mustBoardRow(cs, rowID)
 42	if r.purged {
 43		panic("kourtv2: that comment was already destroyed; there is nothing to withhold")
 44	}
 45	now := heightNow()
 46	if !r.global && r.globalClearedAt != 0 &&
 47		reSetWindowOpen(r.globalClearedAtTime, r.globalClearedAt, now) {
 48		d := ensureGlobalDAO()
 49		fire, _ := approveAction(d.pending,
 50			"boardreset:"+c.id+":"+strconv.FormatUint(claimID, 10)+":"+strconv.FormatUint(rowID, 10),
 51			who, categoryCode, d.purgeM)
 52		if !fire {
 53			return
 54		}
 55	}
 56	r.global = true
 57	scoreIndexDrop(cs, r)
 58	ensureClaimMod(c, ensureMod(c), claimID).
 59		appendLog(who, boardActCode("board-global-hide", rowID, categoryCode), "")
 60	emitGlobalAct(c.id, claimID, "board-global-hide", who)
 61}
 62func GlobalClearRow(cur realm, courtSlug string, claimID, rowID uint64) {
 63	if !cur.IsCurrent() {
 64		panic(errStaleRealm)
 65	}
 66	who := cur.Previous().Address()
 67	if !isGlobalMod(who) {
 68		panic("kourtv2: only a global DAO member may clear a global comment hide")
 69	}
 70	c := mustCourt(courtSlug)
 71	cs := mustClaim(c, claimID)
 72	r := mustBoardRow(cs, rowID)
 73	if !r.global {
 74		panic("kourtv2: that comment is not globally hidden")
 75	}
 76	r.global = false
 77	r.globalClearedAt = heightNow()
 78	r.globalClearedAtTime = nowTime()
 79	scoreIndexPut(cs, r)
 80	ensureClaimMod(c, ensureMod(c), claimID).
 81		appendLog(who, boardActCode("board-global-clear", rowID, ""), "")
 82	emitGlobalAct(c.id, claimID, "board-global-clear", who)
 83}
 84func PurgeBoardRow(cur realm, courtSlug string, claimID, rowID uint64, categoryCode string) {
 85	if !cur.IsCurrent() {
 86		panic(errStaleRealm)
 87	}
 88	who := cur.Previous().Address()
 89	d := ensureGlobalDAO()
 90	if !d.members.Has(who.String()) {
 91		panic("kourtv2: only a global DAO member may purge")
 92	}
 93	mustCategoryCode(categoryCode)
 94	c := mustCourt(courtSlug)
 95	cs := mustClaim(c, claimID)
 96	r := mustBoardRow(cs, rowID)
 97	if r.purged {
 98		return
 99	}
100	fire, votedCode := approveAction(d.pending,
101		"boardpurge:"+c.id+":"+strconv.FormatUint(claimID, 10)+":"+strconv.FormatUint(rowID, 10),
102		who, categoryCode, d.purgeM)
103	if !fire {
104		return
105	}
106	r.purged = true
107	r.text = ""
108	scoreIndexDrop(cs, r)
109	ensureClaimMod(c, ensureMod(c), claimID).
110		appendLog(who, boardActCode("board-purge", rowID, votedCode), "")
111	emitPurge(c.id, claimID, "board-row", who)
112}
113func BoardRowState(courtSlug string, claimID uint64, rowID uint64) string {
114	return boardMark(mustBoardRow(mustClaim(mustCourt(courtSlug), claimID), rowID))
115}
116const maxBatchRows = 64
117func PurgeBoardRange(cur realm, courtSlug string, claimID, fromRowID uint64, categoryCode string) uint64 {
118	if !cur.IsCurrent() {
119		panic(errStaleRealm)
120	}
121	who := cur.Previous().Address()
122	d := ensureGlobalDAO()
123	if !d.members.Has(who.String()) {
124		panic("kourtv2: only a global DAO member may purge")
125	}
126	mustCategoryCode(categoryCode)
127	c := mustCourt(courtSlug)
128	cs := mustClaim(c, claimID)
129	cm := ensureMod(c)
130	clm := lookupClaimMod(cm, claimID)
131	if clm == nil || !clm.boardPurgeAll {
132		fire, _ := approveAction(d.pending,
133			"boardpurgeall:"+c.id+":"+strconv.FormatUint(claimID, 10),
134			who, categoryCode, d.purgeM)
135		if !fire {
136			return fromRowID
137		}
138		clm = ensureClaimMod(c, cm, claimID)
139		clm.boardPurgeAll = true
140		clm.appendLog(who, boardActCode("board-purge-all", 0, categoryCode), "")
141		emitPurge(c.id, claimID, "board-all", who)
142	}
143	if cs.board == nil {
144		return 0
145	}
146	n, next := 0, uint64(0)
147	cs.board.Iterate(beClaimKey(fromRowID), "", func(_ string, v any) bool {
148		r := v.(*boardRow)
149		if r.purged {
150			return false
151		}
152		if n >= maxBatchRows {
153			next = r.id
154			return true
155		}
156		r.purged = true
157		r.text = ""
158		scoreIndexDrop(cs, r)
159		n++
160		return false
161	})
162	return next
163}
164func BoardPurgeOrdered(courtSlug string, claimID uint64) bool {
165	c := mustCourt(courtSlug)
166	if c.mod == nil {
167		return false
168	}
169	clm := lookupClaimMod(c.mod, claimID)
170	return clm != nil && clm.boardPurgeAll
171}