Skip to content

Commit

Permalink
[All] Fix the issue of sending super emoticons and some other normal …
Browse files Browse the repository at this point in the history
…emoticons (#618)

* [Core] Correction of some field names in QFaceExtra

* [Core] Correction of some field names in QFaceExtra x2

* [Core] Introduce `0x9154_1` & spilt `QFaceExtra`

* [Core] faceId >= 260

* [All] Fix the issue of sending super emoticons & add JoinEmojiChan

* [Core] Always send small face by default

* [Core] resolve #618 (comment) & #618 (comment)
  • Loading branch information
pk5ls20 authored Oct 22, 2024
1 parent 6f0b2cb commit 3580687
Show file tree
Hide file tree
Showing 23 changed files with 584 additions and 29 deletions.
67 changes: 67 additions & 0 deletions Lagrange.Core/Common/Entity/SysFaceEntry.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
namespace Lagrange.Core.Common.Entity;

[Serializable]
public class SysFaceEntry
{
public string QSid { get; set; }

public string? QDes { get; set; }

public string? EMCode { get; set; }

public int? QCid { get; set; }

public int? AniStickerType { get; set; }

public int? AniStickerPackId { get; set; }

public int? AniStickerId { get; set; }

public string? Url { get; set; }

public string[]? EmojiNameAlias { get; set; }

public int? AniStickerWidth { get; set; }

public int? AniStickerHeight { get; set; }

public SysFaceEntry(string qSid, string? qDes, string? emCode, int? qCid, int? aniStickerType,
int? aniStickerPackId, int? aniStickerId, string? url, string[]? emojiNameAlias, int? aniStickerWidth,
int? aniStickerHeight)
{
QSid = qSid;
QDes = qDes;
EMCode = emCode;
QCid = qCid;
AniStickerType = aniStickerType;
AniStickerPackId = aniStickerPackId;
AniStickerId = aniStickerId;
Url = url;
EmojiNameAlias = emojiNameAlias;
AniStickerWidth = aniStickerWidth;
AniStickerHeight = aniStickerHeight;
}
}

[Serializable]
public class SysFacePackEntry
{
public string EmojiPackName { get; set; }

public SysFaceEntry[] Emojis { get; set; }

public SysFacePackEntry(string emojiPackName, SysFaceEntry[] emojis)
{
EmojiPackName = emojiPackName;
Emojis = emojis;
}

public uint[] GetUniqueSuperQSids((int AniStickerType, int AniStickerPackId)[] excludeAniStickerTypesAndPackIds)
=> Emojis
.Where(e => e.AniStickerType is not null
&& e.AniStickerPackId is not null
&& !excludeAniStickerTypesAndPackIds.Contains((e.AniStickerType.Value, e.AniStickerPackId.Value)))
.Select(e => uint.Parse(e.QSid))
.Distinct()
.ToArray();
}
12 changes: 12 additions & 0 deletions Lagrange.Core/Common/Interface/Api/OperationExt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -249,4 +249,16 @@ public static Task<MessageResult> FriendShake(this BotContext bot, uint friendUi
/// <param name="avatar">The avatar object, <see cref="ImageEntity"/></param>
public static Task<bool> SetAvatar(this BotContext bot, ImageEntity avatar)
=> bot.ContextCollection.Business.OperationLogic.SetAvatar(avatar);

public static Task<bool> FetchSuperFaceId(this BotContext bot, uint id)
=> bot.ContextCollection.Business.OperationLogic.FetchSuperFaceId(id);

public static Task<SysFaceEntry?> FetchFaceEntity(this BotContext bot, uint id)
=> bot.ContextCollection.Business.OperationLogic.FetchFaceEntity(id);

public static Task<bool> GroupJoinEmojiChain(this BotContext bot, uint groupUin, uint emojiId, uint targetMessageSeq)
=> bot.ContextCollection.Business.OperationLogic.GroupJoinEmojiChain(groupUin, emojiId, targetMessageSeq);

public static Task<bool> FriendJoinEmojiChain(this BotContext bot, uint friendUin, uint emojiId, uint targetMessageSeq)
=> bot.ContextCollection.Business.OperationLogic.FriendJoinEmojiChain(friendUin, emojiId, targetMessageSeq);
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ internal class CachingLogic : LogicBase

private readonly ConcurrentDictionary<uint, BotUserInfo> _cacheUsers;

private readonly Dictionary<uint, SysFaceEntry> _cacheFaceEntities;
private readonly List<uint> _cacheSuperFaceId;

internal CachingLogic(ContextCollection collection) : base(collection)
{
_uinToUid = new Dictionary<uint, string>();
Expand All @@ -35,6 +38,9 @@ internal CachingLogic(ContextCollection collection) : base(collection)
_cachedGroupMembers = new Dictionary<uint, List<BotGroupMember>>();

_cacheUsers = new ConcurrentDictionary<uint, BotUserInfo>();

_cacheFaceEntities = new Dictionary<uint, SysFaceEntry>();
_cacheSuperFaceId = new List<uint>();
}

public override Task Incoming(ProtocolEvent e)
Expand Down Expand Up @@ -92,6 +98,7 @@ public async Task<List<BotGroupMember>> GetCachedMembers(uint groupUin, bool ref
await ResolveMembersUid(groupUin);
return _cachedGroupMembers.TryGetValue(groupUin, out members) ? members : new List<BotGroupMember>();
}

return members;
}

Expand Down Expand Up @@ -142,6 +149,7 @@ private async Task ResolveFriendsUidAndFriendGroups()
{
friend.Group = new(friend.Group.GroupId, friendGroups[friend.Group.GroupId]);
}

friends.AddRange(result.Friends);

next = result.NextUin;
Expand Down Expand Up @@ -190,4 +198,32 @@ private async Task ResolveUser(uint uin)
_cacheUsers.AddOrUpdate(uin, @event.UserInfo, (_key, _value) => @event.UserInfo);
}
}

