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

read.gno

9.02 Kb · 273 lines
  1package catalog
  2
  3import (
  4	"strings"
  5
  6	"gno.land/p/nym-alexiscolin000/gnoradio/store/v0"
  7	"gno.land/p/nym-alexiscolin000/gnoradio/text/v0"
  8	"gno.land/r/nym-alexiscolin000/gnoradio/data"
  9)
 10
 11// ---- Read API for the other GnoRadio realms (values only) ----
 12
 13func GenreName(g int) string {
 14	if g < 1 || g > NumGenres {
 15		return ""
 16	}
 17	return genres[g]
 18}
 19
 20func TrackCount() int    { return int(rd().count(mTracks)) }
 21func ArtistCount() int   { return int(rd().count(mArtists)) }
 22func AlbumCount() int    { return int(rd().count(mAlbums)) }
 23func PlaylistCount() int { return int(rd().count(mPlaylists)) }
 24
 25// TrackBrief is what the radio needs; playable is false for an unknown or
 26// hidden track, or one whose artist is hidden.
 27func TrackBrief(id int) (artistID, genre int, duration int64, playable_ bool) {
 28	rec := point(cTracks, id)
 29	if rec == "" {
 30		return 0, 0, 0, false
 31	}
 32	a := text.Atoi(store.Field(rec, fArtist))
 33	arec := point(cArtists, a)
 34	return a, text.Atoi(store.Field(rec, fGenre)), text.Atoi64(store.Field(rec, fDuration)),
 35		store.Field(rec, fHidden) == "" && arec != "" && store.Field(arec, aHidden) == ""
 36}
 37
 38// TrackBriefFor is TrackBrief and whether addr ("" for nobody) is the
 39// track's artist or one of its collaborators, from the same reads.
 40func TrackBriefFor(id int, addr address) (artistID, genre int, duration int64, playable_, own bool) {
 41	rec := point(cTracks, id)
 42	if rec == "" {
 43		return 0, 0, 0, false, false
 44	}
 45	a := text.Atoi(store.Field(rec, fArtist))
 46	arec := point(cArtists, a)
 47	playable_ = store.Field(rec, fHidden) == "" && arec != "" && store.Field(arec, aHidden) == ""
 48	if addr != "" && arec != "" {
 49		// splits are "addr:pct,…" and an address holds no ',' or ':'
 50		sp := store.Field(rec, fSplits)
 51		own = store.Field(arec, aOwner) == addr.String() || sp != "" && strings.Contains(","+sp, ","+addr.String()+":")
 52	}
 53	return a, text.Atoi(store.Field(rec, fGenre)), text.Atoi64(store.Field(rec, fDuration)), playable_, own
 54}
 55
 56// PlayableTitle is a track's title, "" unless it is playable (TrackBrief).
 57func PlayableTitle(id int) string {
 58	rec := point(cTracks, id)
 59	if rec == "" || store.Field(rec, fHidden) != "" {
 60		return ""
 61	}
 62	if arec := point(cArtists, text.Atoi(store.Field(rec, fArtist))); arec == "" || store.Field(arec, aHidden) != "" {
 63		return ""
 64	}
 65	return store.Field(rec, fTitle)
 66}
 67
 68func TrackTitle(id int) string {
 69	if rec := point(cTracks, id); rec != "" {
 70		return refLabel(store.Field(rec, fOrigin), store.Field(rec, fTitle), "track")
 71	}
 72	return ""
 73}
 74
 75func ArtistName(artistID int) string {
 76	if rec := point(cArtists, artistID); rec != "" {
 77		return refLabel(store.Field(rec, aKind), store.Field(rec, aName), "artist")
 78	}
 79	return ""
 80}
 81
 82func ArtistOwner(artistID int) address { return address(artistAt(artistID, aOwner)) }
 83func ArtistOf(owner address) int       { return artistOf(rd(), owner) }
 84
 85// ArtistPayee is what a payment to an artist checks, from one read: who
 86// is paid, whether verified, and whether the profile is visible.
 87func ArtistPayee(id int) (owner address, verified, visible bool) {
 88	rec := point(cArtists, id)
 89	if rec == "" {
 90		return "", false, false
 91	}
 92	return address(store.Field(rec, aOwner)), store.Field(rec, aVerified) == "1", store.Field(rec, aHidden) == ""
 93}
 94func ArtistVisible(artistID int) bool {
 95	rec := point(cArtists, artistID)
 96	return rec != "" && store.Field(rec, aHidden) == ""
 97}
 98
 99// ---- Value getters for the home realm and tools ----
