From f14494af0e9139a0948a99bf313de506eefa2383 Mon Sep 17 00:00:00 2001 From: Gehongyan Date: Fri, 20 Dec 2024 18:27:44 +0800 Subject: [PATCH] Reactions --- .../QQBot.Net.Samples.SimpleBot/Program.cs | 5 +- .../Entities/Emotes/EmojiType.cs | 32 + src/QQBot.Net.Core/Entities/Emotes/Emote.cs | 34 +- src/QQBot.Net.Core/Entities/Emotes/Emotes.cs | 697 ++++++++++++++++++ src/QQBot.Net.Core/Entities/Emotes/IEmote.cs | 5 + src/QQBot.Net.Core/Entities/Guilds/IGuild.cs | 2 +- .../Entities/Messages/EmojiType.cs | 17 - .../Entities/Messages/IMessage.cs | 24 + .../Entities/RichText/RichText.cs | 2 + src/QQBot.Net.Core/Entities/Roles/IRole.cs | 2 +- src/QQBot.Net.Core/Utils/MentionUtils.cs | 7 +- src/QQBot.Net.Core/Utils/Paging/PageInfo.cs | 1 + .../API/Common/ChannelMessage.cs | 2 +- .../GetChannelMessageReactionUsersResponse.cs | 4 +- .../Entities/Messages/MessageHelper.cs | 40 +- .../Entities/Messages/RestMessage.cs | 31 +- .../Entities/Threads/RestThread.cs | 19 +- .../Entities/Users/RestGuildMember.cs | 2 +- src/QQBot.Net.Rest/QQBotRestApiClient.cs | 9 +- src/QQBot.Net.WebSocket/ClientState.cs | 13 +- .../Entities/Messages/SocketMessage.cs | 33 +- .../Entities/Users/SocketGlobalUser.cs | 14 +- .../Entities/Users/SocketGuildMember.cs | 11 +- src/QQBot.Net.WebSocket/QQBotShardedClient.cs | 5 +- .../QQBotSocketClient.Messages.cs | 2 - src/QQBot.Net.WebSocket/QQBotSocketClient.cs | 5 +- 26 files changed, 954 insertions(+), 64 deletions(-) create mode 100644 src/QQBot.Net.Core/Entities/Emotes/EmojiType.cs create mode 100644 src/QQBot.Net.Core/Entities/Emotes/Emotes.cs delete mode 100644 src/QQBot.Net.Core/Entities/Messages/EmojiType.cs diff --git a/samples/QQBot.Net.Samples.SimpleBot/Program.cs b/samples/QQBot.Net.Samples.SimpleBot/Program.cs index 8479cd7..9596808 100644 --- a/samples/QQBot.Net.Samples.SimpleBot/Program.cs +++ b/samples/QQBot.Net.Samples.SimpleBot/Program.cs @@ -22,7 +22,10 @@ if (message.Source is not MessageSource.User) return; if (message.Channel is SocketTextChannel textChannel) { - IReadOnlyCollection threads = await textChannel.Guild.ForumChannels.First().GetThreadsAsync(); + await message.AddReactionAsync(new Emote(Emotes.System.Angry)); + await Task.Delay(TimeSpan.FromSeconds(5)); + IEnumerable flattenAsync = await message.GetReactionUsersAsync(new Emote(Emotes.System.Angry)).FlattenAsync(); + await message.RemoveReactionAsync(new Emote(Emotes.System.Angry)); } // IUserMessage msg = await message.ReplyAsync( diff --git a/src/QQBot.Net.Core/Entities/Emotes/EmojiType.cs b/src/QQBot.Net.Core/Entities/Emotes/EmojiType.cs new file mode 100644 index 0000000..aa6e0da --- /dev/null +++ b/src/QQBot.Net.Core/Entities/Emotes/EmojiType.cs @@ -0,0 +1,32 @@ +namespace QQBot; + +/// +/// 表示一个表情方式的类型。 +/// +public enum EmojiType +{ + /// + /// 系统表情,小黄脸表情。 + /// + System = 1, + + /// + /// Emoji 表情。 + /// + Emoji = 2, + + /// + /// 超级表情 + /// + SuperEmote = 3, + + /// + /// 商城表情。 + /// + Sticker = 4, + + /// + /// QQ 秀表情。 + /// + QQShow = 6 +} diff --git a/src/QQBot.Net.Core/Entities/Emotes/Emote.cs b/src/QQBot.Net.Core/Entities/Emotes/Emote.cs index 4ebcb9f..568b4d0 100644 --- a/src/QQBot.Net.Core/Entities/Emotes/Emote.cs +++ b/src/QQBot.Net.Core/Entities/Emotes/Emote.cs @@ -11,7 +11,7 @@ namespace QQBot; public class Emote : IEmote { // - private static readonly Regex EmoteRegex = new("""^\d+),faceId="(?\d+)",ext="(?[a-zA-Z0-9+/=]+)"\u200b?>$""", RegexOptions.Compiled); + private static readonly Regex EmoteRegex = new("""^\d+),faceId="(?\d*)",ext="(?[a-zA-Z0-9+/=]+)"\u200b?>$""", RegexOptions.Compiled); /// public string Id { get; } @@ -19,7 +19,7 @@ public class Emote : IEmote /// /// 获取表情符号的类型。 /// - public int Type { get; } + public EmojiType Type { get; } /// public string Name { get; } @@ -30,13 +30,37 @@ public class Emote : IEmote /// 表情符号的类型。 /// 表情符号的 ID。 /// 表情符号的显示名称。 - public Emote(int type, string id, string name) + public Emote(EmojiType type, string id, string name) { - Id = id; Type = type; + Id = id; Name = name; } + /// + /// 初始化一个 类的新实例。 + /// + /// 系统表情符号。 + /// 表情符号名称。 + public Emote(Emotes.System emote, string? name = null) + { + Type = EmojiType.System; + Id = ((int)emote).ToString(); + Name = name ?? Emotes.SystemNames.GetValueRefOrNullRef(emote); + } + + /// + /// 初始化一个 类的新实例。 + /// + /// Emoji 表情符号。 + /// 表情符号名称。 + public Emote(Emotes.Emoji emote, string? name = null) + { + Type = EmojiType.Emoji; + Id = ((int)emote).ToString(); + Name = name ?? Emotes.EmojiNames.GetValueRefOrNullRef(emote); + } + /// /// 将一个表情符号的原始格式解析为一个 。 /// @@ -59,7 +83,7 @@ public static Emote Parse(string text) string json = Encoding.UTF8.GetString(Convert.FromBase64String(ext)); JsonElement element = JsonSerializer.Deserialize(json); string name = element.GetProperty("text").GetString() ?? string.Empty; - return new Emote(type, id, name); + return new Emote((EmojiType)type, id, name); } /// diff --git a/src/QQBot.Net.Core/Entities/Emotes/Emotes.cs b/src/QQBot.Net.Core/Entities/Emotes/Emotes.cs new file mode 100644 index 0000000..095ac74 --- /dev/null +++ b/src/QQBot.Net.Core/Entities/Emotes/Emotes.cs @@ -0,0 +1,697 @@ +using System.Collections.Frozen; + +namespace QQBot; + +/// +/// 提供受支持的表情符号。 +/// +public static class Emotes +{ + /// + /// 提供受支持的系统表情符号。 + /// + public enum System + { + /// 得意 + Proud = 4, + + /// 流泪 + Tearful = 5, + + /// + Sleep = 8, + + /// 大哭 + Crying = 9, + + /// 尴尬 + Embarrassed = 10, + + /// 调皮 + Naughty = 12, + + /// 微笑 + Smile = 14, + + /// + Cool = 16, + + /// 可爱 + Cute = 21, + + /// 傲慢 + Arrogant = 23, + + /// 饥饿 + Hungry = 24, + + /// + Sleepy = 25, + + /// 惊恐 + Terrified = 26, + + /// 流汗 + Sweating = 27, + + /// 憨笑 + SillySmile = 28, + + /// 悠闲 + Relaxed = 29, + + /// 奋斗 + Struggling = 30, + + /// 疑问 + Questioning = 32, + + /// + Shush = 33, + + /// + Dizzy = 34, + + /// 敲打 + Knocking = 38, + + /// 再见 + Goodbye = 39, + + /// 发抖 + Shivering = 41, + + /// 爱情 + Love = 42, + + /// 跳跳 + Jumping = 43, + + /// 拥抱 + Hugging = 49, + + /// 蛋糕 + Cake = 53, + + /// 咖啡 + Coffee = 60, + + /// 玫瑰 + Rose = 63, + + /// 爱心 + Heart = 66, + + /// 太阳 + Sun = 74, + + /// 月亮 + Moon = 75, + + /// + ThumbsUp = 76, + + /// 握手 + Handshake = 78, + + /// 胜利 + Victory = 79, + + /// 飞吻 + FlyingKiss = 85, + + /// 西瓜 + Watermelon = 89, + + /// 冷汗 + ColdSweat = 96, + + /// 擦汗 + WipingSweat = 97, + + /// 抠鼻 + PickingNose = 98, + + /// 鼓掌 + Clapping = 99, + + /// 糗大了 + EmbarrassedBig = 100, + + /// 坏笑 + EvilSmile = 101, + + /// 左哼哼 + LeftHmph = 102, + + /// 右哼哼 + RightHmph = 103, + + /// 哈欠 + Yawn = 104, + + /// 委屈 + Grievance = 106, + + /// 左亲亲 + LeftKiss = 109, + + /// 可怜 + Pitiful = 111, + + /// 示爱 + ShowLove = 116, + + /// 抱拳 + FistSalute = 118, + + /// 拳头 + Fist = 120, + + /// 爱你 + LoveYou = 122, + + /// NO + No = 123, + + /// OK + Ok = 124, + + /// 转圈 + Spinning = 125, + + /// 挥手 + Waving = 129, + + /// 喝彩 + Cheers = 144, + + /// 棒棒糖 + Lollipop = 147, + + /// + Tea = 171, + + /// 泪奔 + CryingRun = 173, + + /// 无奈 + Helpless = 174, + + /// 卖萌 + CuteAct = 175, + + /// 小纠结 + LittleConfused = 176, + + /// doge + Doge = 179, + + /// 惊喜 + Surprise = 180, + + /// 骚扰 + Harassment = 181, + + /// 笑哭 + LaughCry = 182, + + /// 我最美 + IAmTheBest = 183, + + /// 点赞 + Like = 201, + + /// 托脸 + FaceSupport = 203, + + /// 托腮 + FacePalm = 212, + + /// 啵啵 + KissKiss = 214, + + /// 蹭一蹭 + RubRub = 219, + + /// 抱抱 + Hug = 222, + + /// 拍手 + ClapHands = 227, + + /// 佛系 + Zen = 232, + + /// 喷脸 + FaceSpray = 240, + + /// 甩头 + HeadShake = 243, + + /// 加油抱抱 + CheerUpHug = 246, + + /// 脑阔疼 + Headache = 262, + + /// 捂脸 + Facepalm = 264, + + /// 辣眼睛 + EyeBurn = 265, + + /// 哦哟 + OhMy = 266, + + /// 头秃 + Bald = 267, + + /// 问号脸 + QuestionFace = 268, + + /// 暗中观察 + Observing = 269, + + /// emm + Emm = 270, + + /// 吃瓜 + EatingMelon = 271, + + /// 呵呵哒 + Hehe = 272, + + /// 我酸了 + IAmJealous = 273, + + /// 汪汪 + WoofWoof = 277, + + /// + Sweat = 278, + + /// 无眼笑 + NoEyesSmile = 281, + + /// 敬礼 + Salute = 282, + + /// 面无表情 + Expressionless = 284, + + /// 摸鱼 + Fishing = 285, + + /// + Oh = 287, + + /// 睁眼 + OpenEyes = 289, + + /// 敲开心 + VeryHappy = 290, + + /// 摸锦鲤 + TouchKoi = 293, + + /// 期待 + Expectation = 294, + + /// 拜谢 + ThankYou = 297, + + /// 元宝 + Yuanbao = 298, + + /// 牛啊 + Awesome = 299, + + /// 右亲亲 + RightKiss = 305, + + /// 牛气冲天 + Bullish = 306, + + /// 喵喵 + MeowMeow = 307, + + /// 仔细分析 + CarefulAnalysis = 314, + + /// 加油 + CheerUp = 315, + + /// 崇拜 + Worship = 318, + + /// 比心 + HeartGesture = 319, + + /// 庆祝 + Celebration = 320, + + /// 拒绝 + Refuse = 322, + + /// 吃糖 + EatCandy = 324, + + /// 生气 + Angry = 326 + } + + /// + /// 提供受支持的 QQ 表情符号。 + /// + public enum Emoji + { + /// ☀ 晴天 + Sun = 9728, + + /// ☕ 咖啡 + HotBeverage = 9749, + + /// ☺ 可爱 + SmilingFace = 9786, + + /// ✨ 闪光 + Sparkles = 10024, + + /// ❌ 错误 + CrossMark = 10060, + + /// ❔ 问号 + WhiteQuestionMark = 10068, + + /// 🌹 玫瑰 + Rose = 127801, + + /// 🍉 西瓜 + Watermelon = 127817, + + /// 🍎 苹果 + RedApple = 127822, + + /// 🍓 草莓 + Strawberry = 127827, + + /// 🍜 拉面 + SteamingBowl = 127836, + + /// 🍞 面包 + Bread = 127838, + + /// 🍧 刨冰 + ShavedIce = 127847, + + /// 🍺 啤酒 + BeerMug = 127866, + + /// 🍻 干杯 + ClinkingBeerMugs = 127867, + + /// 🎉 庆祝 + PartyPopper = 127881, + + /// 🐛 虫 + Bug = 128027, + + /// 🐮 牛 + CowFace = 128046, + + /// 🐳 鲸鱼 + SpoutingWhale = 128051, + + /// 🐵 猴 + MonkeyFace = 128053, + + /// 👊 拳头 + OncomingFist = 128074, + + /// 👌 好的 + OkHand = 128076, + + /// 👍 厉害 + ThumbsUp = 128077, + + /// 👏 鼓掌 + ClappingHands = 128079, + + /// 👙 内衣 + Bikini = 128089, + + /// 👦 男孩 + Boy = 128102, + + /// 👨 爸爸 + Man = 128104, + + /// 💓 爱心 + BeatingHeart = 128147, + + /// 💝 礼物 + HeartWithRibbon = 128157, + + /// 💤 睡觉 + Zzz = 128164, + + /// 💦 水 + SweatDroplets = 128166, + + /// 💨 吹气 + DashingAway = 128168, + + /// 💪 肌肉 + FlexedBiceps = 128170, + + /// 📫 邮箱 + ClosedMailboxWithRaisedFlag = 128235, + + /// 🔥 火 + Fire = 128293, + + /// 😁 呲牙 + GrinningFaceWithSmilingEyes = 128513, + + /// 😂 激动 + FaceWithTearsOfJoy = 128514, + + /// 😄 高兴 + SmilingFaceWithOpenMouth = 128516, + + /// 😊 嘿嘿 + SmilingFaceWithSmilingEyes = 128522, + + /// 😌 羞涩 + RelievedFace = 128524, + + /// 😏 哼哼 + SmirkingFace = 128527, + + /// 😒 不屑 + UnamusedFace = 128530, + + /// 😓 汗 + FaceWithColdSweat = 128531, + + /// 😔 失落 + PensiveFace = 128532, + + /// 😘 飞吻 + FaceBlowingAKiss = 128536, + + /// 😚 亲亲 + KissingFaceWithClosedEyes = 128538, + + /// 😜 淘气 + WinkingFaceWithTongue = 128540, + + /// 😝 吐舌 + SquintingFaceWithTongue = 128541, + + /// 😭 大哭 + LoudlyCryingFace = 128557, + + /// 😰 紧张 + AnxiousFaceWithSweat = 128560, + + /// 😳 瞪眼 + FlushedFace = 128563 + } + + internal static readonly FrozenDictionary SystemNames = new Dictionary + { + [System.Proud] = "得意", + [System.Tearful] = "流泪", + [System.Sleep] = "睡", + [System.Crying] = "大哭", + [System.Embarrassed] = "尴尬", + [System.Naughty] = "调皮", + [System.Smile] = "微笑", + [System.Cool] = "酷", + [System.Cute] = "可爱", + [System.Arrogant] = "傲慢", + [System.Hungry] = "饥饿", + [System.Sleepy] = "困", + [System.Terrified] = "惊恐", + [System.Sweating] = "流汗", + [System.SillySmile] = "憨笑", + [System.Relaxed] = "悠闲", + [System.Struggling] = "奋斗", + [System.Questioning] = "疑问", + [System.Shush] = "嘘", + [System.Dizzy] = "晕", + [System.Knocking] = "敲打", + [System.Goodbye] = "再见", + [System.Shivering] = "发抖", + [System.Love] = "爱情", + [System.Jumping] = "跳跳", + [System.Hugging] = "拥抱", + [System.Cake] = "蛋糕", + [System.Coffee] = "咖啡", + [System.Rose] = "玫瑰", + [System.Heart] = "爱心", + [System.Sun] = "太阳", + [System.Moon] = "月亮", + [System.ThumbsUp] = "赞", + [System.Handshake] = "握手", + [System.Victory] = "胜利", + [System.FlyingKiss] = "飞吻", + [System.Watermelon] = "西瓜", + [System.ColdSweat] = "冷汗", + [System.WipingSweat] = "擦汗", + [System.PickingNose] = "抠鼻", + [System.Clapping] = "鼓掌", + [System.EmbarrassedBig] = "糗大了", + [System.EvilSmile] = "坏笑", + [System.LeftHmph] = "左哼哼", + [System.RightHmph] = "右哼哼", + [System.Yawn] = "哈欠", + [System.Grievance] = "委屈", + [System.LeftKiss] = "左亲亲", + [System.Pitiful] = "可怜", + [System.ShowLove] = "示爱", + [System.FistSalute] = "抱拳", + [System.Fist] = "拳头", + [System.LoveYou] = "爱你", + [System.No] = "NO", + [System.Ok] = "OK", + [System.Spinning] = "转圈", + [System.Waving] = "挥手", + [System.Cheers] = "喝彩", + [System.Lollipop] = "棒棒糖", + [System.Tea] = "茶", + [System.CryingRun] = "泪奔", + [System.Helpless] = "无奈", + [System.CuteAct] = "卖萌", + [System.LittleConfused] = "小纠结", + [System.Doge] = "doge", + [System.Surprise] = "惊喜", + [System.Harassment] = "骚扰", + [System.LaughCry] = "笑哭", + [System.IAmTheBest] = "我最美", + [System.Like] = "点赞", + [System.FaceSupport] = "托脸", + [System.FacePalm] = "托腮", + [System.KissKiss] = "啵啵", + [System.RubRub] = "蹭一蹭", + [System.Hug] = "抱抱", + [System.ClapHands] = "拍手", + [System.Zen] = "佛系", + [System.FaceSpray] = "喷脸", + [System.HeadShake] = "甩头", + [System.CheerUpHug] = "加油抱抱", + [System.Headache] = "脑阔疼", + [System.Facepalm] = "捂脸", + [System.EyeBurn] = "辣眼睛", + [System.OhMy] = "哦哟", + [System.Bald] = "头秃", + [System.QuestionFace] = "问号脸", + [System.Observing] = "暗中观察", + [System.Emm] = "emm", + [System.EatingMelon] = "吃瓜", + [System.Hehe] = "呵呵哒", + [System.IAmJealous] = "我酸了", + [System.WoofWoof] = "汪汪", + [System.Sweat] = "汗", + [System.NoEyesSmile] = "无眼笑", + [System.Salute] = "敬礼", + [System.Expressionless] = "面无表情", + [System.Fishing] = "摸鱼", + [System.Oh] = "哦", + [System.OpenEyes] = "睁眼", + [System.VeryHappy] = "敲开心", + [System.TouchKoi] = "摸锦鲤", + [System.Expectation] = "期待", + [System.ThankYou] = "拜谢", + [System.Yuanbao] = "元宝", + [System.Awesome] = "牛啊", + [System.RightKiss] = "右亲亲", + [System.Bullish] = "牛气冲天", + [System.MeowMeow] = "喵喵", + [System.CarefulAnalysis] = "仔细分析", + [System.CheerUp] = "加油", + [System.Worship] = "崇拜", + [System.HeartGesture] = "比心", + [System.Celebration] = "庆祝", + [System.Refuse] = "拒绝", + [System.EatCandy] = "吃糖", + [System.Angry] = "生气", + }.ToFrozenDictionary(); + + internal static readonly FrozenDictionary EmojiNames = new Dictionary + { + [Emoji.Sun] = "晴天", + [Emoji.HotBeverage] = "咖啡", + [Emoji.SmilingFace] = "可爱", + [Emoji.Sparkles] = "闪光", + [Emoji.CrossMark] = "错误", + [Emoji.WhiteQuestionMark] = "问号", + [Emoji.Rose] = "玫瑰", + [Emoji.Watermelon] = "西瓜", + [Emoji.RedApple] = "苹果", + [Emoji.Strawberry] = "草莓", + [Emoji.SteamingBowl] = "拉面", + [Emoji.Bread] = "面包", + [Emoji.ShavedIce] = "刨冰", + [Emoji.BeerMug] = "啤酒", + [Emoji.ClinkingBeerMugs] = "干杯", + [Emoji.PartyPopper] = "庆祝", + [Emoji.Bug] = "虫", + [Emoji.CowFace] = "牛", + [Emoji.SpoutingWhale] = "鲸鱼", + [Emoji.MonkeyFace] = "猴", + [Emoji.OncomingFist] = "拳头", + [Emoji.OkHand] = "好的", + [Emoji.ThumbsUp] = "厉害", + [Emoji.ClappingHands] = "鼓掌", + [Emoji.Bikini] = "内衣", + [Emoji.Boy] = "男孩", + [Emoji.Man] = "爸爸", + [Emoji.BeatingHeart] = "爱心", + [Emoji.HeartWithRibbon] = "礼物", + [Emoji.Zzz] = "睡觉", + [Emoji.SweatDroplets] = "水", + [Emoji.DashingAway] = "吹气", + [Emoji.FlexedBiceps] = "肌肉", + [Emoji.ClosedMailboxWithRaisedFlag] = "邮箱", + [Emoji.Fire] = "火", + [Emoji.GrinningFaceWithSmilingEyes] = "呲牙", + [Emoji.FaceWithTearsOfJoy] = "激动", + [Emoji.SmilingFaceWithOpenMouth] = "高兴", + [Emoji.SmilingFaceWithSmilingEyes] = "嘿嘿", + [Emoji.RelievedFace] = "羞涩", + [Emoji.SmirkingFace] = "哼哼", + [Emoji.UnamusedFace] = "不屑", + [Emoji.FaceWithColdSweat] = "汗", + [Emoji.PensiveFace] = "失落", + [Emoji.FaceBlowingAKiss] = "飞吻", + [Emoji.KissingFaceWithClosedEyes] = "亲亲", + [Emoji.WinkingFaceWithTongue] = "淘气", + [Emoji.SquintingFaceWithTongue] = "吐舌", + [Emoji.LoudlyCryingFace] = "大哭", + [Emoji.AnxiousFaceWithSweat] = "紧张", + [Emoji.FlushedFace] = "瞪眼", + }.ToFrozenDictionary(); +} diff --git a/src/QQBot.Net.Core/Entities/Emotes/IEmote.cs b/src/QQBot.Net.Core/Entities/Emotes/IEmote.cs index 8dafcc6..b38c75d 100644 --- a/src/QQBot.Net.Core/Entities/Emotes/IEmote.cs +++ b/src/QQBot.Net.Core/Entities/Emotes/IEmote.cs @@ -5,6 +5,11 @@ namespace QQBot; /// public interface IEmote : IEntity { + /// + /// 获取此表情符号的类型。 + /// + EmojiType Type { get; } + /// /// 获取此表情符号的显示名称或 Unicode 表示。 /// diff --git a/src/QQBot.Net.Core/Entities/Guilds/IGuild.cs b/src/QQBot.Net.Core/Entities/Guilds/IGuild.cs index 1407087..6b0e3f2 100644 --- a/src/QQBot.Net.Core/Entities/Guilds/IGuild.cs +++ b/src/QQBot.Net.Core/Entities/Guilds/IGuild.cs @@ -110,7 +110,7 @@ public interface IGuild : IEntity /// /// 指示当前方法是否应该仅从缓存中获取结果,还是可以通过 API 请求获取数据。 /// 发送请求时要使用的选项。 - /// 一个表示异步获取操作的任务。任务的结果包含此频道内的所有用户。 + /// 一个表示异步操作的可枚举集合,包含此频道内的所有用户。 IAsyncEnumerable> GetUsersAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions? options = null); /// diff --git a/src/QQBot.Net.Core/Entities/Messages/EmojiType.cs b/src/QQBot.Net.Core/Entities/Messages/EmojiType.cs deleted file mode 100644 index c580647..0000000 --- a/src/QQBot.Net.Core/Entities/Messages/EmojiType.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace QQBot; - -/// -/// 表示一个表情方式的类型。 -/// -public enum EmojiType -{ - /// - /// 系统表情。 - /// - System = 1, - - /// - /// Emoji 表情。 - /// - Emoji = 2 -} diff --git a/src/QQBot.Net.Core/Entities/Messages/IMessage.cs b/src/QQBot.Net.Core/Entities/Messages/IMessage.cs index 584c0da..f7ba052 100644 --- a/src/QQBot.Net.Core/Entities/Messages/IMessage.cs +++ b/src/QQBot.Net.Core/Entities/Messages/IMessage.cs @@ -49,4 +49,28 @@ public interface IMessage : IEntity /// 获取此消息中解析出的所有标签。 /// IReadOnlyCollection Tags { get; } + + /// + /// 获此消息指定表情符号的所有回应用户。 + /// + /// 要获取回应用户的表情符号。 + /// 发送请求时要使用的选项。 + /// 一个表示异步操作的可枚举集合,结果包含了所有回应用户的集合。 + IAsyncEnumerable> GetReactionUsersAsync(IEmote emote, RequestOptions? options = null); + + /// + /// 向此消息添加一个回应。 + /// + /// 要用于向此消息添加回应的表情符号。 + /// 发送请求时要使用的选项。 + /// 一个表示添加添加异步操作的任务。 + Task AddReactionAsync(IEmote emote, RequestOptions? options = null); + + /// + /// 从此消息中移除一个当前用户的回应。 + /// + /// 要从此消息移除的回应的表情符号。 + /// 发送请求时要使用的选项。 + /// 一个表示异步移除操作的任务。 + Task RemoveReactionAsync(IEmote emote, RequestOptions? options = null); } diff --git a/src/QQBot.Net.Core/Entities/RichText/RichText.cs b/src/QQBot.Net.Core/Entities/RichText/RichText.cs index dd52ab7..13b0caf 100644 --- a/src/QQBot.Net.Core/Entities/RichText/RichText.cs +++ b/src/QQBot.Net.Core/Entities/RichText/RichText.cs @@ -8,6 +8,8 @@ namespace QQBot; [DebuggerDisplay("{DebuggerDisplay,nq}")] public class RichText { + internal static RichText Empty { get; } = new([]); + /// /// 获取此富文本的段落。 /// diff --git a/src/QQBot.Net.Core/Entities/Roles/IRole.cs b/src/QQBot.Net.Core/Entities/Roles/IRole.cs index 988ddbd..f406b19 100644 --- a/src/QQBot.Net.Core/Entities/Roles/IRole.cs +++ b/src/QQBot.Net.Core/Entities/Roles/IRole.cs @@ -45,7 +45,7 @@ public interface IRole : IEntity, IDeletable /// /// 指示当前方法是否应该仅从缓存中获取结果,还是可以通过 API 请求获取数据。 /// 发送请求时要使用的选项。 - /// 一个表示异步获取操作的任务。任务的结果包含所有拥有此身份组的用户。 + /// 一个表示异步操作的可枚举集合,结果包含所有拥有此身份组的用户。 IAsyncEnumerable> GetUsersAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions? options = null); /// diff --git a/src/QQBot.Net.Core/Utils/MentionUtils.cs b/src/QQBot.Net.Core/Utils/MentionUtils.cs index 64cc93e..2805859 100644 --- a/src/QQBot.Net.Core/Utils/MentionUtils.cs +++ b/src/QQBot.Net.Core/Utils/MentionUtils.cs @@ -115,10 +115,13 @@ public static bool TryParseChannel(string text, out ulong channelId) return false; } - internal static string Resolve(IMessage msg, int startIndex, + internal static string? Resolve(IMessage msg, int startIndex, TagHandling userHandling, TagHandling channelHandling, TagHandling everyoneHandling, TagHandling emojiHandling) { + if (string.IsNullOrWhiteSpace(msg.Content)) + return msg.Content; + StringBuilder text = new(msg.Content[startIndex..]); IReadOnlyCollection tags = msg.Tags; int indexOffset = -startIndex; @@ -209,7 +212,7 @@ internal static string ResolveEmoji(ITag tag, TagHandling mode) { if (mode == TagHandling.Remove) return string.Empty; - if (tag.Value is not Emote emoji) + if (tag.Value is not IEmote emoji) return string.Empty; //Remove if its name contains any bad chars (prevents a few tag exploits) diff --git a/src/QQBot.Net.Core/Utils/Paging/PageInfo.cs b/src/QQBot.Net.Core/Utils/Paging/PageInfo.cs index a420fed..877e8aa 100644 --- a/src/QQBot.Net.Core/Utils/Paging/PageInfo.cs +++ b/src/QQBot.Net.Core/Utils/Paging/PageInfo.cs @@ -7,6 +7,7 @@ internal class PageInfo public int? Count { get; set; } public int PageSize { get; set; } public int? Remaining { get; set; } + public string? Cookie { get; set; } internal PageInfo(ulong? position, int? count, int pageSize) { diff --git a/src/QQBot.Net.Rest/API/Common/ChannelMessage.cs b/src/QQBot.Net.Rest/API/Common/ChannelMessage.cs index ee2e9f7..e967b02 100644 --- a/src/QQBot.Net.Rest/API/Common/ChannelMessage.cs +++ b/src/QQBot.Net.Rest/API/Common/ChannelMessage.cs @@ -15,7 +15,7 @@ internal class ChannelMessage public required ulong GuildId { get; set; } [JsonPropertyName("content")] - public required string Content { get; set; } + public string? Content { get; set; } [JsonPropertyName("timestamp")] [DateTimeOffsetTimestampJsonConverter(Unit = DateTimeOffsetTimestampJsonConverter.Format.ISO8601)] diff --git a/src/QQBot.Net.Rest/API/Rest/GetChannelMessageReactionUsersResponse.cs b/src/QQBot.Net.Rest/API/Rest/GetChannelMessageReactionUsersResponse.cs index 728dca3..97e30fe 100644 --- a/src/QQBot.Net.Rest/API/Rest/GetChannelMessageReactionUsersResponse.cs +++ b/src/QQBot.Net.Rest/API/Rest/GetChannelMessageReactionUsersResponse.cs @@ -8,8 +8,8 @@ internal class GetChannelMessageReactionUsersResponse public required User[] Users { get; set; } [JsonPropertyName("cookie")] - public required string Cookie { get; set; } + public string? Cookie { get; set; } - [JsonPropertyName("ie_end")] + [JsonPropertyName("is_end")] public required bool IsEnd { get; set; } } diff --git a/src/QQBot.Net.Rest/Entities/Messages/MessageHelper.cs b/src/QQBot.Net.Rest/Entities/Messages/MessageHelper.cs index 6f6dd4f..9fe8711 100644 --- a/src/QQBot.Net.Rest/Entities/Messages/MessageHelper.cs +++ b/src/QQBot.Net.Rest/Entities/Messages/MessageHelper.cs @@ -43,9 +43,10 @@ await client.ApiClient } } - public static ImmutableArray ParseTags(string text, IMessageChannel channel, IGuild? guild, + public static ImmutableArray ParseTags(string? text, IMessageChannel channel, IGuild? guild, IRole? everyoneRole, IReadOnlyCollection userMentions) { + if (string.IsNullOrWhiteSpace(text)) return ImmutableArray.Empty; ImmutableArray.Builder tags = ImmutableArray.CreateBuilder(); int index = 0; @@ -128,5 +129,42 @@ public static ImmutableArray ParseTags(string text, IMessageChannel channe return i; } + public static async IAsyncEnumerable> GetReactionUsersAsync(IMessage message, + BaseQQBotClient client, IEmote emote, int? limit, RequestOptions? options) + { + if (message.Channel is not ITextChannel textChannel) + throw new NotSupportedException("Unsupported channel type."); + int? remaining = limit; + bool isEnd = false; + string? cookie = null; + while (remaining <= 0 || !isEnd) + { + GetChannelMessageReactionUsersParams args = new() + { + Cookie = cookie, + Limit = Math.Clamp(remaining ?? QQBotConfig.MaxReactionUsersPerBatch, 1, QQBotConfig.MaxReactionUsersPerBatch) + }; + GetChannelMessageReactionUsersResponse response = await client.ApiClient + .GetChannelMessageReactionUsersAsync(textChannel.Id, message.Id, emote.Type, emote.Id, args, options) + .ConfigureAwait(false); + isEnd = response.IsEnd || response.Users.Length == 0; + cookie = response.Cookie; + remaining -= response.Users.Length; + yield return response.Users; + } + } + public static Task AddReactionAsync(IMessage message, BaseQQBotClient client, IEmote emote, RequestOptions? options) + { + if (message.Channel is not ITextChannel textChannel) + throw new NotSupportedException("Unsupported channel type."); + return client.ApiClient.AddChannelMessageReactionAsync(textChannel.Id, message.Id, emote.Type, emote.Id, options); + } + + public static Task RemoveReactionAsync(IMessage message, BaseQQBotClient client, IEmote emote, RequestOptions? options) + { + if (message.Channel is not ITextChannel textChannel) + throw new NotSupportedException("Unsupported channel type."); + return client.ApiClient.RemoveChannelMessageReactionAsync(textChannel.Id, message.Id, emote.Type, emote.Id, options); + } } diff --git a/src/QQBot.Net.Rest/Entities/Messages/RestMessage.cs b/src/QQBot.Net.Rest/Entities/Messages/RestMessage.cs index 171857c..89991ae 100644 --- a/src/QQBot.Net.Rest/Entities/Messages/RestMessage.cs +++ b/src/QQBot.Net.Rest/Entities/Messages/RestMessage.cs @@ -1,5 +1,6 @@ using System.Collections.Immutable; using System.Diagnostics; +using QQBot.API; namespace QQBot.Rest; @@ -65,7 +66,7 @@ internal static RestUserMessage Create(BaseQQBotClient client, internal virtual void Update(API.ChannelMessage model) { - Content = model.Content; + Content = model.Content ?? string.Empty; Timestamp = model.Timestamp; if (model.Attachments is { Length: > 0 } attachments) Attachments = [..attachments.Select(MessageHelper.CreateAttachment)]; @@ -86,6 +87,26 @@ internal virtual void Update(API.Rest.SendUserGroupMessageParams args, API.Rest. _tags = MessageHelper.ParseTags(Content, Channel, guild, null, []); } + /// + public async IAsyncEnumerable> GetReactionUsersAsync(IEmote emote, RequestOptions? options = null) + { + IAsyncEnumerable> asyncEnumerable = MessageHelper + .GetReactionUsersAsync(this, Client, emote, null, options); + await foreach (IReadOnlyCollection models in asyncEnumerable) + { + IReadOnlyCollection users = [..models.Select(x => RestGuildUser.Create(Client, x))]; + yield return users; + } + } + + /// + public Task AddReactionAsync(IEmote emote, RequestOptions? options = null) => + MessageHelper.AddReactionAsync(this, Client, emote, options); + + /// + public Task RemoveReactionAsync(IEmote emote, RequestOptions? options = null) => + MessageHelper.RemoveReactionAsync(this, Client, emote, options); + private string DebuggerDisplay => $"{Author}: {Content} ({Id}{ Attachments.Count switch { @@ -102,5 +123,13 @@ internal virtual void Update(API.Rest.SendUserGroupMessageParams args, API.Rest. /// IReadOnlyCollection IMessage.Embeds => Embeds; + /// + async IAsyncEnumerable> IMessage.GetReactionUsersAsync(IEmote emote, RequestOptions? options) + { + IAsyncEnumerable> asyncEnumerable = GetReactionUsersAsync(emote, options); + await foreach (IReadOnlyCollection users in asyncEnumerable) + yield return users; + } + #endregion } diff --git a/src/QQBot.Net.Rest/Entities/Threads/RestThread.cs b/src/QQBot.Net.Rest/Entities/Threads/RestThread.cs index 14eefca..17b6b3c 100644 --- a/src/QQBot.Net.Rest/Entities/Threads/RestThread.cs +++ b/src/QQBot.Net.Rest/Entities/Threads/RestThread.cs @@ -30,22 +30,25 @@ public class RestThread : RestEntity, IThread public DateTimeOffset CreatedAt { get; private set; } /// - private RestThread(BaseQQBotClient client, string id, - IForumChannel channel, ulong authorId, string title, string content, DateTimeOffset createdAt) + private RestThread(BaseQQBotClient client, string id, IForumChannel channel, ulong authorId) : base(client, id) { Guild = channel.Guild; Channel = channel; AuthorId = authorId; - Title = title; - RawContent = content; - Content = ForumHelper.ParseContent(content); - CreatedAt = createdAt; + Title = string.Empty; + RawContent = string.Empty; + Content = RichText.Empty; + CreatedAt = DateTimeOffset.Now; } internal static RestThread Create(BaseQQBotClient client, - IForumChannel channel, ulong authorId, API.ThreadInfo model) => - new(client, model.ThreadId, channel, authorId, model.Title, model.Content, model.DateTime); + IForumChannel channel, ulong authorId, API.ThreadInfo model) + { + RestThread thread = new(client, model.ThreadId, channel, authorId); + thread.Update(model); + return thread; + } internal void Update(API.ThreadInfo model) { diff --git a/src/QQBot.Net.Rest/Entities/Users/RestGuildMember.cs b/src/QQBot.Net.Rest/Entities/Users/RestGuildMember.cs index 293a142..dc64d99 100644 --- a/src/QQBot.Net.Rest/Entities/Users/RestGuildMember.cs +++ b/src/QQBot.Net.Rest/Entities/Users/RestGuildMember.cs @@ -92,5 +92,5 @@ public Task RemoveRolesAsync(IEnumerable roles, RequestOptions? options = public override string ToString() => Username; private string DebuggerDisplay => - $"{Nickname ?? Username} ({(Nickname is not null ? $"{Username}, " : string.Empty)}{Id}{(IsBot ?? false ? ", Bot" : "")}, Guild)"; + $"{Nickname ?? Username} ({(Nickname is not null ? $"{Username}, " : string.Empty)}{Id}{(IsBot ?? false ? ", Bot" : "")}, GuildMember)"; } diff --git a/src/QQBot.Net.Rest/QQBotRestApiClient.cs b/src/QQBot.Net.Rest/QQBotRestApiClient.cs index 77622a7..09fb832 100644 --- a/src/QQBot.Net.Rest/QQBotRestApiClient.cs +++ b/src/QQBot.Net.Rest/QQBotRestApiClient.cs @@ -645,8 +645,9 @@ public async Task AddChannelMessageReactionAsync(ulong channelId, string message options = RequestOptions.CreateOrClone(options); BucketIds ids = new(0, channelId); + string emojiTypeString = ((int)emojiType).ToString(); await SendAsync(HttpMethod.Put, - () => $"channels/{channelId}/messages/{messageId}/reactions/{(int)emojiType}/{emojiId}", ids, ClientBucketType.SendEdit, options) + () => $"channels/{channelId}/messages/{messageId}/reactions/{emojiTypeString}/{emojiId}", ids, ClientBucketType.SendEdit, options) .ConfigureAwait(false); } @@ -658,8 +659,9 @@ public async Task RemoveChannelMessageReactionAsync(ulong channelId, string mess options = RequestOptions.CreateOrClone(options); BucketIds ids = new(0, channelId); + string emojiTypeString = ((int)emojiType).ToString(); await SendAsync(HttpMethod.Delete, - () => $"channels/{channelId}/messages/{messageId}/reactions/{(int)emojiType}/{emojiId}", ids, ClientBucketType.SendEdit, options) + () => $"channels/{channelId}/messages/{messageId}/reactions/{emojiTypeString}/{emojiId}", ids, ClientBucketType.SendEdit, options) .ConfigureAwait(false); } @@ -677,8 +679,9 @@ public async Task GetChannelMessageReact query += $"&cookie={args.Cookie}"; BucketIds ids = new(0, channelId); + string emojiTypeString = ((int)emojiType).ToString(); return await SendAsync(HttpMethod.Get, - () => $"channels/{channelId}/messages/{messageId}/reactions/{(int)emojiType}/{emojiId}{query}", ids, ClientBucketType.SendEdit, false, options) + () => $"channels/{channelId}/messages/{messageId}/reactions/{emojiTypeString}/{emojiId}{query}", ids, ClientBucketType.SendEdit, false, options) .ConfigureAwait(false); } diff --git a/src/QQBot.Net.WebSocket/ClientState.cs b/src/QQBot.Net.WebSocket/ClientState.cs index b456824..b9ba3aa 100644 --- a/src/QQBot.Net.WebSocket/ClientState.cs +++ b/src/QQBot.Net.WebSocket/ClientState.cs @@ -12,7 +12,7 @@ internal class ClientState private readonly ConcurrentDictionary _userChannels; private readonly ConcurrentDictionary _guilds; private readonly ConcurrentDictionary _globalUsers; - private readonly ConcurrentDictionary _guildUsers; + private readonly ConcurrentDictionary _guildUsers; internal IReadOnlyCollection Channels => _channels.ToReadOnlyCollection(); @@ -31,7 +31,7 @@ public ClientState(int guildCount) _userChannels = new ConcurrentDictionary(ConcurrentHashSet.DefaultConcurrencyLevel, 0); _guilds = new ConcurrentDictionary(ConcurrentHashSet.DefaultConcurrencyLevel, (int)(guildCount * CollectionMultiplier)); _globalUsers = new ConcurrentDictionary(ConcurrentHashSet.DefaultConcurrencyLevel, 0); - _guildUsers = new ConcurrentDictionary(ConcurrentHashSet.DefaultConcurrencyLevel, 0); + _guildUsers = new ConcurrentDictionary(ConcurrentHashSet.DefaultConcurrencyLevel, 0); } #region Guild @@ -92,15 +92,12 @@ internal SocketGlobalUser GetOrAddGlobalUser(Guid id, Func _guildUsers.GetValueOrDefault(id); + internal SocketGuildUser? GetGuildUser(ulong id) => _guildUsers.GetValueOrDefault(id); internal SocketGuildUser GetOrAddGuildUser(ulong id, Func userFactory) => - _guildUsers.GetOrAdd(id.ToString(), _ => userFactory(id)); + _guildUsers.GetOrAdd(id, _ => userFactory(id)); - internal SocketGuildUser GetOrAddGuildUser(Guid id, Func userFactory) => - _guildUsers.GetOrAdd(id.ToIdString(), _ => userFactory(id)); - - internal SocketGuildUser? RemoveGuildUser(string id) => + internal SocketGuildUser? RemoveGuildUser(ulong id) => _guildUsers.TryRemove(id, out SocketGuildUser? user) ? user : null; #endregion diff --git a/src/QQBot.Net.WebSocket/Entities/Messages/SocketMessage.cs b/src/QQBot.Net.WebSocket/Entities/Messages/SocketMessage.cs index 5c37162..02d5a1b 100644 --- a/src/QQBot.Net.WebSocket/Entities/Messages/SocketMessage.cs +++ b/src/QQBot.Net.WebSocket/Entities/Messages/SocketMessage.cs @@ -61,7 +61,7 @@ internal static SocketMessage Create(QQBotSocketClient client, ClientState state internal virtual void Update(ClientState state, API.ChannelMessage model) { - Content = model.Content; + Content = model.Content ?? string.Empty; Timestamp = model.Timestamp; if (model.Attachments is { Length: > 0 } attachments) Attachments = [..attachments.Select(MessageHelper.CreateAttachment)]; @@ -84,6 +84,37 @@ internal virtual void Update(ClientState state, API.Gateway.MessageCreatedEvent _tags = MessageHelper.ParseTags(model.Content, Channel, guild, (guild as SocketGuild)?.EveryoneRole, []); } + /// + public async IAsyncEnumerable> GetReactionUsersAsync(IEmote emote, RequestOptions? options = null) + { + IAsyncEnumerable> asyncEnumerable = MessageHelper + .GetReactionUsersAsync(this, Client, emote, null, options); + SocketGuild? guild = (Channel as IGuildChannel)?.Guild as SocketGuild; + await foreach (IReadOnlyCollection models in asyncEnumerable) + { + IReadOnlyCollection users = [..models.Select(x => + { + if (guild?.AddOrUpdateUser(x, null) is { } guildMember) + return guildMember; + if (Client.GetGuildUser(x.Id) is { } guildUser) + { + guildUser.Update(Client.State, x); + return guildUser; + } + return RestGuildUser.Create(Client, x); + })]; + yield return users; + } + } + + /// + public Task AddReactionAsync(IEmote emote, RequestOptions? options = null) => + MessageHelper.AddReactionAsync(this, Client, emote, options); + + /// + public Task RemoveReactionAsync(IEmote emote, RequestOptions? options = null) => + MessageHelper.RemoveReactionAsync(this, Client, emote, options); + private string DebuggerDisplay => $"{Author}: {Content} ({Id}{ Attachments.Count switch { diff --git a/src/QQBot.Net.WebSocket/Entities/Users/SocketGlobalUser.cs b/src/QQBot.Net.WebSocket/Entities/Users/SocketGlobalUser.cs index 6ab69cf..92c7648 100644 --- a/src/QQBot.Net.WebSocket/Entities/Users/SocketGlobalUser.cs +++ b/src/QQBot.Net.WebSocket/Entities/Users/SocketGlobalUser.cs @@ -10,16 +10,24 @@ internal class SocketGlobalUser : SocketUser private ushort _references; private readonly UserScope _scope; + private string? _avatar; + /// internal override SocketGlobalUser GlobalUser => this; /// public override string? Avatar { - get => Client.ApiClient.AppId.HasValue && OpenId.HasValue + get => GetAvatarUrl(); + internal set => _avatar = value; + } + + private string? GetAvatarUrl() + { + if (!string.IsNullOrEmpty(_avatar)) return _avatar; + return _avatar ?? (Client.ApiClient.AppId.HasValue && OpenId.HasValue ? UrlUtils.GetUserAvatarUrl(Client.ApiClient.AppId.Value, OpenId.Value) - : null; - internal set { } + : null); } internal Guid? OpenId { get; set; } diff --git a/src/QQBot.Net.WebSocket/Entities/Users/SocketGuildMember.cs b/src/QQBot.Net.WebSocket/Entities/Users/SocketGuildMember.cs index a4dbd02..20879a9 100644 --- a/src/QQBot.Net.WebSocket/Entities/Users/SocketGuildMember.cs +++ b/src/QQBot.Net.WebSocket/Entities/Users/SocketGuildMember.cs @@ -65,9 +65,12 @@ internal static SocketGuildMember Create(SocketGuild guild, ClientState state, A internal void Update(ClientState state, API.User userModel, API.Member? model) { base.Update(state, userModel); - Nickname = model?.Nickname; - RoleIds = model?.Roles; - JoinedAt = model?.JoinedAt; + if (model is not null) + { + Nickname = model.Nickname; + RoleIds = model.Roles; + JoinedAt = model.JoinedAt; + } } /// @@ -118,7 +121,7 @@ public Task RemoveRolesAsync(IEnumerable roles, RequestOptions? options = public override string ToString() => Username; private string DebuggerDisplay => - $"{Nickname ?? Username}{(Nickname is not null ? Username : string.Empty)} ({Id}{(IsBot ?? false ? ", Bot" : "")}, Guild)"; + $"{Nickname ?? Username} ({(Nickname is not null ? $"{Username}, " : string.Empty)}{Id}{(IsBot ?? false ? ", Bot" : "")}, GuildMember)"; #region IGuild diff --git a/src/QQBot.Net.WebSocket/QQBotShardedClient.cs b/src/QQBot.Net.WebSocket/QQBotShardedClient.cs index 1b217b2..15a8355 100644 --- a/src/QQBot.Net.WebSocket/QQBotShardedClient.cs +++ b/src/QQBot.Net.WebSocket/QQBotShardedClient.cs @@ -270,7 +270,10 @@ public int GetShardIdFor(IGuild guild) _shards?.Select(t => t.GetUser(id)).OfType().FirstOrDefault(); /// - public override SocketGuildUser? GetGuildUser(string id) => + public override SocketGuildUser? GetGuildUser(string id) => GetGuildUser(ulong.Parse(id)); + + /// + public SocketGuildUser? GetGuildUser(ulong id) => _shards?.Select(t => t.GetGuildUser(id)).OfType().FirstOrDefault(); // /// diff --git a/src/QQBot.Net.WebSocket/QQBotSocketClient.Messages.cs b/src/QQBot.Net.WebSocket/QQBotSocketClient.Messages.cs index 0a47b34..8cef5b2 100644 --- a/src/QQBot.Net.WebSocket/QQBotSocketClient.Messages.cs +++ b/src/QQBot.Net.WebSocket/QQBotSocketClient.Messages.cs @@ -263,7 +263,6 @@ private async Task HandleUserMessageCreatedAsync(object? payload, string dispatc SocketUserMessage message = SocketUserMessage.Create(this, State, channel, author, data, dispatch); SocketChannelHelper.AddMessage(channel, this, message); await TimedInvokeAsync(_messageReceivedEvent, nameof(MessageReceived), message).ConfigureAwait(false); - await Task.CompletedTask; } private async Task HandleGroupMessageCreatedAsync(object? payload, string dispatch) @@ -281,7 +280,6 @@ await LogGatewayErrorAsync(dispatch, SocketUserMessage message = SocketUserMessage.Create(this, State, channel, author, data, dispatch); SocketChannelHelper.AddMessage(channel, this, message); await TimedInvokeAsync(_messageReceivedEvent, nameof(MessageReceived), message).ConfigureAwait(false); - await Task.CompletedTask; } private async Task HandleDirectMessageCreatedAsync(object? payload, string dispatch) diff --git a/src/QQBot.Net.WebSocket/QQBotSocketClient.cs b/src/QQBot.Net.WebSocket/QQBotSocketClient.cs index 93d8f0b..0fc640c 100644 --- a/src/QQBot.Net.WebSocket/QQBotSocketClient.cs +++ b/src/QQBot.Net.WebSocket/QQBotSocketClient.cs @@ -378,7 +378,10 @@ public override async Task DownloadUsersAsync(IEnumerable? guilds = public override SocketUser? GetUser(string id) => State.GetGlobalUser(id); /// - public override SocketGuildUser? GetGuildUser(string id) => State.GetGuildUser(id); + public override SocketGuildUser? GetGuildUser(string id) => GetGuildUser(ulong.Parse(id)); + + /// + public SocketGuildUser? GetGuildUser(ulong id) => State.GetGuildUser(id); // /// // public override SocketUser? GetUser(string username, string identifyNumber) =>