-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnotification.go
174 lines (149 loc) · 4.6 KB
/
notification.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
package maa
import (
"strings"
"sync"
"sync/atomic"
"unsafe"
)
var (
notificationCallbackID uint64
notificationCallbackAgents = make(map[uint64]Notification)
notificationCallbackAgentsMutex sync.RWMutex
)
func registerNotificationCallback(notify Notification) uint64 {
id := atomic.AddUint64(¬ificationCallbackID, 1)
notificationCallbackAgentsMutex.Lock()
notificationCallbackAgents[id] = notify
notificationCallbackAgentsMutex.Unlock()
return id
}
func unregisterNotificationCallback(id uint64) {
notificationCallbackAgentsMutex.Lock()
delete(notificationCallbackAgents, id)
notificationCallbackAgentsMutex.Unlock()
}
type NotificationType int
// NotificationType
const (
NotificationTypeUnknown NotificationType = iota
NotificationTypeStarting
NotificationTypeSucceeded
NotificationTypeFailed
)
type ResourceLoadingDetail struct {
ResID uint64 `json:"res_id"`
Hash string `json:"hash"`
Path string `json:"path"`
}
type ControllerActionDetail struct {
CtrlID uint64 `json:"ctrl_id"`
UUID string `json:"uuid"`
Action string `json:"action"`
}
type TaskerTaskDetail struct {
TaskID uint64 `json:"task_id"`
Entry string `json:"entry"`
UUID string `json:"uuid"`
Hash string `json:"hash"`
}
type NodeNextListDetail struct {
TaskID uint64 `json:"task_id"`
Name string `json:"name"`
NextList []string `json:"next_list"`
}
type NodeRecognitionDetail struct {
TaskID uint64 `json:"task_id"`
RecID uint64 `json:"reco_id"`
Name string `json:"name"`
}
type NodeActionDetail struct {
TaskID uint64 `json:"task_id"`
NodeID uint64 `json:"node_id"`
Name string `json:"name"`
}
type Notification interface {
OnResourceLoading(notifyType NotificationType, detail ResourceLoadingDetail)
OnControllerAction(notifyType NotificationType, detail ControllerActionDetail)
OnTaskerTask(notifyType NotificationType, detail TaskerTaskDetail)
OnTaskNextList(notifyType NotificationType, detail NodeNextListDetail)
OnTaskRecognition(notifyType NotificationType, detail NodeRecognitionDetail)
OnTaskAction(notifyType NotificationType, detail NodeActionDetail)
OnUnknownNotification(msg, detailsJSON string)
}
type notificationHandler struct {
notify Notification
}
func (n *notificationHandler) OnRawNotification(msg, detailsJSON string) {
if n.notify == nil {
return
}
notifyType := n.notificationType(msg)
switch {
case strings.HasPrefix(msg, "Resource.Loading"):
var detail ResourceLoadingDetail
_ = formJSON([]byte(detailsJSON), &detail)
n.notify.OnResourceLoading(notifyType, detail)
return
case strings.HasPrefix(msg, "Controller.Action"):
var detail ControllerActionDetail
_ = formJSON([]byte(detailsJSON), &detail)
n.notify.OnControllerAction(notifyType, detail)
return
case strings.HasPrefix(msg, "Tasker.Task"):
var detail TaskerTaskDetail
_ = formJSON([]byte(detailsJSON), &detail)
n.notify.OnTaskerTask(notifyType, detail)
return
case strings.HasPrefix(msg, "Node.NextList"):
var detail NodeNextListDetail
_ = formJSON([]byte(detailsJSON), &detail)
n.notify.OnTaskNextList(notifyType, detail)
return
case strings.HasPrefix(msg, "Node.Recognition"):
var detail NodeRecognitionDetail
_ = formJSON([]byte(detailsJSON), &detail)
n.notify.OnTaskRecognition(notifyType, detail)
return
case strings.HasPrefix(msg, "Node.Action"):
var detail NodeActionDetail
_ = formJSON([]byte(detailsJSON), &detail)
n.notify.OnTaskAction(notifyType, detail)
return
default:
n.notify.OnUnknownNotification(msg, detailsJSON)
}
}
func (n *notificationHandler) notificationType(msg string) NotificationType {
switch {
case strings.HasSuffix(msg, ".Starting"):
return NotificationTypeStarting
case strings.HasSuffix(msg, ".Succeeded"):
return NotificationTypeSucceeded
case strings.HasSuffix(msg, ".Failed"):
return NotificationTypeFailed
default:
return NotificationTypeUnknown
}
}
func _MaaNotificationCallbackAgent(message, detailsJson *byte, notifyTransArg uintptr) uintptr {
// Here, we are simply passing the uint64 value as a pointer
// and will not actually dereference this pointer.
id := uint64(notifyTransArg)
notificationCallbackAgentsMutex.RLock()
notify, exists := notificationCallbackAgents[id]
notificationCallbackAgentsMutex.RUnlock()
if !exists || notify == nil {
return 0
}
handler := ¬ificationHandler{notify: notify}
handler.OnRawNotification(bytePtrToString(message), bytePtrToString(detailsJson))
return 0
}
func bytePtrToString(b *byte) string {
length := 0
for ptr := b; *ptr != 0; ptr = (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(ptr)) + 1)) {
length++
}
byteSlice := unsafe.Slice(b, length)
return string(byteSlice)
}