diff --git a/Lagrange.Core/Common/Interface/Api/GroupExt.cs b/Lagrange.Core/Common/Interface/Api/GroupExt.cs index 470bb4624..f5ad0ad71 100644 --- a/Lagrange.Core/Common/Interface/Api/GroupExt.cs +++ b/Lagrange.Core/Common/Interface/Api/GroupExt.cs @@ -1,5 +1,4 @@ using Lagrange.Core.Common.Entity; -using Lagrange.Core.Event.EventArg; using Lagrange.Core.Message; using Lagrange.Core.Message.Entity; diff --git a/Lagrange.Core/Event/EventInvoker.cs b/Lagrange.Core/Event/EventInvoker.cs index 925ea82ba..a025ca755 100644 --- a/Lagrange.Core/Event/EventInvoker.cs +++ b/Lagrange.Core/Event/EventInvoker.cs @@ -59,7 +59,7 @@ internal void PostEvent(EventBase e) } catch (Exception ex) { - PostEvent(new BotLogEvent(Tag, LogLevel.Exception, $"{ex.StackTrace}\n{ex.Message}")); + PostEvent(new BotLogEvent(Tag, LogLevel.Exception, $"{ex}")); } }); } diff --git a/Lagrange.Core/Message/Entity/BounceFaceEntity.cs b/Lagrange.Core/Message/Entity/BounceFaceEntity.cs index b8cd02f38..eaefafe69 100644 --- a/Lagrange.Core/Message/Entity/BounceFaceEntity.cs +++ b/Lagrange.Core/Message/Entity/BounceFaceEntity.cs @@ -1,9 +1,7 @@ -using System.Text; -using Lagrange.Core.Common.Entity; +using Lagrange.Core.Common.Entity; using Lagrange.Core.Internal.Packets.Message.Element; using Lagrange.Core.Internal.Packets.Message.Element.Implementation; using Lagrange.Core.Internal.Packets.Message.Element.Implementation.Extra; -using Lagrange.Core.Utility.Extension; using ProtoBuf; namespace Lagrange.Core.Message.Entity; diff --git a/Lagrange.OneBot/Core/Notify/NotifyService.cs b/Lagrange.OneBot/Core/Notify/NotifyService.cs index 4f401ac3e..842ed8974 100644 --- a/Lagrange.OneBot/Core/Notify/NotifyService.cs +++ b/Lagrange.OneBot/Core/Notify/NotifyService.cs @@ -6,12 +6,13 @@ using Lagrange.OneBot.Core.Entity.Notify; using Lagrange.OneBot.Core.Network; using Lagrange.OneBot.Database; -using LiteDB; +using Lagrange.OneBot.Utility; using Microsoft.Extensions.Logging; +using static Lagrange.Core.Message.MessageChain; namespace Lagrange.OneBot.Core.Notify; -public sealed class NotifyService(BotContext bot, ILogger logger, LagrangeWebSvcCollection service, LiteDatabase database) +public sealed class NotifyService(BotContext bot, ILogger logger, LagrangeWebSvcCollection service, RealmHelper realm) { public void RegisterEvents() { @@ -147,17 +148,18 @@ await service.SendJsonAsync(new OneBotGroupRecall(bot.BotUin) { logger.LogInformation(@event.ToString()); - var collection = database.GetCollection(); - var record = collection.FindOne(Query.And( - Query.EQ("FriendUin", new BsonValue(@event.FriendUin)), - Query.EQ("ClientSequence", new BsonValue(@event.ClientSequence)), - Query.EQ("MessageId", new BsonValue(0x01000000L << 32 | @event.Random)) - )); + var sequence = realm.Do(realm => realm.All() + .First(record => record.TypeInt == (int)MessageType.Friend + && record.FromUinLong == @event.FriendUin + && record.ClientSequenceLong == @event.ClientSequence + && record.MessageIdLong == (0x01000000L << 32 | @event.Random) + ) + .Sequence); await service.SendJsonAsync(new OneBotFriendRecall(bot.BotUin) { UserId = @event.FriendUin, - MessageId = MessageRecord.CalcMessageHash(@event.Random, record.Sequence), + MessageId = MessageRecord.CalcMessageHash(@event.Random, (uint)sequence), Tip = @event.Tip }); }; @@ -207,24 +209,27 @@ await service.SendJsonAsync(new OneBotGroupEssence(bot.BotUin) { logger.LogInformation(@event.ToString()); - var record = database.GetCollection().FindOne(Query.And( - Query.EQ("GroupUin", new BsonValue(@event.TargetGroupUin)), - Query.EQ("Sequence", new BsonValue(@event.TargetSequence)) - )); + var id = realm.Do(realm => realm.All() + .FirstOrDefault(record => record.TypeInt == (int)MessageType.Group + && record.ToUinLong == @event.TargetGroupUin + && record.SequenceLong == @event.TargetSequence)? + .Id); - if (record == null) + if (id == null) { logger.LogInformation( "Unable to find the corresponding message using GroupUin: {} and Sequence: {}", @event.TargetGroupUin, @event.TargetSequence ); + + return; } await service.SendJsonAsync(new OneBotGroupReaction( bot.BotUin, @event.TargetGroupUin, - record?.MessageHash ?? 0, + id.Value, @event.OperatorUin, @event.IsAdd ? "add" : "remove", @event.Code, diff --git a/Lagrange.OneBot/Core/Operation/Generic/FriendJoinEmojiChainOperation.cs b/Lagrange.OneBot/Core/Operation/Generic/FriendJoinEmojiChainOperation.cs index e6b17db93..aa800509f 100644 --- a/Lagrange.OneBot/Core/Operation/Generic/FriendJoinEmojiChainOperation.cs +++ b/Lagrange.OneBot/Core/Operation/Generic/FriendJoinEmojiChainOperation.cs @@ -1,25 +1,27 @@ using System.Text.Json; using System.Text.Json.Nodes; using Lagrange.Core; -using Lagrange.Core.Message; using Lagrange.Core.Common.Interface.Api; using Lagrange.OneBot.Core.Entity.Action; using Lagrange.OneBot.Core.Operation.Converters; using Lagrange.OneBot.Database; -using LiteDB; +using Lagrange.OneBot.Utility; namespace Lagrange.OneBot.Core.Operation.Generic; [Operation(".join_friend_emoji_chain")] -public class FriendJoinEmojiChainOperation(LiteDatabase database) : IOperation +public class FriendJoinEmojiChainOperation(RealmHelper realm) : IOperation { public async Task HandleOperation(BotContext context, JsonNode? payload) { if (payload.Deserialize(SerializerOptions.DefaultOptions) is { } data) { - var message = (MessageChain)database.GetCollection().FindById(data.MessageId); - bool res = await context.FriendJoinEmojiChain(data.UserId, data.EmojiId, message.Sequence); + var sequence = realm.Do(realm => realm.All() + .First(record => record.Id == data.MessageId) + .Sequence); + + bool res = await context.FriendJoinEmojiChain(data.UserId, data.EmojiId, (uint)sequence); return new OneBotResult(null, res ? 0 : -1, res ? "ok" : "failed"); } throw new Exception(); diff --git a/Lagrange.OneBot/Core/Operation/Generic/GroupJoinEmojiChainOperation.cs b/Lagrange.OneBot/Core/Operation/Generic/GroupJoinEmojiChainOperation.cs index 71638e322..cd67a5b36 100644 --- a/Lagrange.OneBot/Core/Operation/Generic/GroupJoinEmojiChainOperation.cs +++ b/Lagrange.OneBot/Core/Operation/Generic/GroupJoinEmojiChainOperation.cs @@ -1,25 +1,27 @@ using System.Text.Json; using System.Text.Json.Nodes; using Lagrange.Core; -using Lagrange.Core.Message; using Lagrange.Core.Common.Interface.Api; using Lagrange.OneBot.Core.Entity.Action; using Lagrange.OneBot.Core.Operation.Converters; using Lagrange.OneBot.Database; -using LiteDB; +using Lagrange.OneBot.Utility; namespace Lagrange.OneBot.Core.Operation.Generic; [Operation(".join_group_emoji_chain")] -public class GroupJoinEmojiChainOperation(LiteDatabase database) : IOperation +public class GroupJoinEmojiChainOperation(RealmHelper realm) : IOperation { public async Task HandleOperation(BotContext context, JsonNode? payload) { if (payload.Deserialize(SerializerOptions.DefaultOptions) is { } data) { - var message = (MessageChain)database.GetCollection().FindById(data.MessageId); - bool res = await context.GroupJoinEmojiChain(data.GroupId, data.EmojiId, message.Sequence); + var sequence = realm.Do(realm => realm.All() + .First(record => record.Id == data.MessageId) + .Sequence); + + bool res = await context.GroupJoinEmojiChain(data.GroupId, data.EmojiId, (uint)sequence); return new OneBotResult(null, res ? 0 : -1, res ? "ok" : "failed"); } throw new Exception(); diff --git a/Lagrange.OneBot/Core/Operation/Group/SetGroupReactionOperation.cs b/Lagrange.OneBot/Core/Operation/Group/SetGroupReactionOperation.cs index e8926a461..aeb6c7ed6 100644 --- a/Lagrange.OneBot/Core/Operation/Group/SetGroupReactionOperation.cs +++ b/Lagrange.OneBot/Core/Operation/Group/SetGroupReactionOperation.cs @@ -2,24 +2,30 @@ using System.Text.Json.Nodes; using Lagrange.Core; using Lagrange.Core.Common.Interface.Api; -using Lagrange.Core.Message; using Lagrange.OneBot.Core.Entity.Action; using Lagrange.OneBot.Core.Operation.Converters; using Lagrange.OneBot.Database; -using LiteDB; +using Lagrange.OneBot.Utility; namespace Lagrange.OneBot.Core.Operation.Group; [Operation("set_group_reaction")] -public class SetGroupReactionOperation(LiteDatabase database) : IOperation +public class SetGroupReactionOperation(RealmHelper realm) : IOperation { public async Task HandleOperation(BotContext context, JsonNode? payload) { if (payload.Deserialize(SerializerOptions.DefaultOptions) is { } data) { - var message = (MessageChain)database.GetCollection().FindById(data.MessageId); + var sequence = realm.Do(realm => realm.All() + .First(record => record.Id == data.MessageId) + .Sequence); - bool result = await context.GroupSetMessageReaction(data.GroupId, message.Sequence, data.Code, data.IsAdd); + bool result = await context.GroupSetMessageReaction( + data.GroupId, + (uint)sequence, + data.Code, + data.IsAdd + ); return new OneBotResult(null, result ? 0 : 1, result ? "ok" : "failed"); } diff --git a/Lagrange.OneBot/Core/Operation/Message/DeleteEssenceMessageOperation.cs b/Lagrange.OneBot/Core/Operation/Message/DeleteEssenceMessageOperation.cs index e9829b35d..30eb62e23 100644 --- a/Lagrange.OneBot/Core/Operation/Message/DeleteEssenceMessageOperation.cs +++ b/Lagrange.OneBot/Core/Operation/Message/DeleteEssenceMessageOperation.cs @@ -6,19 +6,20 @@ using Lagrange.OneBot.Core.Entity.Action; using Lagrange.OneBot.Core.Operation.Converters; using Lagrange.OneBot.Database; -using LiteDB; +using Lagrange.OneBot.Utility; namespace Lagrange.OneBot.Core.Operation.Message; [Operation("delete_essence_msg")] -public class DeleteEssenceMessageOperation(LiteDatabase database) : IOperation +public class DeleteEssenceMessageOperation(RealmHelper realm) : IOperation { public async Task HandleOperation(BotContext context, JsonNode? payload) { if (payload.Deserialize(SerializerOptions.DefaultOptions) is { } getMsg) { - var record = database.GetCollection().FindById(getMsg.MessageId); - var chain = (MessageChain)record; + var chain = realm.Do(realm => realm.All() + .First(record => record.Id == getMsg.MessageId)); + bool result = await context.RemoveEssenceMessage(chain); return new OneBotResult(null, result ? 0 : 1, result ? "ok" : "failed"); } diff --git a/Lagrange.OneBot/Core/Operation/Message/DeleteMessageOperation.cs b/Lagrange.OneBot/Core/Operation/Message/DeleteMessageOperation.cs index 0bdc917e3..5167c6abf 100644 --- a/Lagrange.OneBot/Core/Operation/Message/DeleteMessageOperation.cs +++ b/Lagrange.OneBot/Core/Operation/Message/DeleteMessageOperation.cs @@ -6,22 +6,27 @@ using Lagrange.OneBot.Core.Entity.Action; using Lagrange.OneBot.Core.Operation.Converters; using Lagrange.OneBot.Database; -using LiteDB; +using Lagrange.OneBot.Utility; namespace Lagrange.OneBot.Core.Operation.Message; [Operation("delete_msg")] -public class DeleteMessageOperation(LiteDatabase database) : IOperation +public class DeleteMessageOperation(RealmHelper realm) : IOperation { public async Task HandleOperation(BotContext context, JsonNode? payload) { if (payload.Deserialize(SerializerOptions.DefaultOptions) is { } getMsg) { - var record = database.GetCollection().FindById(getMsg.MessageId); - var chain = (MessageChain)record; + var chain = realm.Do(realm => realm.All() + .First(record => record.Id == getMsg.MessageId)); - if (chain.IsGroup && await context.RecallGroupMessage(chain)) return new OneBotResult(null, 0, "ok"); - if (!chain.IsGroup && await context.RecallFriendMessage(chain)) return new OneBotResult(null, 0, "ok"); + if (chain.Type switch + { + MessageChain.MessageType.Group => await context.RecallGroupMessage(chain), + MessageChain.MessageType.Temp => throw new NotSupportedException(), + MessageChain.MessageType.Friend => await context.RecallFriendMessage(chain), + _ => throw new NotImplementedException(), + }) return new OneBotResult(null, 0, "ok"); } throw new Exception(); diff --git a/Lagrange.OneBot/Core/Operation/Message/GetFriendMessageHistoryOperation.cs b/Lagrange.OneBot/Core/Operation/Message/GetFriendMessageHistoryOperation.cs index 58c0476b7..84e197a8b 100644 --- a/Lagrange.OneBot/Core/Operation/Message/GetFriendMessageHistoryOperation.cs +++ b/Lagrange.OneBot/Core/Operation/Message/GetFriendMessageHistoryOperation.cs @@ -8,22 +8,24 @@ using Lagrange.OneBot.Core.Operation.Converters; using Lagrange.OneBot.Database; using Lagrange.OneBot.Message; -using LiteDB; +using Lagrange.OneBot.Utility; namespace Lagrange.OneBot.Core.Operation.Message; [Operation("get_friend_msg_history")] -public class GetFriendMessageHistoryOperation(LiteDatabase database, MessageService message) : IOperation +public class GetFriendMessageHistoryOperation(RealmHelper realm, MessageService message) : IOperation { public async Task HandleOperation(BotContext context, JsonNode? payload) { if (payload.Deserialize(SerializerOptions.DefaultOptions) is { } history) { - var collection = database.GetCollection(); - var record = history.MessageId == 0 - ? collection.Find(x => x.FriendUin == history.UserId).OrderByDescending(x => x.Time).First() - : collection.FindById(history.MessageId); - var chain = (MessageChain)record; + var chain = realm.Do(realm => history.MessageId == 0 + ? realm.All() + .Where(record => record.FromUin == history.UserId) + .OrderByDescending(record => record.Time) + .First() + : realm.All() + .First(record => record.Id == history.MessageId)); if (await context.GetRoamMessage(chain, history.Count) is { } results) { @@ -33,7 +35,7 @@ public async Task HandleOperation(BotContext context, JsonNode? pa return new OneBotResult(new OneBotFriendMsgHistoryResponse(messages), 0, "ok"); } } - + throw new Exception(); } } diff --git a/Lagrange.OneBot/Core/Operation/Message/GetGroupMessageHistoryOperation.cs b/Lagrange.OneBot/Core/Operation/Message/GetGroupMessageHistoryOperation.cs index db42cba56..5e848b2dc 100644 --- a/Lagrange.OneBot/Core/Operation/Message/GetGroupMessageHistoryOperation.cs +++ b/Lagrange.OneBot/Core/Operation/Message/GetGroupMessageHistoryOperation.cs @@ -2,30 +2,34 @@ using System.Text.Json.Nodes; using Lagrange.Core; using Lagrange.Core.Common.Interface.Api; -using Lagrange.Core.Message; using Lagrange.OneBot.Core.Entity.Action; using Lagrange.OneBot.Core.Entity.Message; using Lagrange.OneBot.Core.Operation.Converters; using Lagrange.OneBot.Database; using Lagrange.OneBot.Message; -using LiteDB; +using Lagrange.OneBot.Utility; namespace Lagrange.OneBot.Core.Operation.Message; [Operation("get_group_msg_history")] -public class GetGroupMessageHistoryOperation(LiteDatabase database, MessageService message) : IOperation +public class GetGroupMessageHistoryOperation(RealmHelper realm, MessageService message) : IOperation { public async Task HandleOperation(BotContext context, JsonNode? payload) { if (payload.Deserialize(SerializerOptions.DefaultOptions) is { } history) { - var collection = database.GetCollection(); - var record = history.MessageId == 0 - ? collection.Find(x => x.GroupUin == history.GroupId).OrderByDescending(x => x.Time).First() - : collection.FindById(history.MessageId); - var chain = (MessageChain)record; + var sequence = realm.Do(realm => history.MessageId == 0 + ? realm.All() + .Where(record => record.ToUin == history.GroupId) + .OrderByDescending(x => x.Time) + .First() + .Sequence + : realm.All() + .First(record => record.Id == history.MessageId) + .Sequence); - if (await context.GetGroupMessage(history.GroupId, (uint)(chain.Sequence - history.Count + 1), chain.Sequence) is { } results) + uint start = (uint)(sequence - (ulong)history.Count + 1); + if (await context.GetGroupMessage(history.GroupId, start, (uint)sequence) is { } results) { var messages = results .Select(x => message.ConvertToGroupMsg(context.BotUin, x)) diff --git a/Lagrange.OneBot/Core/Operation/Message/GetMessageOperation.cs b/Lagrange.OneBot/Core/Operation/Message/GetMessageOperation.cs index a05e8f9d9..9db5c633a 100644 --- a/Lagrange.OneBot/Core/Operation/Message/GetMessageOperation.cs +++ b/Lagrange.OneBot/Core/Operation/Message/GetMessageOperation.cs @@ -1,7 +1,7 @@ using System.Text.Json; using System.Text.Json.Nodes; using Lagrange.Core; -using Lagrange.Core.Common.Entity; +using Lagrange.Core.Common.Interface.Api; using Lagrange.Core.Message; using Lagrange.OneBot.Core.Entity.Action; using Lagrange.OneBot.Core.Entity.Action.Response; @@ -9,31 +9,47 @@ using Lagrange.OneBot.Core.Operation.Converters; using Lagrange.OneBot.Database; using Lagrange.OneBot.Message; -using LiteDB; +using Lagrange.OneBot.Utility; namespace Lagrange.OneBot.Core.Operation.Message; [Operation("get_msg")] -public class GetMessageOperation(LiteDatabase database, MessageService service) : IOperation +public class GetMessageOperation(RealmHelper realm, MessageService service) : IOperation { - public Task HandleOperation(BotContext context, JsonNode? payload) + public async Task HandleOperation(BotContext context, JsonNode? payload) { if (payload.Deserialize(SerializerOptions.DefaultOptions) is { } getMsg) { - var record = database.GetCollection().FindById(getMsg.MessageId); - var chain = (MessageChain)record; + var chain = realm.Do(realm => realm.All().First(record => record.Id == getMsg.MessageId)); - OneBotSender sender = chain switch + OneBotSender sender = chain.Type switch { - { GroupMemberInfo: BotGroupMember g } => new(g.Uin, g.MemberName), - { FriendInfo: BotFriend f } => new(f.Uin, f.Nickname), - _ => new(chain.FriendUin, "") + MessageChain.MessageType.Group => new( + chain.FriendUin, + (await context.FetchMembers((uint)chain.GroupUin!)) + .First(member => member.Uin == chain.FriendUin) + .MemberName + ), + MessageChain.MessageType.Temp => new(chain.FriendUin, string.Empty), + MessageChain.MessageType.Friend => new( + chain.FriendUin, + (await context.FetchFriends()) + .First(friend => friend.Uin == chain.FriendUin) + .Nickname + ), + _ => throw new NotImplementedException(), }; var elements = service.Convert(chain); - var response = new OneBotGetMessageResponse(chain.Time, chain.IsGroup ? "group" : "private", record.MessageHash, sender, elements); + var response = new OneBotGetMessageResponse( + chain.Time, + chain.Type == MessageChain.MessageType.Group ? "group" : "private", + MessageRecord.CalcMessageHash(chain.MessageId, chain.Sequence), + sender, + elements + ); - return Task.FromResult(new OneBotResult(response, 0, "ok")); + return new OneBotResult(response, 0, "ok"); } throw new Exception(); diff --git a/Lagrange.OneBot/Core/Operation/Message/MarkMsgAsReadOperation.cs b/Lagrange.OneBot/Core/Operation/Message/MarkMsgAsReadOperation.cs index 08d5e2f6c..cd5244689 100644 --- a/Lagrange.OneBot/Core/Operation/Message/MarkMsgAsReadOperation.cs +++ b/Lagrange.OneBot/Core/Operation/Message/MarkMsgAsReadOperation.cs @@ -6,19 +6,20 @@ using Lagrange.OneBot.Core.Entity.Action; using Lagrange.OneBot.Core.Operation.Converters; using Lagrange.OneBot.Database; -using LiteDB; +using Lagrange.OneBot.Utility; namespace Lagrange.OneBot.Core.Operation.Message; [Operation("mark_msg_as_read")] -internal class MarkMsgAsReadOperation(LiteDatabase database) : IOperation +internal class MarkMsgAsReadOperation(RealmHelper realm) : IOperation { public async Task HandleOperation(BotContext context, JsonNode? payload) { if (payload.Deserialize(SerializerOptions.DefaultOptions) is { } getMsg) { - var record = database.GetCollection().FindById(getMsg.MessageId); - var chain = (MessageChain)record; + var chain = realm.Do(realm => realm.All() + .First(record => record.Id == getMsg.MessageId)); + bool result = await context.MarkAsRead(chain); return new OneBotResult(null, result ? 0 : 1, result ? "ok" : "failed"); } diff --git a/Lagrange.OneBot/Core/Operation/Message/MessageCommon.cs b/Lagrange.OneBot/Core/Operation/Message/MessageCommon.cs index 41e97d328..8bed0209f 100644 --- a/Lagrange.OneBot/Core/Operation/Message/MessageCommon.cs +++ b/Lagrange.OneBot/Core/Operation/Message/MessageCommon.cs @@ -9,7 +9,7 @@ using Lagrange.OneBot.Core.Entity.Message; using Lagrange.OneBot.Core.Operation.Converters; using Lagrange.OneBot.Message; -using LiteDB; +using Lagrange.OneBot.Utility; using Microsoft.Extensions.Logging; using JsonSerializer = System.Text.Json.JsonSerializer; @@ -21,7 +21,7 @@ public partial class MessageCommon private readonly Dictionary _typeToSegment; - public MessageCommon(LiteDatabase database, ILogger logger) + public MessageCommon(RealmHelper realm, ILogger logger) { _logger = logger; _typeToSegment = new Dictionary(); @@ -31,7 +31,7 @@ public MessageCommon(LiteDatabase database, ILogger logger) if (type.GetCustomAttribute() is { } attribute) { var instance = (SegmentBase)type.CreateInstance(false); - instance.Database = database; + instance.Realm = realm; _typeToSegment[attribute.SendType] = instance; } } diff --git a/Lagrange.OneBot/Core/Operation/Message/SendGroupAiRecordOperation.cs b/Lagrange.OneBot/Core/Operation/Message/SendGroupAiRecordOperation.cs index 618ae4620..10bbdf9ca 100644 --- a/Lagrange.OneBot/Core/Operation/Message/SendGroupAiRecordOperation.cs +++ b/Lagrange.OneBot/Core/Operation/Message/SendGroupAiRecordOperation.cs @@ -2,11 +2,9 @@ using System.Text.Json.Nodes; using Lagrange.Core; using Lagrange.Core.Common.Interface.Api; -using Lagrange.Core.Message; using Lagrange.OneBot.Core.Entity.Action; using Lagrange.OneBot.Core.Entity.Action.Response; using Lagrange.OneBot.Core.Operation.Converters; -using Lagrange.OneBot.Database; namespace Lagrange.OneBot.Core.Operation.Message; diff --git a/Lagrange.OneBot/Core/Operation/Message/SendMessageOperation.cs b/Lagrange.OneBot/Core/Operation/Message/SendMessageOperation.cs index 7d69f5f59..c247abc03 100644 --- a/Lagrange.OneBot/Core/Operation/Message/SendMessageOperation.cs +++ b/Lagrange.OneBot/Core/Operation/Message/SendMessageOperation.cs @@ -2,16 +2,19 @@ using System.Text.Json.Nodes; using Lagrange.Core; using Lagrange.Core.Common.Interface.Api; +using Lagrange.Core.Message; using Lagrange.OneBot.Core.Entity.Action; using Lagrange.OneBot.Core.Entity.Action.Response; using Lagrange.OneBot.Core.Operation.Converters; using Lagrange.OneBot.Database; -using LiteDB; +using Lagrange.OneBot.Utility; +using MessagePack; +using static Lagrange.Core.Message.MessageChain; namespace Lagrange.OneBot.Core.Operation.Message; [Operation("send_msg")] -public sealed class SendMessageOperation(MessageCommon common, LiteDatabase database) : IOperation +public sealed class SendMessageOperation(MessageCommon common, RealmHelper realm) : IOperation { public async Task HandleOperation(BotContext context, JsonNode? payload) { @@ -28,28 +31,24 @@ public async Task HandleOperation(BotContext context, JsonNode? pa if (result.Result != 0) return new OneBotResult(null, (int)result.Result, "failed"); if (result.Sequence == null || result.Sequence == 0) return new OneBotResult(null, 9000, "failed"); - int hash = MessageRecord.CalcMessageHash(result.MessageId, result.Sequence ?? 0); + int obid = MessageRecord.CalcMessageHash(result.MessageId, result.Sequence ?? 0); - if (!chain.IsGroup) database.GetCollection().Insert(hash, new() + if (!chain.IsGroup) { - FriendUin = context.BotUin, - Sequence = result.Sequence ?? 0, - ClientSequence = result.ClientSequence, - Time = DateTimeOffset.FromUnixTimeSeconds(result.Timestamp).LocalDateTime, - MessageId = result.MessageId, - FriendInfo = new( - context.BotUin, - context.ContextCollection.Keystore.Uid ?? string.Empty, - context.BotName ?? string.Empty, - string.Empty, - string.Empty, - string.Empty - ), - Entities = chain, - MessageHash = hash, - TargetUin = chain.FriendUin - }); + realm.Do(realm => realm.Write(() => realm.Add(new MessageRecord + { + Id = obid, + Type = MessageType.Friend, + Sequence = result.Sequence ?? 0, + ClientSequence = result.ClientSequence, + MessageId = result.MessageId, + Time = DateTimeOffset.FromUnixTimeSeconds(result.Timestamp), + FromUin = context.BotUin, + ToUin = chain.FriendUin, + Entities = MessagePackSerializer.Serialize>(chain, MessageRecord.OPTIONS) + }))); + } - return new OneBotResult(new OneBotMessageResponse(hash), 0, "ok"); + return new OneBotResult(new OneBotMessageResponse(obid), 0, "ok"); } } diff --git a/Lagrange.OneBot/Core/Operation/Message/SendPrivateForwardOperation.cs b/Lagrange.OneBot/Core/Operation/Message/SendPrivateForwardOperation.cs index f1bef6041..e1f0fa89a 100644 --- a/Lagrange.OneBot/Core/Operation/Message/SendPrivateForwardOperation.cs +++ b/Lagrange.OneBot/Core/Operation/Message/SendPrivateForwardOperation.cs @@ -8,12 +8,14 @@ using Lagrange.OneBot.Core.Entity.Action.Response; using Lagrange.OneBot.Core.Operation.Converters; using Lagrange.OneBot.Database; -using LiteDB; +using Lagrange.OneBot.Utility; +using MessagePack; +using static Lagrange.Core.Message.MessageChain; namespace Lagrange.OneBot.Core.Operation.Message; [Operation("send_private_forward_msg")] -public class SendPrivateForwardOperation(MessageCommon common, LiteDatabase database) : IOperation +public class SendPrivateForwardOperation(MessageCommon common, RealmHelper realm) : IOperation { public async Task HandleOperation(BotContext context, JsonNode? payload) { @@ -29,29 +31,22 @@ public async Task HandleOperation(BotContext context, JsonNode? pa if (result.Result != 0) return new OneBotResult(null, (int)result.Result, "failed"); if (result.Sequence == null || result.Sequence == 0) return new OneBotResult(null, 9000, "failed"); - int hash = MessageRecord.CalcMessageHash(result.MessageId, result.Sequence ?? 0); + int obid = MessageRecord.CalcMessageHash(result.MessageId, result.Sequence ?? 0); - database.GetCollection().Insert(hash, new() + realm.Do(realm => realm.Write(() => realm.Add(new MessageRecord { - FriendUin = context.BotUin, + Id = obid, + Type = MessageType.Friend, Sequence = result.Sequence ?? 0, ClientSequence = result.ClientSequence, - Time = DateTimeOffset.FromUnixTimeSeconds(result.Timestamp).LocalDateTime, MessageId = result.MessageId, - FriendInfo = new( - context.BotUin, - context.ContextCollection.Keystore.Uid ?? string.Empty, - context.BotName ?? string.Empty, - string.Empty, - string.Empty, - string.Empty - ), - Entities = chain, - MessageHash = hash, - TargetUin = chain.FriendUin - }); - - return new OneBotResult(new OneBotForwardResponse(hash, multi.ResId ?? ""), 0, "ok"); + Time = DateTimeOffset.FromUnixTimeSeconds(result.Timestamp), + FromUin = context.BotUin, + ToUin = chain.FriendUin, + Entities = MessagePackSerializer.Serialize>(chain, MessageRecord.OPTIONS) + }))); + + return new OneBotResult(new OneBotForwardResponse(obid, multi.ResId ?? ""), 0, "ok"); } throw new Exception(); diff --git a/Lagrange.OneBot/Core/Operation/Message/SendPrivateMessageOperation.cs b/Lagrange.OneBot/Core/Operation/Message/SendPrivateMessageOperation.cs index e0f83828b..c985c4737 100644 --- a/Lagrange.OneBot/Core/Operation/Message/SendPrivateMessageOperation.cs +++ b/Lagrange.OneBot/Core/Operation/Message/SendPrivateMessageOperation.cs @@ -2,16 +2,19 @@ using System.Text.Json.Nodes; using Lagrange.Core; using Lagrange.Core.Common.Interface.Api; +using Lagrange.Core.Message; using Lagrange.OneBot.Core.Entity.Action; using Lagrange.OneBot.Core.Entity.Action.Response; using Lagrange.OneBot.Core.Operation.Converters; using Lagrange.OneBot.Database; -using LiteDB; +using Lagrange.OneBot.Utility; +using MessagePack; +using static Lagrange.Core.Message.MessageChain; namespace Lagrange.OneBot.Core.Operation.Message; [Operation("send_private_msg")] -public sealed class SendPrivateMessageOperation(MessageCommon common, LiteDatabase database) : IOperation +public sealed class SendPrivateMessageOperation(MessageCommon common, RealmHelper realm) : IOperation { public async Task HandleOperation(BotContext context, JsonNode? payload) { @@ -28,28 +31,21 @@ public async Task HandleOperation(BotContext context, JsonNode? pa if (result.Result != 0) return new OneBotResult(null, (int)result.Result, "failed"); if (result.Sequence == null || result.Sequence == 0) return new OneBotResult(null, 9000, "failed"); - int hash = MessageRecord.CalcMessageHash(result.MessageId, result.Sequence ?? 0); + int obid = MessageRecord.CalcMessageHash(result.MessageId, result.Sequence ?? 0); - database.GetCollection().Insert(hash, new() + realm.Do(realm => realm.Write(() => realm.Add(new MessageRecord { - FriendUin = context.BotUin, + Id = obid, + Type = MessageType.Friend, Sequence = result.Sequence ?? 0, ClientSequence = result.ClientSequence, - Time = DateTimeOffset.FromUnixTimeSeconds(result.Timestamp).LocalDateTime, MessageId = result.MessageId, - FriendInfo = new( - context.BotUin, - context.ContextCollection.Keystore.Uid ?? string.Empty, - context.BotName ?? string.Empty, - string.Empty, - string.Empty, - string.Empty - ), - Entities = chain, - MessageHash = hash, - TargetUin = chain.FriendUin - }); + Time = DateTimeOffset.FromUnixTimeSeconds(result.Timestamp), + FromUin = context.BotUin, + ToUin = chain.FriendUin, + Entities = MessagePackSerializer.Serialize>(chain, MessageRecord.OPTIONS) + }))); - return new OneBotResult(new OneBotMessageResponse(hash), 0, "ok"); + return new OneBotResult(new OneBotMessageResponse(obid), 0, "ok"); } } diff --git a/Lagrange.OneBot/Core/Operation/Message/SetEssenceMessageOperation.cs b/Lagrange.OneBot/Core/Operation/Message/SetEssenceMessageOperation.cs index 216194708..4de2b5d44 100644 --- a/Lagrange.OneBot/Core/Operation/Message/SetEssenceMessageOperation.cs +++ b/Lagrange.OneBot/Core/Operation/Message/SetEssenceMessageOperation.cs @@ -6,19 +6,20 @@ using Lagrange.OneBot.Core.Entity.Action; using Lagrange.OneBot.Core.Operation.Converters; using Lagrange.OneBot.Database; -using LiteDB; +using Lagrange.OneBot.Utility; namespace Lagrange.OneBot.Core.Operation.Message; [Operation("set_essence_msg")] -public class SetEssenceMessageOperation(LiteDatabase database) : IOperation +public class SetEssenceMessageOperation(RealmHelper realm) : IOperation { public async Task HandleOperation(BotContext context, JsonNode? payload) { if (payload.Deserialize(SerializerOptions.DefaultOptions) is { } getMsg) { - var record = database.GetCollection().FindById(getMsg.MessageId); - var chain = (MessageChain)record; + var chain = realm.Do(realm => realm.All() + .First(record => record.Id == getMsg.MessageId)); + bool result = await context.SetEssenceMessage(chain); return new OneBotResult(null, result ? 0 : 1, result ? "ok" : "failed"); } diff --git a/Lagrange.OneBot/Core/Operation/OperationService.cs b/Lagrange.OneBot/Core/Operation/OperationService.cs index e732ba566..e29cf74af 100644 --- a/Lagrange.OneBot/Core/Operation/OperationService.cs +++ b/Lagrange.OneBot/Core/Operation/OperationService.cs @@ -5,7 +5,7 @@ using Lagrange.OneBot.Core.Notify; using Lagrange.OneBot.Core.Operation.Message; using Lagrange.OneBot.Message; -using LiteDB; +using Lagrange.OneBot.Utility; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using JsonSerializer = System.Text.Json.JsonSerializer; @@ -19,7 +19,7 @@ public sealed class OperationService private readonly Dictionary _operations; private readonly ServiceProvider _service; - public OperationService(BotContext bot, ILogger logger, LiteDatabase context, MessageService message) + public OperationService(BotContext bot, ILogger logger, RealmHelper realm, MessageService message) { _bot = bot; _logger = logger; @@ -33,7 +33,7 @@ public OperationService(BotContext bot, ILogger logger, LiteDa var service = new ServiceCollection(); service.AddSingleton(bot); - service.AddSingleton(context); + service.AddSingleton(realm); service.AddSingleton(logger); service.AddSingleton(message); service.AddSingleton(); diff --git a/Lagrange.OneBot/Database/MessageEntityFormatter.cs b/Lagrange.OneBot/Database/MessageEntityFormatter.cs new file mode 100644 index 000000000..a6cde3ca1 --- /dev/null +++ b/Lagrange.OneBot/Database/MessageEntityFormatter.cs @@ -0,0 +1,58 @@ +using Lagrange.Core.Message; +using Lagrange.Core.Message.Entity; +using MessagePack; +using MessagePack.Formatters; + +namespace Lagrange.OneBot.Database; + +public class MessageEntityFormatter : IMessagePackFormatter +{ + /// + /// DO NOT MODIFY THE ENUMERATION VALUE! + /// IT WILL CAUSE THE DATABASE TO BECOME INVALID! + /// + /// Each newly added IMessageEntity should be given a sequence number + /// + private static readonly Dictionary ID_TYPE = new() { + { 0, typeof(BounceFaceEntity) }, + { 1, typeof(FaceEntity) }, + { 2, typeof(FileEntity) }, + { 3, typeof(ForwardEntity) }, + { 4, typeof(GreyTipEntity) }, + { 5, typeof(GroupReactionEntity) }, + { 6, typeof(ImageEntity) }, + { 7, typeof(JsonEntity) }, + { 8, typeof(KeyboardEntity) }, + { 9, typeof(LightAppEntity) }, + { 10, typeof(LongMsgEntity) }, + { 11, typeof(MarkdownEntity) }, + { 12, typeof(MarketfaceEntity) }, + { 13, typeof(MentionEntity) }, + { 14, typeof(MultiMsgEntity) }, + { 15, typeof(PokeEntity) }, + { 16, typeof(RecordEntity) }, + { 17, typeof(SpecialPokeEntity) }, + { 18, typeof(TextEntity) }, + { 19, typeof(VideoEntity) }, + { 20, typeof(XmlEntity) }, + }; + + private static readonly Dictionary TYPE_ID = ID_TYPE.ToDictionary(m => m.Value, m => m.Key); + + public IMessageEntity? Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options) + { + byte id = reader.ReadByte(); + + return (IMessageEntity?)MessagePackSerializer.Deserialize(ID_TYPE[id], ref reader, options); + } + + public void Serialize(ref MessagePackWriter writer, IMessageEntity? value, MessagePackSerializerOptions options) + { + if (value == null) return; + + var type = value.GetType(); + + writer.Write(TYPE_ID[type]); + MessagePackSerializer.Serialize(type, ref writer, value, options); + } +} \ No newline at end of file diff --git a/Lagrange.OneBot/Database/MessageEntityResolver.cs b/Lagrange.OneBot/Database/MessageEntityResolver.cs new file mode 100644 index 000000000..803a4e841 --- /dev/null +++ b/Lagrange.OneBot/Database/MessageEntityResolver.cs @@ -0,0 +1,17 @@ +using Lagrange.Core.Message; +using MessagePack; +using MessagePack.Formatters; + +namespace Lagrange.OneBot.Database; + +public class MessageEntityResolver : IFormatterResolver +{ + private static readonly MessageEntityFormatter _FORMATTER = new(); + + public IMessagePackFormatter? GetFormatter() + { + if (typeof(T) == typeof(IMessageEntity)) return (IMessagePackFormatter?)_FORMATTER; + + return null; + } +} \ No newline at end of file diff --git a/Lagrange.OneBot/Database/MessageRecord.cs b/Lagrange.OneBot/Database/MessageRecord.cs index 27dd9f4d0..96dbb5b69 100644 --- a/Lagrange.OneBot/Database/MessageRecord.cs +++ b/Lagrange.OneBot/Database/MessageRecord.cs @@ -1,83 +1,120 @@ -using Lagrange.Core.Common.Entity; using Lagrange.Core.Message; -using Lagrange.OneBot.Utility; +using MessagePack; +using MessagePack.Resolvers; +using Realms; +using static Lagrange.Core.Message.MessageChain; namespace Lagrange.OneBot.Database; -[Serializable] -public class MessageRecord +#pragma warning disable CS8618 + +// # ################################################### # +// # WARNING # +// # ################################################### # +// +// When modifying MessageRecord, increment `SchemaVersion`. +// Beyond adding/removing fields (Realm auto-assigns +// defaults; complex processing requires migration logic +// in MigrationCallback), implement migration logic in +// `MigrationCallback` to handle all previous schema +// versions to current version. +// +// SchemaVersion +// Lagrange.OneBot/Extensions/HostApplicationBuilderExtension.cs#L91 +// +// MigrationCallback +// Lagrange.OneBot/Extensions/HostApplicationBuilderExtension.cs#L92 + +public partial class MessageRecord : IRealmObject { - public uint FriendUin { get; set; } + public static readonly MessagePackSerializerOptions OPTIONS = MessagePackSerializerOptions.Standard + .WithResolver(CompositeResolver.Create( + ContractlessStandardResolver.Instance, + new MessageEntityResolver() + )); - public uint GroupUin { get; set; } + [PrimaryKey] + public int Id { get; set; } - public uint Sequence { get; set; } + [MapTo(nameof(Type)), Indexed] + public int TypeInt { get; set; } + public MessageType Type { get => (MessageType)TypeInt; set => TypeInt = (int)value; } - public uint ClientSequence { get; set; } + [MapTo(nameof(Sequence)), Indexed] + public long SequenceLong { get; set; } + public ulong Sequence { get => (ulong)SequenceLong; set => SequenceLong = (long)value; } - public DateTime Time { get; set; } + [MapTo(nameof(ClientSequence)), Indexed] + public long ClientSequenceLong { get; set; } + public ulong ClientSequence { get => (ulong)ClientSequenceLong; set => ClientSequenceLong = (long)value; } - public ulong MessageId { get; set; } + [MapTo(nameof(MessageId)), Indexed] + public long MessageIdLong { get; set; } + public ulong MessageId { get => (ulong)MessageIdLong; set => MessageIdLong = (long)value; } - public BotFriend? FriendInfo { get; set; } + public DateTimeOffset Time { get; set; } - public BotGroupMember? GroupMemberInfo { get; set; } + [MapTo(nameof(FromUin)), Indexed] + public long FromUinLong { get; set; } + public ulong FromUin { get => (ulong)FromUinLong; set => FromUinLong = (long)value; } - public List Entities { get; set; } = []; + [MapTo(nameof(ToUin)), Indexed] + public long ToUinLong { get; set; } + public ulong ToUin { get => (ulong)ToUinLong; set => ToUinLong = (long)value; } - public int MessageHash { get; set; } + public byte[] Entities { get; set; } - public uint TargetUin { get; set; } - - static MessageRecord() - { - Vector2Mapper.RegisterType(); // I HATE THIS - } - - public static explicit operator MessageChain(MessageRecord record) + public static int CalcMessageHash(ulong msgId, uint seq) { - var chain = record.GroupUin != 0 - ? new MessageChain(record.GroupUin, record.FriendUin, record.Sequence, record.MessageId) - : new MessageChain(record.FriendUin, string.Empty, string.Empty, record.TargetUin, record.Sequence, record.ClientSequence, record.MessageId); - - chain.Time = record.Time; - chain.FriendInfo = record.FriendInfo; - chain.GroupMemberInfo = record.GroupMemberInfo; - - chain.AddRange(record.Entities); - return chain; + return ((ushort)seq << 16) | (ushort)msgId; } - public static explicit operator MessageRecord(MessageChain chain) => new() + public static implicit operator MessageRecord(MessageChain chain) => new() { - FriendUin = chain.FriendUin, - GroupUin = chain.GroupUin ?? 0, + Id = CalcMessageHash(chain.MessageId, chain.Sequence), Sequence = chain.Sequence, ClientSequence = chain.ClientSequence, - Time = chain.Time, MessageId = chain.MessageId, - FriendInfo = chain.FriendInfo, - GroupMemberInfo = chain.GroupMemberInfo, - Entities = chain, - MessageHash = CalcMessageHash(chain.MessageId, chain.Sequence), - TargetUin = chain.TargetUin + Time = chain.Time, + FromUin = chain.FriendUin, + ToUin = chain.Type switch + { + MessageType.Group => (ulong)chain.GroupUin!, + MessageType.Temp or + MessageType.Friend => chain.TargetUin, + _ => throw new NotImplementedException(), + }, + Entities = MessagePackSerializer.Serialize>(chain, OPTIONS) }; - public static int CalcMessageHash(ulong msgId, uint seq) - { - var messageId = BitConverter.GetBytes(msgId); - var sequence = BitConverter.GetBytes(seq); - - byte[] id = [messageId[0], messageId[1], sequence[0], sequence[1]]; - return BitConverter.ToInt32(id.AsSpan()); - } - - public static int CalcMessageHash(uint random, uint seq) + public static implicit operator MessageChain(MessageRecord record) { - var messageId = BitConverter.GetBytes(random); - var sequence = BitConverter.GetBytes(seq); + var chain = record.Type switch + { + MessageType.Group => new MessageChain( + (uint)record.ToUin, + (uint)record.FromUin, + (uint)record.Sequence, + record.MessageId + ), + MessageType.Temp or + MessageType.Friend => new MessageChain( + (uint)record.FromUin, + string.Empty, + string.Empty, + (uint)record.ToUin, + (uint)record.Sequence, + (uint)record.ClientSequence, + record.MessageId + ), + _ => throw new NotImplementedException(), + }; + + var entities = MessagePackSerializer.Deserialize>(record.Entities, OPTIONS); + chain.AddRange(entities); + + chain.Time = record.Time.DateTime; - byte[] id = [messageId[0], messageId[1], sequence[0], sequence[1]]; - return BitConverter.ToInt32(id.AsSpan()); + return chain; } } diff --git a/Lagrange.OneBot/Extensions/HostApplicationBuilderExtension.cs b/Lagrange.OneBot/Extensions/HostApplicationBuilderExtension.cs index 63c45f1e9..43d7355a5 100644 --- a/Lagrange.OneBot/Extensions/HostApplicationBuilderExtension.cs +++ b/Lagrange.OneBot/Extensions/HostApplicationBuilderExtension.cs @@ -5,15 +5,12 @@ using Lagrange.OneBot.Core.Network.Service; using Lagrange.OneBot.Core.Notify; using Lagrange.OneBot.Core.Operation; -using Lagrange.OneBot.Database; using Lagrange.OneBot.Message; using Lagrange.OneBot.Utility; -using LiteDB; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; - +using Realms; using JsonSerializer = System.Text.Json.JsonSerializer; namespace Lagrange.OneBot.Extensions; @@ -81,62 +78,21 @@ public static HostApplicationBuilder ConfigureLagrangeCore(this HostApplicationB public static HostApplicationBuilder ConfigureOneBot(this HostApplicationBuilder builder) { builder.Services.AddOptions() - .AddSingleton(services => // Database + .AddSingleton(services => // Realm Configuration { var configuration = services.GetRequiredService(); - var logger = services.GetRequiredService>(); - - BsonMapper.Global.TrimWhitespace = false; - BsonMapper.Global.EmptyStringToNull = false; - - // Specify ctor for some classes - BsonMapper.Global.RegisterType( - LiteDbUtility.IMessageEntitySerialize, - LiteDbUtility.IMessageEntityDeserialize - ); - - string path = configuration["ConfigPath:Database"] ?? $"lagrange-{configuration["Account:Uin"]}.db"; - bool isFirstCreate = false; - if (!File.Exists(path)) isFirstCreate = true; + string prefix = configuration["ConfigPath:Database"] ?? $"./lagrange-{configuration["Account:Uin"]}-db"; + if (!Directory.Exists(prefix)) Directory.CreateDirectory(prefix); + string path = Path.GetFullPath(Path.Join(prefix, ".realm")); - var db = new LiteDatabase(path) + return new RealmConfiguration(path) { - CheckpointSize = 50 + SchemaVersion = 1, + MigrationCallback = null, }; - - string[] expressions = ["$.Sequence", "$.MessageId", "$.FriendUin", "$.GroupUin"]; - - bool hasFirstIndex = false; - var indexes = db.GetCollection("$indexes"); - foreach (var expression in expressions) - { - if (indexes.Exists(Query.EQ("expression", expression))) continue; - - logger.LogWarning("In the database index"); - logger.LogWarning("Depending on the size of the database will consume some time and memory"); - logger.LogWarning("Not yet finished, please wait..."); - - hasFirstIndex = true; - break; - } - - var records = db.GetCollection(); - foreach (var expression in expressions) - { - records.EnsureIndex(BsonExpression.Create(expression)); - } - - // Skipping the first database creation is a restart after indexing - if (!isFirstCreate && hasFirstIndex) - { - db.Dispose(); // Ensure that the database is written correctly - logger.LogInformation("Indexing Complete! Press any key to close and restart the program manually!"); - Console.ReadKey(true); - Environment.Exit(0); - } - return db; }) + .AddSingleton() // // OneBot Netword Service .AddSingleton() diff --git a/Lagrange.OneBot/FodyWeavers.xml b/Lagrange.OneBot/FodyWeavers.xml new file mode 100644 index 000000000..cc07b8953 --- /dev/null +++ b/Lagrange.OneBot/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/Lagrange.OneBot/FodyWeavers.xsd b/Lagrange.OneBot/FodyWeavers.xsd new file mode 100644 index 000000000..f526bddb0 --- /dev/null +++ b/Lagrange.OneBot/FodyWeavers.xsd @@ -0,0 +1,28 @@ + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/Lagrange.OneBot/Lagrange.OneBot.csproj b/Lagrange.OneBot/Lagrange.OneBot.csproj index 354262ec6..da556595c 100644 --- a/Lagrange.OneBot/Lagrange.OneBot.csproj +++ b/Lagrange.OneBot/Lagrange.OneBot.csproj @@ -22,9 +22,10 @@ - + + diff --git a/Lagrange.OneBot/Message/Entity/ReplySegment.cs b/Lagrange.OneBot/Message/Entity/ReplySegment.cs index 1708123fd..8ccea3f57 100644 --- a/Lagrange.OneBot/Message/Entity/ReplySegment.cs +++ b/Lagrange.OneBot/Message/Entity/ReplySegment.cs @@ -22,10 +22,12 @@ public partial class ReplySegment : SegmentBase public override void Build(MessageBuilder builder, SegmentBase segment) { - if (segment is ReplySegment reply && Database is not null) + if (segment is ReplySegment reply && Realm is not null) { - var messageRecord = Database.GetCollection().FindById(int.Parse(reply.MessageId)); - reply.TargetChain ??= (MessageChain)messageRecord; + var chain = Realm.Do(realm => realm.All() + .First(record => record.Id == int.Parse(reply.MessageId))); + + reply.TargetChain ??= chain; var build = MessagePacker.Build(reply.TargetChain, ""); var virtualElem = build.Body?.RichText?.Elems; @@ -37,14 +39,14 @@ public override void Build(MessageBuilder builder, SegmentBase segment) public override SegmentBase FromEntity(MessageChain chain, IMessageEntity entity) { - if (entity is not ForwardEntity forward || Database is null) throw new ArgumentException("The entity is not a forward entity."); + if (entity is not ForwardEntity forward || Realm is null) throw new ArgumentException("The entity is not a forward entity."); - var collection = Database.GetCollection(); + var id = Realm.Do(realm => realm.All() + .FirstOrDefault(record => record.Id == MessageRecord.CalcMessageHash(forward.MessageId, forward.Sequence))? + .Id); - int hash = MessageRecord.CalcMessageHash(forward.MessageId, forward.Sequence); - var query = collection.FindById(hash); - return query == null + return !id.HasValue ? new ReplySegment { MessageId = 0.ToString() } - : new ReplySegment { MessageId = query.MessageHash.ToString() }; + : new ReplySegment { MessageId = id.Value.ToString() }; } } \ No newline at end of file diff --git a/Lagrange.OneBot/Message/MessageService.cs b/Lagrange.OneBot/Message/MessageService.cs index c59a853b0..ee4824eb2 100644 --- a/Lagrange.OneBot/Message/MessageService.cs +++ b/Lagrange.OneBot/Message/MessageService.cs @@ -10,7 +10,7 @@ using Lagrange.OneBot.Core.Network; using Lagrange.OneBot.Database; using Lagrange.OneBot.Message.Entity; -using LiteDB; +using Lagrange.OneBot.Utility; using Microsoft.Extensions.Configuration; using JsonSerializer = System.Text.Json.JsonSerializer; @@ -22,7 +22,7 @@ namespace Lagrange.OneBot.Message; public sealed class MessageService { private readonly LagrangeWebSvcCollection _service; - private readonly LiteDatabase _context; + private readonly RealmHelper _realm; private readonly IConfiguration _config; private readonly Dictionary> _entityToFactory; private readonly bool _stringPost; @@ -34,10 +34,10 @@ static MessageService() Options = new JsonSerializerOptions { TypeInfoResolver = new DefaultJsonTypeInfoResolver { Modifiers = { ModifyTypeInfo } } }; } - public MessageService(BotContext bot, LagrangeWebSvcCollection service, LiteDatabase context, IConfiguration config) + public MessageService(BotContext bot, LagrangeWebSvcCollection service, RealmHelper realm, IConfiguration config) { _service = service; - _context = context; + _realm = realm; _config = config; _stringPost = config.GetValue("Message:StringPost"); @@ -54,7 +54,7 @@ public MessageService(BotContext bot, LagrangeWebSvcCollection service, LiteData if (attribute != null) { var instance = (SegmentBase)type.CreateInstance(false); - instance.Database = _context; + instance.Realm = _realm; if (_entityToFactory.TryGetValue(attribute.Entity, out var factories)) factories.Add((attribute.Type, instance)); else _entityToFactory[attribute.Entity] = [(attribute.Type, instance)]; @@ -64,8 +64,7 @@ public MessageService(BotContext bot, LagrangeWebSvcCollection service, LiteData private void OnFriendMessageReceived(BotContext bot, FriendMessageEvent e) { - var record = (MessageRecord)e.Chain; - _context.GetCollection().Insert(new BsonValue(record.MessageHash), record); + _realm.Do(realm => realm.Write(() => realm.Add(e.Chain))); if (_config.GetValue("Message:IgnoreSelf") && e.Chain.FriendUin == bot.BotUin) return; // ignore self message @@ -99,8 +98,8 @@ public object ConvertToPrivateMsg(uint uin, MessageChain chain) private void OnGroupMessageReceived(BotContext bot, GroupMessageEvent e) { - var record = (MessageRecord)e.Chain; - _context.GetCollection().Insert(new BsonValue(record.MessageHash), record); + _realm.Do(realm => realm.Write(() => realm.Add(e.Chain))); + if (_config.GetValue("Message:IgnoreSelf") && e.Chain.FriendUin == bot.BotUin) return; // ignore self message var request = ConvertToGroupMsg(bot.BotUin, e.Chain); @@ -121,12 +120,12 @@ public object ConvertToGroupMsg(uint uin, MessageChain chain) private void OnTempMessageReceived(BotContext bot, TempMessageEvent e) { var record = (MessageRecord)e.Chain; - _context.GetCollection().Insert(new BsonValue(record.MessageHash), record); + _realm.Do(realm => realm.Write(() => realm.Add(record))); var segments = Convert(e.Chain); var request = new OneBotPrivateMsg(bot.BotUin, new OneBotSender(e.Chain.FriendUin, e.Chain.FriendInfo?.Nickname ?? string.Empty), "group", ((DateTimeOffset)e.Chain.Time).ToUnixTimeSeconds()) { - MessageId = record.MessageHash, + MessageId = record.Id, UserId = e.Chain.FriendUin, Message = segments, RawMessage = ToRawMessage(segments) diff --git a/Lagrange.OneBot/Message/SegmentBase.cs b/Lagrange.OneBot/Message/SegmentBase.cs index 0528545c4..ec802aec5 100644 --- a/Lagrange.OneBot/Message/SegmentBase.cs +++ b/Lagrange.OneBot/Message/SegmentBase.cs @@ -1,11 +1,11 @@ using Lagrange.Core.Message; -using LiteDB; +using Lagrange.OneBot.Utility; namespace Lagrange.OneBot.Message; public abstract class SegmentBase { - public LiteDatabase? Database { protected get; set; } + public RealmHelper? Realm { protected get; set; } public abstract void Build(MessageBuilder builder, SegmentBase segment); diff --git a/Lagrange.OneBot/Utility/FallbackAsync.cs b/Lagrange.OneBot/Utility/FallbackAsync.cs index 2d1b84b54..8c6dd237f 100644 --- a/Lagrange.OneBot/Utility/FallbackAsync.cs +++ b/Lagrange.OneBot/Utility/FallbackAsync.cs @@ -1,6 +1,3 @@ - -using System.Diagnostics.CodeAnalysis; - namespace Lagrange.OneBot.Utility.Fallbacks; public class FallbackAsync diff --git a/Lagrange.OneBot/Utility/LiteDbUtility.cs b/Lagrange.OneBot/Utility/LiteDbUtility.cs deleted file mode 100644 index 006e566b5..000000000 --- a/Lagrange.OneBot/Utility/LiteDbUtility.cs +++ /dev/null @@ -1,49 +0,0 @@ -using Lagrange.Core.Message; -using Lagrange.Core.Message.Entity; -using LiteDB; - -namespace Lagrange.OneBot.Utility; - -public static class LiteDbUtility -{ - public static BsonValue IMessageEntitySerialize(IMessageEntity entity) - { - var type = entity.GetType(); - var result = BsonMapper.Global.Serialize(type, entity); - result["_type"] = new BsonValue(DefaultTypeNameBinder.Instance.GetName(type)); - return result; - } - - public static IMessageEntity IMessageEntityDeserialize(BsonValue bson) - { - if (!bson.IsDocument) throw new Exception("bson not BsonDocument"); - - var doc = bson.AsDocument; - if (!doc.TryGetValue("_type", out var typeBson) || !typeBson.IsString) - { - throw new Exception("no `_type` or `_type` not string"); - } - - var type = DefaultTypeNameBinder.Instance.GetType(typeBson.AsString); - - if (type == typeof(MarkdownEntity)) return MarkdownEntityDeserialize(doc); - - return (IMessageEntity)BsonMapper.Global.Deserialize(type, bson); - } - - private static MarkdownEntity MarkdownEntityDeserialize(BsonDocument doc) - { - if (!doc.TryGetValue("Data", out var dataBson) || !dataBson.IsDocument) - { - throw new Exception("no `Data` or `Data` not document"); - } - - var dataDocument = dataBson.AsDocument; - if (!dataDocument.TryGetValue("Content", out var contentBson) || !contentBson.IsString) - { - throw new InvalidCastException("no `Data.Content` or `Data.Content` not string"); - } - - return new(new MarkdownData() { Content = contentBson.AsString }); - } -} \ No newline at end of file diff --git a/Lagrange.OneBot/Utility/RealmHelper.cs b/Lagrange.OneBot/Utility/RealmHelper.cs new file mode 100644 index 000000000..1acd0b653 --- /dev/null +++ b/Lagrange.OneBot/Utility/RealmHelper.cs @@ -0,0 +1,20 @@ +using Realms; + +namespace Lagrange.OneBot.Utility; + +public class RealmHelper(RealmConfiguration configuration) +{ + private readonly RealmConfiguration _configuration = configuration; + + public T Do(Func action) + { + using Realm realm = Realm.GetInstance(_configuration); + return action(realm); + } + + public void Do(Action action) + { + using Realm realm = Realm.GetInstance(_configuration); + action(realm); + } +} \ No newline at end of file diff --git a/Lagrange.OneBot/Utility/Vector2Mapper.cs b/Lagrange.OneBot/Utility/Vector2Mapper.cs deleted file mode 100644 index 63831bdee..000000000 --- a/Lagrange.OneBot/Utility/Vector2Mapper.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Numerics; -using LiteDB; - -namespace Lagrange.OneBot.Utility; - -public static class Vector2Mapper -{ - public static void RegisterType() => BsonMapper.Global.RegisterType(Serialize, Deserialize); - - public static BsonValue Serialize(Vector2 parameter) => new BsonDocument(new Dictionary - { - { "X", parameter.X }, - { "Y", parameter.Y } - }); - - public static Vector2 Deserialize(BsonValue bsonValue) - { - float x = (float)bsonValue["X"].AsDouble; - float y = (float)bsonValue["Y"].AsDouble; - return new Vector2(x, y); - } -} \ No newline at end of file