1package communityreg
2
3import (
4 "errors"
5 "std"
6
7 "gno.land/p/demo/avl"
8 "gno.land/p/demo/ownable"
9 "gno.land/p/zenao/communities"
10 zenaov1 "gno.land/p/zenao/zenao/v1"
11)
12
13var (
14 Ownable *ownable.Ownable
15
16 registered avl.Tree // <communityPkgPath> -> func() communities.Info
17 communityesByMembers avl.Tree // <memberID>/<communityPkgPath> -> communityPkgPath
18 communitiesByPkgPath avl.Tree // <communityPkgPath> -> communities.Info
19
20 ErrCommunityNotFound = errors.New("community not found")
21)
22
23func init() {
24 Ownable = ownable.NewWithAddress(std.Address("g1djrkw9tf4px658j85cc6fhsvm50uf9s0g6kfsm")) // zenao-dev-admin
25}
26
27// XXX: split this package into communityreg and communitiesindex
28
29func Register(infoGetter communities.InfoGetter) {
30 pkgPath := std.PreviousRealm().PkgPath()
31
32 if infoGetter == nil {
33 registered.Remove(pkgPath)
34 // XXX: remove from index??
35 return
36 }
37
38 registered.Set(pkgPath, infoGetter)
39}
40
41func getInfo(pkgPath string) (*zenaov1.CommunityInfo, bool) {
42 raw, ok := registered.Get(pkgPath)
43 if !ok {
44 return nil, false
45 }
46 return raw.(communities.InfoGetter)(), true
47}
48
49func mustGetInfo(pkgPath string) *zenaov1.CommunityInfo {
50 info, ok := getInfo(pkgPath)
51 if !ok {
52 panic(ErrCommunityNotFound)
53 }
54 return info
55}
56
57func IndexCommunity(pkgPath string) {
58 Ownable.AssertCallerIsOwner()
59
60 if prev := getCommunityByPkgPath(pkgPath); prev != nil {
61 panic("community already indexed: " + pkgPath)
62 }
63
64 info := mustGetInfo(pkgPath)
65 communitiesByPkgPath.Set(pkgPath, info)
66}
67
68func AddMember(communityPkgPath string, memberID string) {
69 Ownable.AssertCallerIsOwner()
70
71 if prev := getCommunityByPkgPath(communityPkgPath); prev == nil {
72 panic("community not found: " + communityPkgPath)
73 }
74
75 key := memberID + "/" + communityPkgPath
76 communityesByMembers.Set(key, communityPkgPath)
77 info := mustGetInfo(communityPkgPath)
78 communitiesByPkgPath.Set(communityPkgPath, info)
79}
80
81func RemoveMember(communityPkgPath string, memberID string) {
82 Ownable.AssertCallerIsOwner()
83
84 if prev := getCommunityByPkgPath(communityPkgPath); prev == nil {
85 panic("community not found: " + communityPkgPath)
86 }
87
88 key := memberID + "/" + communityPkgPath
89 communityesByMembers.Remove(key)
90 info := mustGetInfo(communityPkgPath)
91 communitiesByPkgPath.Set(communityPkgPath, info)
92}
93
94func getCommunityByPkgPath(pkgPath string) *zenaov1.CommunityInfo {
95 raw, ok := communitiesByPkgPath.Get(pkgPath)
96 if !ok {
97 return nil
98 }
99 return raw.(*zenaov1.CommunityInfo)
100}
101
102func mustGetCommunityByPkgPath(pkgPath string) *zenaov1.CommunityInfo {
103 info := getCommunityByPkgPath(pkgPath)
104 if info == nil {
105 panic(ErrCommunityNotFound)
106 }
107 return info
108}
109
110func listCommunities(limit, offset uint32) []*zenaov1.CommunityInfo {
111 return listCommunitiesInternal(&communitiesByPkgPath, "", "", false, limit, offset)
112}
113
114func listCommunitiesByMembers(memberID string, limit, offset uint32) []*zenaov1.CommunityInfo {
115 // ff is 255 in hex, which is the highest byte value, so it will match all keys that start with memberID.
116 fromKey := memberID + "/"
117 toKey := memberID + "/\xff"
118
119 return listCommunitiesInternal(&communityesByMembers, fromKey, toKey, false, limit, offset)
120}
121
122func listCommunitiesInternal(at avl.ITree, fromKey string, toKey string, rev bool, limit, offset uint32) []*zenaov1.CommunityInfo {
123 res := []*zenaov1.CommunityInfo{}
124 count := uint32(0)
125 it := func(key string, value interface{}) bool {
126 if count < offset {
127 count++
128 return false
129 }
130 var info zenaov1.CommunityInfo
131 switch val := value.(type) {
132 case *zenaov1.CommunityInfo:
133 info = *val
134 case string:
135 info = *mustGetCommunityByPkgPath(val)
136 }
137 info.PkgPath = key
138 res = append(res, &info)
139 return uint32(len(res)) >= limit
140 }
141 if rev {
142 at.ReverseIterate(toKey, fromKey, it)
143 } else {
144 at.Iterate(fromKey, toKey, it)
145 }
146 return res
147}
communityreg.gno
3.73 Kb ยท 147 lines