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

hub.gno

6.03 Kb · 213 lines
  1// The `hub.gno` file exposes safe, read-only views over the realm's
  2// persistent state.
  3//
  4// Note for future maintainers: these reads perform no caller
  5// authorization, so do not graft user-identity gating onto them.
  6
  7package boards2
  8
  9import (
 10	hubexts "gno.land/p/gnoland/boards/exts/hub/v0"
 11	"gno.land/p/gnoland/boards/v0"
 12)
 13
 14// Safe view types are defined in the hub extensions package and
 15// re-exported here so callers can keep using them via this realm.
 16type (
 17	Board   = hubexts.Board
 18	Comment = hubexts.Comment
 19	Flag    = hubexts.Flag
 20	Member  = hubexts.Member
 21	Thread  = hubexts.Thread
 22)
 23
 24// GetBoard returns a safe board.
 25func GetBoard(id uint64) (Board, bool) {
 26	b, found := gBoards.Get(boards.ID(id))
 27	if !found {
 28		return Board{}, false
 29	}
 30	return hubexts.NewSafeBoard(b), true
 31}
 32
 33// GetThread returns a safe board thread.
 34func GetThread(boardID, threadID uint64) (Thread, bool) {
 35	t, found := getBoardThread(boardID, threadID)
 36	if !found {
 37		return Thread{}, false
 38	}
 39	return hubexts.NewSafeThread(t), true
 40}
 41
 42// GetComment returns a safe thread comment or reply.
 43// `commentID` can be the ID of a top level comment or of a nested reply.
 44func GetComment(boardID, threadID, commentID uint64) (Comment, bool) {
 45	c, found := getComment(boardID, threadID, commentID)
 46	if !found {
 47		return Comment{}, false
 48	}
 49	return hubexts.NewSafeComment(c), true
 50}
 51
 52// GetBoards returns a list with all boards.
 53// To reverse iterate use a negative count.
 54func GetBoards(start, count int) []Board {
 55	var boards_ []Board
 56	gBoards.Iterate(start, count, func(b *boards.Board) bool {
 57		boards_ = append(boards_, hubexts.NewSafeBoard(b))
 58		return false
 59	})
 60	return boards_
 61}
 62
 63// GetThreads returns a list with threads of a board.
 64// To reverse iterate use a negative count.
 65// A board without thread storage has no threads, so nil is returned.
 66func GetThreads(boardID uint64, start, count int) []Thread {
 67	b, found := gBoards.Get(boards.ID(boardID))
 68	if !found || b.Threads == nil {
 69		return nil
 70	}
 71
 72	var threads []Thread
 73	b.Threads.Iterate(start, count, func(thread *boards.Post) bool {
 74		threads = append(threads, hubexts.NewSafeThread(thread))
 75		return false
 76	})
 77	return threads
 78}
 79
 80// GetMembers returns a list with the members of a board.
 81// A zero `boardID` refers to the realm, so the realm admin users are returned.
 82// A non permissioned board has no members, so nil is returned.
 83func GetMembers(boardID uint64, start, count int) []Member {
 84	perms := gPerms
 85	if boardID != 0 {
 86		b, found := gBoards.Get(boards.ID(boardID))
 87		if !found {
 88			return nil
 89		}
 90		perms = b.Permissions
 91	}
 92
 93	if perms == nil {
 94		return nil
 95	}
 96
 97	var members []Member
 98	perms.IterateUsers(start, count, func(u boards.User) bool {
 99		members = append(members, hubexts.NewSafeMember(u))
100		return false
101	})
102	return members
103}
104
105// GetReposts returns a list with repost of a board thread.
106// To reverse iterate use a negative count.
107// A repost is not included when its destination thread has been deleted,
108// so the total accessible results can be shorter than the thread's RepostCount(),
109// and a single call can return fewer than count results.
110// (The reason for the discrepancy is that the start index can be large,
111// and this function cannot scan all reposts up to the start index to
112// resolve the discrepancy.)
113func GetReposts(boardID, threadID uint64, start, count int) []Thread {
114	t, found := getBoardThread(boardID, threadID)
115	if !found {
116		return nil
117	}
118
119	var reposts []Thread
120	t.Reposts.Iterate(start, count, func(rBoardID, rRepostID boards.ID) bool {
121		r, found := getBoardThread(uint64(rBoardID), uint64(rRepostID))
122		if found {
123			reposts = append(reposts, hubexts.NewSafeThread(r))
124		}
125		return false
126	})
127	return reposts
128}
129
130// GetFlags returns a list with thread or comment moderation flags.
131// To reverse iterate use a negative count.
132// Thread flags are returned when `commentID` is zero, or the flags of the
133// comment or reply with that ID are returned otherwise.
134func GetFlags(boardID, threadID, commentID uint64, start, count int) []Flag {
135	var storage boards.FlagStorage
136	if commentID == 0 {
137		t, found := getBoardThread(boardID, threadID)
138		if !found {
139			return nil
140		}
141
142		storage = t.Flags
143	} else {
144		c, found := getComment(boardID, threadID, commentID)
145		if !found {
146			return nil
147		}
148
149		storage = c.Flags
150	}
151
152	var flags []Flag
153	storage.Iterate(start, count, func(f boards.Flag) bool {
154		flags = append(flags, hubexts.NewSafeFlag(f))
155		return false
156	})
157	return flags
158}
159
160// GetComments returns a list with top-level comments of a thread.
161// To reverse iterate use a negative count.
162func GetComments(boardID, threadID uint64, start, count int) []Comment {
163	t, found := getBoardThread(boardID, threadID)
164	if !found {
165		return nil
166	}
167
168	var comments []Comment
169	// Replies only has direct replies.
170	t.Replies.Iterate(start, count, func(comment *boards.Post) bool {
171		comments = append(comments, hubexts.NewSafeComment(comment))
172		return false
173	})
174	return comments
175}
176
177// GetReplies returns a list with the direct replies of a comment or reply.
178// To reverse iterate use a negative count.
179// `commentID` can be the ID of a top level comment or of a nested reply.
180func GetReplies(boardID, threadID, commentID uint64, start, count int) []Comment {
181	c, found := getComment(boardID, threadID, commentID)
182	if !found {
183		return nil
184	}
185
186	var replies []Comment
187	c.Replies.Iterate(start, count, func(comment *boards.Post) bool {
188		replies = append(replies, hubexts.NewSafeComment(comment))
189		return false
190	})
191	return replies
192}
193
194// getBoardThread returns a board thread from their IDs.
195func getBoardThread(boardID, threadID uint64) (*boards.Post, bool) {
196	b, found := gBoards.Get(boards.ID(boardID))
197	if !found {
198		return nil, false
199	}
200	return getThread(b, boards.ID(threadID))
201}
202
203// getComment returns a thread comment or reply from their IDs.
204// It searches the thread's flat index of all comments and replies, so
205// nested replies are addressable by ID and not only top level comments.
206func getComment(boardID, threadID, commentID uint64) (*boards.Post, bool) {
207	t, found := getBoardThread(boardID, threadID)
208	if !found {
209		return nil, false
210	}
211
212	return getReply(t, boards.ID(commentID))
213}