Search Apps Documentation Source Content File Folder Download Copy Actions Download

hub.gno

5.70 Kb · 201 lines
  1// Package hub exposes safe, read-only views over boards2's persistent
  2// state. The Get* functions are crossing functions: callers must invoke
  3// them with `cross` (e.g. `hub.GetBoard(cross, id)`). The crossing into
  4// hub gives each call a live `cur` whose `Previous()` is the caller's
  5// realm — that's what boards2's protected entry points use for the
  6// namespace check.
  7//
  8// Note for future maintainers: inside a Get* body, `cur.Previous()` is
  9// the *immediate* caller's realm, which may be an intermediary, not
 10// necessarily the end user. Do not graft user-identity gating onto
 11// these reads.
 12package hub
 13
 14import (
 15	"gno.land/p/gnoland/boards"
 16
 17	boards2 "gno.land/r/gnoland/boards2/v1"
 18)
 19
 20// GetBoard returns a safe board.
 21func GetBoard(cur realm, id uint64) (Board, bool) {
 22	b, found := getBoard(0, cur, id)
 23	if !found {
 24		return Board{}, false
 25	}
 26	return NewSafeBoard(b), true
 27}
 28
 29// GetThread returns a safe board thread.
 30func GetThread(cur realm, boardID, threadID uint64) (Thread, bool) {
 31	t, found := getThread(0, cur, boardID, threadID)
 32	if !found {
 33		return Thread{}, false
 34	}
 35	return NewSafeThread(t), true
 36}
 37
 38// GetComment returns a safe thread comment.
 39func GetComment(cur realm, boardID, threadID, commentID uint64) (Comment, bool) {
 40	c, found := getComment(0, cur, boardID, threadID, commentID)
 41	if !found {
 42		return Comment{}, false
 43	}
 44	return NewSafeComment(c), true
 45}
 46
 47// GetBoards returns a list with all boards.
 48// To reverse iterate use a negative count.
 49func GetBoards(cur realm, start, count int) []Board {
 50	var boards_ []Board
 51	boards2.Iterate(cross(cur), start, count, func(b *boards.Board) bool {
 52		boards_ = append(boards_, NewSafeBoard(b))
 53		return false
 54	})
 55	return boards_
 56}
 57
 58// GetThreads returns a list with threads of a board.
 59// To reverse iterate use a negative count.
 60func GetThreads(cur realm, boardID uint64, start, count int) []Thread {
 61	b, found := getBoard(0, cur, boardID)
 62	if !found {
 63		return nil
 64	}
 65
 66	var threads []Thread
 67	b.Threads.Iterate(start, count, func(thread *boards.Post) bool {
 68		threads = append(threads, NewSafeThread(thread))
 69		return false
 70	})
 71	return threads
 72}
 73
 74// GetMembers returns a list with the members of a board.
 75// To reverse iterate use a negative count.
 76func GetMembers(cur realm, boardID uint64, start, count int) []boards.User {
 77	b, found := getBoard(0, cur, boardID)
 78	if !found {
 79		return nil
 80	}
 81
 82	var members []boards.User
 83	b.Permissions.IterateUsers(start, count, func(u boards.User) bool {
 84		members = append(members, u)
 85		return false
 86	})
 87	return members
 88}
 89
 90// GetReposts returns a list with repost of a board thread.
 91// To reverse iterate use a negative count.
 92func GetReposts(cur realm, boardID, threadID uint64, start, count int) []Thread {
 93	t, found := getThread(0, cur, boardID, threadID)
 94	if !found {
 95		return nil
 96	}
 97
 98	var reposts []Thread
 99	t.Reposts.Iterate(start, count, func(rBoardID, rRepostID boards.ID) bool {
100		r, found := getThread(0, cur, uint64(rBoardID), uint64(rRepostID))
101		if found {
102			reposts = append(reposts, NewSafeThread(r))
103		}
104		return false
105	})
106	return reposts
107}
108
109// GetFlag returns a list with thread or comment moderation flags.
110// To reverse iterate use a negative count.
111// Thread flags are returned when `commentID` is zero, or comment flags are returned otherwise.
112func GetFlags(cur realm, boardID, threadID, commentID uint64, start, count int) []boards.Flag {
113	var storage boards.FlagStorage
114	if commentID == 0 {
115		t, found := getThread(0, cur, boardID, threadID)
116		if !found {
117			return nil
118		}
119
120		storage = t.Flags
121	} else {
122		c, found := getComment(0, cur, boardID, threadID, commentID)
123		if !found {
124			return nil
125		}
126
127		storage = c.Flags
128	}
129
130	var flags []boards.Flag
131	storage.Iterate(start, count, func(f boards.Flag) bool {
132		flags = append(flags, f)
133		return false
134	})
135	return flags
136}
137
138// GetComments returns a list with all thread comments and replies.
139// To reverse iterate use a negative count.
140// Top level comments can be filtered by checking `Comment.ParentID`, replies
141// always have a parent comment or reply, while comments have no parent.
142func GetComments(cur realm, boardID, threadID uint64, start, count int) []Comment {
143	t, found := getThread(0, cur, boardID, threadID)
144	if !found {
145		return nil
146	}
147
148	var comments []Comment
149	t.Replies.Iterate(start, count, func(comment *boards.Post) bool {
150		comments = append(comments, NewSafeComment(comment))
151		return false
152	})
153	return comments
154}
155
156// GetReplies returns a list with top level comment replies.
157// To reverse iterate use a negative count.
158func GetReplies(cur realm, boardID, threadID, commentID uint64, start, count int) []Comment {
159	c, found := getComment(0, cur, boardID, threadID, commentID)
160	if !found {
161		return nil
162	}
163
164	var replies []Comment
165	c.Replies.Iterate(start, count, func(comment *boards.Post) bool {
166		replies = append(replies, NewSafeComment(comment))
167		return false
168	})
169	return replies
170}
171
172// getBoard fetches a raw *boards.Board via boards2's protected
173// GetBoard. Non-crossing helper: rlm is hub's own cur, threaded
174// through from the enclosing crossing function.
175func getBoard(_ int, rlm realm, boardID uint64) (*boards.Board, bool) {
176	return boards2.GetBoard(cross(rlm), boards.ID(boardID))
177}
178
179func getThread(_ int, rlm realm, boardID, threadID uint64) (*boards.Post, bool) {
180	b, found := getBoard(0, rlm, boardID)
181	if !found {
182		return nil, false
183	}
184
185	t, found := b.Threads.Get(boards.ID(threadID))
186	if !found {
187		// When thread is not found search it within hidden threads
188		meta := b.Meta.(*boards2.BoardMeta)
189		t, found = meta.HiddenThreads.Get(boards.ID(threadID))
190	}
191	return t, found
192}
193
194func getComment(_ int, rlm realm, boardID, threadID, commentID uint64) (*boards.Post, bool) {
195	t, found := getThread(0, rlm, boardID, threadID)
196	if !found {
197		return nil, false
198	}
199
200	return t.Replies.Get(boards.ID(commentID))
201}