Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[All] Fix the issue of sending super emoticons and some other normal emoticons #618

Merged
merged 11 commits into from
Oct 22, 2024
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,13 +38,17 @@ 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)
{
return e switch
{
GroupSysDecreaseEvent groupSysDecreaseEvent when groupSysDecreaseEvent.MemberUid != Collection.Keystore.Uid => CacheUid(groupSysDecreaseEvent.GroupUin, true),
GroupSysDecreaseEvent groupSysDecreaseEvent when groupSysDecreaseEvent.MemberUid != Collection.Keystore.Uid
=> CacheUid(groupSysDecreaseEvent.GroupUin, true),
GroupSysIncreaseEvent groupSysIncreaseEvent => CacheUid(groupSysIncreaseEvent.GroupUin, true),
GroupSysAdminEvent groupSysAdminEvent => CacheUid(groupSysAdminEvent.GroupUin, true),
_ => Task.CompletedTask,
Expand Down Expand Up @@ -92,6 +99,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 +150,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 +199,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 @@ -212,6 +212,7 @@ public async Task<List<IBotFSEntry>> FetchGroupFSList(uint groupUin, string targ
if (((GroupFSListEvent)events[0]).IsEnd) break;
startIndex += 20;
}

return entries;
}

Expand All @@ -222,7 +223,8 @@ public async Task<string> FetchGroupFSDownload(uint groupUin, string fileId)
return $"{((GroupFSDownloadEvent)events[0]).FileUrl}{fileId}";
}

public async Task<(int, string)> GroupFSMove(uint groupUin, string fileId, string parentDirectory, string targetDirectory)
public async Task<(int, string)> GroupFSMove(uint groupUin, string fileId, string parentDirectory,
string targetDirectory)
pk5ls20 marked this conversation as resolved.
Show resolved Hide resolved
{
var groupFSMoveEvent = GroupFSMoveEvent.Create(groupUin, fileId, parentDirectory, targetDirectory);
var events = await Collection.Business.SendEvent(groupFSMoveEvent);
Expand Down Expand Up @@ -271,7 +273,8 @@ public Task<bool> GroupFSUpload(uint groupUin, FileEntity fileEntity, string tar
{
try
{
return FileUploader.UploadGroup(Collection, MessageBuilder.Group(groupUin).Build(), fileEntity, targetDirectory);
return FileUploader.UploadGroup(Collection, MessageBuilder.Group(groupUin).Build(), fileEntity,
targetDirectory);
}
catch
{
Expand Down Expand Up @@ -324,7 +327,8 @@ public async Task<bool> RecallFriendMessage(uint friendUin, MessageResult result
if (result.Sequence == null) return false;
if (await Collection.Business.CachingLogic.ResolveUid(null, friendUin) is not { } uid) return false;

var recallMessageEvent = RecallFriendMessageEvent.Create(uid, result.ClientSequence, result.Sequence ?? 0, (uint)(result.MessageId & uint.MaxValue), result.Timestamp);
var recallMessageEvent = RecallFriendMessageEvent.Create(uid, result.ClientSequence, result.Sequence ?? 0,
(uint)(result.MessageId & uint.MaxValue), result.Timestamp);
var events = await Collection.Business.SendEvent(recallMessageEvent);
return events.Count != 0 && ((RecallFriendMessageEvent)events[0]).ResultCode == 0;
}
Expand All @@ -334,7 +338,8 @@ public async Task<bool> RecallFriendMessage(MessageChain chain)
if (await Collection.Business.CachingLogic.ResolveUid(null, chain.TargetUin) is not { } uid) return false;

uint timestamp = (uint)new DateTimeOffset(chain.Time).ToUnixTimeSeconds();
var recallMessageEvent = RecallFriendMessageEvent.Create(uid, chain.ClientSequence, chain.Sequence, (uint)(chain.MessageId & uint.MaxValue), timestamp);
var recallMessageEvent = RecallFriendMessageEvent.Create(uid, chain.ClientSequence, chain.Sequence,
(uint)(chain.MessageId & uint.MaxValue), timestamp);
var events = await Collection.Business.SendEvent(recallMessageEvent);
return events.Count != 0 && ((RecallFriendMessageEvent)events[0]).ResultCode == 0;
}
Expand All @@ -350,7 +355,8 @@ public async Task<bool> RecallFriendMessage(MessageChain chain)

foreach (var result in resolved)
{
var uins = await Task.WhenAll(ResolveUid(result.InvitorMemberUid), ResolveUid(result.TargetMemberUid), ResolveUid(result.OperatorUid));
var uins = await Task.WhenAll(ResolveUid(result.InvitorMemberUid), ResolveUid(result.TargetMemberUid),
ResolveUid(result.OperatorUid));
uint invitorUin = uins[0];
uint targetUin = uins[1];
uint operatorUin = uins[2];
Expand Down Expand Up @@ -487,7 +493,8 @@ public async Task<bool> SetGroupRequest(uint groupUin, ulong sequence, uint type
return results.Count != 0 && results[0].ResultCode == 0;
}

public async Task<bool> SetGroupFilteredRequest(uint groupUin, ulong sequence, uint type, bool accept, string reason)
public async Task<bool> SetGroupFilteredRequest(uint groupUin, ulong sequence, uint type, bool accept,
string reason)
{
var inviteEvent = SetGroupFilteredRequestEvent.Create(accept, groupUin, sequence, type, reason);
var results = await Collection.Business.SendEvent(inviteEvent);
Expand Down Expand Up @@ -664,7 +671,8 @@ public async Task<bool> SetAvatar(ImageEntity avatar)

var ticket = ((HighwayUrlEvent)highwayUrlResults[0]).SigSession;
var md5 = avatar.ImageStream.Value.Md5().UnHex();
return await Collection.Highway.UploadSrcByStreamAsync(90, avatar.ImageStream.Value, ticket, md5, Array.Empty<byte>());
return await Collection.Highway.UploadSrcByStreamAsync(90, avatar.ImageStream.Value, ticket, md5,
Array.Empty<byte>());
}

public async Task<bool> GroupSetAvatar(uint groupUin, ImageEntity avatar)
Expand Down Expand Up @@ -697,4 +705,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
Loading