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  }