github.com/Mrs4s/MiraiGo@v0.0.0-20240226124653-54bdd873e3fe/client/events.go (about) 1 package client 2 3 import ( 4 "fmt" 5 "reflect" 6 "runtime/debug" 7 "sync" 8 9 "github.com/Mrs4s/MiraiGo/message" 10 ) 11 12 // protected all EventHandle, since write is very rare, use 13 // only one lock to save memory 14 var eventMu sync.RWMutex 15 16 type EventHandle[T any] struct { 17 // QQClient? 18 handlers []func(client *QQClient, event T) 19 } 20 21 func (handle *EventHandle[T]) Subscribe(handler func(client *QQClient, event T)) { 22 eventMu.Lock() 23 defer eventMu.Unlock() 24 // shrink the slice 25 newHandlers := make([]func(client *QQClient, event T), len(handle.handlers)+1) 26 copy(newHandlers, handle.handlers) 27 newHandlers[len(handle.handlers)] = handler 28 handle.handlers = newHandlers 29 } 30 31 func (handle *EventHandle[T]) dispatch(client *QQClient, event T) { 32 eventMu.RLock() 33 defer func() { 34 eventMu.RUnlock() 35 if pan := recover(); pan != nil { 36 fmt.Printf("event error: %v\n%s", pan, debug.Stack()) 37 } 38 }() 39 for _, handler := range handle.handlers { 40 handler(client, event) 41 } 42 if len(client.eventHandlers.subscribedEventHandlers) > 0 { 43 for _, h := range client.eventHandlers.subscribedEventHandlers { 44 ht := reflect.TypeOf(h) 45 for i := 0; i < ht.NumMethod(); i++ { 46 method := ht.Method(i) 47 if method.Type.NumIn() != 3 { 48 continue 49 } 50 if method.Type.In(1) != reflect.TypeOf(client) || method.Type.In(2) != reflect.TypeOf(event) { 51 continue 52 } 53 method.Func.Call([]reflect.Value{reflect.ValueOf(h), reflect.ValueOf(client), reflect.ValueOf(event)}) 54 } 55 } 56 } 57 } 58 59 type eventHandlers struct { 60 // todo: move to event handle 61 guildChannelMessageHandlers []func(*QQClient, *message.GuildChannelMessage) 62 guildMessageReactionsUpdatedHandlers []func(*QQClient, *GuildMessageReactionsUpdatedEvent) 63 guildMessageRecalledHandlers []func(*QQClient, *GuildMessageRecalledEvent) 64 guildChannelUpdatedHandlers []func(*QQClient, *GuildChannelUpdatedEvent) 65 guildChannelCreatedHandlers []func(*QQClient, *GuildChannelOperationEvent) 66 guildChannelDestroyedHandlers []func(*QQClient, *GuildChannelOperationEvent) 67 memberJoinedGuildHandlers []func(*QQClient, *MemberJoinGuildEvent) 68 69 serverUpdatedHandlers []func(*QQClient, *ServerUpdatedEvent) bool 70 subscribedEventHandlers []any 71 groupMessageReceiptHandlers sync.Map 72 } 73 74 func (c *QQClient) SubscribeEventHandler(handler any) { 75 c.eventHandlers.subscribedEventHandlers = append(c.eventHandlers.subscribedEventHandlers, handler) 76 } 77 78 func (s *GuildService) OnGuildChannelMessage(f func(*QQClient, *message.GuildChannelMessage)) { 79 s.c.eventHandlers.guildChannelMessageHandlers = append(s.c.eventHandlers.guildChannelMessageHandlers, f) 80 } 81 82 func (s *GuildService) OnGuildMessageReactionsUpdated(f func(*QQClient, *GuildMessageReactionsUpdatedEvent)) { 83 s.c.eventHandlers.guildMessageReactionsUpdatedHandlers = append(s.c.eventHandlers.guildMessageReactionsUpdatedHandlers, f) 84 } 85 86 func (s *GuildService) OnGuildMessageRecalled(f func(*QQClient, *GuildMessageRecalledEvent)) { 87 s.c.eventHandlers.guildMessageRecalledHandlers = append(s.c.eventHandlers.guildMessageRecalledHandlers, f) 88 } 89 90 func (s *GuildService) OnGuildChannelUpdated(f func(*QQClient, *GuildChannelUpdatedEvent)) { 91 s.c.eventHandlers.guildChannelUpdatedHandlers = append(s.c.eventHandlers.guildChannelUpdatedHandlers, f) 92 } 93 94 func (s *GuildService) OnGuildChannelCreated(f func(*QQClient, *GuildChannelOperationEvent)) { 95 s.c.eventHandlers.guildChannelCreatedHandlers = append(s.c.eventHandlers.guildChannelCreatedHandlers, f) 96 } 97 98 func (s *GuildService) OnGuildChannelDestroyed(f func(*QQClient, *GuildChannelOperationEvent)) { 99 s.c.eventHandlers.guildChannelDestroyedHandlers = append(s.c.eventHandlers.guildChannelDestroyedHandlers, f) 100 } 101 102 func (s *GuildService) OnMemberJoinedGuild(f func(*QQClient, *MemberJoinGuildEvent)) { 103 s.c.eventHandlers.memberJoinedGuildHandlers = append(s.c.eventHandlers.memberJoinedGuildHandlers, f) 104 } 105 106 func (c *QQClient) OnServerUpdated(f func(*QQClient, *ServerUpdatedEvent) bool) { 107 c.eventHandlers.serverUpdatedHandlers = append(c.eventHandlers.serverUpdatedHandlers, f) 108 } 109 110 func NewUinFilterPrivate(uin int64) func(*message.PrivateMessage) bool { 111 return func(msg *message.PrivateMessage) bool { 112 return msg.Sender.Uin == uin 113 } 114 } 115 116 func (c *QQClient) onGroupMessageReceipt(id string, f ...func(*QQClient, *groupMessageReceiptEvent)) { 117 if len(f) == 0 { 118 c.eventHandlers.groupMessageReceiptHandlers.Delete(id) 119 return 120 } 121 c.eventHandlers.groupMessageReceiptHandlers.LoadOrStore(id, f[0]) 122 } 123 124 func (c *QQClient) dispatchGuildChannelMessage(msg *message.GuildChannelMessage) { 125 if msg == nil { 126 return 127 } 128 for _, f := range c.eventHandlers.guildChannelMessageHandlers { 129 cover(func() { 130 f(c, msg) 131 }) 132 } 133 } 134 135 func (c *QQClient) dispatchGuildMessageReactionsUpdatedEvent(e *GuildMessageReactionsUpdatedEvent) { 136 if e == nil { 137 return 138 } 139 for _, f := range c.eventHandlers.guildMessageReactionsUpdatedHandlers { 140 cover(func() { 141 f(c, e) 142 }) 143 } 144 } 145 146 func (c *QQClient) dispatchGuildMessageRecalledEvent(e *GuildMessageRecalledEvent) { 147 if e == nil { 148 return 149 } 150 for _, f := range c.eventHandlers.guildMessageRecalledHandlers { 151 cover(func() { 152 f(c, e) 153 }) 154 } 155 } 156 157 func (c *QQClient) dispatchGuildChannelUpdatedEvent(e *GuildChannelUpdatedEvent) { 158 if e == nil { 159 return 160 } 161 for _, f := range c.eventHandlers.guildChannelUpdatedHandlers { 162 cover(func() { 163 f(c, e) 164 }) 165 } 166 } 167 168 func (c *QQClient) dispatchGuildChannelCreatedEvent(e *GuildChannelOperationEvent) { 169 if e == nil { 170 return 171 } 172 for _, f := range c.eventHandlers.guildChannelCreatedHandlers { 173 cover(func() { 174 f(c, e) 175 }) 176 } 177 } 178 179 func (c *QQClient) dispatchGuildChannelDestroyedEvent(e *GuildChannelOperationEvent) { 180 if e == nil { 181 return 182 } 183 for _, f := range c.eventHandlers.guildChannelDestroyedHandlers { 184 cover(func() { 185 f(c, e) 186 }) 187 } 188 } 189 190 func (c *QQClient) dispatchMemberJoinedGuildEvent(e *MemberJoinGuildEvent) { 191 if e == nil { 192 return 193 } 194 for _, f := range c.eventHandlers.memberJoinedGuildHandlers { 195 cover(func() { 196 f(c, e) 197 }) 198 } 199 } 200 201 func (c *QQClient) dispatchGroupMessageReceiptEvent(e *groupMessageReceiptEvent) { 202 c.eventHandlers.groupMessageReceiptHandlers.Range(func(_, f any) bool { 203 go f.(func(*QQClient, *groupMessageReceiptEvent))(c, e) 204 return true 205 }) 206 } 207 208 func cover(f func()) { 209 defer func() { 210 if pan := recover(); pan != nil { 211 fmt.Printf("event error: %v\n%s", pan, debug.Stack()) 212 } 213 }() 214 f() 215 }