diff --git a/Makefile b/Makefile index 922b4cb174..a54dd2faec 100644 --- a/Makefile +++ b/Makefile @@ -35,6 +35,9 @@ P2E_DOCKER_IMAGE=$(DOCKER_REGISTRY)/p2e-update-leaderboard:$(shell git rev-parse FEED_DOCKER_IMAGE=$(DOCKER_REGISTRY)/feed-clean-pinata-keys:$(shell git rev-parse --short HEAD) MULTISIG_DOCKER_IMAGE=$(DOCKER_REGISTRY)/cosmos-multisig-backend:$(shell git rev-parse --short HEAD) +GNODEV=gnodev --add-account g193vp9tjhfpldvgg3gn433ayv8pn7rtfv8shyeq $$(find gno -name gno.mod -type f -exec dirname {} \;) +GNODEV_E2E=$(GNODEV) --unsafe-api --server-mode + ARCH := $(shell uname -m) @@ -431,9 +434,13 @@ generate.internal-contracts-clients: node_modules install-gno: node_modules yarn install-gno +.PHONY: start.gnodev +start.gnodev: + $(GNODEV) + .PHONY: start.gnodev-e2e start.gnodev-e2e: - gnodev --unsafe-api --server-mode --add-account g193vp9tjhfpldvgg3gn433ayv8pn7rtfv8shyeq $$(find gno -name gno.mod -type f -exec dirname {} \;) + $(GNODEV_E2E) .PHONY: clone-gno clone-gno: diff --git a/gno/r/cockpit/gno.mod b/gno/r/cockpit/gno.mod new file mode 100644 index 0000000000..c9d7118c54 --- /dev/null +++ b/gno/r/cockpit/gno.mod @@ -0,0 +1,9 @@ +module gno.land/r/teritori/cockpit + +require ( + gno.land/p/demo/mux v0.0.0-latest + gno.land/p/demo/users v0.0.0-latest + gno.land/r/demo/profile v0.0.0-latest + gno.land/r/demo/users v0.0.0-latest + gno.land/r/gnoland/ghverify v0.0.0-latest +) diff --git a/gno/r/cockpit/render.gno b/gno/r/cockpit/render.gno new file mode 100644 index 0000000000..95cb74a0e4 --- /dev/null +++ b/gno/r/cockpit/render.gno @@ -0,0 +1,82 @@ +package cockpit + +import ( + "std" + + "gno.land/p/demo/mux" + "gno.land/p/demo/users" + "gno.land/r/demo/profile" + rusers "gno.land/r/demo/users" + "gno.land/r/gnoland/ghverify" +) + +const ( + chainId = "test4" + pkgPath = "r/teritori/cockpit" + userSlug = "u" + usersRealm = "r/demo/users" + ghLinkHint = "r/gnoland/ghverify?help&__func=RequestVerification" + ghProfileHint = "/r/demo/profile:u/" +) + +func Render(reqPath string) string { + router := mux.NewRouter() + + router.HandleFunc("", renderHome) + router.HandleFunc(userSlug+"/{aon}", renderUser) + + return router.Render(reqPath) +} + +func renderHome(res *mux.ResponseWriter, req *mux.Request) { + res.Write("# Cockpit\n\n") + res.Write("See `:" + userSlug + "/{addressOrName}`\n\n") + res.Write("Examples:\n") + elems := rusers.ListUsersByPrefix("", 20) + for _, elem := range elems { + res.Write("- [ " + elem + " ](./" + pkgPath + ":" + userSlug + "/@" + elem + ")\n") + } +} + +func renderUser(res *mux.ResponseWriter, req *mux.Request) { + addr, username, ok := resolveUserBasics(req.GetVar("aon")) + if !ok { + res.Write("404") + return + } + + // FIXME: markdown injection, spam + res.Write("# " + profile.GetStringField(addr, profile.DisplayName, "Anon") + "\n") + + if username != "" { + res.Write("- Username: [" + username + "](/" + usersRealm + ":" + username + ")\n") + } else { + res.Write("- Username: [Not registered](/" + usersRealm + "?help&__func=Register)\n") + } + + handle := ghverify.GetHandleByAddress(addr.String()) + if handle != "" { + res.Write("- GitHub: [" + handle + "](https://github.com/" + handle + ")\n") + } else { + res.Write("- GitHub: [Not linked](/" + ghLinkHint + ")\n") + } + + res.Write("- Address: [" + addr.String() + "](https://gnoscan.io/accounts/" + addr.String() + "?chainId=" + chainId + ")\n\n") + + // FIXME: markdown injection, spam + res.Write("```\n" + profile.GetStringField(addr, profile.Bio, "No bio") + "\n```\n[Full profile / edit](" + ghProfileHint + addr.String() + ")\n") +} + +func resolveUserBasics(aon string) (std.Address, string, bool) { + user := rusers.GetUserByAddressOrName(users.AddressOrName(aon)) + if user != nil { + return user.Address, user.Name, true + } + + addr := std.Address(aon) + if addr.IsValid() { + return addr, "", true + } + + return addr, "", false +}