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

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}