Search Apps Documentation Source Content File Folder Download Copy Actions Download

util.gno

3.70 Kb · 150 lines
  1package social
  2
  3import (
  4	"strconv"
  5	"strings"
  6
  7	"gno.land/p/nt/avl/v0"
  8	"gno.land/p/nt/ufmt/v0"
  9	"gno.land/r/sys/users"
 10)
 11
 12//----------------------------------------
 13// private utility methods
 14
 15// Get the UserPosts for the user.
 16func getUserPosts(userAddr address) *UserPosts {
 17	userPosts, exists := gUserPostsByAddress.Get(userAddr.String())
 18	if !exists {
 19		return nil
 20	}
 21
 22	return userPosts.(*UserPosts)
 23}
 24
 25// Get the UserPosts for the userAddr. If not found, add a new UserPosts to
 26// gUserPostsByAddress and update gUserAddressByName with the username.
 27// (The caller usually has already called usernameOf to get the username, but if
 28// it is "" then this will get it.)
 29func getOrCreateUserPosts(userAddr address, username string) *UserPosts {
 30	userPosts := getUserPosts(userAddr)
 31	if userPosts != nil {
 32		return userPosts
 33	}
 34
 35	if username == "" {
 36		username = usernameOf(userAddr)
 37	}
 38	if username == "" {
 39		username = userAddr.String()
 40	}
 41
 42	userPosts = newUserPosts(gRealmPath+":"+username, userAddr)
 43	gUserPostsByAddress.Set(userAddr.String(), userPosts)
 44	gUserAddressByName.Set(username, userAddr)
 45
 46	return userPosts
 47}
 48
 49func padZero(u64 uint64, length int) string {
 50	str := strconv.Itoa(int(u64))
 51	if len(str) >= length {
 52		return str
 53	} else {
 54		return strings.Repeat("0", length-len(str)) + str
 55	}
 56}
 57
 58func postIDKey(pid PostID) string {
 59	return padZero(uint64(pid), 10)
 60}
 61
 62func reactionKey(reaction Reaction) string {
 63	return strconv.Itoa(int(reaction))
 64}
 65
 66// If reactions has an value for the given reaction, then return it.
 67// Otherwise, add the reaction key to reactions, set the value to an empty avl.Tree and return it.
 68func getOrCreateReactionValue(reactions *avl.Tree, reaction Reaction) *avl.Tree {
 69	key := reactionKey(reaction)
 70	valueI, exists := reactions.Get(key)
 71	if exists {
 72		return valueI.(*avl.Tree)
 73	} else {
 74		value := avl.NewTree()
 75		reactions.Set(key, value)
 76		return value
 77	}
 78}
 79
 80// listByteStringKeysByPrefix returns up to maxResults keys from tree that start
 81// with the given prefix, treating keys as byte strings (not Unicode runes).
 82// Inlined from gno.land/p/jefft0/avlhelpers which is not yet deployed.
 83func listByteStringKeysByPrefix(tree avl.ITree, prefix string, maxResults int) []string {
 84	result := []string{}
 85	end := ""
 86	n := len(prefix)
 87	for n > 0 {
 88		if ascii := int(prefix[n-1]); ascii < 0xff {
 89			end = prefix[0:n-1] + string(ascii+1)
 90			break
 91		}
 92		n--
 93	}
 94	tree.Iterate(prefix, end, func(key string, value any) bool {
 95		result = append(result, key)
 96		return len(result) >= maxResults
 97	})
 98	return result
 99}
100
101func indentBody(indent string, body string) string {
102	lines := strings.Split(body, "\n")
103	res := ""
104	for i, line := range lines {
105		if i > 0 {
106			res += "\n"
107		}
108		res += indent + line
109	}
110	return res
111}
112
113// NOTE: length must be greater than 3.
114func summaryOf(str string, length int) string {
115	lines := strings.SplitN(str, "\n", 2)
116	line := lines[0]
117	if len(line) > length {
118		line = line[:(length-3)] + "..."
119	} else if len(lines) > 1 {
120		// len(line) <= 80
121		line = line + "..."
122	}
123	return line
124}
125
126func displayAddressMD(addr address) string {
127	user := users.ResolveAddress(addr)
128	if user == nil {
129		return "[" + addr.String() + "](/r/gnoland/users/v1:" + addr.String() + ")"
130	} else {
131		return "[@" + user.Name() + "](" + gRealmPath + ":" + user.Name() + ")"
132	}
133}
134
135func usernameOf(addr address) string {
136	user := users.ResolveAddress(addr)
137	if user == nil {
138		return ""
139	} else {
140		return user.Name()
141	}
142}
143
144// Return the User info as a JSON string.
145// (This is a temporary utility until gno.land supports returning structured data directly.)
146func marshalJsonUser(user *users.UserData) string {
147	return ufmt.Sprintf(
148		"{\"address\": \"%s\", \"name\": \"%s\", \"deleted\": %t}",
149		user.Addr().String(), user.Name(), user.IsDeleted())
150}