Skip to content Search Apps Documentation Source Content File Folder Download Copy Actions State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

avatar.gno

5.03 Kb · 173 lines
  1package avatar
  2
  3import (
  4	"chain"
  5	"chain/runtime"
  6	"strings"
  7
  8	"gno.land/p/g17khqpukees4237dtn3astzapmp462vjhsz6st4/settlers/nft/v0"
  9	"gno.land/p/nt/grc721/v0"
 10	"gno.land/p/nt/mdalert/v0"
 11	"gno.land/p/nt/ownable/v0"
 12	settlers "gno.land/r/g17khqpukees4237dtn3astzapmp462vjhsz6st4/settlers/nft"
 13)
 14
 15const (
 16	// MinSize is the minimum size allowed for an avatar in pixels.
 17	MinSize = 32
 18
 19	// MaxSize is the maximum size allowed for an avatar in pixels.
 20	MaxSize = 2048
 21)
 22
 23var (
 24	// Notice is a realm-wide message the admin can post at any time, shown at the top of the page.
 25	// It never affects SVG, URI or Markdown, it is purely informational.
 26	Notice string
 27
 28	// NoticeType is the style Notice is shown as.
 29	NoticeType mdalert.Type
 30
 31	// Realm path is the path of this realm.
 32	RealmPath string
 33
 34	// Admin account for the realm, only valid to post or clear realm-wide notices.
 35	admin *ownable.Ownable
 36
 37	// Go snippet is the Go usage example.
 38	goSnippet string
 39
 40	// Gnokey snippet is the gnokey example.
 41	gnokeySnippet string
 42)
 43
 44func init(cur realm) {
 45	RealmPath = strings.TrimPrefix(cur.PkgPath(), runtime.ChainDomain())
 46	admin = ownable.NewWithAddress(cur.Previous().Address())
 47	pkgPath := runtime.ChainDomain() + RealmPath
 48
 49	goSnippet = "import \"" + pkgPath + "\"\n\n" +
 50		"func RenderUser(addr address) string {\n\treturn avatar.Markdown(addr, 32, true) " +
 51		"+ \" \" + addr.String()\n}\n"
 52
 53	gnokeySnippet = "gnokey query vm/qrender \\\n" +
 54		"  -remote <remote> \\\n" +
 55		"  -data \"" + pkgPath + ":svg/{address}?size=256\" \\\n" +
 56		"  | tail -n +2 | sed '1s/^data: //' > settler.svg\n"
 57}
 58
 59// Admin returns the address of the admin account.
 60func Admin() address { return admin.Owner() }
 61
 62// TransferAdmin makes another account the admin. Only the admin can call it.
 63func TransferAdmin(cur realm, newAdmin address) {
 64	assertIsCurrent(cur)
 65	if err := admin.TransferOwnership(0, cur, newAdmin); err != nil {
 66		panic(err)
 67	}
 68}
 69
 70// SetNotice posts a realm-wide message, shown at the top of the page.
 71func SetNotice(cur realm, alertType mdalert.Type, msg string) {
 72	assertIsCurrent(cur)
 73	admin.AssertOwnedBy(cur.Previous().Address())
 74	assertIsValidAlertType(alertType)
 75
 76	NoticeType = alertType
 77	Notice = msg
 78	chain.Emit("NoticeSet", "type", string(alertType))
 79}
 80
 81// ClearNotice removes the current notice.
 82func ClearNotice(cur realm) {
 83	assertIsCurrent(cur)
 84	admin.AssertOwnedBy(cur.Previous().Address())
 85
 86	NoticeType = ""
 87	Notice = ""
 88	chain.Emit("NoticeCleared")
 89}
 90
 91// SVG returns the SVG document of the Settler of an address, or an empty text if it has none.
 92//
 93// The size is the width and height in pixels of the square image, from 32 to 2048 (multiples of 32 keep
 94// every art pixel as a whole number of screen pixels). A size of 0 or less leaves out the width and the
 95// height, so that the image scales to its container. If transparent is true, the image has no background.
 96func SVG(addr address, size int, transparent bool) string {
 97	if tid, traits := lookup(addr); tid != "" {
 98		return nft.RenderSVG(traits, options(size, transparent))
 99	}
100	return ""
101}
102
103// URI returns the image of the Settler of an address as a "data:image/svg+xml;charset=utf-8," URI, that can
104// be used as the source of an image or as the address of a Markdown image, or an empty text if it has none.
105// The size and transparent are the same as in SVG.
106func URI(addr address, size int, transparent bool) string {
107	if tid, traits := lookup(addr); tid != "" {
108		return nft.RenderDataURI(traits, options(size, transparent))
109	}
110	return ""
111}
112
113// Markdown returns the avatar of an address as a Markdown image, or an empty text if it has none:
114//
115//	![Settler #12](data:image/svg+xml;charset=utf-8,...)
116//
117// The size and transparent are the same as in SVG.
118func Markdown(addr address, size int, transparent bool) string {
119	if tid, traits := lookup(addr); tid != "" {
120		uri := nft.RenderDataURI(traits, options(size, transparent))
121		return "![Settler #" + string(tid) + "](" + uri + ")"
122	}
123	return ""
124}
125
126// lookup returns the ID and traits of the Settler of an address, or an empty ID and a zero-value Traits if it
127// has none.
128func lookup(addr address) (grc721.TokenID, nft.Traits) {
129	tid := settlers.TokenOf(addr)
130	if tid == "" {
131		return "", nft.Traits{}
132	}
133
134	traits, err := settlers.TraitsOf(tid)
135	if err != nil {
136		return "", nft.Traits{}
137	}
138	return tid, traits
139}
140
141// options builds the nft.Options for an image; size is clamped between MinSize and MaxSize (0 or less is
142// left as 0, so the image has no fixed size and scales to its container), and transparent controls whether
143// the background is drawn.
144func options(size int, transparent bool) nft.Options {
145	switch {
146	case size <= 0:
147		size = 0
148	case size < MinSize:
149		size = MinSize
150	case size > MaxSize:
151		size = MaxSize
152	}
153
154	return nft.Options{
155		Size:         size,
156		NoBackground: transparent,
157	}
158}
159
160func assertIsCurrent(cur realm) {
161	if !cur.IsCurrent() {
162		panic("unauthorized")
163	}
164}
165
166func assertIsValidAlertType(t mdalert.Type) {
167	switch t {
168	case mdalert.TypeCaution, mdalert.TypeInfo, mdalert.TypeNote,
169		mdalert.TypeSuccess, mdalert.TypeTip, mdalert.TypeWarning:
170		return
171	}
172	panic("invalid notice type")
173}