github.com/Mrs4s/go-cqhttp@v1.2.0/coolq/event.go (about) 1 package coolq 2 3 import ( 4 "encoding/hex" 5 "encoding/json" 6 "fmt" 7 "path" 8 "strconv" 9 "strings" 10 11 "github.com/Mrs4s/MiraiGo/binary" 12 "github.com/Mrs4s/MiraiGo/client" 13 "github.com/Mrs4s/MiraiGo/message" 14 log "github.com/sirupsen/logrus" 15 16 "github.com/Mrs4s/go-cqhttp/db" 17 "github.com/Mrs4s/go-cqhttp/global" 18 "github.com/Mrs4s/go-cqhttp/internal/base" 19 "github.com/Mrs4s/go-cqhttp/internal/cache" 20 "github.com/Mrs4s/go-cqhttp/internal/download" 21 ) 22 23 // ToFormattedMessage 将给定[]message.IMessageElement转换为通过coolq.SetMessageFormat所定义的消息上报格式 24 func ToFormattedMessage(e []message.IMessageElement, source message.Source) (r any) { 25 if base.PostFormat == "string" { 26 r = toStringMessage(e, source) 27 } else if base.PostFormat == "array" { 28 r = toElements(e, source) 29 } 30 return 31 } 32 33 type event struct { 34 PostType string 35 DetailType string 36 SubType string 37 Time int64 38 SelfID int64 39 Others global.MSG 40 } 41 42 func (ev *event) MarshalJSON() ([]byte, error) { 43 buf := global.NewBuffer() 44 defer global.PutBuffer(buf) 45 46 detail := "" 47 switch ev.PostType { 48 case "message", "message_sent": 49 detail = "message_type" 50 case "notice": 51 detail = "notice_type" 52 case "request": 53 detail = "request_type" 54 case "meta_event": 55 detail = "meta_event_type" 56 default: 57 panic("unknown post type: " + ev.PostType) 58 } 59 fmt.Fprintf(buf, `{"post_type":"%s","%s":"%s","time":%d,"self_id":%d`, ev.PostType, detail, ev.DetailType, ev.Time, ev.SelfID) 60 if ev.SubType != "" { 61 fmt.Fprintf(buf, `,"sub_type":"%s"`, ev.SubType) 62 } 63 for k, v := range ev.Others { 64 v, err := json.Marshal(v) 65 if err != nil { 66 log.Warnf("marshal message payload error: %v", err) 67 return nil, err 68 } 69 fmt.Fprintf(buf, `,"%s":%s`, k, v) 70 } 71 buf.WriteByte('}') 72 return append([]byte(nil), buf.Bytes()...), nil 73 } 74 75 func (bot *CQBot) privateMessageEvent(_ *client.QQClient, m *message.PrivateMessage) { 76 bot.checkMedia(m.Elements, m.Sender.Uin) 77 source := message.Source{ 78 SourceType: message.SourcePrivate, 79 PrimaryID: m.Sender.Uin, 80 } 81 cqm := toStringMessage(m.Elements, source) 82 id := bot.InsertPrivateMessage(m, source) 83 log.Infof("收到好友 %v(%v) 的消息: %v (%v)", m.Sender.DisplayName(), m.Sender.Uin, cqm, id) 84 typ := "message/private/friend" 85 if m.Sender.Uin == bot.Client.Uin { 86 typ = "message_sent/private/friend" 87 } 88 fm := global.MSG{ 89 "message_id": id, 90 "user_id": m.Sender.Uin, 91 "target_id": m.Target, 92 "message": ToFormattedMessage(m.Elements, source), 93 "raw_message": cqm, 94 "font": 0, 95 "sender": global.MSG{ 96 "user_id": m.Sender.Uin, 97 "nickname": m.Sender.Nickname, 98 "sex": "unknown", 99 "age": 0, 100 }, 101 } 102 bot.dispatchEvent(typ, fm) 103 } 104 105 func (bot *CQBot) groupMessageEvent(c *client.QQClient, m *message.GroupMessage) { 106 bot.checkMedia(m.Elements, m.GroupCode) 107 for _, elem := range m.Elements { 108 if file, ok := elem.(*message.GroupFileElement); ok { 109 log.Infof("群 %v(%v) 内 %v(%v) 上传了文件: %v", m.GroupName, m.GroupCode, m.Sender.DisplayName(), m.Sender.Uin, file.Name) 110 bot.dispatchEvent("notice/group_upload", global.MSG{ 111 "group_id": m.GroupCode, 112 "user_id": m.Sender.Uin, 113 "file": global.MSG{ 114 "id": file.Path, 115 "name": file.Name, 116 "size": file.Size, 117 "busid": file.Busid, 118 "url": c.GetGroupFileUrl(m.GroupCode, file.Path, file.Busid), 119 }, 120 }) 121 // return 122 } 123 } 124 source := message.Source{ 125 SourceType: message.SourceGroup, 126 PrimaryID: m.GroupCode, 127 } 128 cqm := toStringMessage(m.Elements, source) 129 id := bot.InsertGroupMessage(m, source) 130 log.Infof("收到群 %v(%v) 内 %v(%v) 的消息: %v (%v)", m.GroupName, m.GroupCode, m.Sender.DisplayName(), m.Sender.Uin, cqm, id) 131 gm := bot.formatGroupMessage(m) 132 if gm == nil { 133 return 134 } 135 gm.Others["message_id"] = id 136 bot.dispatch(gm) 137 } 138 139 func (bot *CQBot) tempMessageEvent(_ *client.QQClient, e *client.TempMessageEvent) { 140 m := e.Message 141 bot.checkMedia(m.Elements, m.Sender.Uin) 142 source := message.Source{ 143 SourceType: message.SourcePrivate, 144 PrimaryID: e.Session.Sender, 145 } 146 cqm := toStringMessage(m.Elements, source) 147 if base.AllowTempSession { 148 bot.tempSessionCache.Store(m.Sender.Uin, e.Session) 149 } 150 151 id := m.Id 152 // todo(Mrs4s) 153 // if bot.db != nil { // nolint 154 // id = bot.InsertTempMessage(m.Sender.Uin, m) 155 // } 156 log.Infof("收到来自群 %v(%v) 内 %v(%v) 的临时会话消息: %v", m.GroupName, m.GroupCode, m.Sender.DisplayName(), m.Sender.Uin, cqm) 157 tm := global.MSG{ 158 "temp_source": e.Session.Source, 159 "message_id": id, 160 "user_id": m.Sender.Uin, 161 "message": ToFormattedMessage(m.Elements, source), 162 "raw_message": cqm, 163 "font": 0, 164 "sender": global.MSG{ 165 "user_id": m.Sender.Uin, 166 "group_id": m.GroupCode, 167 "nickname": m.Sender.Nickname, 168 "sex": "unknown", 169 "age": 0, 170 }, 171 } 172 bot.dispatchEvent("message/private/group", tm) 173 } 174 175 func (bot *CQBot) guildChannelMessageEvent(c *client.QQClient, m *message.GuildChannelMessage) { 176 bot.checkMedia(m.Elements, int64(m.Sender.TinyId)) 177 guild := c.GuildService.FindGuild(m.GuildId) 178 if guild == nil { 179 return 180 } 181 channel := guild.FindChannel(m.ChannelId) 182 source := message.Source{ 183 SourceType: message.SourceGuildChannel, 184 PrimaryID: int64(m.GuildId), 185 SecondaryID: int64(m.ChannelId), 186 } 187 log.Infof("收到来自频道 %v(%v) 子频道 %v(%v) 内 %v(%v) 的消息: %v", guild.GuildName, guild.GuildId, channel.ChannelName, m.ChannelId, m.Sender.Nickname, m.Sender.TinyId, toStringMessage(m.Elements, source)) 188 id := bot.InsertGuildChannelMessage(m) 189 ev := bot.event("message/guild/channel", global.MSG{ 190 "guild_id": fU64(m.GuildId), 191 "channel_id": fU64(m.ChannelId), 192 "message_id": id, 193 "user_id": fU64(m.Sender.TinyId), 194 "message": ToFormattedMessage(m.Elements, source), // todo: 增加对频道消息 Reply 的支持 195 "self_tiny_id": fU64(bot.Client.GuildService.TinyId), 196 "sender": global.MSG{ 197 "user_id": m.Sender.TinyId, 198 "tiny_id": fU64(m.Sender.TinyId), 199 "nickname": m.Sender.Nickname, 200 }, 201 }) 202 ev.Time = m.Time 203 bot.dispatch(ev) 204 } 205 206 func (bot *CQBot) guildMessageReactionsUpdatedEvent(c *client.QQClient, e *client.GuildMessageReactionsUpdatedEvent) { 207 guild := c.GuildService.FindGuild(e.GuildId) 208 if guild == nil { 209 return 210 } 211 msgID := encodeGuildMessageID(e.GuildId, e.ChannelId, e.MessageId, message.SourceGuildChannel) 212 str := fmt.Sprintf("频道 %v(%v) 消息 %v 表情贴片已更新: ", guild.GuildName, guild.GuildId, msgID) 213 currentReactions := make([]global.MSG, len(e.CurrentReactions)) 214 for i, r := range e.CurrentReactions { 215 str += fmt.Sprintf("%v*%v ", r.Face.Name, r.Count) 216 currentReactions[i] = global.MSG{ 217 "emoji_id": r.EmojiId, 218 "emoji_index": r.Face.Index, 219 "emoji_type": r.EmojiType, 220 "emoji_name": r.Face.Name, 221 "count": r.Count, 222 "clicked": r.Clicked, 223 } 224 } 225 if len(e.CurrentReactions) == 0 { 226 str += "无任何表情" 227 } 228 log.Infof(str) 229 bot.dispatchEvent("notice/message_reactions_updated", global.MSG{ 230 "guild_id": fU64(e.GuildId), 231 "channel_id": fU64(e.ChannelId), 232 "message_id": msgID, 233 "operator_id": fU64(e.OperatorId), 234 "current_reactions": currentReactions, 235 "self_tiny_id": fU64(bot.Client.GuildService.TinyId), 236 "user_id": e.OperatorId, 237 }) 238 } 239 240 func (bot *CQBot) guildChannelMessageRecalledEvent(c *client.QQClient, e *client.GuildMessageRecalledEvent) { 241 guild := c.GuildService.FindGuild(e.GuildId) 242 if guild == nil { 243 return 244 } 245 channel := guild.FindChannel(e.ChannelId) 246 if channel == nil { 247 return 248 } 249 operator, err := c.GuildService.FetchGuildMemberProfileInfo(e.GuildId, e.OperatorId) 250 if err != nil { 251 log.Errorf("处理频道撤回事件时出现错误: 获取操作者资料时出现错误 %v", err) 252 return 253 } 254 msgID := encodeGuildMessageID(e.GuildId, e.ChannelId, e.MessageId, message.SourceGuildChannel) 255 log.Infof("用户 %v(%v) 撤回了频道 %v(%v) 子频道 %v(%v) 的消息 %v", operator.Nickname, operator.TinyId, guild.GuildName, guild.GuildId, channel.ChannelName, channel.ChannelId, msgID) 256 bot.dispatchEvent("notice/guild_channel_recall", global.MSG{ 257 "guild_id": fU64(e.GuildId), 258 "channel_id": fU64(e.ChannelId), 259 "operator_id": fU64(e.OperatorId), 260 "message_id": msgID, 261 "self_tiny_id": fU64(bot.Client.GuildService.TinyId), 262 "user_id": e.OperatorId, 263 }) 264 } 265 266 func (bot *CQBot) guildChannelUpdatedEvent(c *client.QQClient, e *client.GuildChannelUpdatedEvent) { 267 guild := c.GuildService.FindGuild(e.GuildId) 268 if guild == nil { 269 return 270 } 271 log.Infof("频道 %v(%v) 子频道 %v(%v) 信息已更新", guild.GuildName, guild.GuildId, e.NewChannelInfo.ChannelName, e.NewChannelInfo.ChannelId) 272 bot.dispatchEvent("notice/channel_updated", global.MSG{ 273 "guild_id": fU64(e.GuildId), 274 "channel_id": fU64(e.ChannelId), 275 "operator_id": fU64(e.OperatorId), 276 "self_tiny_id": fU64(bot.Client.GuildService.TinyId), 277 "user_id": e.OperatorId, 278 "old_info": convertChannelInfo(e.OldChannelInfo), 279 "new_info": convertChannelInfo(e.NewChannelInfo), 280 }) 281 } 282 283 func (bot *CQBot) guildChannelCreatedEvent(c *client.QQClient, e *client.GuildChannelOperationEvent) { 284 guild := c.GuildService.FindGuild(e.GuildId) 285 if guild == nil { 286 return 287 } 288 member, _ := c.GuildService.FetchGuildMemberProfileInfo(e.GuildId, e.OperatorId) 289 if member == nil { 290 member = &client.GuildUserProfile{Nickname: "未知"} 291 } 292 log.Infof("频道 %v(%v) 内用户 %v(%v) 创建了子频道 %v(%v)", guild.GuildName, guild.GuildId, member.Nickname, member.TinyId, e.ChannelInfo.ChannelName, e.ChannelInfo.ChannelId) 293 bot.dispatchEvent("notice/channel_created", global.MSG{ 294 "guild_id": fU64(e.GuildId), 295 "channel_id": fU64(e.ChannelInfo.ChannelId), 296 "operator_id": fU64(e.OperatorId), 297 "self_tiny_id": fU64(bot.Client.GuildService.TinyId), 298 "user_id": e.OperatorId, 299 "channel_info": convertChannelInfo(e.ChannelInfo), 300 }) 301 } 302 303 func (bot *CQBot) guildChannelDestroyedEvent(c *client.QQClient, e *client.GuildChannelOperationEvent) { 304 guild := c.GuildService.FindGuild(e.GuildId) 305 if guild == nil { 306 return 307 } 308 member, _ := c.GuildService.FetchGuildMemberProfileInfo(e.GuildId, e.OperatorId) 309 if member == nil { 310 member = &client.GuildUserProfile{Nickname: "未知"} 311 } 312 log.Infof("频道 %v(%v) 内用户 %v(%v) 删除了子频道 %v(%v)", guild.GuildName, guild.GuildId, member.Nickname, member.TinyId, e.ChannelInfo.ChannelName, e.ChannelInfo.ChannelId) 313 bot.dispatchEvent("notice/channel_destroyed", global.MSG{ 314 "guild_id": fU64(e.GuildId), 315 "channel_id": fU64(e.ChannelInfo.ChannelId), 316 "operator_id": fU64(e.OperatorId), 317 "self_tiny_id": fU64(bot.Client.GuildService.TinyId), 318 "user_id": e.OperatorId, 319 "channel_info": convertChannelInfo(e.ChannelInfo), 320 }) 321 } 322 323 func (bot *CQBot) groupMutedEvent(c *client.QQClient, e *client.GroupMuteEvent) { 324 g := c.FindGroup(e.GroupCode) 325 if e.TargetUin == 0 { 326 if e.Time != 0 { 327 log.Infof("群 %v 被 %v 开启全员禁言.", 328 formatGroupName(g), formatMemberName(g.FindMember(e.OperatorUin))) 329 } else { 330 log.Infof("群 %v 被 %v 解除全员禁言.", 331 formatGroupName(g), formatMemberName(g.FindMember(e.OperatorUin))) 332 } 333 } else { 334 if e.Time > 0 { 335 log.Infof("群 %v 内 %v 被 %v 禁言了 %v 秒.", 336 formatGroupName(g), formatMemberName(g.FindMember(e.TargetUin)), formatMemberName(g.FindMember(e.OperatorUin)), e.Time) 337 } else { 338 log.Infof("群 %v 内 %v 被 %v 解除禁言.", 339 formatGroupName(g), formatMemberName(g.FindMember(e.TargetUin)), formatMemberName(g.FindMember(e.OperatorUin))) 340 } 341 } 342 typ := "notice/group_ban/ban" 343 if e.Time == 0 { 344 typ = "notice/group_ban/lift_ban" 345 } 346 bot.dispatchEvent(typ, global.MSG{ 347 "duration": e.Time, 348 "group_id": e.GroupCode, 349 "operator_id": e.OperatorUin, 350 "user_id": e.TargetUin, 351 }) 352 } 353 354 func (bot *CQBot) groupRecallEvent(c *client.QQClient, e *client.GroupMessageRecalledEvent) { 355 g := c.FindGroup(e.GroupCode) 356 gid := db.ToGlobalID(e.GroupCode, e.MessageId) 357 log.Infof("群 %v 内 %v 撤回了 %v 的消息: %v.", 358 formatGroupName(g), formatMemberName(g.FindMember(e.OperatorUin)), formatMemberName(g.FindMember(e.AuthorUin)), gid) 359 360 ev := bot.event("notice/group_recall", global.MSG{ 361 "group_id": e.GroupCode, 362 "user_id": e.AuthorUin, 363 "operator_id": e.OperatorUin, 364 "message_id": gid, 365 }) 366 ev.Time = int64(e.Time) 367 bot.dispatch(ev) 368 } 369 370 func (bot *CQBot) groupNotifyEvent(c *client.QQClient, e client.INotifyEvent) { 371 group := c.FindGroup(e.From()) 372 switch notify := e.(type) { 373 case *client.GroupPokeNotifyEvent: 374 sender := group.FindMember(notify.Sender) 375 receiver := group.FindMember(notify.Receiver) 376 log.Infof("群 %v 内 %v 戳了戳 %v", formatGroupName(group), formatMemberName(sender), formatMemberName(receiver)) 377 bot.dispatchEvent("notice/notify/poke", global.MSG{ 378 "group_id": group.Code, 379 "user_id": notify.Sender, 380 "sender_id": notify.Sender, 381 "target_id": notify.Receiver, 382 }) 383 case *client.GroupRedBagLuckyKingNotifyEvent: 384 sender := group.FindMember(notify.Sender) 385 luckyKing := group.FindMember(notify.LuckyKing) 386 log.Infof("群 %v 内 %v 的红包被抢完, %v 是运气王", formatGroupName(group), formatMemberName(sender), formatMemberName(luckyKing)) 387 bot.dispatchEvent("notice/notify/lucky_king", global.MSG{ 388 "group_id": group.Code, 389 "user_id": notify.Sender, 390 "sender_id": notify.Sender, 391 "target_id": notify.LuckyKing, 392 }) 393 case *client.MemberHonorChangedNotifyEvent: 394 log.Info(notify.Content()) 395 bot.dispatchEvent("notice/notify/honor", global.MSG{ 396 "group_id": group.Code, 397 "user_id": notify.Uin, 398 "honor_type": func() string { 399 switch notify.Honor { 400 case client.Talkative: 401 return "talkative" 402 case client.Performer: 403 return "performer" 404 case client.Emotion: 405 return "emotion" 406 case client.Legend: 407 return "legend" 408 case client.StrongNewbie: 409 return "strong_newbie" 410 default: 411 return "ERROR" 412 } 413 }(), 414 }) 415 } 416 } 417 418 func (bot *CQBot) friendNotifyEvent(c *client.QQClient, e client.INotifyEvent) { 419 friend := c.FindFriend(e.From()) 420 if notify, ok := e.(*client.FriendPokeNotifyEvent); ok { 421 if notify.Receiver == notify.Sender { 422 log.Infof("好友 %v 戳了戳自己.", friend.Nickname) 423 } else { 424 log.Infof("好友 %v 戳了戳你.", friend.Nickname) 425 } 426 bot.dispatchEvent("notice/notify/poke", global.MSG{ 427 "user_id": notify.Sender, 428 "sender_id": notify.Sender, 429 "target_id": notify.Receiver, 430 }) 431 } 432 } 433 434 func (bot *CQBot) memberTitleUpdatedEvent(c *client.QQClient, e *client.MemberSpecialTitleUpdatedEvent) { 435 group := c.FindGroup(e.GroupCode) 436 mem := group.FindMember(e.Uin) 437 log.Infof("群 %v(%v) 内成员 %v(%v) 获得了新的头衔: %v", group.Name, group.Code, mem.DisplayName(), mem.Uin, e.NewTitle) 438 bot.dispatchEvent("notice/notify/title", global.MSG{ 439 "group_id": group.Code, 440 "user_id": e.Uin, 441 "title": e.NewTitle, 442 }) 443 } 444 445 func (bot *CQBot) friendRecallEvent(c *client.QQClient, e *client.FriendMessageRecalledEvent) { 446 f := c.FindFriend(e.FriendUin) 447 gid := db.ToGlobalID(e.FriendUin, e.MessageId) 448 if f != nil { 449 log.Infof("好友 %v(%v) 撤回了消息: %v", f.Nickname, f.Uin, gid) 450 } else { 451 log.Infof("好友 %v 撤回了消息: %v", e.FriendUin, gid) 452 } 453 ev := bot.event("notice/friend_recall", global.MSG{ 454 "user_id": e.FriendUin, 455 "message_id": gid, 456 }) 457 ev.Time = e.Time 458 bot.dispatch(ev) 459 } 460 461 func (bot *CQBot) offlineFileEvent(c *client.QQClient, e *client.OfflineFileEvent) { 462 f := c.FindFriend(e.Sender) 463 if f == nil { 464 return 465 } 466 log.Infof("好友 %v(%v) 发送了离线文件 %v", f.Nickname, f.Uin, e.FileName) 467 bot.dispatchEvent("notice/offline_file", global.MSG{ 468 "user_id": e.Sender, 469 "file": global.MSG{ 470 "name": e.FileName, 471 "size": e.FileSize, 472 "url": e.DownloadUrl, 473 }, 474 }) 475 } 476 477 func (bot *CQBot) joinGroupEvent(c *client.QQClient, group *client.GroupInfo) { 478 if group == nil { 479 return 480 } 481 log.Infof("Bot进入了群 %v.", formatGroupName(group)) 482 bot.dispatch(bot.groupIncrease(group.Code, 0, c.Uin)) 483 } 484 485 func (bot *CQBot) leaveGroupEvent(c *client.QQClient, e *client.GroupLeaveEvent) { 486 if e.Operator != nil { 487 log.Infof("Bot被 %v T出了群 %v.", formatMemberName(e.Operator), formatGroupName(e.Group)) 488 } else { 489 log.Infof("Bot退出了群 %v.", formatGroupName(e.Group)) 490 } 491 bot.dispatch(bot.groupDecrease(e.Group.Code, c.Uin, e.Operator)) 492 } 493 494 func (bot *CQBot) memberPermissionChangedEvent(_ *client.QQClient, e *client.MemberPermissionChangedEvent) { 495 st := "unset" 496 if e.NewPermission == client.Administrator { 497 st = "set" 498 } 499 bot.dispatchEvent("notice/group_admin/"+st, global.MSG{ 500 "group_id": e.Group.Code, 501 "user_id": e.Member.Uin, 502 }) 503 } 504 505 func (bot *CQBot) memberCardUpdatedEvent(_ *client.QQClient, e *client.MemberCardUpdatedEvent) { 506 log.Infof("群 %v 的 %v 更新了名片 %v -> %v", formatGroupName(e.Group), formatMemberName(e.Member), e.OldCard, e.Member.CardName) 507 bot.dispatchEvent("notice/group_card", global.MSG{ 508 "group_id": e.Group.Code, 509 "user_id": e.Member.Uin, 510 "card_new": e.Member.CardName, 511 "card_old": e.OldCard, 512 }) 513 } 514 515 func (bot *CQBot) memberJoinEvent(_ *client.QQClient, e *client.MemberJoinGroupEvent) { 516 log.Infof("新成员 %v 进入了群 %v.", formatMemberName(e.Member), formatGroupName(e.Group)) 517 bot.dispatch(bot.groupIncrease(e.Group.Code, 0, e.Member.Uin)) 518 } 519 520 func (bot *CQBot) memberLeaveEvent(_ *client.QQClient, e *client.MemberLeaveGroupEvent) { 521 if e.Operator != nil { 522 log.Infof("成员 %v 被 %v T出了群 %v.", formatMemberName(e.Member), formatMemberName(e.Operator), formatGroupName(e.Group)) 523 } else { 524 log.Infof("成员 %v 离开了群 %v.", formatMemberName(e.Member), formatGroupName(e.Group)) 525 } 526 bot.dispatch(bot.groupDecrease(e.Group.Code, e.Member.Uin, e.Operator)) 527 } 528 529 func (bot *CQBot) friendRequestEvent(_ *client.QQClient, e *client.NewFriendRequest) { 530 log.Infof("收到来自 %v(%v) 的好友请求: %v", e.RequesterNick, e.RequesterUin, e.Message) 531 flag := strconv.FormatInt(e.RequestId, 10) 532 bot.friendReqCache.Store(flag, e) 533 bot.dispatchEvent("request/friend", global.MSG{ 534 "user_id": e.RequesterUin, 535 "comment": e.Message, 536 "flag": flag, 537 }) 538 } 539 540 func (bot *CQBot) friendAddedEvent(_ *client.QQClient, e *client.NewFriendEvent) { 541 log.Infof("添加了新好友: %v(%v)", e.Friend.Nickname, e.Friend.Uin) 542 bot.tempSessionCache.Delete(e.Friend.Uin) 543 bot.dispatchEvent("notice/friend_add", global.MSG{ 544 "user_id": e.Friend.Uin, 545 }) 546 } 547 548 func (bot *CQBot) groupInvitedEvent(_ *client.QQClient, e *client.GroupInvitedRequest) { 549 log.Infof("收到来自群 %v(%v) 内用户 %v(%v) 的加群邀请.", e.GroupName, e.GroupCode, e.InvitorNick, e.InvitorUin) 550 flag := strconv.FormatInt(e.RequestId, 10) 551 bot.dispatchEvent("request/group/invite", global.MSG{ 552 "group_id": e.GroupCode, 553 "user_id": e.InvitorUin, 554 "invitor_id": 0, 555 "comment": "", 556 "flag": flag, 557 }) 558 } 559 560 func (bot *CQBot) groupJoinReqEvent(_ *client.QQClient, e *client.UserJoinGroupRequest) { 561 log.Infof("群 %v(%v) 收到来自用户 %v(%v) 的加群请求.", e.GroupName, e.GroupCode, e.RequesterNick, e.RequesterUin) 562 flag := strconv.FormatInt(e.RequestId, 10) 563 bot.dispatchEvent("request/group/add", global.MSG{ 564 "group_id": e.GroupCode, 565 "user_id": e.RequesterUin, 566 "invitor_id": e.ActionUin, 567 "comment": e.Message, 568 "flag": flag, 569 }) 570 } 571 572 func (bot *CQBot) otherClientStatusChangedEvent(_ *client.QQClient, e *client.OtherClientStatusChangedEvent) { 573 if e.Online { 574 log.Infof("Bot 账号在客户端 %v (%v) 登录.", e.Client.DeviceName, e.Client.DeviceKind) 575 } else { 576 log.Infof("Bot 账号在客户端 %v (%v) 登出.", e.Client.DeviceName, e.Client.DeviceKind) 577 } 578 bot.dispatchEvent("notice/client_status", global.MSG{ 579 "online": e.Online, 580 "client": global.MSG{ 581 "app_id": e.Client.AppId, 582 "device_name": e.Client.DeviceName, 583 "device_kind": e.Client.DeviceKind, 584 }, 585 }) 586 } 587 588 func (bot *CQBot) groupEssenceMsg(c *client.QQClient, e *client.GroupDigestEvent) { 589 g := c.FindGroup(e.GroupCode) 590 gid := db.ToGlobalID(e.GroupCode, e.MessageID) 591 if e.OperationType == 1 { 592 log.Infof( 593 "群 %v 内 %v 将 %v 的消息(%v)设为了精华消息.", 594 formatGroupName(g), 595 formatMemberName(g.FindMember(e.OperatorUin)), 596 formatMemberName(g.FindMember(e.SenderUin)), 597 gid, 598 ) 599 } else { 600 log.Infof( 601 "群 %v 内 %v 将 %v 的消息(%v)移出了精华消息.", 602 formatGroupName(g), 603 formatMemberName(g.FindMember(e.OperatorUin)), 604 formatMemberName(g.FindMember(e.SenderUin)), 605 gid, 606 ) 607 } 608 if e.OperatorUin == bot.Client.Uin { 609 return 610 } 611 subtype := "delete" 612 if e.OperationType == 1 { 613 subtype = "add" 614 } 615 bot.dispatchEvent("notice/essence/"+subtype, global.MSG{ 616 "group_id": e.GroupCode, 617 "sender_id": e.SenderUin, 618 "operator_id": e.OperatorUin, 619 "message_id": gid, 620 }) 621 } 622 623 func (bot *CQBot) groupIncrease(groupCode, operatorUin, userUin int64) *event { 624 return bot.event("notice/group_increase/approve", global.MSG{ 625 "group_id": groupCode, 626 "operator_id": operatorUin, 627 "user_id": userUin, 628 }) 629 } 630 631 func (bot *CQBot) groupDecrease(groupCode, userUin int64, operator *client.GroupMemberInfo) *event { 632 op := userUin 633 if operator != nil { 634 op = operator.Uin 635 } 636 subtype := "leave" 637 if operator != nil { 638 if userUin == bot.Client.Uin { 639 subtype = "kick_me" 640 } else { 641 subtype = "kick" 642 } 643 } 644 return bot.event("notice/group_decrease/"+subtype, global.MSG{ 645 "group_id": groupCode, 646 "operator_id": op, 647 "user_id": userUin, 648 }) 649 } 650 651 func (bot *CQBot) checkMedia(e []message.IMessageElement, sourceID int64) { 652 for _, elem := range e { 653 switch i := elem.(type) { 654 case *message.GroupImageElement: 655 if i.Flash && sourceID != 0 { 656 u, err := bot.Client.GetGroupImageDownloadUrl(i.FileId, sourceID, i.Md5) 657 if err != nil { 658 log.Warnf("获取闪照地址时出现错误: %v", err) 659 } else { 660 i.Url = u 661 } 662 } 663 data := binary.NewWriterF(func(w *binary.Writer) { 664 w.Write(i.Md5) 665 w.WriteUInt32(uint32(i.Size)) 666 w.WriteString(i.ImageId) 667 w.WriteString(i.Url) 668 }) 669 cache.Image.Insert(i.Md5, data) 670 671 case *message.GuildImageElement: 672 data := binary.NewWriterF(func(w *binary.Writer) { 673 w.Write(i.Md5) 674 w.WriteUInt32(uint32(i.Size)) 675 w.WriteString(i.DownloadIndex) 676 w.WriteString(i.Url) 677 }) 678 filename := hex.EncodeToString(i.Md5) + ".image" 679 cache.Image.Insert(i.Md5, data) 680 if i.Url != "" && !global.PathExists(path.Join(global.ImagePath, "guild-images", filename)) { 681 r := download.Request{URL: i.Url} 682 if err := r.WriteToFile(path.Join(global.ImagePath, "guild-images", filename)); err != nil { 683 log.Warnf("下载频道图片时出现错误: %v", err) 684 } 685 } 686 case *message.FriendImageElement: 687 data := binary.NewWriterF(func(w *binary.Writer) { 688 w.Write(i.Md5) 689 w.WriteUInt32(uint32(i.Size)) 690 w.WriteString(i.ImageId) 691 w.WriteString(i.Url) 692 }) 693 cache.Image.Insert(i.Md5, data) 694 695 case *message.VoiceElement: 696 // todo: don't download original file? 697 i.Name = strings.ReplaceAll(i.Name, "{", "") 698 i.Name = strings.ReplaceAll(i.Name, "}", "") 699 if !global.PathExists(path.Join(global.VoicePath, i.Name)) { 700 err := download.Request{URL: i.Url}.WriteToFile(path.Join(global.VoicePath, i.Name)) 701 if err != nil { 702 log.Warnf("语音文件 %v 下载失败: %v", i.Name, err) 703 continue 704 } 705 } 706 case *message.ShortVideoElement: 707 data := binary.NewWriterF(func(w *binary.Writer) { 708 w.Write(i.Md5) 709 w.Write(i.ThumbMd5) 710 w.WriteUInt32(uint32(i.Size)) 711 w.WriteUInt32(uint32(i.ThumbSize)) 712 w.WriteString(i.Name) 713 w.Write(i.Uuid) 714 }) 715 filename := hex.EncodeToString(i.Md5) + ".video" 716 cache.Video.Insert(i.Md5, data) 717 i.Name = filename 718 i.Url = bot.Client.GetShortVideoUrl(i.Uuid, i.Md5) 719 } 720 } 721 }