public_flag.gno
3.61 Kb ยท 138 lines
1package boards2
2
3import (
4 "chain"
5 "chain/runtime"
6 "strconv"
7
8 "gno.land/p/gnoland/boards"
9)
10
11// SetFlaggingThreshold sets the number of flags required to hide a thread or comment.
12//
13// Threshold is only applicable within the board where it's setted.
14func SetFlaggingThreshold(_ realm, boardID boards.ID, threshold int) {
15 if threshold < 1 {
16 panic("invalid flagging threshold")
17 }
18
19 assertRealmIsNotLocked()
20
21 board := mustGetBoard(boardID)
22 assertBoardIsNotFrozen(board)
23
24 caller := runtime.PreviousRealm().Address()
25 args := boards.Args{board.ID, threshold}
26 board.Permissions.WithPermission(cross, caller, PermissionBoardFlaggingUpdate, args, func(realm) {
27 assertRealmIsNotLocked()
28
29 gFlaggingThresholds.Set(boardID.String(), threshold)
30
31 chain.Emit(
32 "FlaggingThresholdUpdated",
33 "caller", caller.String(),
34 "boardID", board.ID.String(),
35 "threshold", strconv.Itoa(threshold),
36 )
37 })
38}
39
40// GetFlaggingThreshold returns the number of flags required to hide a thread or comment within a board.
41func GetFlaggingThreshold(boardID boards.ID) int {
42 assertBoardExists(boardID)
43 return getFlaggingThreshold(boardID)
44}
45
46// FlagThread adds a new flag to a thread.
47//
48// Flagging requires special permissions and hides the thread when
49// the number of flags reaches a pre-defined flagging threshold.
50func FlagThread(_ realm, boardID, threadID boards.ID, reason string) {
51 caller := runtime.PreviousRealm().Address()
52 board := mustGetBoard(boardID)
53 isRealmOwner := gPerms.HasRole(caller, RoleOwner)
54 if !isRealmOwner {
55 assertRealmIsNotLocked()
56 assertBoardIsNotFrozen(board)
57 }
58
59 thread, found := board.Threads.Get(threadID)
60 if !found {
61 panic("thread not found")
62 }
63
64 assertThreadIsNotFrozen(thread)
65
66 flagThread := func() {
67 hide := flagItem(thread, caller, reason, getFlaggingThreshold(board.ID))
68 if hide || isRealmOwner {
69 // Realm owners can hide with a single flag
70 thread.Hidden = true
71 }
72
73 chain.Emit(
74 "ThreadFlagged",
75 "caller", caller.String(),
76 "boardID", board.ID.String(),
77 "threadID", thread.ID.String(),
78 "reason", reason,
79 )
80 }
81
82 // Realm owners should be able to flag without permissions even when board is frozen
83 if isRealmOwner {
84 flagThread()
85 return
86 }
87
88 args := boards.Args{caller, board.ID, thread.ID, reason}
89 board.Permissions.WithPermission(cross, caller, PermissionThreadFlag, args, func(realm) {
90 flagThread()
91 })
92}
93
94// FlagReply adds a new flag to a comment or reply.
95//
96// Flagging requires special permissions and hides the comment or reply
97// when the number of flags reaches a pre-defined flagging threshold.
98func FlagReply(_ realm, boardID, threadID, replyID boards.ID, reason string) {
99 caller := runtime.PreviousRealm().Address()
100 board := mustGetBoard(boardID)
101 isRealmOwner := gPerms.HasRole(caller, RoleOwner)
102 if !isRealmOwner {
103 assertRealmIsNotLocked()
104 assertBoardIsNotFrozen(board)
105 }
106
107 thread := mustGetThread(board, threadID)
108 assertThreadIsNotFrozen(thread)
109
110 reply := mustGetReply(thread, replyID)
111 flagReply := func() {
112 hide := flagItem(reply, caller, reason, getFlaggingThreshold(board.ID))
113 if hide || isRealmOwner {
114 // Realm owners can hide with a single flag
115 reply.Hidden = true
116 }
117
118 chain.Emit(
119 "ReplyFlagged",
120 "caller", caller.String(),
121 "boardID", board.ID.String(),
122 "threadID", thread.ID.String(),
123 "replyID", reply.ID.String(),
124 "reason", reason,
125 )
126 }
127
128 // Realm owners should be able to flag without permissions even when board is frozen
129 if isRealmOwner {
130 flagReply()
131 return
132 }
133
134 args := boards.Args{caller, board.ID, thread.ID, reply.ID, reason}
135 board.Permissions.WithPermission(cross, caller, PermissionReplyFlag, args, func(realm) {
136 flagReply()
137 })
138}