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

render.gno

3.96 Kb · 174 lines
  1package user
  2
  3import (
  4	"net/url"
  5	"strconv"
  6	"strings"
  7
  8	"gno.land/p/jeronimoalbi/pager/v0"
  9	"gno.land/r/akkadia/beta/admin"
 10)
 11
 12// Render handles RESTful routing and returns Markdown responses.
 13func Render(iUrl string) string {
 14	assertRenderURLLen(iUrl)
 15	u, err := url.Parse(iUrl)
 16	if err != nil {
 17		return "404\n"
 18	}
 19
 20	query := u.Query()
 21
 22	switch u.Path {
 23	case "":
 24		return renderHome()
 25	case "users":
 26		return renderUsersList(iUrl)
 27	case "user":
 28		addr := address(query.Get("address"))
 29		return renderUser(iUrl, addr)
 30	default:
 31		return renderError("Not found")
 32	}
 33}
 34
 35func renderHome() string {
 36	output := `# AKKADIA User
 37
 38## Introduction
 39
 40User realm stores address-keyed profiles for AKKADIA.
 41
 42- **created_at**: recorded when the user is created
 43- **properties**: admin-managed key/value attributes
 44
 45## Stats
 46
 47`
 48	output += "* **Total Users**: " + strconv.Itoa(GetTotalUserSize()) + "\n"
 49	output += `
 50## Quick Links
 51
 52* [Browse Users](./user:users)
 53
 54## User Lookup
 55
 56<gno-form path="user">
 57  <gno-input name="address" placeholder="Enter the address" />
 58</gno-form>
 59`
 60	return output
 61}
 62
 63func renderUsersList(iUrl string) string {
 64	output := "# Users\n\n"
 65	output += "[← Home](./user:)\n\n"
 66
 67	totalUsers := GetTotalUserSize()
 68	if totalUsers == 0 {
 69		output += "*No users registered yet.*\n"
 70		return output
 71	}
 72
 73	pages, err := pager.New(iUrl, totalUsers, pager.WithPageSize(20))
 74	if err != nil {
 75		return renderError("Invalid page")
 76	}
 77
 78	currentPage := pages.Page()
 79	addrStrs := ListUsers(currentPage, pages.PageSize())
 80	for _, addrStr := range addrStrs {
 81		nickname := ""
 82		listed := ListUsersByAddresses(address(addrStr))
 83		if len(listed) > 0 {
 84			nickname = listed[0]["nickname"]
 85		}
 86		if nickname != "" {
 87			output += "* [" + escapeMarkdown(nickname) + " (" + addrStr + ")](./user:user?address=" + addrStr + "&page=" + strconv.Itoa(currentPage) + ")\n"
 88		} else {
 89			output += "* [" + addrStr + "](./user:user?address=" + addrStr + "&page=" + strconv.Itoa(currentPage) + ")\n"
 90		}
 91	}
 92
 93	if pages.HasPages() {
 94		output += "\n" + pager.Picker(pages)
 95	}
 96
 97	return output
 98}
 99
100func renderUser(iUrl string, addr address) string {
101	if !addr.IsValid() {
102		return renderError("Invalid address")
103	}
104
105	u, _ := url.Parse(iUrl)
106	page := normalizeRenderPage(u.Query().Get("page"))
107
108	addrStr := addr.String()
109	if !HasUser(addr) {
110		return renderError("User not found")
111	}
112
113	users := ListUsersByAddresses(addr)
114
115	output := "# User Detail\n\n"
116	if page != "" {
117		output += "[← Back to List](./user:users?page=" + page + ")\n\n"
118	} else {
119		output += "[← Home](./user:)\n\n"
120	}
121	output += "* **Address**: " + addrStr + " [[View on Explorer](" + admin.GetExplorerURL() + "/m/explorer/player?address=" + addrStr + ")]\n\n"
122
123	if len(users) > 0 {
124		output += "## Properties\n\n"
125		for k, v := range users[0] {
126			if k == "address" {
127				continue
128			}
129			output += "* **" + escapeMarkdown(k) + "**: " + escapeMarkdown(v) + "\n"
130		}
131	}
132
133	return output
134}
135
136func normalizeRenderPage(rawPage string) string {
137	if rawPage == "" {
138		return ""
139	}
140	page, err := strconv.Atoi(rawPage)
141	if err != nil || page < 1 {
142		return ""
143	}
144	return strconv.Itoa(page)
145}
146
147func renderError(message string) string {
148	output := "# Error\n\n"
149	output += "> " + message + "\n\n"
150	output += "[← Back to Home](./user:)\n"
151	return output
152}
153
154func escapeMarkdown(s string) string {
155	s = strings.ReplaceAll(s, "\\", "\\\\")
156	s = strings.ReplaceAll(s, "\n", "\\n")
157	s = strings.ReplaceAll(s, "`", "\\`")
158	s = strings.ReplaceAll(s, "*", "\\*")
159	s = strings.ReplaceAll(s, "_", "\\_")
160	s = strings.ReplaceAll(s, "{", "\\{")
161	s = strings.ReplaceAll(s, "}", "\\}")
162	s = strings.ReplaceAll(s, "[", "\\[")
163	s = strings.ReplaceAll(s, "]", "\\]")
164	s = strings.ReplaceAll(s, "(", "\\(")
165	s = strings.ReplaceAll(s, ")", "\\)")
166	s = strings.ReplaceAll(s, "#", "\\#")
167	s = strings.ReplaceAll(s, "+", "\\+")
168	s = strings.ReplaceAll(s, "-", "\\-")
169	s = strings.ReplaceAll(s, ".", "\\.")
170	s = strings.ReplaceAll(s, "!", "\\!")
171	s = strings.ReplaceAll(s, "|", "\\|")
172	s = strings.ReplaceAll(s, ">", "\\>")
173	return s
174}