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

hub.gno

6.02 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	"gno.land/p/gnoland/boards"
 11	hubexts "gno.land/p/gnoland/boards/exts/hub"
 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}