public.gno
4.70 Kb · 196 lines
1package boards
2
3import (
4 "chain"
5 "chain/runtime/unsafe"
6 "strconv"
7)
8
9//----------------------------------------
10// Public facing functions
11
12func GetBoardIDFromName(name string) (BoardID, bool) {
13 boardI := gBoardsByName.Get(name)
14 if boardI == nil {
15 return 0, false
16 }
17 return boardI.(*Board).id, true
18}
19
20func CreateBoard(cur realm, name string) BoardID {
21 if !cur.Previous().IsUserCall() {
22 panic("invalid non-user call")
23 }
24
25 bid := incGetBoardID()
26 caller := unsafe.OriginCaller()
27 if usernameOf(caller) == "" {
28 panic("unauthorized")
29 }
30 url := "/r/archive/boards:" + name
31 board := newBoard(bid, url, name, caller)
32 bidkey := boardIDKey(bid)
33 gBoards.Set(bidkey, board)
34 gBoardsByName.Set(name, board)
35 return board.id
36}
37
38// checkAnonFee reads unsafe.OriginSend() to verify the anonymous-posting
39// fee was attached to the tx. Callers MUST also assert
40// cur.Previous().IsUserCall() before calling — see
41// docs/resources/effective-gno.md#verifying-inbound-coin-payments.
42func checkAnonFee() bool {
43 sent := unsafe.OriginSend()
44 anonFeeCoin := chain.NewCoin("ugnot", int64(gDefaultAnonFee))
45 if len(sent) == 1 && sent[0].IsGTE(anonFeeCoin) {
46 return true
47 }
48 return false
49}
50
51func CreateThread(cur realm, bid BoardID, title string, body string) PostID {
52 if !cur.Previous().IsUserCall() {
53 panic("invalid non-user call")
54 }
55
56 caller := unsafe.OriginCaller()
57 if usernameOf(caller) == "" {
58 if !checkAnonFee() {
59 panic("please register, otherwise minimum fee " + strconv.Itoa(gDefaultAnonFee) + " is required if anonymous")
60 }
61 }
62 board := getBoard(bid)
63 if board == nil {
64 panic("board not exist")
65 }
66 thread := board.AddThread(caller, title, body)
67 return thread.id
68}
69
70func CreateReply(cur realm, bid BoardID, threadid, postid PostID, body string) PostID {
71 if !cur.Previous().IsUserCall() {
72 panic("invalid non-user call")
73 }
74
75 caller := unsafe.OriginCaller()
76 if usernameOf(caller) == "" {
77 if !checkAnonFee() {
78 panic("please register, otherwise minimum fee " + strconv.Itoa(gDefaultAnonFee) + " is required if anonymous")
79 }
80 }
81 board := getBoard(bid)
82 if board == nil {
83 panic("board not exist")
84 }
85 thread := board.GetThread(threadid)
86 if thread == nil {
87 panic("thread not exist")
88 }
89 if postid == threadid {
90 reply := thread.AddReply(caller, body)
91 return reply.id
92 } else {
93 post := thread.GetReply(postid)
94 reply := post.AddReply(caller, body)
95 return reply.id
96 }
97}
98
99// If dstBoard is private, does not ping back.
100// If board specified by bid is private, panics.
101func CreateRepost(cur realm, bid BoardID, postid PostID, title string, body string, dstBoardID BoardID) PostID {
102 if !cur.Previous().IsUserCall() {
103 panic("invalid non-user call")
104 }
105
106 caller := unsafe.OriginCaller()
107 if usernameOf(caller) == "" {
108 // TODO: allow with gDefaultAnonFee payment.
109 if !checkAnonFee() {
110 panic("please register, otherwise minimum fee " + strconv.Itoa(gDefaultAnonFee) + " is required if anonymous")
111 }
112 }
113 board := getBoard(bid)
114 if board == nil {
115 panic("src board not exist")
116 }
117 if board.IsPrivate() {
118 panic("cannot repost from a private board")
119 }
120 dst := getBoard(dstBoardID)
121 if dst == nil {
122 panic("dst board not exist")
123 }
124 thread := board.GetThread(postid)
125 if thread == nil {
126 panic("thread not exist")
127 }
128 repost := thread.AddRepostTo(caller, title, body, dst)
129 return repost.id
130}
131
132func DeletePost(cur realm, bid BoardID, threadid, postid PostID, reason string) {
133 if !cur.Previous().IsUserCall() {
134 panic("invalid non-user call")
135 }
136
137 caller := unsafe.OriginCaller()
138 board := getBoard(bid)
139 if board == nil {
140 panic("board not exist")
141 }
142 thread := board.GetThread(threadid)
143 if thread == nil {
144 panic("thread not exist")
145 }
146 if postid == threadid {
147 // delete thread
148 if !thread.HasPermission(caller, DeletePermission) {
149 panic("unauthorized")
150 }
151 board.DeleteThread(threadid)
152 } else {
153 // delete thread's post
154 post := thread.GetReply(postid)
155 if post == nil {
156 panic("post not exist")
157 }
158 if !post.HasPermission(caller, DeletePermission) {
159 panic("unauthorized")
160 }
161 thread.DeletePost(postid)
162 }
163}
164
165func EditPost(cur realm, bid BoardID, threadid, postid PostID, title, body string) {
166 if !cur.Previous().IsUserCall() {
167 panic("invalid non-user call")
168 }
169
170 caller := unsafe.OriginCaller()
171 board := getBoard(bid)
172 if board == nil {
173 panic("board not exist")
174 }
175 thread := board.GetThread(threadid)
176 if thread == nil {
177 panic("thread not exist")
178 }
179 if postid == threadid {
180 // edit thread
181 if !thread.HasPermission(caller, EditPermission) {
182 panic("unauthorized")
183 }
184 thread.Update(title, body)
185 } else {
186 // edit thread's post
187 post := thread.GetReply(postid)
188 if post == nil {
189 panic("post not exist")
190 }
191 if !post.HasPermission(caller, EditPermission) {
192 panic("unauthorized")
193 }
194 post.Update(title, body)
195 }
196}