- Introduced a new scheduler to manage timed tasks within the event dispatcher. - Updated the dispatcher to support the new scheduler, allowing for improved event processing. - Enhanced action serialization in the OneBot11 adapter to convert message chains to the appropriate format. - Added new dependencies for cron scheduling and other indirect packages in go.mod and go.sum. - Improved logging for event publishing and handler matching, providing better insights during execution. - Refactored plugin loading to include scheduled job management.
239 lines
5.5 KiB
Go
239 lines
5.5 KiB
Go
package onebot11
|
||
|
||
import (
|
||
"fmt"
|
||
|
||
"cellbot/internal/protocol"
|
||
)
|
||
|
||
// ConvertMessageChainToOB11 将通用消息链转换为 OneBot11 格式
|
||
func ConvertMessageChainToOB11(chain protocol.MessageChain) interface{} {
|
||
if len(chain) == 0 {
|
||
return ""
|
||
}
|
||
|
||
// 转换为 OneBot11 消息段格式
|
||
segments := make([]MessageSegment, 0, len(chain))
|
||
for _, seg := range chain {
|
||
ob11Seg := convertSegmentToOB11(seg)
|
||
if ob11Seg != nil {
|
||
segments = append(segments, *ob11Seg)
|
||
}
|
||
}
|
||
|
||
// 如果只有一个文本消息段,直接返回文本字符串
|
||
if len(segments) == 1 && segments[0].Type == SegmentTypeText {
|
||
if text, ok := segments[0].Data["text"].(string); ok {
|
||
return text
|
||
}
|
||
}
|
||
|
||
return segments
|
||
}
|
||
|
||
// convertSegmentToOB11 将通用消息段转换为 OneBot11 消息段
|
||
func convertSegmentToOB11(seg protocol.MessageSegment) *MessageSegment {
|
||
switch seg.Type {
|
||
case protocol.SegmentTypeText:
|
||
// 文本消息段
|
||
return &MessageSegment{
|
||
Type: SegmentTypeText,
|
||
Data: map[string]interface{}{
|
||
"text": seg.Data["text"],
|
||
},
|
||
}
|
||
|
||
case protocol.SegmentTypeMention:
|
||
// @提及(OneBot12 -> OneBot11)
|
||
userID := seg.Data["user_id"]
|
||
return &MessageSegment{
|
||
Type: SegmentTypeAt,
|
||
Data: map[string]interface{}{
|
||
"qq": userID,
|
||
},
|
||
}
|
||
|
||
case protocol.SegmentTypeAt:
|
||
// OneBot11 兼容格式
|
||
userID, ok := seg.Data["user_id"]
|
||
if !ok {
|
||
userID = seg.Data["qq"]
|
||
}
|
||
return &MessageSegment{
|
||
Type: SegmentTypeAt,
|
||
Data: map[string]interface{}{
|
||
"qq": userID,
|
||
},
|
||
}
|
||
|
||
case protocol.SegmentTypeImage:
|
||
// 图片消息段
|
||
fileID, ok := seg.Data["file_id"].(string)
|
||
if !ok {
|
||
// 兼容 file 字段
|
||
fileID, _ = seg.Data["file"].(string)
|
||
}
|
||
return &MessageSegment{
|
||
Type: SegmentTypeImage,
|
||
Data: map[string]interface{}{
|
||
"file": fileID,
|
||
},
|
||
}
|
||
|
||
case protocol.SegmentTypeVoice:
|
||
// 语音消息段(OneBot12 -> OneBot11)
|
||
fileID, ok := seg.Data["file_id"].(string)
|
||
if !ok {
|
||
fileID, _ = seg.Data["file"].(string)
|
||
}
|
||
return &MessageSegment{
|
||
Type: SegmentTypeRecord,
|
||
Data: map[string]interface{}{
|
||
"file": fileID,
|
||
},
|
||
}
|
||
|
||
case protocol.SegmentTypeRecord:
|
||
// OneBot11 兼容格式
|
||
fileID, ok := seg.Data["file"].(string)
|
||
if !ok {
|
||
fileID, _ = seg.Data["file_id"].(string)
|
||
}
|
||
return &MessageSegment{
|
||
Type: SegmentTypeRecord,
|
||
Data: map[string]interface{}{
|
||
"file": fileID,
|
||
},
|
||
}
|
||
|
||
case protocol.SegmentTypeVideo:
|
||
// 视频消息段
|
||
fileID, ok := seg.Data["file_id"].(string)
|
||
if !ok {
|
||
fileID, _ = seg.Data["file"].(string)
|
||
}
|
||
return &MessageSegment{
|
||
Type: SegmentTypeVideo,
|
||
Data: map[string]interface{}{
|
||
"file": fileID,
|
||
},
|
||
}
|
||
|
||
case protocol.SegmentTypeReply:
|
||
// 回复消息段
|
||
messageID := seg.Data["message_id"]
|
||
return &MessageSegment{
|
||
Type: SegmentTypeReply,
|
||
Data: map[string]interface{}{
|
||
"id": messageID,
|
||
},
|
||
}
|
||
|
||
case protocol.SegmentTypeFace:
|
||
// 表情消息段
|
||
faceID := seg.Data["id"]
|
||
return &MessageSegment{
|
||
Type: SegmentTypeFace,
|
||
Data: map[string]interface{}{
|
||
"id": faceID,
|
||
},
|
||
}
|
||
|
||
default:
|
||
// 其他类型,尝试直接转换
|
||
return &MessageSegment{
|
||
Type: seg.Type,
|
||
Data: seg.Data,
|
||
}
|
||
}
|
||
}
|
||
|
||
// ConvertOB11ToMessageChain 将 OneBot11 消息段转换为通用消息链
|
||
func ConvertOB11ToMessageChain(ob11Message interface{}) (protocol.MessageChain, error) {
|
||
chain := protocol.MessageChain{}
|
||
|
||
// 如果是字符串,转换为文本消息段
|
||
if str, ok := ob11Message.(string); ok {
|
||
return protocol.NewMessageChain(protocol.NewTextSegment(str)), nil
|
||
}
|
||
|
||
// 如果是数组,解析为消息段数组
|
||
if segments, ok := ob11Message.([]MessageSegment); ok {
|
||
for _, seg := range segments {
|
||
genericSeg := convertOB11SegmentToGeneric(seg)
|
||
chain = append(chain, genericSeg)
|
||
}
|
||
return chain, nil
|
||
}
|
||
|
||
// 如果是接口数组,尝试转换
|
||
if segments, ok := ob11Message.([]interface{}); ok {
|
||
for _, seg := range segments {
|
||
if segMap, ok := seg.(map[string]interface{}); ok {
|
||
segType, _ := segMap["type"].(string)
|
||
segData, _ := segMap["data"].(map[string]interface{})
|
||
genericSeg := convertOB11SegmentToGeneric(MessageSegment{
|
||
Type: segType,
|
||
Data: segData,
|
||
})
|
||
chain = append(chain, genericSeg)
|
||
}
|
||
}
|
||
return chain, nil
|
||
}
|
||
|
||
return nil, fmt.Errorf("unsupported message format: %T", ob11Message)
|
||
}
|
||
|
||
// convertOB11SegmentToGeneric 将 OneBot11 消息段转换为通用消息段
|
||
func convertOB11SegmentToGeneric(seg MessageSegment) protocol.MessageSegment {
|
||
switch seg.Type {
|
||
case SegmentTypeText:
|
||
return protocol.NewTextSegment(seg.Data["text"].(string))
|
||
|
||
case SegmentTypeAt:
|
||
// OneBot11 @ 转换为 OneBot12 mention
|
||
userID := seg.Data["qq"]
|
||
return protocol.NewMentionSegment(userID)
|
||
|
||
case SegmentTypeImage:
|
||
fileID, ok := seg.Data["file"].(string)
|
||
if !ok {
|
||
fileID, _ = seg.Data["file_id"].(string)
|
||
}
|
||
return protocol.NewImageSegment(fileID)
|
||
|
||
case SegmentTypeRecord:
|
||
// OneBot11 record 转换为 OneBot12 voice
|
||
fileID, ok := seg.Data["file"].(string)
|
||
if !ok {
|
||
fileID, _ = seg.Data["file_id"].(string)
|
||
}
|
||
return protocol.MessageSegment{
|
||
Type: protocol.SegmentTypeVoice,
|
||
Data: map[string]interface{}{
|
||
"file_id": fileID,
|
||
},
|
||
}
|
||
|
||
case SegmentTypeReply:
|
||
messageID := seg.Data["id"]
|
||
return protocol.NewReplySegment(messageID)
|
||
|
||
case SegmentTypeFace:
|
||
return protocol.MessageSegment{
|
||
Type: protocol.SegmentTypeFace,
|
||
Data: map[string]interface{}{
|
||
"id": seg.Data["id"],
|
||
},
|
||
}
|
||
|
||
default:
|
||
// 其他类型,直接转换
|
||
return protocol.MessageSegment{
|
||
Type: seg.Type,
|
||
Data: seg.Data,
|
||
}
|
||
}
|
||
}
|