-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathreply.go
231 lines (220 loc) · 6.73 KB
/
reply.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
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"github.com/sirupsen/logrus"
"net/http"
"strconv"
"strings"
)
type QQMessage struct {
Interval int64 `json:"interval"`
MetaEventType string `json:"meta_event_type"`
PostType string `json:"post_type"`
Message []Message `json:"message"`
RawMessage string `json:"raw_message"`
//Sender int64 `json:"sender"`
SelfId int64 `json:"self_id"`
Time int64 `json:"time"`
Status AppStatus `json:"status"`
UserId int64 `json:"user_id"`
TargetId int64 `json:"target_id"`
GroupId int64 `json:"group_id"`
MessageType string `json:"message_type"`
SubType string `json:"sub_type"`
Font int64 `json:"font"`
MessageId int64 `json:"message_id"`
CqTypes ReceivedCQTypes `json:"-"`
}
type AppStatus struct {
AppEnabled bool `json:"app_enabled"`
AppGood bool `json:"app_good"`
AppInitialized bool `json:"app_initialized"`
Good bool `json:"good"`
Online bool `json:"online"`
PluginsGood bool `json:"plugins_good"`
Stat MsgStatus `json:"stat"`
}
type MsgStatus struct {
PacketReceived int64 `json:"packet_received"`
PacketSent int64 `json:"packet_sent"`
PacketLost int64 `json:"packet_lost"`
MessageReceived int64 `json:"message_received"`
MessageSent int64 `json:"message_sent"`
DisconnectTimes int64 `json:"disconnect_times"`
LostTimes int64 `json:"lost_times"`
LastMessageTime int64 `json:"last_message_time"`
}
type ReceivedCQTypes struct {
atSelf bool
hasImage bool
hasJson bool
hasFace bool
hasReply bool
}
func reply(ctx *gin.Context) {
var req QQMessage
err := ctx.ShouldBindJSON(&req)
if err != nil {
logrus.Error(err)
ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
if req.MetaEventType == "heartbeat" {
HeartbeatContinue()
return
}
logrus.Info("Received message: ", req.Message)
sender := SendMsgData{
MessageType: req.MessageType,
UserId: strconv.FormatInt(req.UserId, 10),
GroupId: strconv.FormatInt(req.GroupId, 10),
Message: make([]Message, 0, 5),
AutoEscape: false,
ReceivedMsg: req.RawMessage,
}
if strings.HasPrefix(req.RawMessage, "NerdBot ") {
msg := req.ExecuteCommand()
sender.Message = append(sender.Message, msg)
err = sender.Send()
if err != nil {
logrus.Error(err)
}
return
}
cqMessage, remainText, types := ParseCQCode(req.RawMessage)
req.CqTypes = types
remainText = strings.Trim(remainText, " ")
enableGroupChat, ok := GlobalConfig.AI.EnableGroupChat[req.GroupId]
var chatMode string
enableAIReply := true
if req.MessageType == "group" {
if ok && enableGroupChat {
// if the bot is in group mode
chatMode = "group"
// do not reply if the bot is not mentioned
if !req.CqTypes.atSelf {
enableAIReply = false
}
} else if req.CqTypes.atSelf {
chatMode = "private"
}
} else if req.MessageType == "private" {
if cqMessage == nil {
chatMode = "private"
}
}
if chatMode == "private" {
sender.Message = append(sender.Message, Message{
Type: "reply",
Data: map[string]interface{}{
"id": req.MessageId,
},
})
}
if chatMode != "" {
err = sender.AddAIPrompts(chatMode)
if err != nil {
logrus.Error("Add AI "+chatMode+" prompts error: ", err)
ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
if enableAIReply {
err = sender.AIChat(chatMode)
if err != nil {
logrus.Error("AI chat in "+chatMode+" error: ", err)
ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
}
}
}
func (req QQMessage) ExecuteCommand() Message {
var isAdmin = false
var msg = Message{
Type: "text",
Data: map[string]interface{}{
"text": "",
},
}
enableGroupChat, ok := GlobalConfig.AI.EnableGroupChat[req.GroupId]
var id int64
if req.MessageType == "group" && enableGroupChat {
id = req.GroupId
} else {
id = req.UserId
}
idStr := strconv.FormatInt(id, 10)
remainText := strings.Replace(req.RawMessage, "NerdBot ", "", -1)
remainText = strings.Trim(remainText, " ")
for _, id := range GlobalConfig.Server.AdminIds {
if req.UserId == id {
isAdmin = true
}
}
if remainText == "clear" {
DeleteRecord(idStr)
msg.Data["text"] = fmt.Sprintf("[通知]ID: %d 的上下文已被清除。", id)
return msg
}
//all the command below need Auth
if !isAdmin {
msg.Data["text"] = "[错误]\n对不起,您没有权限执行该命令"
return msg
}
if req.MessageType == "private" {
} else if req.MessageType == "group" {
if remainText == "group mode" {
if !ok || !enableGroupChat {
GlobalConfig.AI.EnableGroupChat[req.GroupId] = true
DeleteRecord(idStr)
msg.Data["text"] = "[通知]\n群" + strconv.FormatInt(req.GroupId, 10) + "的群聊模式已开启,之后所有群聊文字信息" +
"将以同一session供机器人进行分析。如需机器人进行回复,请在输入信息中@戴便机器人。\n注意: 此功能为实验性功能。另,群聊模式可能使用大量token," +
"请注意您的token使用量。"
} else {
msg.Data["text"] = "[错误]\n群" + strconv.FormatInt(req.GroupId, 10) + "的群聊模式已开启,无须重复操作。"
}
return msg
} else if remainText == "private mode" {
if ok && enableGroupChat {
GlobalConfig.AI.EnableGroupChat[req.GroupId] = false
DeleteRecord(idStr)
msg.Data["text"] = "[通知]\n群聊模式已关闭,机器人将恢复 1 vs 1 对话"
} else {
msg.Data["text"] = "[错误]群聊模式已经为关闭状态,无须操作"
}
return msg
}
}
if strings.HasPrefix(remainText, "set temperature") {
str := strings.Replace(remainText, "set temperature", "", -1)
str = strings.Trim(str, " ")
temp, err := strconv.ParseFloat(str, 10)
if err != nil {
logrus.Error(err)
}
if temp < 0 || temp > 1 {
msg.Data["text"] = "[错误]无效的temperature设置,值应该为0~1之间的小数"
logrus.Error("invalid temperature setting: ", temp)
return msg
}
record, err := RetrieveOrDefaultRecord(idStr)
if err != nil {
msg.Data["text"] = fmt.Sprintf("[错误]temperature参数设置失败:获取记录失败")
logrus.Error(err)
} else {
record.Temperature = temp
err = StoreRecord(idStr, record)
if err != nil {
msg.Data["text"] = fmt.Sprintf("[错误]temperature参数设置失败:存储记录失败")
logrus.Error(err)
} else {
msg.Data["text"] = fmt.Sprintf("[通知]新的temperature参数已生效: %f", temp)
}
}
return msg
}
msg.Data["text"] = "[错误]未查询到相应指令"
logrus.Error("invalid command: ", req.RawMessage)
return msg
}