Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Lagrange.Core/Common/Interface/OperationExt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,7 @@ public static Task<BotStranger> FetchStranger(this BotContext context, long uin)

public static Task SetGroupNotification(this BotContext context, long groupUin, ulong sequence, BotGroupNotificationType type, bool isFiltered, GroupNotificationOperate operate, string message = "") =>
context.EventContext.GetLogic<OperationLogic>().SetGroupNotification(groupUin, sequence, type, isFiltered, operate, message);

public static Task SetGroupReaction(this BotContext context, long groupUin, ulong sequence, string code, bool isAdd) =>
context.EventContext.GetLogic<OperationLogic>().SetGroupReaction(groupUin, sequence, code, isAdd);
}
21 changes: 21 additions & 0 deletions Lagrange.Core/Events/EventArgs/BotGroupReactionEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
namespace Lagrange.Core.Events.EventArgs;

public class BotGroupReactionEvent(long targetGroupUin, ulong targetSequence, long operatorUin, bool isAdd, string code, ulong currentCount) : EventBase
{
public long TargetGroupUin { get; } = targetGroupUin;

public ulong TargetSequence { get; } = targetSequence;

public long OperatorUin { get; } = operatorUin;

public bool IsAdd { get; } = isAdd;

public string Code { get; } = code;

public ulong CurrentCount { get; } = currentCount;

public override string ToEventMessage()
{
return $"{nameof(BotGroupReactionEvent)}: Target {TargetGroupUin} > {TargetSequence} Operator {OperatorUin} {(IsAdd ? "Add" : "Reduce")} {Code} Current {CurrentCount}";
}
}
30 changes: 17 additions & 13 deletions Lagrange.Core/Internal/Context/EventContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ namespace Lagrange.Core.Internal.Context;
internal class EventContext : IDisposable
{
private const string Tag = nameof(EventContext);

private readonly BotContext _context;

private readonly FrozenDictionary<Type, List<ILogic>> _events;

private readonly FrozenDictionary<Type, ILogic> _logics;
Expand All @@ -27,7 +27,7 @@ public EventContext(BotContext context)
{
var events = new Dictionary<Type, List<ILogic>>();
var logics = new Dictionary<Type, ILogic>();

foreach (var type in typeof(ILogic).Assembly.GetTypes())
{
if (type.HasImplemented<ILogic>() && Activator.CreateInstance(type, context) is ILogic instance)
Expand All @@ -39,30 +39,30 @@ public EventContext(BotContext context)
list = [];
events.Add(@event.EventType, list);
}

list.Add(instance);
}

logics[type] = instance;
}
}

_context = context;
_events = events.ToFrozenDictionary();
_logics = logics.ToFrozenDictionary();
}

public async ValueTask<T> SendEvent<T>(ProtocolEvent @event) where T : ProtocolEvent
{
try
{
await HandleOutgoingEvent(@event);
var (frame, attribute) = await _context.ServiceContext.Resolve(@event);
var (frame, attribute) = await _context.ServiceContext.Resolve(@event);
if (frame.Sequence == 0) throw new LagrangeException("The sequence number is 0 for the SSOFrame");

var @return = await _context.PacketContext.SendPacket(frame, attribute);
var resolved = await _context.ServiceContext.Resolve(@return);

if (resolved is T result)
{
await HandleIncomingEvent(result);
Expand All @@ -76,7 +76,7 @@ public async ValueTask<T> SendEvent<T>(ProtocolEvent @event) where T : ProtocolE
throw new LagrangeException("An error occurred while sending the event", e);
}
}

private async ValueTask HandleIncomingEvent(ProtocolEvent @event)
{
if (_events.TryGetValue(@event.GetType(), out var logics))
Expand Down Expand Up @@ -112,7 +112,7 @@ private async ValueTask HandleOutgoingEvent(ProtocolEvent @event)
}
}
}

public async ValueTask HandleOutgoingEvent(EventBase @event)
{
if (_events.TryGetValue(@event.GetType(), out var logics))
Expand Down Expand Up @@ -142,8 +142,12 @@ public async Task HandleServerPacket(SsoPacket packet)
{
_context.LogWarning(Tag, "Service not found for command: {0}", e, e.Command);
}
catch (Exception e)
{
_context.LogError(Tag, "Handle {0} server packet failed", e, packet.Command);
}
}

public T GetLogic<T>() where T : ILogic => (T)_logics[typeof(T)];

public void Dispose()
Expand Down
10 changes: 5 additions & 5 deletions Lagrange.Core/Internal/Context/PacketContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
Task.Run(async () => // Schedule the task to the ThreadPool
{
ReadOnlyMemory<byte> frame;

switch (options.RequestType)
{
case RequestType.D2Auth:
Expand Down Expand Up @@ -72,18 +72,18 @@
throw new InvalidOperationException($"Unknown RequestType: {options.RequestType}");
}
}

await _context.SocketContext.Send(frame);
});

