1package eventreg
2
3import (
4 "errors"
5 "std"
6
7 "gno.land/p/demo/avl"
8 "gno.land/p/demo/ownable"
9 "gno.land/p/demo/seqid"
10 "gno.land/p/zenao/events"
11 zenaov1 "gno.land/p/zenao/zenao/v1"
12)
13
14// all dates are in unix seconds for easier interfacing with maketx call and vm/qeval
15
16var (
17 Ownable *ownable.Ownable
18
19 registered avl.Tree // <eventPkgPath> -> func() events.Info
20 eventsByPkgPath avl.Tree // <eventPkgPath> -> events.Info
21 eventsByEndDate avl.Tree // <endDateUnixSeconds>/<eventPkgPath> -> eventPkgPath
22 eventsByParticipant avl.Tree // <participantID>/<endDateUnixSeconds>/<eventPkgPath> -> eventPkgPath
23 eventsByCreator avl.Tree // <creatorID>/<endDateUnixSeconds>/<eventPkgPath> -> eventPkgPath
24 participantsByEvent avl.Tree // <eventPkgPath>/<participantID> -> participantID
25)
26
27func init() {
28 Ownable = ownable.NewWithAddress(std.Address("g1djrkw9tf4px658j85cc6fhsvm50uf9s0g6kfsm")) // zenao-dev-admin
29}
30
31// XXX: split this package into eventreg and eventsindex
32
33func Register(infoGetter events.InfoGetter) {
34 pkgPath := std.PreviousRealm().PkgPath()
35
36 if infoGetter == nil {
37 registered.Remove(pkgPath)
38 // XXX: remove from index??
39 return
40 }
41
42 registered.Set(pkgPath, infoGetter)
43}
44
45func getInfo(pkgPath string) (*zenaov1.EventInfo, bool) {
46 raw, ok := registered.Get(pkgPath)
47 if !ok {
48 return nil, false
49 }
50 return raw.(events.InfoGetter)(), true
51}
52
53func mustGetInfo(pkgPath string) *zenaov1.EventInfo {
54 info, ok := getInfo(pkgPath)
55 if !ok {
56 panic(ErrEventNotFound)
57 }
58 return info
59}
60
61func IndexEvent(pkgPath string) {
62 Ownable.AssertCallerIsOwner()
63
64 if prev := getEventByPkgPath(pkgPath); prev != nil {
65 panic("already added")
66 }
67
68 info := mustGetInfo(pkgPath)
69 key := pkgPath
70 eventsByPkgPath.Set(key, info)
71
72 key = unixTimeKey(info.EndDate) + "/" + pkgPath
73 eventsByEndDate.Set(key, pkgPath)
74
75 key = info.Creator + "/" + unixTimeKey(info.EndDate) + "/" + pkgPath
76 eventsByCreator.Set(key, pkgPath)
77}
78
79func UpdateIndex(pkgPath string) {
80 Ownable.AssertCallerIsOwner()
81
82 prevInfo := mustGetEventByPkgPath(pkgPath)
83
84 info := mustGetInfo(pkgPath)
85 eventsByPkgPath.Set(pkgPath, info)
86
87 if prevInfo.EndDate != info.EndDate {
88 key := unixTimeKey(prevInfo.EndDate) + "/" + pkgPath
89 eventsByEndDate.Remove(key)
90
91 newKey := unixTimeKey(info.EndDate) + "/" + pkgPath
92 eventsByEndDate.Set(newKey, pkgPath)
93
94 key = prevInfo.Creator + "/" + unixTimeKey(prevInfo.EndDate) + "/" + pkgPath
95 eventsByCreator.Remove(key)
96
97 newKey = info.Creator + "/" + unixTimeKey(info.EndDate) + "/" + pkgPath
98 eventsByCreator.Set(newKey, pkgPath)
99
100 startKey := pkgPath + "/"
101 endKey := startKey[:len(startKey)-1] + string('/'+1)
102 participantsByEvent.Iterate(startKey, endKey, func(key string, value interface{}) bool {
103 userID := value.(string)
104
105 key = userID + "/" + unixTimeKey(prevInfo.EndDate) + "/" + pkgPath
106 eventsByParticipant.Remove(key)
107
108 newKey = userID + "/" + unixTimeKey(info.EndDate) + "/" + pkgPath
109 eventsByParticipant.Set(newKey, pkgPath)
110
111 return false
112 })
113 } else if prevInfo.Creator != info.Creator {
114 key := prevInfo.Creator + "/" + unixTimeKey(prevInfo.EndDate) + "/" + pkgPath
115 eventsByCreator.Remove(key)
116
117 newKey := info.Creator + "/" + unixTimeKey(info.EndDate) + "/" + pkgPath
118 eventsByCreator.Set(newKey, pkgPath)
119 }
120}
121
122func AddParticipant(eventPkgPath string, userID string) {
123 Ownable.AssertCallerIsOwner()
124
125 evt := mustGetEventByPkgPath(eventPkgPath)
126
127 key := userID + "/" + unixTimeKey(evt.EndDate) + "/" + eventPkgPath
128 eventsByParticipant.Set(key, eventPkgPath)
129
130 key = eventPkgPath + "/" + userID
131 participantsByEvent.Set(key, userID)
132
133 info := mustGetInfo(eventPkgPath)
134 eventsByPkgPath.Set(eventPkgPath, info)
135}
136
137func RemoveParticipant(eventPkgPath string, userID string) {
138 Ownable.AssertCallerIsOwner()
139
140 evt := mustGetEventByPkgPath(eventPkgPath)
141
142 key := userID + "/" + unixTimeKey(evt.EndDate) + "/" + eventPkgPath
143 eventsByParticipant.Remove(key)
144
145 key = eventPkgPath + "/" + userID
146 participantsByEvent.Remove(key)
147
148 info := mustGetInfo(eventPkgPath)
149 eventsByPkgPath.Set(eventPkgPath, info)
150}
151
152var ErrEventNotFound = errors.New("event not found")
153
154func getEventByPkgPath(pkgPath string) *zenaov1.EventInfo {
155 raw, ok := eventsByPkgPath.Get(pkgPath)
156 if !ok {
157 return nil
158 }
159 info := raw.(*zenaov1.EventInfo)
160 return info
161}
162
163func mustGetEventByPkgPath(pkgPath string) *zenaov1.EventInfo {
164 evt := getEventByPkgPath(pkgPath)
165 if evt == nil {
166 panic(ErrEventNotFound)
167 }
168 return evt
169}
170
171func listEvents(from, to int64, limit uint32) []*zenaov1.EventInfo {
172 fromKey := unixTimeKey(from) + "/"
173 toKey := unixTimeKey(to) + "/"
174
175 return listEventsInternal(&eventsByEndDate, fromKey, toKey, from > to, limit)
176}
177
178func listEventsByCreator(creatorID string, from, to int64, limit uint32) []*zenaov1.EventInfo {
179 fromKey := creatorID + "/" + unixTimeKey(from) + "/"
180 toKey := creatorID + "/" + unixTimeKey(to) + "/"
181
182 return listEventsInternal(&eventsByCreator, fromKey, toKey, from > to, limit)
183}
184
185func listEventsByParticipant(participantID string, from, to int64, limit uint32) []*zenaov1.EventInfo {
186 fromKey := participantID + "/" + unixTimeKey(from) + "/"
187 toKey := participantID + "/" + unixTimeKey(to) + "/"
188
189 return listEventsInternal(&eventsByParticipant, fromKey, toKey, from > to, limit)
190}
191
192func listEventsInternal(at avl.ITree, fromKey string, toKey string, rev bool, limit uint32) []*zenaov1.EventInfo {
193 res := []*zenaov1.EventInfo{}
194 it := func(key string, value interface{}) bool {
195 var evt zenaov1.EventInfo
196 switch val := value.(type) {
197 case *zenaov1.EventInfo:
198 evt = *val
199 evt.PkgPath = key
200 case string:
201 evt = *mustGetEventByPkgPath(val)
202 evt.PkgPath = val
203 }
204 res = append(res, &evt)
205 return uint32(len(res)) >= limit
206 }
207 if rev {
208 at.ReverseIterate(toKey, fromKey, it)
209 } else {
210 at.Iterate(fromKey, toKey, it)
211 }
212 return res
213}
214
215func unixTimeKey(t int64) string {
216 if t < 0 {
217 panic("negative unix time")
218 }
219 return seqid.ID(t).Binary()
220}
eventreg.gno
5.82 Kb ยท 220 lines