100
101// GetTrack returns a copy of a track; ok is false if unknown. A pointer's
102// empty title reads as its platform ("Audius track").
103func GetTrack(id int) (Track, bool) {
104	if tr := getTrack(rd(), id); tr != nil {
105		tr.Title = refLabel(tr.Origin, tr.Title, "track")
106		return *tr, true
107	}
108	return Track{}, false
109}
110
111func GetArtist(id int) (Artist, bool) {
112	t := rd()
113	if a := getArtist(t, id); a != nil {
114		a.Name = refLabel(a.Kind, a.Name, "artist")
115		return *withLists(t, a), true
116	}
117	return Artist{}, false
118}
119
120// ArtistByRef looks a pointer artist up by its platform id ("audius-user:12").
121func ArtistByRef(ref string) int {
122	v, _ := data.Get(cNames, strings.TrimSpace(ref))
123	return text.Atoi(v)
124}
125
126// ArtistByName looks a profile up by its (case-insensitive) name.
127func ArtistByName(name string) int {
128	v, _ := data.Get(cNames, skeleton(strings.TrimSpace(name)))
129	return text.Atoi(v)
130}
131
132func GetAlbum(id int) (Album, bool) {
133	if a := getAlbum(rd(), id); a != nil {
134		return *a, true
135	}
136	return Album{}, false
137}
138
139func GetPlaylist(id int) (Playlist, bool) {
140	if p := getPlaylist(rd(), id); p != nil {
141		return *p, true
142	}
143	return Playlist{}, false
144}
145
146// ReportCount is the number of open (unresolved) reports.
147func ReportCount() int { return int(rd().count(mOpen)) }
148
149func GetReport(id int) (ReportInfo, bool) { return getReport(rd(), id) }
150
151// UserStats returns a listener's public counters and playlists. The like
152// count reads the listener's own like ranges, one page.
153func UserStats(addr address) (likes, follows int, tipped int64, lists []int) {
154	_, likes = rangePage(cLikes, addr.String(), 0, 0)
155	u := user(rd(), addr)
156	return likes, store.Count(u.Follows), u.Tipped, u.Playlists
157}
158
159// LikedPage lists a listener's liked track ids, newest tracks first,
160// paginated. Likes are keyed by track id, so this is the newest music the
161// listener liked, not the order of their likes (that needs an index per like,
162// which would add to every like's storage deposit).
163func LikedPage(addr address, offset, limit int) []int {
164	ids, _ := rangePage(cLikes, addr.String(), max0(offset), store.Limit(limit, 100))
165	return ids
166}
167
168// ---- Narrow getters: one field without copying a whole struct ----
169
170// ArtistTrackCount is the number of tracks an artist published.
171func ArtistTrackCount(artistID int) int {
172	tl, _ := lists(rd(), artistID)
173	return store.Count(tl)
174}
175
176// ArtistTrackPage lists an artist's track ids in publishing order, paginated.
177func ArtistTrackPage(artistID, offset, limit int) []int {
178	if offset < 0 {
179		return nil
180	}
181	tl, _ := lists(rd(), artistID)
182	return store.Page(tl, offset, store.Limit(limit, 100), false)
183}
184
185// ArtistBrief returns what a link to an artist needs, without the bio or the
186// id lists; ok is false for an unknown artist.
187func ArtistBrief(artistID int) (name string, verified, hidden, ok bool) {
188	rec := point(cArtists, artistID)
189	if rec == "" {
190		return "", false, false, false
191	}
192	return refLabel(store.Field(rec, aKind), store.Field(rec, aName), "artist"), store.Field(rec, aVerified) != "", store.Field(rec, aHidden) != "", true
193}
194
195// PlaylistBrief returns a playlist's header without its track ids.
196func PlaylistBrief(id int) (owner address, title string, tracks int, hidden, ok bool) {
197	rec := rd().val(cPlaylists, store.Pad(id)) // counts the ids without decoding them
198	if id < 1 || rec == "" {
199		return "", "", 0, false, false
200	}
201	f := store.Fields(rec)
202	return address(f[0]), f[1], store.Count(f[4]), f[3] != "", true
203}
204
205// FollowsPage lists the artist ids a listener follows, paginated.
206func FollowsPage(addr address, offset, limit int) []int {
207	return store.Page(user(rd(), addr).Follows, max0(offset), store.Limit(limit, 100), false)
208}
209
210// GenrePage lists the track ids of a genre (hidden ones included), newest first.
211func GenrePage(genre, offset, limit int) []int {
212	if genre < 1 || genre > NumGenres {
213		return nil
214	}
215	ids, _ := rangePage(cGenres, store.Pad(genre), max0(offset), store.Limit(limit, 100))
216	return ids
217}
218
219// GenreCount is the number of tracks filed under a genre.
220func GenreCount(genre int) int {
221	if genre < 1 || genre > NumGenres {
222		return 0
223	}
224	return int(rd().count(mGenre + genre))
225}
226
227// TrackPage lists track ids, newest first when newest is true.
228// Ids are dense (1..count), so these pages are arithmetic.
229func TrackPage(offset, limit int, newest bool) []int {
230	return seqPage(TrackCount(), offset, limit, newest)
231}
232func ArtistPage(offset, limit int) []int   { return seqPage(ArtistCount(), offset, limit, false) }
233func AlbumPage(offset, limit int) []int    { return seqPage(AlbumCount(), offset, limit, true) }
234func PlaylistPage(offset, limit int) []int { return seqPage(PlaylistCount(), offset, limit, true) }
235
236// ReportPage lists open report ids, newest first.
237func ReportPage(offset, limit int) []int {
238	keys, _ := store.Rows(data.PageAt(cReports, max0(offset), store.Limit(limit, 100), true))
239	out := make([]int, 0, len(keys))
240	for _, k := range keys {
241		out = append(out, text.Atoi(k))
242	}
243	return out
244}
245
246func seqPage(n, offset, limit int, newest bool) []int {
247	var out []int
248	for k := max0(offset); k < n && len(out) < store.Limit(limit, 100); k++ {
249		if newest {
250			out = append(out, n-k)
251		} else {
252			out = append(out, k+1)
253		}
254	}
255	return out
256}
257
258func max0(n int) int {
259	if n < 0 {
260		return 0
261	}
262	return n
263}
264
265func TopLiked() []Rank   { return rd().top(topLiked) }
266func TopArtists() []Rank { return rd().top(topArtists) }
267func TopFans() []Rank    { return rd().top(topFans) }
268
269func Admin() address            { return adminAddr() }
270func PendingAdmin() address     { return admin.Pending() } // the address the admin role is offered to, "" if none
271func Version() string           { return version }
272func RightsTerms() string       { return rightsTerms }
273func HostAllowed(h string) bool { return data.Has(cHosts, strings.ToLower(h)) }