return new ValueTask<SsoPacket>(tcs, 0);
}

public void DispatchPacket(ReadOnlySpan<byte> buffer)
{
var service = _servicePacker.Parse(buffer);
var sso = _ssoPacker.Parse(service);

if (_pendingTasks.TryRemove(sso.Sequence, out var tcs))
{
if (sso is { RetCode: not 0, Extra: var extra })
Expand All @@ -98,7 +98,7 @@
}
else
{
_ = _context.EventContext.HandleServerPacket(sso);
Task.Run(() => context.EventContext.HandleServerPacket(sso));

Check failure on line 101 in Lagrange.Core/Internal/Context/PacketContext.cs

View workflow job for this annotation

GitHub Actions / build (macos-latest, osx-arm64)

The name 'context' does not exist in the current context

Check failure on line 101 in Lagrange.Core/Internal/Context/PacketContext.cs

View workflow job for this annotation

GitHub Actions / build (macos-latest, osx-arm64, .dylib)

The name 'context' does not exist in the current context
}
}
}
15 changes: 15 additions & 0 deletions Lagrange.Core/Internal/Events/System/AddGroupReactionEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace Lagrange.Core.Internal.Events.System;

internal class AddGroupReactionEventReq(long groupUin, ulong sequence, string code) : ProtocolEvent
{
public long GroupUin { get; } = groupUin;

public ulong Sequence { get; } = sequence;

public string Code { get; } = code;
}

internal class AddGroupReactionEventResp : ProtocolEvent
{
public static readonly AddGroupReactionEventResp Default = new();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace Lagrange.Core.Internal.Events.System;

internal class ReduceGroupReactionEventReq(long groupUin, ulong sequence, string code) : ProtocolEvent
{
public long GroupUin { get; } = groupUin;

public ulong Sequence { get; } = sequence;

public string Code { get; } = code;
}

internal class ReduceGroupReactionEventResp : ProtocolEvent
{
public static readonly ReduceGroupReactionEventResp Default = new();
}
10 changes: 10 additions & 0 deletions Lagrange.Core/Internal/Logic/OperationLogic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -274,4 +274,14 @@ await context.EventContext.SendEvent<SetGroupNotificationEventResp>(
);
}
}

public async Task SetGroupReaction(long groupUin, ulong sequence, string code, bool isAdd)
{
if (isAdd) await context.EventContext.SendEvent<AddGroupReactionEventResp>(
new AddGroupReactionEventReq(groupUin, sequence, code)
);
else await context.EventContext.SendEvent<ReduceGroupReactionEventResp>(
new ReduceGroupReactionEventReq(groupUin, sequence, code)
);
}
}
53 changes: 45 additions & 8 deletions Lagrange.Core/Internal/Logic/PushLogic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public async ValueTask Incoming(ProtocolEvent e)
case Type.TempMessage:
{
var message = await context.EventContext.GetLogic<MessagingLogic>().Parse(messageEvent.MsgPush.CommonMessage);
if (message.Entities[0] is LightAppEntity {AppName: "com.tencent.qun.invite"} || message.Entities[0] is LightAppEntity {AppName: "com.tencent.tuwen.lua"})
if (message.Entities[0] is LightAppEntity { AppName: "com.tencent.qun.invite" } || message.Entities[0] is LightAppEntity { AppName: "com.tencent.tuwen.lua" })
{
var app = (LightAppEntity)message.Entities[0];
using var document = JsonDocument.Parse(app.Payload);
Expand Down Expand Up @@ -152,8 +152,8 @@ public async ValueTask Incoming(ProtocolEvent e)
var pkgType210 = (Event0x210SubType)messageEvent.MsgPush.CommonMessage.ContentHead.SubType;
switch (pkgType210)
{
case Event0x210SubType.FriendRequestNotice
when messageEvent.MsgPush.CommonMessage.MessageBody.MsgContent is { } content:
case Event0x210SubType.FriendRequestNotice when messageEvent.MsgPush.CommonMessage.MessageBody.MsgContent is { } content:
{
var friendRequest = ProtoHelper.Deserialize<FriendRequest>(content.Span);
context.EventInvoker.PostEvent(new BotFriendRequestEvent(
friendRequest.Info!.SourceUid,
Expand All @@ -162,6 +162,12 @@ public async ValueTask Incoming(ProtocolEvent e)
friendRequest.Info.Source ?? string.Empty
));
break;
}
default:
{
context.LogWarning(nameof(PushLogic), "Unknown 0x210 sub type: {0}", null, pkgType210);
break;
}
}

break;
Expand Down Expand Up @@ -195,6 +201,40 @@ public async ValueTask Incoming(ProtocolEvent e)
}
break;
}
case Event0x2DCSubType.SubType16 when messageEvent.MsgPush.CommonMessage.MessageBody.MsgContent is { } content:
{
var reader = new BinaryPacket(content);
// group uin and 1 byte
reader.Skip(4 + 1);
var proto = reader.ReadBytes(Prefix.Int16 | Prefix.LengthOnly);
var body = ProtoHelper.Deserialize<NotifyMessageBody>(proto);

switch ((Event0x2DCSubType16SubType)body.SubType)
{
case Event0x2DCSubType16SubType.GroupReactionNotice:
{
var reaction = body.Reaction.Data.Data;

long @operator = context.CacheContext.ResolveUin(reaction.Data.OperatorUid);

context.EventInvoker.PostEvent(new BotGroupReactionEvent(
body.GroupUin,
reaction.Target.Sequence,
@operator,
reaction.Data.Type == 1,
reaction.Data.Code,
reaction.Data.CurrentCount
));
break;
}
default:
{
context.LogWarning(nameof(PushLogic), "Unknown 0x2DCSub16 sub type: {0}", null, body.SubType);
break;
}
}
break;
}
default:
{
context.LogWarning(nameof(PushLogic), "Unknown 0x2DC sub type: {0}", null, pkgType);
Expand Down Expand Up @@ -244,14 +284,11 @@ private enum Event0x2DCSubType
GroupGreyTipNotice20 = 20,
}