private async Task ResolveEmojiCache()
{
var fetchSysEmojisEvent = FetchFullSysFacesEvent.Create();
var events = await Collection.Business.SendEvent(fetchSysEmojisEvent);
var emojiPacks = ((FetchFullSysFacesEvent)events[0]).FacePacks;

emojiPacks
.SelectMany(pack => pack.Emojis)
.Where(emoji => uint.TryParse(emoji.QSid, out _))
.ToList()
.ForEach(emoji => _cacheFaceEntities[uint.Parse(emoji.QSid)] = emoji);

_cacheSuperFaceId.AddRange(emojiPacks
.SelectMany(emojiPack => emojiPack.GetUniqueSuperQSids(new[] { (1, 1) })));
}

public async Task<bool> GetCachedIsSuperFaceId(uint id)
{
if (!_cacheSuperFaceId.Any()) await ResolveEmojiCache();
return _cacheSuperFaceId.Contains(id);
}

public async Task<SysFaceEntry?> GetCachedFaceEntity(uint faceId)
{
if (!_cacheFaceEntities.ContainsKey(faceId)) await ResolveEmojiCache();
return _cacheFaceEntities.GetValueOrDefault(faceId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using Lagrange.Core.Message;
using Lagrange.Core.Message.Entity;
using Lagrange.Core.Message.Filter;
using Lagrange.Core.Utility.Extension;
using FriendPokeEvent = Lagrange.Core.Event.EventArg.FriendPokeEvent;
using GroupPokeEvent = Lagrange.Core.Event.EventArg.GroupPokeEvent;

Expand Down Expand Up @@ -382,6 +383,13 @@ private async Task ResolveOutgoingChain(MessageChain chain)
{
switch (entity)
{
case FaceEntity face:
{
var cache = Collection.Business.CachingLogic;
face.SysFaceEntry ??= await cache.GetCachedFaceEntity(face.FaceId);
break;
}

case ForwardEntity forward when forward.TargetUin != 0:
{
var cache = Collection.Business.CachingLogic;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -697,4 +697,24 @@ public async Task<bool> GroupSetAvatar(uint groupUin, ImageEntity avatar)
var ret = (FetchGroupAtAllRemainEvent)results[0];
return (ret.RemainAtAllCountForUin, ret.RemainAtAllCountForGroup);
}

public async Task<bool> FetchSuperFaceId(uint id) => await Collection.Business.CachingLogic.GetCachedIsSuperFaceId(id);

public async Task<SysFaceEntry?> FetchFaceEntity(uint id) => await Collection.Business.CachingLogic.GetCachedFaceEntity(id);

public async Task<bool> GroupJoinEmojiChain(uint groupUin, uint emojiId, uint targetMessageSeq)
{
var groupJoinEmojiChainEvent = GroupJoinEmojiChainEvent.Create(targetMessageSeq, emojiId, groupUin);
var results = await Collection.Business.SendEvent(groupJoinEmojiChainEvent);
return results.Count != 0 && results[0].ResultCode == 0;
}

public async Task<bool> FriendJoinEmojiChain(uint friendUin, uint emojiId, uint targetMessageSeq)
{
string? friendUid = await Collection.Business.CachingLogic.ResolveUid(null, friendUin);
if (friendUid == null) return false;
var friendJoinEmojiChainEvent = FriendJoinEmojiChainEvent.Create(targetMessageSeq, emojiId, friendUid);
var results = await Collection.Business.SendEvent(friendJoinEmojiChainEvent);
return results.Count != 0 && results[0].ResultCode == 0;
}
}
14 changes: 14 additions & 0 deletions Lagrange.Core/Internal/Event/Action/FriendJoinEmojiChainEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
namespace Lagrange.Core.Internal.Event.Action;

internal class FriendJoinEmojiChainEvent : JoinEmojiChainEvent
{
private FriendJoinEmojiChainEvent(uint targetMessageSeq, uint targetFaceId, string friendUid) : base(targetMessageSeq, targetFaceId)
{
FriendUid = friendUid;
}

private FriendJoinEmojiChainEvent(int resultCode) : base(resultCode) { }

public static FriendJoinEmojiChainEvent Create(uint targetMessageSeq, uint targetFaceId, string friendUid)
=> new(targetMessageSeq, targetFaceId, friendUid);
}
14 changes: 14 additions & 0 deletions Lagrange.Core/Internal/Event/Action/GroupJoinEmojiChainEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
namespace Lagrange.Core.Internal.Event.Action;

internal class GroupJoinEmojiChainEvent : JoinEmojiChainEvent
{
private GroupJoinEmojiChainEvent(uint targetMessageSeq, uint targetFaceId, uint groupUin) : base(targetMessageSeq, targetFaceId)
{
GroupUin = groupUin;
}

private GroupJoinEmojiChainEvent(int resultCode) : base(resultCode) { }

public static GroupJoinEmojiChainEvent Create(uint targetMessageSeq, uint targetFaceId, uint groupUin)
=> new(targetMessageSeq, targetFaceId, groupUin);
}
22 changes: 22 additions & 0 deletions Lagrange.Core/Internal/Event/Action/JoinEmojiChainEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
namespace Lagrange.Core.Internal.Event.Action;

internal class JoinEmojiChainEvent : ProtocolEvent
{
public uint TargetMessageSeq { get; set; }

public uint TargetFaceId { get; set; }

public uint? GroupUin { get; set; }

public string? FriendUid { get; set; }

protected JoinEmojiChainEvent(uint targetMessageSeq, uint targetFaceId) : base(true)
{
TargetMessageSeq = targetMessageSeq;
TargetFaceId = targetFaceId;
}

protected JoinEmojiChainEvent(int resultCode) : base(resultCode) { }

public static JoinEmojiChainEvent Result(int resultCode) => new(resultCode);
}
22 changes: 22 additions & 0 deletions Lagrange.Core/Internal/Event/System/FetchFullSysFacesEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using Lagrange.Core.Common.Entity;

namespace Lagrange.Core.Internal.Event.System;

internal class FetchFullSysFacesEvent : ProtocolEvent
{
public List<SysFacePackEntry> FacePacks { get; set; }

private FetchFullSysFacesEvent(List<SysFacePackEntry> facePacks) : base(true)
{
FacePacks = facePacks;
}

private FetchFullSysFacesEvent(int resultCode, List<SysFacePackEntry> facePacks) : base(resultCode)
{
FacePacks = facePacks;
}

public static FetchFullSysFacesEvent Create() => new(new List<SysFacePackEntry>());

public static FetchFullSysFacesEvent Result(int resultCode, List<SysFacePackEntry> emojiPacks) => new(resultCode, emojiPacks);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@ namespace Lagrange.Core.Internal.Packets.Message.Element.Implementation.Extra;
/// Constructed at <see cref="CommonElem"/>, Service Type 33, Big face
/// </summary>
[ProtoContract]
internal class QFaceExtra
internal class QBigFaceExtra
{
[ProtoMember(1)] public string? Field1 { get; set; }
[ProtoMember(1)] public string? AniStickerPackId { get; set; }

[ProtoMember(2)] public string? Field2 { get; set; }
[ProtoMember(2)] public string? AniStickerId { get; set; }

[ProtoMember(3)] public int? FaceId { get; set; } // 318

[ProtoMember(4)] public int? Field4 { get; set; }

[ProtoMember(5)] public int? Field5 { get; set; }
[ProtoMember(5)] public int? AniStickerType { get; set; }

[ProtoMember(6)] public string? Field6 { get; set; }

Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
using ProtoBuf;


#pragma warning disable CS8618
namespace Lagrange.Core.Internal.Packets.Message.Element.Implementation.Extra;

/// <summary>
/// Constructed at <see cref="CommonElem"/>, Service Type 33, Small face (FaceId >= 260)
/// </summary>
[ProtoContract]
internal class QSmallFaceExtra
{
[ProtoMember(1)] public uint FaceId { get; set; }
[ProtoMember(2)] public string Preview { get; set; }
[ProtoMember(3)] public string Preview2 { get; set; }

[ProtoMember(2)] public string? Text { get; set; }

[ProtoMember(3)] public string? CompatText { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using ProtoBuf;

#pragma warning disable CS8618
// ReSharper disable InconsistentNaming

namespace Lagrange.Core.Internal.Packets.Service.Oidb.Request;

[ProtoContract]
[OidbSvcTrpcTcp(0x90EE, 1)]
internal class OidbSvcTrpcTcp0x90EE_1
{
[ProtoMember(1)] public uint FaceId { get; set; }

[ProtoMember(2)] public uint TargetMsgSeq { get; set; }

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

[ProtoMember(4)] public int Field4 { get; set; } // group 2 friend 1 ?

[ProtoMember(5)] public uint? TargetGroupId { get; set; }

[ProtoMember(6)] public string? TargetUid { get; set; }

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using ProtoBuf;

#pragma warning disable CS8618
// ReSharper disable InconsistentNaming

namespace Lagrange.Core.Internal.Packets.Service.Oidb.Request;

[ProtoContract]
[OidbSvcTrpcTcp(0x9154, 1)]
internal class OidbSvcTrpcTcp0x9154_1
{
[ProtoMember(1)] public int Field1 { get; set; } // 0

[ProtoMember(2)] public int Field2 { get; set; } // 7

[ProtoMember(3)] public string Field3 { get; set; } // 0
}
Loading

0 comments on commit 3580687

Please sign in to comment.