llonebot-dist 7.8.4 → 7.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/llbot.js CHANGED
@@ -4083,7 +4083,7 @@ var Msg;
4083
4083
  }),
4084
4084
  msgContent: ProtoField(2, "bytes"),
4085
4085
  msgEncryptContent: ProtoField(3, "bytes")
4086
- })
4086
+ }, "optional")
4087
4087
  });
4088
4088
  Msg2.PbMultiMsgItem = ProtoMessage.of({
4089
4089
  fileName: ProtoField(1, "string"),
@@ -7207,7 +7207,7 @@ class WebUITokenUtil {
7207
7207
  }
7208
7208
  const webuiTokenUtil = new WebUITokenUtil(path__default.join(DATA_DIR, "webui_token.txt"));
7209
7209
  const logFileName = `llbot-${(/* @__PURE__ */ new Date()).toLocaleString("zh-CN")}.log`.replace(/\//g, "-").replace(/:/g, "-");
7210
- const version$3 = "7.8.4";
7210
+ const version$3 = "7.9.0";
7211
7211
  var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
7212
7212
  function getDefaultExportFromCjs(x) {
7213
7213
  return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
@@ -30205,7 +30205,7 @@ let GetGroupInfo$1 = class GetGroupInfo extends BaseAction {
30205
30205
  remark_name: groupDetail.remarkName,
30206
30206
  avatar_url: `https://p.qlogo.cn/gh/${groupDetail.groupCode}/${groupDetail.groupCode}/0`,
30207
30207
  // 以下是非 OneBot 11 标准字段
30208
- owner_id: +groupDetail.ownerUin,
30208
+ owner_id: +groupDetail.ownerUin || +await this.ctx.ntUserApi.getUinByUid(groupDetail.ownerUid),
30209
30209
  // 群主 QQ 号
30210
30210
  is_top: groupDetail.isTop,
30211
30211
  // 是否置顶群聊
@@ -33788,7 +33788,10 @@ class OneBot11Adapter extends Service2 {
33788
33788
  });
33789
33789
  this.ctx.on("nt/system-message-created", async (input) => {
33790
33790
  const sysMsg = Msg.Message.decode(input);
33791
- const { msgType, subType } = sysMsg.contentHead ?? {};
33791
+ if (!sysMsg.body) {
33792
+ return;
33793
+ }
33794
+ const { msgType, subType } = sysMsg.contentHead;
33792
33795
  if (msgType === 528 && subType === 39) {
33793
33796
  const tip = Notify.ProfileLike.decode(sysMsg.body.msgContent);
33794
33797
  if (tip.msgType !== 0 || tip.subType !== 203) return;
@@ -33961,7 +33964,7 @@ class OneBot11Adapter extends Service2 {
33961
33964
  if (!pushMsg.message.body) {
33962
33965
  return null;
33963
33966
  }
33964
- const { msgType, subType } = pushMsg.message?.contentHead ?? {};
33967
+ const { msgType, subType } = pushMsg.message.contentHead;
33965
33968
  if (msgType === 732 && subType === 16) {
33966
33969
  const notify = Msg.NotifyMessageBody.decode(pushMsg.message.body.msgContent.subarray(7));
33967
33970
  if (notify.field13 === 35) {
@@ -35714,6 +35717,64 @@ async function parseFriendRequest(bot, input) {
35714
35717
  }
35715
35718
  });
35716
35719
  }
35720
+ async function parseReactionAdded(bot, input, time2) {
35721
+ const { info, target } = input.reaction.data.body;
35722
+ const peer = {
35723
+ chatType: ChatType.Group,
35724
+ peerUid: input.groupCode.toString(),
35725
+ guildId: ""
35726
+ };
35727
+ const targetMsg = await bot.ctx.ntMsgApi.getMsgsBySeqAndCount(peer, target.sequence.toString(), 1, true, true);
35728
+ if (targetMsg.msgList.length === 0) {
35729
+ bot.ctx.logger.error("解析群表情回应失败:未找到消息");
35730
+ return;
35731
+ }
35732
+ const user = await bot.ctx.ntUserApi.getUserSimpleInfo(info.operatorUid);
35733
+ const groupAll = await bot.ctx.ntGroupApi.getGroupAllInfo(input.groupCode.toString());
35734
+ return bot.event("reaction-added", {
35735
+ message: {
35736
+ id: targetMsg.msgList[0].msgId,
35737
+ content: info.code,
35738
+ timestamp: time2 * 1e3
35739
+ },
35740
+ user: decodeUser(user.coreInfo),
35741
+ channel: {
35742
+ id: groupAll.groupCode,
35743
+ name: groupAll.groupName,
35744
+ type: Channel.Type.TEXT
35745
+ },
35746
+ guild: decodeGuild(groupAll)
35747
+ });
35748
+ }
35749
+ async function parseReactionRemoved(bot, input, time2) {
35750
+ const { info, target } = input.reaction.data.body;
35751
+ const peer = {
35752
+ chatType: ChatType.Group,
35753
+ peerUid: input.groupCode.toString(),
35754
+ guildId: ""
35755
+ };
35756
+ const targetMsg = await bot.ctx.ntMsgApi.getMsgsBySeqAndCount(peer, target.sequence.toString(), 1, true, true);
35757
+ if (targetMsg.msgList.length === 0) {
35758
+ bot.ctx.logger.error("解析群表情回应失败:未找到消息");
35759
+ return;
35760
+ }
35761
+ const user = await bot.ctx.ntUserApi.getUserSimpleInfo(info.operatorUid);
35762
+ const groupAll = await bot.ctx.ntGroupApi.getGroupAllInfo(input.groupCode.toString());
35763
+ return bot.event("reaction-removed", {
35764
+ message: {
35765
+ id: targetMsg.msgList[0].msgId,
35766
+ content: info.code,
35767
+ timestamp: time2 * 1e3
35768
+ },
35769
+ user: decodeUser(user.coreInfo),
35770
+ channel: {
35771
+ id: groupAll.groupCode,
35772
+ name: groupAll.groupName,
35773
+ type: Channel.Type.TEXT
35774
+ },
35775
+ guild: decodeGuild(groupAll)
35776
+ });
35777
+ }
35717
35778
  class SatoriAdapter extends Service2 {
35718
35779
  constructor(ctx, config2) {
35719
35780
  super(ctx, "satori", true);
@@ -35732,7 +35793,8 @@ class SatoriAdapter extends Service2 {
35732
35793
  "ntGroupApi",
35733
35794
  "ntUserApi",
35734
35795
  "ntWebApi",
35735
- "store"
35796
+ "store",
35797
+ "app"
35736
35798
  ];
35737
35799
  selfId;
35738
35800
  server;
@@ -35817,6 +35879,31 @@ class SatoriAdapter extends Service2 {
35817
35879
  this.server.dispatch(event);
35818
35880
  }
35819
35881
  });
35882
+ this.ctx.app.pmhq.addResListener(async (data) => {
35883
+ if (data.type === "recv" && data.data.cmd === "trpc.msg.olpush.OlPushService.MsgPush") {
35884
+ const pushMsg = Msg.PushMsg.decode(Buffer.from(data.data.pb, "hex"));
35885
+ if (!pushMsg.message.body) {
35886
+ return;
35887
+ }
35888
+ const { msgTime, msgType, subType } = pushMsg.message.contentHead;
35889
+ if (msgType === 732 && subType === 16) {
35890
+ const notify = Msg.NotifyMessageBody.decode(pushMsg.message.body.msgContent.subarray(7));
35891
+ if (notify.field13 === 35) {
35892
+ if (notify.reaction.data.body.info.type === 1) {
35893
+ const event = await parseReactionAdded(this, notify, msgTime).catch((e) => this.ctx.logger.error(e));
35894
+ if (event) {
35895
+ this.server.dispatch(event);
35896
+ }
35897
+ } else {
35898
+ const event = await parseReactionRemoved(this, notify, msgTime).catch((e) => this.ctx.logger.error(e));
35899
+ if (event) {
35900
+ this.server.dispatch(event);
35901
+ }
35902
+ }
35903
+ }
35904
+ }
35905
+ }
35906
+ });
35820
35907
  }
35821
35908
  event(type2, data) {
35822
35909
  const sn = ++this._eventSeq;
@@ -49535,7 +49622,7 @@ class MilkyHttpHandler {
49535
49622
  this.app.use(express.json({ limit: "1024mb" }));
49536
49623
  if (this.config.accessToken) {
49537
49624
  this.app.use(`${this.config.prefix}/api`, (req, res, next) => {
49538
- if (req.headers["content-type"] !== "application/json") {
49625
+ if (!req.headers["content-type"]?.includes("application/json")) {
49539
49626
  this.ctx.logger.warn(
49540
49627
  "MilkyHttp",
49541
49628
  `${req.ip} -> ${req.path} (Content-Type not application/json)`
@@ -49953,7 +50040,10 @@ const IncomingSegment = discriminatedUnion("type", [
49953
50040
  }).describe("文本消息段"),
49954
50041
  object({
49955
50042
  type: literal("mention"),
49956
- data: object({ user_id: ZUin.describe("提及的 QQ 号") })
50043
+ data: object({
50044
+ user_id: ZUin.describe("提及的 QQ 号"),
50045
+ name: ZString.describe("去掉 `@` 前缀的提及的名称")
50046
+ })
49957
50047
  }).describe("提及消息段"),
49958
50048
  object({
49959
50049
  type: literal("mention_all"),
@@ -49968,7 +50058,15 @@ const IncomingSegment = discriminatedUnion("type", [
49968
50058
  }).describe("表情消息段"),
49969
50059
  object({
49970
50060
  type: literal("reply"),
49971
- data: object({ message_seq: ZInt64.describe("被引用的消息序列号") })
50061
+ data: object({
50062
+ message_seq: ZInt64.describe("被引用的消息序列号"),
50063
+ sender_id: ZUin.describe("被引用的消息发送者 QQ 号"),
50064
+ sender_name: ZString.nullish().describe("被引用的消息发送者名称,仅在合并转发中能够获取"),
50065
+ time: ZInt64.describe("被引用的消息的 Unix 时间戳(秒)"),
50066
+ get segments() {
50067
+ return array(lazy(() => IncomingSegment)).describe("被引用的消息内容");
50068
+ }
50069
+ })
49972
50070
  }).describe("回复消息段"),
49973
50071
  object({
49974
50072
  type: literal("image"),
@@ -50033,8 +50131,12 @@ const IncomingSegment = discriminatedUnion("type", [
50033
50131
  xml_payload: ZString.describe("XML 数据")
50034
50132
  })
50035
50133
  }).describe("XML 消息段")
50036
- ]).describe("接收消息段");
50134
+ ]).catch({
50135
+ type: "text",
50136
+ data: { text: "[unknown]" }
50137
+ }).describe("接收消息段");
50037
50138
  const IncomingForwardedMessage = object({
50139
+ message_seq: ZInt64.describe("消息序列号"),
50038
50140
  sender_name: ZString.describe("发送者名称"),
50039
50141
  avatar_url: ZString.describe("发送者头像 URL"),
50040
50142
  time: ZInt64.describe("消息 Unix 时间戳(秒)"),
@@ -50081,10 +50183,20 @@ const OutgoingSegment = discriminatedUnion("type", [
50081
50183
  }).describe("视频消息段"),
50082
50184
  object({
50083
50185
  type: literal("forward"),
50084
- data: object({ get messages() {
50085
- return array(lazy(() => OutgoingForwardedMessage)).describe("合并转发消息段");
50086
- } })
50087
- }).describe("合并转发消息段")
50186
+ data: object({
50187
+ get messages() {
50188
+ return array(lazy(() => OutgoingForwardedMessage)).describe("合并转发消息内容");
50189
+ },
50190
+ title: ZString.nullish().describe("合并转发标题"),
50191
+ preview: array(ZString).min(1).max(4).nullish().describe("合并转发预览文本,若提供,至少 1 条,至多 4 条"),
50192
+ summary: ZString.nullish().describe("合并转发摘要"),
50193
+ prompt: ZString.nullish().describe("合并转发的预览外显文本,仅对移动端 QQ 有效")
50194
+ })
50195
+ }).describe("合并转发消息段"),
50196
+ object({
50197
+ type: literal("light_app"),
50198
+ data: object({ json_payload: ZString.describe("小程序 JSON 数据") })
50199
+ }).describe("小程序消息段")
50088
50200
  ]).describe("发送消息段");
50089
50201
  const OutgoingForwardedMessage = object({
50090
50202
  user_id: ZUin.describe("发送者 QQ 号"),
@@ -50145,6 +50257,15 @@ const MessageRecallEvent = object({
50145
50257
  operator_id: ZUin.describe("操作者 QQ 号"),
50146
50258
  display_suffix: ZString.describe("撤回提示的后缀文本")
50147
50259
  });
50260
+ const PeerPinChangeEvent = object({
50261
+ message_scene: _enum([
50262
+ "friend",
50263
+ "group",
50264
+ "temp"
50265
+ ]).describe("发生改变的会话的消息场景"),
50266
+ peer_id: ZUin.describe("发生改变的好友 QQ 号或群号"),
50267
+ is_pinned: ZBoolean.describe("是否被置顶, `false` 表示取消置顶")
50268
+ });
50148
50269
  const FriendRequestEvent = object({
50149
50270
  initiator_id: ZUin.describe("申请好友的用户 QQ 号"),
50150
50271
  initiator_uid: ZString.describe("用户 UID"),
@@ -50265,6 +50386,12 @@ discriminatedUnion("event_type", [
50265
50386
  self_id: ZUin.describe("机器人 QQ 号"),
50266
50387
  data: MessageRecallEvent
50267
50388
  }).describe("消息撤回事件"),
50389
+ object({
50390
+ event_type: literal("peer_pin_change"),
50391
+ time: ZInt64.describe("事件 Unix 时间戳(秒)"),
50392
+ self_id: ZUin.describe("机器人 QQ 号"),
50393
+ data: PeerPinChangeEvent
50394
+ }).describe("会话置顶变更事件"),
50268
50395
  object({
50269
50396
  event_type: literal("friend_request"),
50270
50397
  time: ZInt64.describe("事件 Unix 时间戳(秒)"),
@@ -50362,7 +50489,7 @@ discriminatedUnion("event_type", [
50362
50489
  data: GroupFileUploadEvent
50363
50490
  }).describe("群文件上传事件")
50364
50491
  ]).describe("事件");
50365
- var version$1 = "1.1.0";
50492
+ var version$1 = "1.2.0-rc.1";
50366
50493
  const milkyPackageVersion = version$1;
50367
50494
  const milkyVersion = milkyPackageVersion.split(".").slice(0, 2).join(".");
50368
50495
  const CachedApiBase = object({ no_cache: ZBooleanWithDefault(false).describe("是否强制不使用缓存") });
@@ -50419,6 +50546,19 @@ const GetGroupMemberInfoInput = object({
50419
50546
  user_id: ZUin.describe("群成员 QQ 号")
50420
50547
  }).extend(CachedApiBase.shape);
50421
50548
  const GetGroupMemberInfoOutput = object({ member: lazy(() => GroupMemberEntity).describe("群成员信息") });
50549
+ const GetPeerPinsOutput = object({
50550
+ friends: array(lazy(() => FriendEntity)).describe("置顶的好友列表"),
50551
+ groups: array(lazy(() => GroupEntity)).describe("置顶的群列表")
50552
+ });
50553
+ const SetPeerPinInput = object({
50554
+ message_scene: _enum([
50555
+ "friend",
50556
+ "group",
50557
+ "temp"
50558
+ ]).describe("要设置的会话的消息场景"),
50559
+ peer_id: ZUin.describe("要设置的好友 QQ 号或群号"),
50560
+ is_pinned: ZBooleanWithDefault(true).describe("是否置顶, `false` 表示取消置顶")
50561
+ });
50422
50562
  const SetAvatarInput = object({ uri: ZString.describe("头像文件 URI,支持 `file://` `http(s)://` `base64://` 三种格式") });
50423
50563
  const SetNicknameInput = object({ new_nickname: ZString.describe("新昵称") });
50424
50564
  const SetBioInput = object({ new_bio: ZString.describe("新个性签名") });
@@ -50503,6 +50643,7 @@ const RejectFriendRequestInput = object({
50503
50643
  is_filtered: ZBooleanWithDefault(false).describe("是否是被过滤的请求"),
50504
50644
  reason: ZString.nullish().describe("拒绝理由")
50505
50645
  });
50646
+ const ZRobustArray = (element) => z.array(element.catch(null)).transform((val) => val.filter((item) => item !== null));
50506
50647
  const SetGroupNameInput = object({
50507
50648
  group_id: ZUin.describe("群号"),
50508
50649
  new_group_name: ZString.describe("新群名称")
@@ -50569,7 +50710,8 @@ const QuitGroupInput = object({ group_id: ZUin.describe("群号") });
50569
50710
  const SendGroupMessageReactionInput = object({
50570
50711
  group_id: ZUin.describe("群号"),
50571
50712
  message_seq: ZInt64.describe("要回应的消息序列号"),
50572
- reaction: ZString.describe("表情 ID"),
50713
+ reaction: ZString.describe("发送的回应的表情 ID"),
50714
+ reaction_type: _enum(["face", "emoji"]).default("face").describe("发送的回应类型"),
50573
50715
  is_add: ZBooleanWithDefault(true).describe("是否添加表情,`false` 表示取消")
50574
50716
  });
50575
50717
  const SendGroupNudgeInput = object({
@@ -50582,7 +50724,7 @@ const GetGroupNotificationsInput = object({
50582
50724
  limit: ZInt32WithDefault(20).describe("获取的最大通知数量")
50583
50725
  });
50584
50726
  const GetGroupNotificationsOutput = object({
50585
- notifications: array(lazy(() => GroupNotification)).describe("获取到的群通知(notification_seq 降序排列),序列号不一定连续"),
50727
+ notifications: ZRobustArray(GroupNotification).describe("获取到的群通知(notification_seq 降序排列),序列号不一定连续"),
50586
50728
  next_notification_seq: ZInt64.nullish().describe("下一页起始通知序列号")
50587
50729
  });
50588
50730
  const AcceptGroupRequestInput = object({
@@ -50729,7 +50871,7 @@ const GetImplInfo = defineApi(
50729
50871
  impl_version: version$3,
50730
50872
  qq_protocol_version: deviceInfo.buildVer,
50731
50873
  qq_protocol_type: transformProtocolOsType(deviceInfo.devType),
50732
- milky_version: "1.1"
50874
+ milky_version: "1.2"
50733
50875
  });
50734
50876
  }
50735
50877
  );
@@ -50766,10 +50908,14 @@ const GetFriendList2 = defineApi(
50766
50908
  GetFriendListOutput,
50767
50909
  async (ctx, payload) => {
50768
50910
  const friends = await ctx.ntFriendApi.getBuddyList();
50911
+ const category = /* @__PURE__ */ new Map();
50769
50912
  const friendList = [];
50770
50913
  for (const friend of friends) {
50771
- const category = await ctx.ntFriendApi.getCategoryById(friend.baseInfo.categoryId);
50772
- friendList.push(transformFriend(friend, category));
50914
+ const { categoryId } = friend.baseInfo;
50915
+ if (!category.has(categoryId)) {
50916
+ category.set(categoryId, await ctx.ntFriendApi.getCategoryById(categoryId));
50917
+ }
50918
+ friendList.push(transformFriend(friend, category.get(categoryId)));
50773
50919
  }
50774
50920
  return Ok({
50775
50921
  friends: friendList
@@ -50881,6 +51027,65 @@ const GetGroupMemberInfo2 = defineApi(
50881
51027
  });
50882
51028
  }
50883
51029
  );
51030
+ const GetPeerPins = defineApi(
51031
+ "get_peer_pins",
51032
+ z.object({}),
51033
+ GetPeerPinsOutput,
51034
+ async (ctx, payload) => {
51035
+ const friends = await ctx.ntFriendApi.getBuddyList();
51036
+ const category = /* @__PURE__ */ new Map();
51037
+ const groups = await ctx.ntGroupApi.getGroups();
51038
+ return Ok({
51039
+ friends: await Promise.all(
51040
+ friends.filter((e) => e.relationFlags?.topTime !== "0").map(async (e) => {
51041
+ const { categoryId } = e.baseInfo;
51042
+ if (!category.has(categoryId)) {
51043
+ category.set(categoryId, await ctx.ntFriendApi.getCategoryById(categoryId));
51044
+ }
51045
+ return transformFriend(e, category.get(categoryId));
51046
+ })
51047
+ ),
51048
+ groups: groups.filter((e) => e.isTop).map((e) => {
51049
+ return {
51050
+ group_id: +e.groupCode,
51051
+ group_name: e.groupName,
51052
+ member_count: e.memberCount,
51053
+ max_member_count: e.maxMember
51054
+ };
51055
+ })
51056
+ });
51057
+ }
51058
+ );
51059
+ const SetPeerPin = defineApi(
51060
+ "set_peer_pin",
51061
+ SetPeerPinInput,
51062
+ z.object({}),
51063
+ async (ctx, payload) => {
51064
+ if (payload.message_scene === "friend") {
51065
+ const uid = await ctx.ntUserApi.getUidByUin(payload.peer_id.toString());
51066
+ const result = await ctx.ntFriendApi.setTop(uid, payload.is_pinned);
51067
+ if (result.result !== 0) {
51068
+ return Failed(-500, result.errMsg);
51069
+ }
51070
+ } else if (payload.message_scene === "group") {
51071
+ const result = await ctx.ntGroupApi.setTop(payload.peer_id.toString(), payload.is_pinned);
51072
+ if (result.result !== 0) {
51073
+ return Failed(-500, result.errMsg);
51074
+ }
51075
+ } else if (payload.message_scene === "temp") {
51076
+ const uid = await ctx.ntUserApi.getUidByUin(payload.peer_id.toString());
51077
+ const result = await ctx.ntMsgApi.setContactLocalTop({
51078
+ chatType: ChatType.TempC2CFromGroup,
51079
+ peerUid: uid,
51080
+ guildId: ""
51081
+ }, payload.is_pinned);
51082
+ if (result.result !== 0) {
51083
+ return Failed(-500, result.errMsg);
51084
+ }
51085
+ }
51086
+ return Ok({});
51087
+ }
51088
+ );
50884
51089
  const SetAvatar = defineApi(
50885
51090
  "set_avatar",
50886
51091
  SetAvatarInput,
@@ -51008,6 +51213,8 @@ const SystemApi = [
51008
51213
  GetGroupInfo2,
51009
51214
  GetGroupMemberList2,
51010
51215
  GetGroupMemberInfo2,
51216
+ GetPeerPins,
51217
+ SetPeerPin,
51011
51218
  SetAvatar,
51012
51219
  SetNickname,
51013
51220
  SetBio,
@@ -51071,6 +51278,9 @@ async function transformOutgoingMessage(ctx, segments, peerUid, isGroup = false)
51071
51278
  const videoElement = await SendElement.video(ctx, tempPath, thumbTempPath);
51072
51279
  elements.push(videoElement);
51073
51280
  deleteAfterSentFiles.push(tempPath);
51281
+ } else if (segment.type === "light_app") {
51282
+ const arkElement = SendElement.ark(segment.data.json_payload);
51283
+ elements.push(arkElement);
51074
51284
  }
51075
51285
  } catch (error2) {
51076
51286
  ctx.logger.error("MilkyTransform", `Failed to transform segment ${segment.type}: ${error2}`);
@@ -51081,9 +51291,9 @@ async function transformOutgoingMessage(ctx, segments, peerUid, isGroup = false)
51081
51291
  deleteAfterSentFiles
51082
51292
  };
51083
51293
  }
51084
- async function transformOutgoingForwardMessages(ctx, messages, peer) {
51294
+ async function transformOutgoingForwardMessages(ctx, messages, peer, options) {
51085
51295
  const encoder = new ForwardMessageEncoder(ctx, peer);
51086
- return await encoder.generate(messages);
51296
+ return await encoder.generate(messages, options);
51087
51297
  }
51088
51298
  class ForwardMessageEncoder {
51089
51299
  constructor(ctx, peer) {
@@ -51289,7 +51499,12 @@ class ForwardMessageEncoder {
51289
51499
  unlink(tempPath).catch((e) => {
51290
51500
  });
51291
51501
  } else if (type2 === "forward") {
51292
- const innerRaw = await this.generate(data.messages);
51502
+ const innerRaw = await this.generate(data.messages, {
51503
+ title: data.title,
51504
+ preview: data.preview,
51505
+ summary: data.summary,
51506
+ prompt: data.prompt
51507
+ });
51293
51508
  this.innerRaws.push(innerRaw);
51294
51509
  const resid = await this.ctx.app.pmhq.uploadForward(this.peer, innerRaw.multiMsgItems);
51295
51510
  this.children.push(this.packForwardMessage(resid, innerRaw.uuid, innerRaw));
@@ -51327,7 +51542,7 @@ class ForwardMessageEncoder {
51327
51542
  await this.visit(item);
51328
51543
  }
51329
51544
  }
51330
- async generate(content) {
51545
+ async generate(content, options) {
51331
51546
  await this.render(content);
51332
51547
  const msg = this.results;
51333
51548
  const tsum = this.tsum;
@@ -51353,10 +51568,10 @@ class ForwardMessageEncoder {
51353
51568
  return {
51354
51569
  multiMsgItems,
51355
51570
  tsum,
51356
- source: this.isGroup ? "群聊的聊天记录" : "聊天记录",
51357
- summary: `查看${tsum}条转发消息`,
51358
- news,
51359
- prompt: "[聊天记录]",
51571
+ source: options?.title ?? (this.isGroup ? "群聊的聊天记录" : "聊天记录"),
51572
+ summary: options?.summary ?? `查看${tsum}条转发消息`,
51573
+ news: options?.preview?.map((e) => ({ text: e })) ?? news,
51574
+ prompt: options?.prompt ?? "[聊天记录]",
51360
51575
  uuid: crypto.randomUUID()
51361
51576
  };
51362
51577
  }
@@ -52923,7 +53138,8 @@ async function transformIncomingSegments(ctx, message) {
52923
53138
  segments.push({
52924
53139
  type: "mention",
52925
53140
  data: {
52926
- user_id: +element.textElement.atUid
53141
+ user_id: +element.textElement.atUid,
53142
+ name: element.textElement.content.slice(1)
52927
53143
  }
52928
53144
  });
52929
53145
  } else if (element.textElement?.content) {
@@ -52948,7 +53164,10 @@ async function transformIncomingSegments(ctx, message) {
52948
53164
  segments.push({
52949
53165
  type: "reply",
52950
53166
  data: {
52951
- message_seq: +element.replyElement.replayMsgSeq
53167
+ message_seq: +element.replyElement.replayMsgSeq,
53168
+ sender_id: +element.replyElement.senderUid,
53169
+ time: +element.replyElement.replyMsgTime,
53170
+ segments: await transformIncomingSegments(ctx, message.records[0])
52952
53171
  }
52953
53172
  });
52954
53173
  break;
@@ -53042,88 +53261,98 @@ async function transformIncomingSegments(ctx, message) {
53042
53261
  }
53043
53262
  async function transformIncomingForwardedMessage(ctx, message) {
53044
53263
  const { body, contentHead, routingHead } = message;
53045
- const segments = [];
53046
- for (const elem of body.richText.elems) {
53047
- if (elem.text) {
53048
- segments.push({
53049
- type: "text",
53050
- data: {
53051
- text: elem.text.str
53052
- }
53053
- });
53054
- } else if (elem.commonElem) {
53055
- const { businessType, serviceType } = elem.commonElem;
53056
- if (serviceType === 33) {
53057
- const { faceId } = Msg.QSmallFaceExtra.decode(elem.commonElem.pbElem);
53058
- segments.push({
53059
- type: "face",
53060
- data: {
53061
- face_id: faceId.toString(),
53062
- is_large: false
53063
- }
53064
- });
53065
- } else if (serviceType === 48 && (businessType === 10 || businessType === 20)) {
53066
- const { extBizInfo, msgInfoBody } = Media.MsgInfo.decode(elem.commonElem.pbElem);
53067
- const { index: index2, pic } = msgInfoBody[0];
53068
- const rkeyData = await ctx.ntFileApi.rkeyManager.getRkey();
53069
- const rkey = businessType === 10 ? rkeyData.private_rkey : rkeyData.group_rkey;
53070
- const url2 = `https://${pic.domain}${pic.urlPath}&spec=0${rkey}`;
53071
- segments.push({
53072
- type: "image",
53073
- data: {
53074
- resource_id: index2.fileUuid,
53075
- temp_url: url2,
53076
- width: index2.info.width,
53077
- height: index2.info.height,
53078
- summary: extBizInfo.pic.summary || "[图片]",
53079
- sub_type: extBizInfo.pic.bizType === 0 ? "normal" : "sticker"
53080
- }
53081
- });
53082
- } else if (serviceType === 48 && (businessType === 11 || businessType === 21)) {
53083
- const { msgInfoBody } = Media.MsgInfo.decode(elem.commonElem.pbElem);
53084
- const { index: index2 } = msgInfoBody[0];
53085
- const url2 = await ctx.ntFileApi.getVideoUrlByPacket(index2.fileUuid, businessType === 21);
53264
+ const transformSegments = async (elems) => {
53265
+ const segments = [];
53266
+ for (const elem of elems) {
53267
+ if (elem.text) {
53086
53268
  segments.push({
53087
- type: "video",
53269
+ type: "text",
53088
53270
  data: {
53089
- resource_id: index2.fileUuid,
53090
- temp_url: url2,
53091
- width: index2.info.width,
53092
- height: index2.info.height,
53093
- duration: index2.info.time
53271
+ text: elem.text.str
53094
53272
  }
53095
53273
  });
53096
- }
53097
- } else if (elem.srcMsg) {
53098
- segments.push({
53099
- type: "reply",
53100
- data: {
53101
- message_seq: elem.srcMsg.origSeqs[0]
53274
+ } else if (elem.commonElem) {
53275
+ const { businessType, serviceType } = elem.commonElem;
53276
+ if (serviceType === 33) {
53277
+ const { faceId } = Msg.QSmallFaceExtra.decode(elem.commonElem.pbElem);
53278
+ segments.push({
53279
+ type: "face",
53280
+ data: {
53281
+ face_id: faceId.toString(),
53282
+ is_large: false
53283
+ }
53284
+ });
53285
+ } else if (serviceType === 48 && (businessType === 10 || businessType === 20)) {
53286
+ const { extBizInfo, msgInfoBody } = Media.MsgInfo.decode(elem.commonElem.pbElem);
53287
+ const { index: index2, pic } = msgInfoBody[0];
53288
+ const rkeyData = await ctx.ntFileApi.rkeyManager.getRkey();
53289
+ const rkey = businessType === 10 ? rkeyData.private_rkey : rkeyData.group_rkey;
53290
+ const url2 = `https://${pic.domain}${pic.urlPath}&spec=0${rkey}`;
53291
+ segments.push({
53292
+ type: "image",
53293
+ data: {
53294
+ resource_id: index2.fileUuid,
53295
+ temp_url: url2,
53296
+ width: index2.info.width,
53297
+ height: index2.info.height,
53298
+ summary: extBizInfo.pic.summary || "[图片]",
53299
+ sub_type: extBizInfo.pic.bizType === 0 ? "normal" : "sticker"
53300
+ }
53301
+ });
53302
+ } else if (serviceType === 48 && (businessType === 11 || businessType === 21)) {
53303
+ const { msgInfoBody } = Media.MsgInfo.decode(elem.commonElem.pbElem);
53304
+ const { index: index2 } = msgInfoBody[0];
53305
+ const url2 = await ctx.ntFileApi.getVideoUrlByPacket(index2.fileUuid, businessType === 21);
53306
+ segments.push({
53307
+ type: "video",
53308
+ data: {
53309
+ resource_id: index2.fileUuid,
53310
+ temp_url: url2,
53311
+ width: index2.info.width,
53312
+ height: index2.info.height,
53313
+ duration: index2.info.time
53314
+ }
53315
+ });
53102
53316
  }
53103
- });
53104
- } else if (elem.richMsg && elem.richMsg.serviceId === 35) {
53105
- const xml = inflateSync(elem.richMsg.template.subarray(1)).toString();
53106
- const resId = xml.match(/m_resid="([^"]+)"/)?.[1];
53107
- if (resId) {
53108
- const parser = new XMLParser();
53109
- const content = parser.parse(xml);
53317
+ } else if (elem.srcMsg) {
53318
+ const elems2 = elem.srcMsg.elems.map((e) => Msg.Elem.decode(e));
53319
+ const { contentHead: contentHead2, routingHead: routingHead2 } = Msg.Message.decode(elem.srcMsg.srcMsg);
53110
53320
  segments.push({
53111
- type: "forward",
53321
+ type: "reply",
53112
53322
  data: {
53113
- forward_id: resId,
53114
- title: content.msg.item.title[0],
53115
- preview: content.msg.item.title.slice(1),
53116
- summary: content.msg.item.summary
53323
+ message_seq: elem.srcMsg.origSeqs[0],
53324
+ sender_id: elem.srcMsg.senderUin,
53325
+ sender_name: contentHead2.msgType === 82 ? routingHead2.group.groupCard : routingHead2.c2c.friendName,
53326
+ time: elem.srcMsg.time,
53327
+ segments: await transformSegments(elems2)
53117
53328
  }
53118
53329
  });
53330
+ } else if (elem.richMsg && elem.richMsg.serviceId === 35) {
53331
+ const xml = inflateSync(elem.richMsg.template.subarray(1)).toString();
53332
+ const resId = xml.match(/m_resid="([^"]+)"/)?.[1];
53333
+ if (resId) {
53334
+ const parser = new XMLParser();
53335
+ const content = parser.parse(xml);
53336
+ segments.push({
53337
+ type: "forward",
53338
+ data: {
53339
+ forward_id: resId,
53340
+ title: content.msg.item.title[0],
53341
+ preview: content.msg.item.title.slice(1),
53342
+ summary: content.msg.item.summary
53343
+ }
53344
+ });
53345
+ }
53119
53346
  }
53120
53347
  }
53121
- }
53348
+ return segments;
53349
+ };
53122
53350
  return {
53351
+ message_seq: contentHead.msgSeq,
53123
53352
  sender_name: contentHead.msgType === 82 ? routingHead.group.groupCard : routingHead.c2c.friendName,
53124
53353
  avatar_url: contentHead.forward.avatar,
53125
53354
  time: contentHead.msgTime,
53126
- segments
53355
+ segments: await transformSegments(body.richText.elems)
53127
53356
  };
53128
53357
  }
53129
53358
  const SendPrivateMessage = defineApi(
@@ -53145,13 +53374,21 @@ const SendPrivateMessage = defineApi(
53145
53374
  }
53146
53375
  let result;
53147
53376
  if (payload.message[0].type === "forward") {
53377
+ const forwardData = payload.message[0].data;
53148
53378
  const raw = await transformOutgoingForwardMessages(
53149
53379
  ctx,
53150
- payload.message[0].data.messages,
53151
- peer
53380
+ forwardData.messages,
53381
+ peer,
53382
+ {
53383
+ title: forwardData.title,
53384
+ preview: forwardData.preview,
53385
+ summary: forwardData.summary,
53386
+ prompt: forwardData.prompt
53387
+ }
53152
53388
  );
53153
53389
  const resid = await ctx.app.pmhq.uploadForward(peer, raw.multiMsgItems);
53154
53390
  const uuid2 = randomUUID();
53391
+ const prompt = raw.prompt;
53155
53392
  result = await ctx.app.sendMessage(ctx, peer, [{
53156
53393
  elementType: 10,
53157
53394
  elementId: "",
@@ -53165,7 +53402,7 @@ const SendPrivateMessage = defineApi(
53165
53402
  type: "normal",
53166
53403
  width: 300
53167
53404
  },
53168
- desc: raw.prompt,
53405
+ desc: prompt,
53169
53406
  extra: JSON.stringify({
53170
53407
  filename: uuid2,
53171
53408
  tsum: raw.tsum
@@ -53179,7 +53416,7 @@ const SendPrivateMessage = defineApi(
53179
53416
  uniseq: uuid2
53180
53417
  }
53181
53418
  },
53182
- prompt: raw.prompt,
53419
+ prompt,
53183
53420
  ver: "0.0.0.5",
53184
53421
  view: "contact"
53185
53422
  })
@@ -53214,13 +53451,21 @@ const SendGroupMessage = defineApi(
53214
53451
  const peer = { chatType: 2, peerUid: groupCode, guildId: "" };
53215
53452
  let result;
53216
53453
  if (payload.message[0].type === "forward") {
53454
+ const forwardData = payload.message[0].data;
53217
53455
  const raw = await transformOutgoingForwardMessages(
53218
53456
  ctx,
53219
- payload.message[0].data.messages,
53220
- peer
53457
+ forwardData.messages,
53458
+ peer,
53459
+ {
53460
+ title: forwardData.title,
53461
+ preview: forwardData.preview,
53462
+ summary: forwardData.summary,
53463
+ prompt: forwardData.prompt
53464
+ }
53221
53465
  );
53222
53466
  const resid = await ctx.app.pmhq.uploadForward(peer, raw.multiMsgItems);
53223
53467
  const uuid2 = randomUUID();
53468
+ const prompt = raw.prompt;
53224
53469
  result = await ctx.app.sendMessage(ctx, peer, [{
53225
53470
  elementType: 10,
53226
53471
  elementId: "",
@@ -53234,7 +53479,7 @@ const SendGroupMessage = defineApi(
53234
53479
  type: "normal",
53235
53480
  width: 300
53236
53481
  },
53237
- desc: raw.prompt,
53482
+ desc: prompt,
53238
53483
  extra: JSON.stringify({
53239
53484
  filename: uuid2,
53240
53485
  tsum: raw.tsum
@@ -53248,7 +53493,7 @@ const SendGroupMessage = defineApi(
53248
53493
  uniseq: uuid2
53249
53494
  }
53250
53495
  },
53251
- prompt: raw.prompt,
53496
+ prompt,
53252
53497
  ver: "0.0.0.5",
53253
53498
  view: "contact"
53254
53499
  })
@@ -53983,7 +54228,11 @@ const SendGroupMessageReaction = defineApi(
53983
54228
  peer,
53984
54229
  payload.message_seq.toString(),
53985
54230
  payload.reaction,
53986
- payload.is_add
54231
+ payload.is_add,
54232
+ {
54233
+ face: "1",
54234
+ emoji: "2"
54235
+ }[payload.reaction_type]
53987
54236
  );
53988
54237
  if (result.result !== 0) {
53989
54238
  return Failed(-500, result.errMsg);
@@ -54699,7 +54948,10 @@ async function transformGroupMessageEvent(ctx, message) {
54699
54948
  async function transformSystemMessageEvent(ctx, data) {
54700
54949
  try {
54701
54950
  const sysMsg = Msg.Message.decode(data);
54702
- const { msgType, subType } = sysMsg.contentHead ?? {};
54951
+ if (!sysMsg.body) {
54952
+ return null;
54953
+ }
54954
+ const { msgType, subType } = sysMsg.contentHead;
54703
54955
  if (msgType === 33) {
54704
54956
  const tip = Notify.GroupMemberChange.decode(sysMsg.body.msgContent);
54705
54957
  if (tip.type !== 130) return null;
@@ -54757,6 +55009,19 @@ async function transformSystemMessageEvent(ctx, data) {
54757
55009
  }
54758
55010
  };
54759
55011
  } else if (msgType === 528 && subType === 39) {
55012
+ const tip = Notify.FriendDeleteOrPinChange.decode(sysMsg.body.msgContent);
55013
+ if (tip.body.type !== 7) return null;
55014
+ const messageScene = tip.body.pinChanged?.body.groupCode ? "group" : "friend";
55015
+ const peerId = messageScene === "group" ? tip.body.pinChanged.body.groupCode : Number(await ctx.ntUserApi.getUinByUid(tip.body.pinChanged.body.uid));
55016
+ const isPinned = tip.body.pinChanged?.body.info.timestamp.length !== 0;
55017
+ return {
55018
+ eventType: "peer_pin_change",
55019
+ data: {
55020
+ message_scene: messageScene,
55021
+ peer_id: peerId,
55022
+ is_pinned: isPinned
55023
+ }
55024
+ };
54760
55025
  }
54761
55026
  return null;
54762
55027
  } catch (error2) {
@@ -54770,7 +55035,7 @@ async function transformOlpushEvent(ctx, data) {
54770
55035
  if (!pushMsg.message.body) {
54771
55036
  return null;
54772
55037
  }
54773
- const { msgType, subType } = pushMsg.message?.contentHead ?? {};
55038
+ const { msgType, subType } = pushMsg.message.contentHead;
54774
55039
  if (msgType === 732 && subType === 16) {
54775
55040
  const notify = Msg.NotifyMessageBody.decode(pushMsg.message.body.msgContent.subarray(7));
54776
55041
  if (notify.field13 === 35) {
@@ -54907,6 +55172,7 @@ class MilkyAdapter extends Service2 {
54907
55172
  }
54908
55173
  });
54909
55174
  this.ctx.on("nt/message-deleted", async (message) => {
55175
+ if (!message.elements[0].grayTipElement?.revokeElement) return;
54910
55176
  if (message.chatType === ChatType.C2C) {
54911
55177
  const eventData = await transformPrivateMessageDeleted(this.ctx, message);
54912
55178
  if (eventData) {
@@ -59662,8 +59928,8 @@ class NTQQMsgApi extends Service2 {
59662
59928
  getEmojiIdType(emojiId) {
59663
59929
  return emojiId.length > 3 ? "2" : "1";
59664
59930
  }
59665
- async setEmojiLike(peer, msgSeq, emojiId, setEmoji) {
59666
- return await invoke(NTMethod.EMOJI_LIKE, [peer, msgSeq, emojiId, this.getEmojiIdType(emojiId), setEmoji]);
59931
+ async setEmojiLike(peer, msgSeq, emojiId, setEmoji, emojiType) {
59932
+ return await invoke(NTMethod.EMOJI_LIKE, [peer, msgSeq, emojiId, emojiType ?? this.getEmojiIdType(emojiId), setEmoji]);
59667
59933
  }
59668
59934
  async getMultiMsg(peer, rootMsgId, parentMsgId) {
59669
59935
  return await invoke(NTMethod.GET_MULTI_MSG, [peer, rootMsgId, parentMsgId]);
@@ -60007,6 +60273,9 @@ class NTQQMsgApi extends Service2 {
60007
60273
  async deleteFavEmoji(emojiIds) {
60008
60274
  return await invoke("nodeIKernelMsgService/deleteFavEmoji", [emojiIds]);
60009
60275
  }
60276
+ async setContactLocalTop(peer, isTop) {
60277
+ return await invoke("nodeIKernelMsgService/setContactLocalTop", [peer, isTop]);
60278
+ }
60010
60279
  }
60011
60280
  class HttpUtil {
60012
60281
  static async getCookies(url2) {