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}