private enum Event0x2DCSubType16Field13
private enum Event0x2DCSubType16SubType
{
GroupMemberSpecialTitleNotice = 6,
GroupNameChangeNotice = 12,
GroupTodoNotice = 23,
GroupReactionNotice = 35,
}

private enum Event0x210SubType
{
FriendRequestNotice = 35,
Expand Down
2 changes: 1 addition & 1 deletion Lagrange.Core/Internal/Packets/Notify/GroupReaction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ internal partial class GroupReactionData3
{
[ProtoMember(1)] public string Code { get; set; }

[ProtoMember(3)] public uint Count { get; set; }
[ProtoMember(3)] public uint CurrentCount { get; set; }

[ProtoMember(4)] public string OperatorUid { get; set; }

Expand Down
4 changes: 2 additions & 2 deletions Lagrange.Core/Internal/Packets/Notify/NotifyMessageBody.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ namespace Lagrange.Core.Internal.Packets.Notify;
[ProtoPackable]
internal partial class NotifyMessageBody
{
[ProtoMember(1)] public uint Type { get; set; }
[ProtoMember(1)] public uint NotifyType { get; set; }

[ProtoMember(4)] public long GroupUin { get; set; }

[ProtoMember(5)] public byte[]? EventParam { get; set; }

[ProtoMember(11)] public GroupRecall Recall { get; set; }

[ProtoMember(13)] public uint? Field13 { get; set; }
[ProtoMember(13)] public uint SubType { get; set; }

[ProtoMember(21)] public string OperatorUid { get; set; }

Expand Down
20 changes: 20 additions & 0 deletions Lagrange.Core/Internal/Packets/Service/SetGroupReaction.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using Lagrange.Proto;

namespace Lagrange.Core.Internal.Packets.Service;

#pragma warning disable CS8618

[ProtoPackable]
public partial class SetGroupReactionRequest
{
[ProtoMember(2)] public long GroupUin { get; set; }

[ProtoMember(3)] public ulong Sequence { get; set; }

[ProtoMember(4)] public string Code { get; set; }

[ProtoMember(5)] public ulong Type { get; set; }
}

[ProtoPackable]
public partial class SetGroupReactionResponse;
31 changes: 31 additions & 0 deletions Lagrange.Core/Internal/Services/System/AddGroupReactionService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using Lagrange.Core.Common;
using Lagrange.Core.Internal.Events;
using Lagrange.Core.Internal.Events.System;
using Lagrange.Core.Internal.Packets.Service;

namespace Lagrange.Core.Internal.Services.System;

[EventSubscribe<AddGroupReactionEventReq>(Protocols.All)]
[Service("OidbSvcTrpcTcp.0x9082_1")]
internal class AddGroupReactionService : OidbService<AddGroupReactionEventReq, AddGroupReactionEventResp, SetGroupReactionRequest, SetGroupReactionResponse>
{
private protected override uint Command => 0x9082;

private protected override uint Service => 1;

private protected override Task<SetGroupReactionRequest> ProcessRequest(AddGroupReactionEventReq request, BotContext context)
{
return Task.FromResult(new SetGroupReactionRequest
{
GroupUin = request.GroupUin,
Sequence = request.Sequence,
Code = request.Code,
Type = request.Code.Length <= 3 ? 1ul : 2ul
});
}

private protected override Task<AddGroupReactionEventResp> ProcessResponse(SetGroupReactionResponse response, BotContext context)
{
return Task.FromResult(AddGroupReactionEventResp.Default);
}
}
Loading
Loading