Skip to content

Commit

Permalink
[Core] Add bounce face (Recvive not available)
Browse files Browse the repository at this point in the history
  • Loading branch information
dogdie233 committed Jan 8, 2025
1 parent 07a5d28 commit ce15e6d
Show file tree
Hide file tree
Showing 4 changed files with 182 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,24 @@ private async Task ResolveOutgoingChain(MessageChain chain)
face.SysFaceEntry ??= await cache.GetCachedFaceEntity(face.FaceId);
break;
}
case BounceFaceEntity bounceFace:
{
var cache = Collection.Business.CachingLogic;

// ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
if (bounceFace.Name != null)
break;

string name = (await cache.GetCachedFaceEntity(bounceFace.FaceId))?.QDes ?? string.Empty;

// Because the name is used as a preview text, it should not start with '/'
// But the QDes of the face may start with '/', so remove it
if (name.StartsWith('/'))
name = name[1..];

bounceFace.Name = name;
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
@@ -0,0 +1,23 @@
#pragma warning disable CS8618

using ProtoBuf;

namespace Lagrange.Core.Internal.Packets.Message.Element.Implementation.Extra;

[ProtoContract]
internal class QBounceFaceExtra
{
[ProtoMember(1)] public int Field1 { get; set; } = 13;

[ProtoMember(2)] public uint Count { get; set; } = 1;

[ProtoMember(3)] public string Name { get; set; } = string.Empty;

[ProtoMember(6)] public QSmallFaceExtra Face { get; set; }

[ProtoContract]
public class FallbackPreviewTextPb
{
[ProtoMember(1)] public string Text { get; set; } = string.Empty;
}
}
112 changes: 112 additions & 0 deletions Lagrange.Core/Message/Entity/BounceFaceEntity.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
using System.Text;
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;

[MessageElement(typeof(CommonElem))]
public class BounceFaceEntity : IMessageEntity
{
public uint FaceId { get; set; }

public uint Count { get; set; }

public string Name { get; set; }

public bool ShouldAddPreviewText { get; set; }

public BounceFaceEntity() : this(0, 0, string.Empty) {}

public BounceFaceEntity(SysFaceEntry face, uint count, bool shouldAddPreviewText = true)
{
if (!face.AniStickerId.HasValue)
throw new ArgumentException("Face does not have a sticker ID", nameof(face));

FaceId = (uint)face.AniStickerId.Value;
Count = count;
Name = face.QDes ?? string.Empty;
ShouldAddPreviewText = shouldAddPreviewText;

// Because the name is used as a preview text, it should not start with '/'
// But the QDes of the face may start with '/', so remove it
if (Name.StartsWith('/'))
Name = Name[1..];
}

public BounceFaceEntity(uint faceId, uint count, string? name = null, bool shouldAddPreviewText = true)
{
FaceId = faceId;
Count = count;

// If the name is null, it will be assigned in MessagingLogic.ResolveOutgoingChain
Name = name!;
ShouldAddPreviewText = shouldAddPreviewText;
}

IEnumerable<Elem> IMessageEntity.PackElement()
{
byte[] pbElem;
using (var ms = new MemoryStream())
{
Serializer.Serialize(ms, new QBounceFaceExtra
{
Field1 = 13,
Face = new QSmallFaceExtra
{
FaceId = FaceId,
Text = Name,
CompatText = Name
},
Count = Count,
Name = Name
});
pbElem = ms.ToArray();
}

var common = new CommonElem
{
ServiceType = 23,
PbElem = pbElem,
BusinessType = 13
};

if (!ShouldAddPreviewText)
return new Elem[] { new() { CommonElem = common } };

byte[] textFallbackPb;
using (var ms = new MemoryStream())
{
Serializer.Serialize(ms, new QBounceFaceExtra.FallbackPreviewTextPb { Text = $"[{Name}]请使用最新版手机QQ体验新功能。" });
textFallbackPb = ms.ToArray();
}
return new Elem[]
{
new() { CommonElem = common },
new()
{
Text = new Text
{
Str = ToPreviewText(),
PbReserve = textFallbackPb
}
}
};
}

IMessageEntity? IMessageEntity.UnpackElement(Elem elem)
{
if (elem.CommonElem is not { ServiceType: 23 } common)
return null;

var extra = Serializer.Deserialize<QBounceFaceExtra>(common.PbElem.AsSpan());
return new BounceFaceEntity(extra.Face.FaceId, extra.Count, extra.Name);
}

public string ToPreviewString() => "$[BounceFace | Name: {Name}({FaceId}) | Count: {Count}]";

public string ToPreviewText() => $"[{Name}]x{Count}";
}
29 changes: 29 additions & 0 deletions Lagrange.Core/Message/MessageBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,35 @@ public MessageBuilder SpecialPoke(SpecialPokeFaceType type, uint count = 1)
return this;
}

/// <summary>
/// Add a bounce face entity to message chain
/// </summary>
/// <param name="face">The face entry of the face to be added to the message chain</param>
/// <param name="count">The number of face entities to generate</param>
/// <param name="shouldAddPreviewText">Should the entity add a preview text</param>
public MessageBuilder BounceFace(SysFaceEntry face, uint count, bool shouldAddPreviewText = true)
{
var bounceFaceEntity = new BounceFaceEntity(face, count, shouldAddPreviewText);
_chain.Add(bounceFaceEntity);

return this;
}

/// <summary>
/// Add a bounce face entity to message chain
/// </summary>
/// <param name="faceId">The face ID of the face to be added to the message chain</param>
/// <param name="count">The number of face entities to generate, default is 1</param>
/// <param name="name">The name of the face</param>
/// <param name="shouldAddPreviewText">Should the entity add a preview text</param>
public MessageBuilder BounceFace(uint faceId, uint count, string? name = null, bool shouldAddPreviewText = true)
{
var bounceFaceEntity = new BounceFaceEntity(faceId, count, name, shouldAddPreviewText);
_chain.Add(bounceFaceEntity);

return this;
}

/// <summary>
/// Add a dedicated LightApp entity to message chain
/// </summary>
Expand Down

0 comments on commit ce15e6d

Please sign in to comment.